Help needed in fixing character animation

Right now, I am polishing off the animation sequences for my character and I am faced with two final problems. 

One, my character skids when jumping and then pressing and holding the left or right button. 

https://www.youtube.com/watch?v=h00vTu_82bM

Two, if the character jumps and then another button is pressed the animation will stop mid-way.

https://www.youtube.com/watch?v=ciIdq_0_dtY&feature=youtu.be

I am not sure where to place the sequence-changing code in these two situations.

Sorry, I reposted this topic but was not getting any replies (except for Brent’s). I know this goes against community guidelines, but I have to present at least a prototype of the first scene without any bugs.

Please advise on these two issues, thanks! 

And of course the code:

local function jump() local vx, vy = anim:getLinearVelocity() local stopped = (vy^2 \<= 0.5) if stopped == true then local jumpVecY = -13 anim.gravityScale = 1 anim:applyLinearImpulse(0, jumpVecY \* anim.mass, anim.x, anim.y ) anim:setSequence("jump") anim:play() end end local function walk(xScale) local vx, vy = anim:getLinearVelocity() local stopped = (vy^2 \<= 0.5) if stopped == true then anim:setLinearVelocity(xScale \* 150, 0) anim.xScale = xScale anim:setSequence("walk") anim:play() end end local function idle() anim:setLinearVelocity(0, 0) anim:setSequence("idle") anim:play() anim.xScale = anim.xScale end local function simulatorControl(event) if event.phase == "down" then if event.keyName == "space" then jump() end end end local function makeControls(self, event) if event.phase == "began" then if self.name == "left" then walk(-1) elseif self.name == "right" then walk(1) elseif self.name == "jump" then jump() end elseif event.phase == "ended" or event.phase == "moved" then idle() end end

I really don’t want to make a bad impression by having errors…  :frowning:

Thanks again!

I’ll respond to this one as well: did you implement the “foot sensor” as I suggested yesterday?

If that’s not a viable solution, then I think you’ll have to add in detection for the character’s linear velocity (downward Y) upon hitting a platform. If it’s positive (thus player is not in “upward jump”) then I guess you can set the sequence to idle… that might handle almost every instance of case #1.

For #2, this is another case where you should have a “flag” of some sort which tells you “is the character currently in a jump?”. The foot sensor method is one way, but other people find other ways. In any case, you should set a flag like that and then, if the player presses left/right during that point, the sequence does not change.

My problem is that the jump is in one frame, it is a touch listener, not a runtime listener.

I guess I will try to change the jump from a touch to an enterFrame.

Not sure how that changes things. I assume jump is done with a touch event on your UI “Jump” button? If so, just set a flag when the jump starts and reset it when the jump ends.

I change the linearVelocity check to a foot sensor check. The only problem is now I have to Live Build my app to test for bugs. (I don’t want to make functionality for arrow keys just for testing ( ͡° ͜ʖ ͡°) 

Also, I want to learn how to Live Build, so I will give it a try. 

Then, I will use the flag as you recommended.

Thanks!

Hey, Brent, I added a flag just like you said, But I haven’t been having much luck, here are the modifications:

local function checkVelocities() local vx, vy = anim:getLinearVelocity() local stopped = (vx ^2 + vy ^2 \<= 1) local stoppedvy = (vy ^2 \<= 0.5) if stopped == true and anim.sequence ~= "idle" then idle() end if stoppedvy == true then anim.isJumping = false else anim.isJumping = true if anim.sequence ~= "jump" then anim:setSequence("jump") anim:play() end end end local function makeControls(self, event) if event.phase == "began" then if self.name == "left" and anim.isJumping == false then walk(-1) elseif self.name == "right" and anim.isJumping == false then walk(1) end elseif event.phase == "ended" or event.phase == "cancelled" then idle() end return true end&nbsp;

Also, recall, that the jump is now a touch listener on the screen not on a button. 

If I am doing something wrong, can you please say so? (In case, that sounded rude, it’s not, I really appreciate your help) Thank you. Right now the problem is problem #2. I have not tested #1 yet, as I need Live Builds to replicate it. 

I’m still not a big fan of checking velocities. It generally works, but I want to be certain that my approach works. That’s why I prefer the foot sensor method.

I suggest detecting the “ended” collision phase of the foot sensor element instead… meaning when the foot sensor exits (stops) making contact with a solid surface. When it does, set your “isJumping” flag to true. And of course, when the foot sensor begins (“began” phase) collision with a solid surface, set it back to false.

Brent

Ok, but now it only stays at true. 

if ( event.element1 == 2 and event.object2.objType == "ground" ) then if ( event.phase == "began" ) then anim.sensorOverlaps = anim.sensorOverlaps + 1 anim.isJumping = false elseif ( event.phase == "ended" ) then anim.sensorOverlaps = anim.sensorOverlaps - 1 anim.isJumping = true end end

You should only change its state if it’s completely outside of all ground objects. You seem to have the groundwork laid for this (no pun intended) with the “sensorOverlaps” check. Set the other flag to true only if that value is 0, meaning it’s not in contact with any other pieces of ground.

But now it only stays at false. Sensor Overlaps never hits 0, it only hits 1. 

I’d need to see your code…

local anim = display.newSprite(parent, sheet, sequenceData ) anim.x = 90 anim.y = 0 anim:setSequence("idle") local walkBodyParams = {halfWidth = 30, halfHeight = 50, x = -10, y = 0} physics.addBody(anim, "dynamic", {box = walkBodyParams}, {box = {halfWidth = 20, halfHeight = 10, x = -10, y = 50}, isSensor = true} ) anim:play() anim.isSleepingAllowed = false anim.isFixedRotation = true anim.sensorOverlaps = 1 anim.isJumping = false local function sensorCollide(event) if ( event.element1 == 2 and event.object2.objType == "ground" ) then if ( event.phase == "began" ) then anim.sensorOverlaps = anim.sensorOverlaps + 1 anim.isJumping = false elseif ( event.phase == "ended" ) then anim.sensorOverlaps = anim.sensorOverlaps - 1 end if anim.sensorOverlaps == 0 then anim.isJumping = true end end end

Keep in mind, the character starts out with 1, instead of 0 sensor overlaps as was told in the tutorial on the Corona website.

Code should be more like this… note that I moved the check for “zero overlaps” inside the “ended” condition block:

[lua]

local function sensorCollide(event)

    if ( event.element1 == 2 and event.object2.objType == “ground” ) then

       if ( event.phase == “began” ) then

           anim.sensorOverlaps = anim.sensorOverlaps + 1

           anim.isJumping = false

       elseif ( event.phase == “ended” ) then

           anim.sensorOverlaps = anim.sensorOverlaps - 1

           if anim.sensorOverlaps == 0 then

              anim.isJumping = true

           end

       end

    end

  end

[/lua]

Also, you should not start the “sensorOverlaps” at 1. Always start it at 0 and let the physics engine control that value. If you start it at 1, and then the character begins at some point where the sensor is touching ground, then the value will become 2 because you’re adding +1 to it… and of course that’s wrong, because in truth the sensor is only touching one ground element.

Take care,

Brent

Now it won’t allow me to jump, because the sensorOverlaps value stays at 0, permanently. The character starts off falling in mid-air, and then hits the ground. All of the time, the sensorOverlaps are at 0. (I am printing them out on an enterFrame)

Is this some sort of glitch or am I not detecting the collision right? (it’s probably me)

There’s nothing in the collision code that should be keeping it at 0. Maybe you’re resetting it to 0 at some other place in your code.

I checked my code using a find and replace, it only appears in that function and the jump function:

local function jump(event) if (event.phase == "began" and anim.sensorOverlaps \> 0 and anim.sequence ~= "jump")

I assume you must have set the “sensorOverlaps” property on the character at one point, initially, before the game really gets running…

And where I set it on the character:

 anim.sensorOverlaps = 0

Sorry, forgot about that one.

I don’t mean to digress from this topic (we’ll get back to it), but may I ask why you’re using “global” collision detection for a game that appears to use one primary character that may collide with various enemies, hazards, etc.? Generally, this is the ideal case to use “local” collision detection…

Brent