[Solved] Player on top of a moving platform

Hi guys,

I’ve been searching around the forums but can’t seem to find a definite answer. How do you make an object stay on top of another moving object?

In my game I have a platform that moves from left to right. However, when my character jumps onto it, it just ‘slides’ off. It doesn’t follow the movement of the platform.

I’m guessing I need to use some kind of joint for this?

Maybe you could set a higher friction on your physics objects?

A good idea would be to create a joint as soon as the character gets on the object and then remove it before you get him down.

If you think it’s fine Have a look: https://docs.coronalabs.com/api/library/physics/newJoint.html

@ojnab - I tried. Doesn’t work sadly.

@maximo97 - I played with Weld Joint and Rope Joint just to test things out. For some reason my character will fall through the platform once the joints are created. Take a look at the image below. 

cKPYWT6.png

This is based on the examples found in the Corona Samples Code folder.

You should show me the code otherwise I would not know how to help you …

However, if you have difficulty with joints another simple solution could be a runtime event, something like this:

local character local platform --your code here --Runtime function local function followRuntime() --I follow the status of the platform movement. --(below horizontal, vertical and diagonal movements) --properly positions the character character.x = platform.x character.y = platform.y - (character.height/2) end --when the character gets on the platform local function jumps() --your code here --start to the event Runtime Runtime:addEventListener( "enterFrame", followRuntime ) end --when the character down local function getOff() --your code here --Remove the event because I do not need more Runtime:removeEventListener("enterFrame", followRuntime) end

Thanks for your suggestion  :slight_smile: I will use that if I can’t get the joints to work. 

Here are the codes that I tried.

-- Character creation function createCharacter() character = display.newImageRect("images/prototype/char.png", 40, 51) physics.addBody(character, "dynamic", {bounce = 0.0, friction = 1, density = 1}) character.isBullet = true character.x = halfWidth character.y = groundPlatform.y - 30 character.isFixedRotation = true character.myName = "maincharacter" character.collision = onCollision character:addEventListener( "collision", character ) character.currentPhase = "grounded" camera:add(character, 1, true) end -- Platform creation function createPlatforms() platforms[platformsCount] = display.newImageRect("images/prototype/platform.png", 126, 22) physics.addBody(platforms[platformsCount], "static", {bounce = 0.0}) platforms[platformsCount].x = halfWidth platforms[platformsCount].y = character.y - 100 platforms[platformsCount].collision = onCollision platforms[platformsCount]:addEventListener("collision", platforms[platformsCount]) platforms[platformsCount].myName = "platform" camera:add(platforms[platformsCount], 2, false) movePlatforms(platforms[platformsCount]) platformsCount = platformsCount + 1 end -- Collision function onCollision(self, event) if (self.myName == "maincharacter" and event.other.myName == "platform") then -- Trigger collision event character.currentPhase = "grounded" timer.performWithDelay(10, function() myJoint = physics.newJoint( "rope", character, event.other, 0, -20, 0, 20 ) myJoint.maxLength = 100 end, 1) end end

Before you start you should write code that is bootable least because I lost a bit of time to re-create the missing parts. That said I am attaching the code that I created, it is like your but I added the missing parts and changed some of coordinates for my tests. Essentially the mistake was to create the joint as a parameter before passing the character and then the platform (to be done the other way).

Also they needed to be repaired the coordinates of the joint. Finally if you want the character does not rock you set myJoint.maxLength = 0. I attach the code:

local physics = require "physics" physics.start() local platforms local character local function movePlatforms(obj) local nowX = obj.x transition.to(obj, {time = 5000, iterations = 0, x = nowX+200, transition = easing.continuousLoop}) end -- Collision function onCollision(self, event) if (self.myName == "maincharacter" and event.other.myName == "platform") then -- Trigger collision event character.currentPhase = "grounded" timer.performWithDelay(10, function() myJoint = physics.newJoint( "rope", platforms, character, 0, -(character.height/2)-(platforms.height/2), 0, 0 ) myJoint.maxLength = 0 end, 1) end end -- Character creation function createCharacter() character = display.newImageRect("character.png", 40, 51) physics.addBody(character, "dynamic", {bounce = 0.0, friction = 1, density = 1}) character.isBullet = true character.x = 50 character.y = 250 character.isFixedRotation = true character.myName = "maincharacter" character.collision = onCollision character:addEventListener( "collision", character ) character.currentPhase = "grounded" --camera:add(character, 1, true) return character end local character = createCharacter() -- Platform creation function createPlatforms() local platforms platforms = display.newImageRect("platforms.png", 100, 22) physics.addBody(platforms, "static", {bounce = 0.0}) platforms.x = character.x platforms.y = character.y+(character.height\*.5)+20 platforms.collision = onCollision platforms:addEventListener("collision", platforms) platforms.myName = "platform" --camera:add(platforms, 2, false) movePlatforms(platforms) return platforms end platforms = createPlatforms()

If you want the character to move with the platform, the platform must be moved with physics, not discrete manual changes.

Discrete manual changes bypass the physics system.  It is like teleporting the platform to a new location, so no friction calculations are done.

You can also use joints to temporarily link two objects, but this will run into visual and responsive issues depending on your usage and other factors.  So be cautious here.

Here is an example of a conveyor belt, which uses linear velocity to move a platform and in turn to move an object on the platform:

https://forums.coronalabs.com/topic/67141-how-to-implement-a-conveyor-belt/

@roaminggamer - That did the trick. Thank you  :slight_smile:

@maximo97 - Thanks for taking the time to help me out. Tried out the code you posted and now I understand how the joint works. Will come in handy for another game idea I had in mind  :smiley:

Maybe you could set a higher friction on your physics objects?

A good idea would be to create a joint as soon as the character gets on the object and then remove it before you get him down.

If you think it’s fine Have a look: https://docs.coronalabs.com/api/library/physics/newJoint.html

@ojnab - I tried. Doesn’t work sadly.

@maximo97 - I played with Weld Joint and Rope Joint just to test things out. For some reason my character will fall through the platform once the joints are created. Take a look at the image below. 

cKPYWT6.png

This is based on the examples found in the Corona Samples Code folder.

You should show me the code otherwise I would not know how to help you …

However, if you have difficulty with joints another simple solution could be a runtime event, something like this:

local character local platform --your code here --Runtime function local function followRuntime() --I follow the status of the platform movement. --(below horizontal, vertical and diagonal movements) --properly positions the character character.x = platform.x character.y = platform.y - (character.height/2) end --when the character gets on the platform local function jumps() --your code here --start to the event Runtime Runtime:addEventListener( "enterFrame", followRuntime ) end --when the character down local function getOff() --your code here --Remove the event because I do not need more Runtime:removeEventListener("enterFrame", followRuntime) end

Thanks for your suggestion  :slight_smile: I will use that if I can’t get the joints to work. 

Here are the codes that I tried.

-- Character creation function createCharacter() character = display.newImageRect("images/prototype/char.png", 40, 51) physics.addBody(character, "dynamic", {bounce = 0.0, friction = 1, density = 1}) character.isBullet = true character.x = halfWidth character.y = groundPlatform.y - 30 character.isFixedRotation = true character.myName = "maincharacter" character.collision = onCollision character:addEventListener( "collision", character ) character.currentPhase = "grounded" camera:add(character, 1, true) end -- Platform creation function createPlatforms() platforms[platformsCount] = display.newImageRect("images/prototype/platform.png", 126, 22) physics.addBody(platforms[platformsCount], "static", {bounce = 0.0}) platforms[platformsCount].x = halfWidth platforms[platformsCount].y = character.y - 100 platforms[platformsCount].collision = onCollision platforms[platformsCount]:addEventListener("collision", platforms[platformsCount]) platforms[platformsCount].myName = "platform" camera:add(platforms[platformsCount], 2, false) movePlatforms(platforms[platformsCount]) platformsCount = platformsCount + 1 end -- Collision function onCollision(self, event) if (self.myName == "maincharacter" and event.other.myName == "platform") then -- Trigger collision event character.currentPhase = "grounded" timer.performWithDelay(10, function() myJoint = physics.newJoint( "rope", character, event.other, 0, -20, 0, 20 ) myJoint.maxLength = 100 end, 1) end end

Before you start you should write code that is bootable least because I lost a bit of time to re-create the missing parts. That said I am attaching the code that I created, it is like your but I added the missing parts and changed some of coordinates for my tests. Essentially the mistake was to create the joint as a parameter before passing the character and then the platform (to be done the other way).

Also they needed to be repaired the coordinates of the joint. Finally if you want the character does not rock you set myJoint.maxLength = 0. I attach the code:

local physics = require "physics" physics.start() local platforms local character local function movePlatforms(obj) local nowX = obj.x transition.to(obj, {time = 5000, iterations = 0, x = nowX+200, transition = easing.continuousLoop}) end -- Collision function onCollision(self, event) if (self.myName == "maincharacter" and event.other.myName == "platform") then -- Trigger collision event character.currentPhase = "grounded" timer.performWithDelay(10, function() myJoint = physics.newJoint( "rope", platforms, character, 0, -(character.height/2)-(platforms.height/2), 0, 0 ) myJoint.maxLength = 0 end, 1) end end -- Character creation function createCharacter() character = display.newImageRect("character.png", 40, 51) physics.addBody(character, "dynamic", {bounce = 0.0, friction = 1, density = 1}) character.isBullet = true character.x = 50 character.y = 250 character.isFixedRotation = true character.myName = "maincharacter" character.collision = onCollision character:addEventListener( "collision", character ) character.currentPhase = "grounded" --camera:add(character, 1, true) return character end local character = createCharacter() -- Platform creation function createPlatforms() local platforms platforms = display.newImageRect("platforms.png", 100, 22) physics.addBody(platforms, "static", {bounce = 0.0}) platforms.x = character.x platforms.y = character.y+(character.height\*.5)+20 platforms.collision = onCollision platforms:addEventListener("collision", platforms) platforms.myName = "platform" --camera:add(platforms, 2, false) movePlatforms(platforms) return platforms end platforms = createPlatforms()

If you want the character to move with the platform, the platform must be moved with physics, not discrete manual changes.

Discrete manual changes bypass the physics system.  It is like teleporting the platform to a new location, so no friction calculations are done.

You can also use joints to temporarily link two objects, but this will run into visual and responsive issues depending on your usage and other factors.  So be cautious here.

Here is an example of a conveyor belt, which uses linear velocity to move a platform and in turn to move an object on the platform:

https://forums.coronalabs.com/topic/67141-how-to-implement-a-conveyor-belt/

@roaminggamer - That did the trick. Thank you  :slight_smile:

@maximo97 - Thanks for taking the time to help me out. Tried out the code you posted and now I understand how the joint works. Will come in handy for another game idea I had in mind  :smiley: