local rect = display.newRect(100, 100, 100, 100)
local moving, moving2
function moving()
transition.to(rect, {time=500, x=300, y=100, onComplete=moving2})
end
function moving2()
transition.to(rect, {time=500, x=100, y=300, onComplete=moving})
end
Hi everyone. I'm a newbie to Lua, so I would like know why my rectangle is not moving on my screen with this function? When I use only this code below, it moves but stops at the end. I'd like it to repeatedly move from one side to the other:
local rect = display.newRect(100, 100, 100, 100)
transition.to(rect, {time=500, x=300, y=100, onComplete=moving2})
You need to call one of the functions. Just put:
moving()
as the last line.
Like they said, it's not moving because you don't call
moving()
or
moving2()
in your code.
Just so you know, you don't have do this complicated stuff with two different functions in the onComplete parameter. You can have the same effect on your object with one transition by changing it's easing function and setting the iterations parameter to -1 for an infinite loop.
Here is a list of the available easing functions : http://docs.coronalabs.com/api/library/easing/index.html, as you can see the easing.continuousLoop function will do what you want.
You can try something like this instead :
local rect = display.newRect(100, 300, 100, 100)
transition.to(rect, {
time = 500,
x = 300,
y = 100,
iterations = -1,
transition = easing.continuousLoop,
})
after putting at the end
moving()
it works fine. already tested it. or you may start by
moving2()
thanks everyone, it works well putting moving () at the end
I've tried quickly the last code with easing.continuousLoop but it was not working exactly as i want, but i gonna check it deeply later because it could be helpful
Anyway thanks all
Oh man, using a local object and calling it from both transitions is at some point going to cause a serious error, using your existing code pass the "rect" to each transition so it doesn't get nabbed by "still in transition."
local rect = display.newRect(100, 100, 100, 100)
local moving, moving2
function moving(inObj)
if (inObj == nil) then inObj = rect end
transition.to(inObj, {time=500, x=300, y=100, onComplete = function(iObj)
moving2(iObj)
end})
end
function moving2(inObj)
transition.to(inObj, {time=500, x=100, y=300, onComplete, onComplete = function(iObj)
moving(iObj)
end})
end
OR
if you just want to be lazy :)
local rect = display.newRect(100, 100, 100, 100)
local movingIndex = 0
local moveData = {
{time = 500, x = 300, y = 100},
{time = 500, x = 300, y = 100}
}
function MoveObject(inObj)
movingIndex = movingIndex + 1
if (movingIndex > #moveData) then movingIndex = 1 end
transition.to(inObj, {tag = "movingObjects", time=moveData[movingIndex].time, x=moveData[movingIndex].x, y=moveData[movingIndex].y, onComplete = function(iObj)
MoveObject(iObj)
end})
end
MoveObject(rect)
That way you just have one function and can just add animation points to the moveData table :)
By tagging the transition with tag = "movingObjects" we can pause and resume any running transition with just one call like transition.pause("movingObjects") or cancel etc. useful when you want to pause and/or are moving to another see without having to wait for a transition to end or by wrapping it in a pcall()
Just food for thought :)
btw:: I didn't test the code above I just wrote it in this editor so may have 1 or two things that need tweeeking.
Related
I have a function called particle.new, and one of the parameters is called "colour". I need this to always be a table, but it isn't. This gives me an error because I'm using it with a function called love.graphics.setColor(), and I need to give it a table. I'm using my colour variable with it, which gives me an error because it is expecting a table and it thinks that colour isn't a table. Anyway, here's my code.
particle = {}
particle.__index = particle
function particle.new (x, y, colour, mass, drag)
local self = setmetatable({}, particle)
self.x, self.y, self.colour, self.mass, self.drag = x, y, colour, mass, drag
return self
end
function particle:draw ()
prevColor = love.graphics.getColor()
love.graphics.setColor(self.colour)
love.graphics.point(self.x, self.y)
love.graphics.setColor(prevColor)
end
function particle:update ()
end
function love.load()
gravity = -9.32
particles = {}
table.insert(particles, particle.new(50,50,{255, 0, 0, 255},1,0.2))
end
function love.draw()
for i = 1, table.maxn(particles) do
particles[i]:draw()
end
end
By the way, I'm using the Love2D game engine.
Your issue is not with self.colour not being a table, it's with this line
prevColor = love.graphics.getColor()
When you do that, prevColor is only getting one of the four returned values.
The solution to this is to enclose the function call in a table, so that all 4 values are kept. (Like what #EgorSkriptunoff said)
prevColor = {love.graphics.getColor()}
As for your question:
Use assert and type to check the variable type
assert(type(colour)=="table", "-Error message goes here-")
Do note however, assert will throw an error which will bring up the blue love2d screen and stop your program from running.
I have animation with 5 frames. I want to make pause for x seconds every time one animation cycle ends
1,2,3,4,5 (pause) 1,2,3,4,5 (pause) ...
Array<AtlasRegion> regions = atlas.findRegions("coin");
animGoldCoin = new Animation(1.0f / 20.0f, regions, PlayMode.LOOP);
I can't find way to do this.
Thanks
I don't really like the animation class, you can make your own.
float pauseTime=5f; // lets say that you want to pause your animation for x seconds after each cicle
float stateTime=0f; // this variable will keep the time, is our timer
float frameTime=1/20f; //amount of time from frame to frame
int frame=0; // your frame index
boolean waiting=false; // where this is true, you wait for that x seconds to pass
void Update()
{
stateTime+=Gdx.graphics.getDeltaTime();
if(!waiting && stateTime>frameTime) // that frame time passed
{
stateTime=0f; // reset our 'timer'
frame++; // increment the frame
}
if(waiting && stateTime>=0)
{
frame=0;
waiting=false;
}
if(frame>=NUMBER_OF_FRAMES)
{
frame--;
waiting=true;
stateTime=-pauseTime;
}
}
}
I think this will work, do you understand what I did?
I just had a similar problem but managed to come up with a solution. It works well for me but may not be the best way to go about it.. I'm still learning.
I created a new animation from the old animation's frames but with a speed of 0. It stops on the frame its at until the player speed changes.
if(speedX == 0f && speedY == 0f){
playerIdle = new Animation(0f,playerAnim.getKeyFrames());
playerAnim = playerIdle;
}
I know its an old question, but hopefully this will be useful to someone.
I made a quick solution in my search to pause a Libgdx animation.
I wanted an animation to pause when I pressed the spacebar.
I did try the above method of instantiating a new object and it did work. So I tried to just set the frame duration to 0, but that didn't work for some reason. This a less expensive method w/o instantiation.
If you want to pause an animation simply create three variables two are Boolean variables named toStop and hasLaunched another is a TextureRegion named launchFrame. Haslaunched is used to tell me when the spacebar is pressed.
if (InputHandler.hasLaunched && toStop ) {
launchFrame = launchBarAnimation.getKeyFrame(runTime);
toStop = false;
} else if (InputHandler.hasLaunched && !toStop){
batcher.draw(launchFrame, 90, 20, 50, 37);
} else {
batcher.draw(launchBarAnimation.getKeyFrame(runTime), 90, 20, 50, 37);
}
I'm beginner for coding, I've questions :
First I'd like know why that code is not moving :
local speed = 5
function cube ()
for i = 1,20,2 do
local rect = display.newRect(50,50,50,50)
rect.x = screenleft-300 + (50*i)
rect.y = _y
rect.x = rect.x - speed
if (rect.x < -450 )then
rect.x = 1200
end
end
end
timer.performWithDelay(1, cube, -1)
Secondly : What's the difference between
Runtime:addEventListener( "enterFrame", cube )
and
timer.performWithDelay(1, cube, -1)
Because I get the same result with both of them
And to be done, Why when I use the function "for" to duplicate something like the square i've done upside, this one put the image behind eachother and not like the square beside eachother ( the image i'm trying to duplicate has more than 4 side )
Thanks for all your reply !
thks a lot dude , I know what you mean by here but my question is little bit weird maybe lol and maybe we can't do it
I try to explain again :
for i=1,10,1 do
local Circle = display.newCircle(50, 20, 20)
Circle.x = _x + (50*i)
Circle.y = _y
end
So here I've a Circle line like that 00000 (imagine 0 are circle ^^)
and I want to make that line moving from the left to the right screen, but when i try to make it move with :
Circle.x = Circle.x - speed
Corona don't recognize the " circle.x " so I can't, maybe because is insert into the"FOR"
SO my question is : "How to move this Circle line if that's possible with the "FOR" ?
I hope I've Been clearer
Anyway, Thanks for all
I'll answer your second question first:
Runtime:addEventListener( "enterFrame", cube )
The function addEventListener adds a listener to the object’s list of listeners. When the named event occurs (in this case "enterFrame"), the listener will be invoked and be supplied with a table representing the event. In your code, the listener will call cube() on every frame (normaly, games run at 60 frames per second).
timer.performWithDelay(delay, listener [, iterations])
performWithDelay does what it says it does: Call a specified function after a delay. The timer function returns an object that can be used with other timer.* functions. In your code timer.performWithDelay(1, cube, -1) the function is calling cube() every 1ms and it is going to do so forever. This is not a good thing to do. There's nothing catching the return of the timer function and it is going to be running forever.
Now, to answer your main question. I believe what you are trying to do is create a square an move it in the screen. If that's correct, here's how you should do it:
local square = display.newRect(100,100,50,50)
local speed = 2
-- called every frame
local function moveSquare()
square.x = square.x + speed
end
Runtime:addEventListener("enterFrame", moveSquare)
The reason your code doesn't do what you want it to do is because you misunderstood a some basic CoronaSDK things.
Hope this little code helps you to understand more about how CoronaSDK works. Don't forget to check the documentation of Corona in http://docs.coronalabs.com/
You're creating an object locally in a loop and trying to move it outside of the loop. This doesn't work due to the way lua uses local variables. See http://www.lua.org/pil/4.2.html for more info about this.
Also, you'll need to place the objects into a single display group in order to move them easily. If you're using Box2D physics at all, I recommend reading up on it more at http://docs.coronalabs.com/api/library/physics/index.html.
Your code:
for i=1,10,1 do
local Circle = display.newCircle(50, 20, 20)
Circle.x = _x + (50*i)
Circle.y = _y
end
Should Be Changed to:
local Circle = display.newGroup(); --Forward declaration of Variable. Place this before any calls for it.
local speed = 2;
for i=1,10,1 do
local object = display.newCircle(50,20,20);
object.x = _x + (50*i);
object.y = _y;
Circle:insert(object); --Insert this local object into the display group
end
function moveCircle()
Circle.x = Circle.x + speed;
end
Runtime:addEventListener( "enterFrame", moveCircle);
This will move the Circle line every frame, on the X-axis, by the speed variable's value.
If you're trying to move it with a for-loop, then we'd need to see more of you code in context.
I have set of 6 movieclips as array_0 and another set of 6 movieclips as array_1. It is like two choices for different screens. Both these arrays are nested in another array as all_array. all 12 movieclips are positioned to a same x and y at initial load and that is outside the visible stage. I would like to use two different global variables for indexing. for example, cCat_Sel which ranges from 0-5 and another cScr_Sel ranges from 0-1. cCat_Sel will be changed on a click event of six buttons separate objects on stage (each button for each category).
so it will show the content for each category as per the value of cScr_Sel. if cScr_Sel is 0 then it will use all_array[0][cCat_Sel] to access the current target and similarly respective array for value of 1 as all_array[1][cCat_Sel]
I have done all the work including all tween animations to move current target and make it visible. But the tween does not bring the second set of mcs to visible area. I have two functions one for movein and one for move out by using tween animation for mc.x property. every relevant click event; I have to move current mc out and make alpha 0 and once that is finished, move in new current target and make alpha 1.
Somehow I have to combine these two tweens in one function. This is the part that I am stuck. or may be putting these mcs in two different arrays not a correct approach. I can easily achieve what I want on Enter Frame event of the root to check for cCat_Sel and cScr_Sel variables and do both animations one after the other but it seems like enter frame uses too much of cpu and makes it slower and probably not preferable.
willing to try anybody's suggestions or guidance. Thanks in advance.
I do not have any formal or informal programming education at all but I make things work by reading and trying out few things as per stackoverflow question and answers and sometime google. because most of my answers I have found from stack overflow.
Update:
function fnSlideInOut(cMc:Object, pMc:Object){
var HideX:Number =650;
var ShowX:Number = 0;
if(cMc != null){
if(cMc.x != ShowX){
//cMc.alpha = 1;
var SlideMcIn:Tween = new Tween(cMc, "x", Strong.easeOut, 650, ShowX, 0.5, true);
SlideMcIn.addEventListener(TweenEvent.MOTION_FINISH, fnSlideInFinish);
SlideMcIn.start();
}
}
if(pMc != null){
if(pMc.x != HideX){
//pMc.alpha = 1;
var SlideMcOut:Tween = new Tween(pMc, "x", Strong.easeOut, 0, HideX, 0.5, true);
SlideMcOut.addEventListener(TweenEvent.MOTION_FINISH, fnSlideOutFinish);
SlideMcOut.start();
}
}
function fnSlideOutFinish(e:TweenEvent){
//SlideMcOut.obj.alpha = 0;
SlideMcOut.removeEventListener(TweenEvent.MOTION_FINISH, fnSlideOutFinish);
}
function fnSlideInFinish(e:TweenEvent){
//SlideMcIn.obj.alpha = 1;
SlideMcIn.removeEventListener(TweenEvent.MOTION_FINISH, fnSlideInFinish);
}
}//End Function
fnSlideInOut(cScr_Sel, pScr_Sel);
I would like expert like you to comment on any kind of errors for the above code. It works 99 times but 1 time the movieclip either does not reach the destination or current and previous both targets showing and that too not where they are suppose to. This only happens when button click event happens in a quick succession. Thanks again
A option could be to use a third party library like TweenLite. It will then make it easy for you to run your second animation right after the first one is complete:
private function startAnimation():void
{
var mcToHide:MovieClip = all_array[cScr_Sel][cCat_Sel];
TweenLite.to(mcToHide, 1, {x: HIDDEN_X_POSITION, y:HIDDEN_Y_POSITION, alpha:0, onComplete:finishAnimation});
}
private function finishAnimation():void
{
var mcToShow:MovieClip = all_array[(cScr_Sel + 1) % 2][cCat_Sel];
TweenLite.to(mcToShow, 1, {x: VISIBLE_X_POSITION, y:VISIBLE_Y_POSITION, alpha:1});
}
You can then call startAnimation() on a relevant mouse click event and after having set cScr_Sel and cCat_Sel accordingly to your needs.
I'm trying to make an animation for my game, of an ant leaving it's nest. It should descend the nest going right and down, facing down and then look straight again.
I created two sequences of actions, one for moving and the other for rotating and put them together in a CCSpawn. If I execute only the moving action it works fine, but when the actions are executed together, at the end the sprite moves back to it's original position.
I have no idea of what's happening. Can you guys help?
CCLayer * gameLayer = CCLayer::create();
Ant* ant = Ant::create(); // Ant is a CCSprite
CCPoint nestp = ccp(45, 172);
ant->setPosition(nestp);
gameLayer->addChild(ant);
addChild(gameLayer);
// ant walking animation
CCAnimate * antWalk = CCAnimate::create(_antWalk);
ant->runAction(CCRepeatForever::create(antWalk));
CCPoint p1 = ccp(55, 165), p2 = ccp(75,160), p3 = ccp(90,110), p4 = ccp(105, 50);
CCSequence *moveOut = (CCSequence *)CCSequence::create(CCMoveTo::create(0.3, p1), CCMoveTo::create(0.3, p2), CCMoveTo::create(0.7, p3), CCMoveTo::create(0.7, p4), NULL);
CCSequence *rotateOut = (CCSequence *) CCSequence::create(CCRotateTo::create(0.5, 50), CCDelayTime::create(1), CCRotateTo::create(0.5, 0));
CCSpawn *leaveNest = (CCSpawn *)CCSpawn::create(moveOut, rotateOut, NULL);
ant->runAction(leaveNest);
When reviewing my own question I realized that I had forgotten to add NULL to the end of the rotating sequence. It should be like this:
CCSequence *rotateOut = (CCSequence *) CCSequence::create(CCRotateTo::create(0.5, 50), CCDelayTime::create(1), CCRotateTo::create(0.5, 0), NULL);
I wouldn't expect this behaviour, as there were no errors, that's why I took so long to find out but now it works fine! I hope it'll help someone running in the same issue.