Desperately Need some assistance in RPG game physics jump implementation

Hi,

I am building a small RPG game using corona sdk. So far so good, I have implemented the character movement with animation when up, down, left, right button is pressed.

I am running into issues when pressing jump button, the the character jumps upward and keeps moving upward with a velocity set to it. 

My question is this is a top down 2d rpg game, so player movement is along the x, and y axis. The jump is also in the y axis, so this means it is always in contact with the ground when jumping. So I am perplexed on how the character can stop on collision with the ground ?

I am not so good with non physics jump, please give me some feedback if there are any physics based jump experts!

Here is the code :

– When jump arrow is touched, move character down

– Make character jump

function jump:touch(event)

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

  myAnimation:setLinearVelocity( 0, -200 )

  print(playerInAir)

end

end

jump:addEventListener(“touch”,jump)

I have also tried a clear tutorial on physics jump in : 

http://thatssopanda.com/uncategorized/refining-our-character-movement-with-corona-sdk/

But the code, simply does nothing to the character, when the button is pressed the character does not jump! :

– Make character jump
function up:touch(event)
if(event.phase == “began” and playerInAir == false) then
playerInAir = true
guy:setLinearVelocity( 0, -200 )
print(playerInAir)
end
end
up:addEventListener(“touch”,up)

Please HELP! Thanks a million in advance

RPG games would generally not use physics

So you think a non physics way would be ideal for jump movement? Like using transition.

If you look in the SampleCode/Physics folder that comes with Corona, you will find a folder called PhysicsContact. You might find it helpful in what you’re trying to accomplish.

Rob

This thread can be closed now. I have received assistance and solved it using a non physics method, using transition.to. Thanks.

Hi Ahmed, if you would like an alternative method for non-physics, but not using transitions, let me know here in this thread.

Also, I’m curious, how do you visualise the jump, if you’re looking down vertically on the character? Are you moving the shadow, instead of the character then?

But the code, simply does nothing to the character, when the button is pressed the character does not jump! :

function up:touch(event)
if(event.phase == “began” and playerInAir == false) then
playerInAir = true
guy:setLinearVelocity( 0, -200 )
print(playerInAir)
end
end
up:addEventListener(“touch”,up)

Please HELP! Thanks a million in advance

Hello,

make sure that playerInAir is initialize to false when beginning.

If you just write local playerInAir, that means playerInAir is equal to nil, which is different to false.

Yvan

Hi Thomas6,

I am still learning my way through corona and it was a pretty good learning curve for me to implement jump, although I need to commit many more hours to make the jump look perfect.

I would like to learn if there is any other non physics method of doing jump. Please share your code if any! It may come in handy in other scenarios.

Regarding visualization of jump, I simply haven’t done anything about it, as I was busy figuring out accurate jump code. 

I have not implemented anything on shadows. Do you have any feedback on how I can implement shadows of the character when it jumps?

When the Jump button is pressed it will move vertically upwards, I will show a bit of shadow at the bottom

When the jump button and move up button is pressed togather, the shadow will move in that direction so will the player. The player will stop y displacement from the initial position when the jump is over.

As I have said, I am still learning so not an expert yet. I have recently implemented dialogue for character module, so lets see how it goes. Your suggestions are most welcome. I am beginning to understand that many things are involved in developing even a small rpg top down game. I am up for the challenge as I am enjoying coding in corona.

Thanks,

Tanvir

hi Ahmed,

Try this in a completely empty project, just in the main.lua file - use the iPhone 4 setting in the simulator.

First read to code to try to see what’s going on, then ask me questions! :wink:

-- these are all graphic elements local BG = display.newRect(0,0,640,960) BG.x = 320 BG.y = 480 BG:setFillColor(.7,.7,0) local bottom = display.newRect(0,0,640,160) bottom:setFillColor(.7,.3,0) bottom.anchorY = 0 bottom.x = 320 bottom.y = 800 local heroSideways = display.newRect(0,0,96,96) heroSideways.anchorY = 1 heroSideways.x = 320 heroSideways.y = 800 local heroShadow = display.newCircle(0,0,50,50) heroShadow.x = 320 heroShadow.y = 400 heroShadow:setFillColor(0,0,0) heroShadow.alpha = .5 local heroTopview = display.newCircle(0,0,48,48) heroTopview.x = 320 heroTopview.y = 400 -- these are the variables needed for jumping local heroIsStandingOnGround = true local heroVerticalPosition = 0 local heroVerticalSpeed = 0 local heroVerticalAcceleration = 5 -- this is the frameLoop code, that runs 30 or 60 frames per second local frameLoop = function(event) -- first we check if the hero is standing on the ground -- if the hero is standing on the ground, nothing happens, everything stays the same, standing still if heroIsStandingOnGround == true then -- do nothing else -- hero is jumping, because he is not standing on the ground -- first we adjust the hero's speed each frame by adding the acceleration to the current speed (acceleration = a change in speed over time) heroVerticalSpeed = heroVerticalSpeed + heroVerticalAcceleration -- then we adjust the hero's position each frame by adding the speed to the current positions (speed = a change in position over time) heroVerticalPosition = heroVerticalPosition + heroVerticalSpeed -- now the last thing we do is see if the hero has landed again, by checking if his position is bigger or equal than zero -- remember, in Corona coordinates, a higher Y values means lower on the screen, so if the hero position is bigger then zero that means he is lower than the ground if heroVerticalPosition \>= 0 then heroVerticalPosition = 0 heroVerticalSpeed = 0 heroIsStandingOnGround = true end -- then we adjust the graphics to reflect the hero's position -- this is for the sideways view: heroSideways.y = 800 + heroVerticalPosition -- this is for the top view: heroTopview.xScale = 1 - heroVerticalPosition/500 heroTopview.yScale = heroTopview.xScale heroShadow.x = heroTopview.x - heroVerticalPosition/2 heroShadow.y = heroTopview.y - heroVerticalPosition/2 end end -- here we add the frameLoop to the Runtime so it runs every 30 of 60 frames per second Runtime:addEventListener( "enterFrame", frameLoop ) print("added") -- this is the touchListener function which is the jump function as well! local screenTouched = function(event) if event.phase == "ended" then -- first check if the hero is already jumping or not if heroIsStandingOnGround == false then -- this means the hero is already jumping, so you can't "extra" jump -- so basically we do nothing! else -- okay, the hero is not yet jumping so we can jump now! heroIsStandingOnGround = false -- because the hero is now jumping heroVerticalSpeed = -40 end end end -- and here we add the touchListener to the runtime Runtime:addEventListener("touch", screenTouched)

Hehe, I’m impressed with myself, actually: if you take out the comments that’s only 51 lines of code! Not bad!

Any luck with this, Ahmed?

Hi Thomas,

My sincere apologies for responding so late. I was swamped with work at office, I only manage to do some coding when I get back home a few hours at night. I was busy implementing health bar for the character, and successfully implemented it last night without any issues and resolved associated issues which came up.

I am surely going to try your code tonight, jump with shadow is the main part left for me for the character mechanics. Do you think I can communicate with you over skype if I run into issues with your code? Please let me know.

Thanks a million for posting your code snippet, will find some time to experiment with it tonight. I hope you are doing well.

With regards,

Tanvir Ahmed

hi Ahmed,

No need to apologize! A forum reply doesn’t oblige you to anything - I was just curious to see if it had helped you out.

Skyping won’t work for me due to life being too busy, I’m afraid, but it’s also better to have all questions and answers here in the forum, so it can help other people too that search for this information. So, feel free to ask questions here if you want, and I’ll try to help you out!

Good luck!

Thomas

Hi Thomas,

I tried your code again in my free time and works like a charm :slight_smile:

Would it be please possible to modify it a bit so that :

  • There are up, down, left , right and jump button

  • When pressing up button it does what it does in your code at the moment

  • When pressing up and jump button togather, the object will follow a small parabolic path and jump upward y displacement from initial position, shadow will be adjusted accordingly

  • When pressing right and jump button togather, the object will follow a parabollic jump to the right and stop at +x displacement from initial position, shadow will be adjusted accordingly

  • When pressing left and jump button togather, the object will follow a parabollic jump to the left and stop at -x displacement from initial position, shadow will be adjusted accordingly

  • When pressing down and jump button togather, the object will follow a parabollic jump downwards and stop at -y displacement from initial position, shadow will be adjusted accordingly

Please let me know if it would be possible, If you show me just one direction, then I should be able to do for the rest.

With regards,

Tanvir Ahmed

Hi Ahmed,

I’m superbusy at the moment, so unfortunately I don’t have the time… 

Are you understanding what’s going on with the code at the moment? The best plan is that you understand my code, and are able to adjust the code to make it to what you want to.

In essence, what my code does is the following:

  1. Touch listeners are created for buttons, simply setting states of the player (e.g. "upButtonPressed = true)

  2. Then you have a big enterFrame function that does the following each frame (so 30 or 60 times per second)

  3. If a button is pressed in a certain direction ( if upButtonPressed == true) you add the player acceleration to the player speed. You also need to set a maximum speed for the player, of course.

  4. Then you add the player speed to the player position

  5. Then you check for collisions, and update the sprite to the new position

Thanks for the detailed explanation. I shall try to implement as you suggested. 

Hey Ahmed, try this out! :slight_smile:

Set the FPS to 60 in a config.lua file, and use the iPhone4S skin.

I didn’t implement multitouch, because I hate it, so that’s up to you! The rest works perfectly.

-------------- -- main.lua -- -------------- -- create all graphics layers and elements local gameWorldGroup = display.newGroup() local userInterfaceGroup = display.newGroup() local heroGroup = display.newGroup() local gameBackGround = display.newRect(0,0,2000,2000) gameBackGround:setFillColor(0,.5,.5) gameWorldGroup:insert(gameBackGround) local upButton = display.newRect(200,660,100,100) local downButton = display.newRect(200,860,100,100) local leftButton = display.newRect(100,760,100,100) local rightButton = display.newRect(300,760,100,100) local jumpButton = display.newRect(500,760,100,100) userInterfaceGroup:insert(upButton) userInterfaceGroup:insert(downButton) userInterfaceGroup:insert(leftButton) userInterfaceGroup:insert(rightButton) userInterfaceGroup:insert(jumpButton) userInterfaceGroup.alpha = .5 local heroCircle = display.newCircle(0,0,50,50) local heroShadow = display.newCircle(0,0,52,52) heroShadow:setFillColor(0,0,0) heroShadow.alpha = .5 heroGroup:insert(heroShadow) heroGroup:insert(heroCircle) gameWorldGroup:insert(heroGroup) gameWorldGroup.x = 320 gameWorldGroup.y = 480 -- create all "physics" variables local heroIsJumping = false local heroHorizontalPosition = 0 local heroVerticalPosition = 0 local heroJumpHeight = 0 local heroHorizontalSpeed = 0 local heroVerticalSpeed = 0 local heroJumpSpeed = 0 local heroMaxSpeed = 5 local heroMoveAcceleration = .5 local heroGravity = .3 local heroMoveFriction = 0.8 local upButtonIsPressed = false local downButtonIsPressed = false local leftButtonIsPressed = false local downButtonIsPressed = false local jumpButtonIsPressed = false -- create variables that adjust the circle sizes local heroCircleScaleFactor = .01 local heroShadowDistanceFactor = 1 -- create all touchListener functions local upButtonTouched = function(event) if event.phase == "began" then display.getCurrentStage():setFocus(event.target) upButtonIsPressed = true elseif event.phase == "ended" or event.phase == "cancelled" then display.getCurrentStage():setFocus(nil) upButtonIsPressed = false end return true end -- upButtonTouched() local downButtonTouched = function(event) print("down") if event.phase == "began" then display.getCurrentStage():setFocus(event.target) downButtonIsPressed = true elseif event.phase == "ended" or event.phase == "cancelled" then display.getCurrentStage():setFocus(nil) downButtonIsPressed = false end return true end -- downButtonTouched() local leftButtonTouched = function(event) if event.phase == "began" then display.getCurrentStage():setFocus(event.target) leftButtonIsPressed = true elseif event.phase == "ended" or event.phase == "cancelled" then display.getCurrentStage():setFocus(nil) leftButtonIsPressed = false end return true end -- leftButtonTouched() local rightButtonTouched = function(event) if event.phase == "began" then display.getCurrentStage():setFocus(event.target) rightButtonIsPressed = true elseif event.phase == "ended" or event.phase == "cancelled" then display.getCurrentStage():setFocus(nil) rightButtonIsPressed = false end return true end -- rightButtonTouched() local jumpButtonTouched = function(event) if event.phase == "began" then display.getCurrentStage():setFocus(event.target) jumpButtonIsPressed = true heroJumpSpeed = -5 heroIsJumping = true elseif event.phase == "ended" or event.phase == "cancelled" then display.getCurrentStage():setFocus(nil) jumpButtonIsPressed = false end return true end -- jumpButtonTouched -- create enterFrame loop function local frameLoop = function(event) print(heroJumpHeight) -- first we calculate the change to the hero's speed, based on the 4 movement buttons if upButtonIsPressed == true then heroVerticalSpeed = heroVerticalSpeed - heroMoveAcceleration if heroVerticalSpeed \< -heroMaxSpeed then heroVerticalSpeed = -heroMaxSpeed end elseif downButtonIsPressed == true then heroVerticalSpeed = heroVerticalSpeed + heroMoveAcceleration if heroVerticalSpeed \> heroMaxSpeed then heroVerticalSpeed = heroMaxSpeed end elseif leftButtonIsPressed == true then heroHorizontalSpeed = heroHorizontalSpeed - heroMoveAcceleration if heroHorizontalSpeed \< -heroMaxSpeed then heroHorizontalSpeed = -heroMaxSpeed end elseif rightButtonIsPressed == true then heroHorizontalSpeed = heroHorizontalSpeed + heroMoveAcceleration if heroHorizontalSpeed \> heroMaxSpeed then heroHorizontalSpeed = heroMaxSpeed end else -- if none of the 4 direction move buttons is pressed, then we apply friction to slow down the hero to a standstill -- we don't know if the hero was moving horizontally or vertically, so we just apply to friction to both to make sure heroHorizontalSpeed = heroHorizontalSpeed \* heroMoveFriction heroVerticalSpeed = heroVerticalSpeed \* heroMoveFriction end -- after we've calculated the speed, we change the position based on the hero's speed -- first we apply the speed to calculate the new position variables: heroHorizontalPosition = heroHorizontalPosition + heroHorizontalSpeed heroVerticalPosition = heroVerticalPosition + heroVerticalSpeed -- then we check and calculate if the hero is jumping -- we can do this separately from the horizontal and vertical movement because they are basically not related if heroIsJumping == true then heroJumpSpeed = heroJumpSpeed + heroGravity heroJumpHeight = heroJumpHeight + heroJumpSpeed if heroJumpHeight \> 0 then heroJumpHeight = 0 heroIsJumping = false end end -- I'm not coding this here, but after you've got the H & V coordinates and jump height for the new hero position, you can use these -- coordinates to do collision testing with obstacles or enemies, and adjust the position variables if needed -- So, as I said, I won't do this check here, and just apply the position variables to the hero's displayGroup right away! heroGroup.x = heroHorizontalPosition heroGroup.y = heroVerticalPosition heroCircle.xScale = 1 - heroJumpHeight\* heroCircleScaleFactor heroCircle.yScale = heroCircle.xScale heroShadow.x = heroJumpHeight \* -heroShadowDistanceFactor heroShadow.y = heroJumpHeight \* -heroShadowDistanceFactor end -- frameLoop() -- add touch listeners to buttons upButton:addEventListener("touch", upButtonTouched) downButton:addEventListener("touch", downButtonTouched) leftButton:addEventListener("touch", leftButtonTouched) rightButton:addEventListener("touch", rightButtonTouched) jumpButton:addEventListener("touch", jumpButtonTouched) -- add frameLoop function to enterFrame Runtime event (so it runs 60 times per second) Runtime:addEventListener("enterFrame", frameLoop)

Thanks for taking your valuable time to help me out with this. I will try this out tonight and let you know how things go. 

At the moment I am a bit engrossed with how I can implement water waves with Tiled map editor so that I can have a small beach on my game.

No hurry, take your time. For waves, by the way, I would advice overlapping semitransparant sprites moving in a sine-wave pattern.

Any advice on how I can get water waves implemented?