It is currently Sun Aug 20, 2017 2:08 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 13 posts ] 
Author Message
PostPosted: Mon Jun 19, 2017 8:14 am 
Offline
User avatar

Joined: Sun Nov 09, 2008 9:18 pm
Posts: 957
Location: Pennsylvania, USA
I finally implemented moving platforms, in my third NES game. They were kind of tricky to get working (without remaining bugs) because of their interaction with an already quite complex main character state machine. I had two options available to me for how to implement them (pseudo code);

Code:
-Have all entities which are platforms mark themselves as such, and keep track of all active platform entity indices in an array

-The main character checks all active platform entities prior to checking for map collisions.

-Collision is done with a thin rectangle on the top portion of the platform. If there's a hit the player is locked to the top of the platform, but only if he is currently descending.

-Platform entities lock the player vertically to stay on top of the platform. I have not yet implemented horizontally moving platforms, though.


The second option was:

Code:
-All platform entities have a collision routine which interact with the main character AFTER the main character's collision routine has already run, setting an "on platform" flag if a rectangle collision is detected, as well as a couple of other flags to trigger his "landing on something" state transition.

-Collision is done with a thin rectangle on the top portion of the platform. If there's a hit the player is locked to the top of the platform, but only if he is currently descending.

-Platform entities lock the player vertically to stay on top of the platform. I have not yet implemented horizontally moving platforms, though.


I ended up going with the second option, as it ended up working just as well doing it this way and kept additional clutter out of the main character's state machine. *edit* It has occurred to me the second option should make horizontal platforms easier as they will have direct access to their horizontal velocity and can add it on to the player's position. The first option would have made the plumbing for this slightly more complex, potentially. At least with how I've architected things...

I left out a lot of details. But one interesting detail was that whenever the main character leaves a platform, at first it didn't look right because the platform was ascending and descending and when the main character falls, his y velocity was 0 so it looked unnatural. I eventually found a way to transfer the current velocity of the platform to the character right as he falls, so it looks like it should.

I also left out details about when the various flags are cleared or set, which allow platforms to be right next to each other moving at different offsets but still hold up the player as expected.

I'd be curious to hear at a high level how moving platforms work in your games. What's particularly interesting to me when designing various bits of a game engine is whether objects should perform an action ON another object, or whether the target object should perform the action ON ITSELF based on detecting some condition or other. I suppose depending on any given game engine there's going to be a heap of trade offs with all such decisions. A few years ago I had been under the illusion that there's one, crowningly perfect way to do everything; however I no longer believe this is the case.


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 8:59 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 18806
Location: NE Indiana, USA (NTSC)
Lifts in Haunted: Halloween '85 and its sequel The Curse of Possum Hollow are stored in a separate table from actors (players, enemies, and powerups). Only actor 0 (Donny or Tami) can ride lifts. Here's my recollection of how it works:

  1. Despawn a lift more than half a screen off the left side
  2. Spawn a lift that has scrolled onto the right side
  3. Find the highest landable lift
  4. When moving actor 0, treat the highest landable lift as a floor
  5. If actor 0 is riding the highest landable lift, move actor 0 by the same amount

Each frame, before moving any actors or lifts, the engine checks all active lifts against actor 0's position, looking for lifts that actor 0 could land on. A lift is considered landable if its horizontal center position is within 16 pixels of the player's and the vertical position of its surface is not above the player's feet. Then it stores the index and height of the highest landable lift (if any) for use by the walker code, which uses it to determine whether to treat the lift as a one-way floor.

Before a lift moves during each frame, it saves its old position to a temporary variable. After it moves, if the landable lift's vertical position is close enough to that of actor 0, actor 0 is moved by the difference between the old and new positions.


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 9:52 am 
Offline
User avatar

Joined: Fri Feb 27, 2009 2:35 pm
Posts: 203
Location: Fort Wayne, Indiana
In Nova the Squrirel, I do barely any special handling and my moving platforms are just regular sprites that modify the player with flags.

  1. Platform detects collision with the player's feet (with a positive player Y velocity).
  2. Zero player Y velocity, set PlayerRidingSomething, snap player's Y position to the platform, move the player with the same X and Y offset the platform did.
  3. Player routine detects PlayerRidingSomething and it forces its two bottom background collision detectors to be solid.
  4. PlayerRidingSomething causes a skip over any Y snapping stuff that would normally happen when standing on a solid, but everything else like offering to jump with the A button happens.
  5. PlayerRidingSomething is cleared.

I guess this is equivalent to GradualGames's second option?


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 9:59 am 
Offline
User avatar

Joined: Sun Nov 09, 2008 9:18 pm
Posts: 957
Location: Pennsylvania, USA
NovaSquirrel wrote:
In Nova the Squrirel, I do barely any special handling and my moving platforms are just regular sprites that modify the player with flags.

  1. Platform detects collision with the player's feet (with a positive player Y velocity).
  2. Zero player Y velocity, set PlayerRidingSomething, snap player's Y position to the platform, move the player with the same X and Y offset the platform did.
  3. Player routine detects PlayerRidingSomething and it forces its two bottom background collision detectors to be solid.
  4. PlayerRidingSomething causes a skip over any Y snapping stuff that would normally happen when standing on a solid, but everything else like offering to jump with the A button happens.
  5. PlayerRidingSomething is cleared.

I guess this is equivalent to GradualGames's second option?


Yeah sounds similar---platform acts on player, rather than player re-acts to platform.


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 10:19 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5543
Location: Canada
IMO, moving platforms are a decidedly non-trivial thing to implement in any game, NES or not. Here's a bunch of potential problem questions:

  • If things other than the player fall on it, are they carried by it?
  • If it "pinches" a character between itself and a wall, is it halted, or does it damage the character?
  • If a pinched character is damaged but not incapacitated, do they exist "inside" the platform after the pinch? How does collision resolution keep them from moving in degenerate ways? (What happens if a player is completely inside a wall in your engine? Can they "zip"?)
  • If moved by the platform, does it affect their maximum velocity or is this movement added outside that consideration? (Do they move faster than normal when walking with the platform?)
  • Does collision still apply to them while being moved by the platform?
  • Does the platform move the character before or after the character moves itself in each frame?
  • Is standing on a platform a special state for the character, or is the character code "oblivious" to it? (Is all the movement done by the platform code independently?)
  • If the platform can change shape or appear and disappear, again what happens if a character ends up "inside" it? (Zipping problem again.)
  • Is it a solid block, or is it something you can jump up through, or walk through from the side? This can obviate a few of the above problems.
  • Do you need a separate collision system for moving objects like platforms and static objects like walls?

I don't really think there's a single answer to most of these. Depending on the game context there's good reason to go a number of different ways with things.

It's also very valid to solve a problem just by making sure it isn't used anywhere the problem can happen. Super Mario Bros. moving platforms are never placed anywhere they might pinch Mario against a wall, or have to carry an enemy, and in romhacks you've probably seen that you can use a moving platform to travel through walls. (This is something they had to change for Mario Maker, where they weren't allowed to restrict the creator.)


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 10:24 am 
Offline
User avatar

Joined: Sun Nov 09, 2008 9:18 pm
Posts: 957
Location: Pennsylvania, USA
rainwarrior wrote:
IMO, moving platforms are a decidedly non-trivial thing to implement in any game, NES or not. Here's a bunch of potential problem questions:

  • If things other than the player fall on it, are they carried by it?
  • If it "pinches" a character between itself and a wall, is it halted, or does it damage the character?
  • If a pinched character is damaged but not incapacitated, do they exist "inside" the platform after the pinch? How does collision resolution keep them from moving in degenerate ways? (What happens if a player is completely inside a wall in your engine? Can they "zip"?)
  • If moved by the platform, does it affect their maximum velocity or is this movement added outside that consideration? (Do they move faster than normal when walking with the platform?)
  • Does collision still apply to them while being moved by the platform?
  • Does the platform move the character before or after the character moves itself in each frame?
  • Is standing on a platform a special state for the character, or is the character code "oblivious" to it? (Is all the movement done by the platform code independently?)
  • If the platform can change shape or appear and disappear, again what happens if a character ends up "inside" it? (Zipping problem again.)
  • Is it a solid block, or is it something you can jump up through, or walk through from the side? This can obviate a few of the above problems.
  • Do you need a separate collision system for moving objects like platforms and static objects like walls?

I don't really think there's a single answer to most of these. Depending on the game context there's good reason to go a number of different ways with things.

It's also very valid to solve a problem just by making sure it isn't used anywhere the problem can happen. Super Mario Bros. moving platforms are never placed anywhere they might pinch Mario against a wall, and in romhacks you've probably seen that you can use a moving platform to travel through walls. (This is something they had to change for Mario Maker, where they weren't allowed to restrict the creator.)


Good post. I agree with the last paragraph wholeheartedly, as I have increased the complexity with each additional game, the amount of cases that become possible to have to resolve seem to multiply exponentially. It seems it was very smart to keep my first game (Nomolos) to as few features as I could possibly stand to have in a game...I didn't have to deal with nearly as many considerations in that game as I do in my current platformer, which introduced quite a few new things I wasn't doing before. I'm frequently asking myself: "Do I really want to make platforms work in THIS case or just always have them be a certain distance away from X, "etc.


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 10:51 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 18806
Location: NE Indiana, USA (NTSC)
For example, I'll answer these for the Haunted engine:

"things other than the player" No.
"pinches" Haven't tested lift-ceiling interaction. There's no specific code to damage the player.
"What happens if a player is completely inside a wall in your engine?" Usually a gradual upward ejection, and if that's not possible, it concludes that it must be the right wall of a level section and triggers an exit.
"is this movement added outside that consideration? (Do they move faster than normal when walking with the platform?)" Movement is in addition to player, so yes.
"Does collision still apply to them while being moved" Yes
"Does the platform move the character before or after the character moves itself in each frame?" Floor solidity is sort of "during"; lift movement is after.
"Is standing on a platform a special state for the character" No. Walker sees a lift as no different from a slab, other than that only actor 0 can use lifts.
"is it something you can jump up through" Yes: lifts are one-way platforms. This means that in Curse, Down Down drops through it the same way it drops through any other one-way slab.
"Do you need a separate collision system" Lifts disregard terrain.

"It's also very valid to solve a problem just by making sure it isn't used anywhere the problem can happen." Some of the things that I haven't tested I haven't tested for exactly this reason: the level designer never put a solid slab close enough to the lift's range.


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 6:58 pm 
Offline

Joined: Thu Aug 20, 2015 3:09 am
Posts: 274
It's been a while and it wasn't on the NES, but:

1) update all platforms first, storing a delta of how far each one moves
2) any entity that collides with the top of a platform gets moved by the delta amount, without changing its velocity

Both were implemented in the "tick" and "hit" callbacks of the platform object's code. The ordering constraint was enforced by always updating the player last, which I also used for lag reduction (not that I actually needed it).

I vaguely remember using pixel precision for everything but velocity to avoid the dreaded wobble. Which was more complicated than it sounds because I was using position verlet integration. :roll:


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 7:12 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 9900
Location: Rio de Janeiro - Brazil
Rahsennor wrote:
1) update all platforms first, storing a delta of how far each one moves
2) any entity that collides with the top of a platform gets moved by the delta amount, without changing its velocity

That's pretty much my approach. The "speed" fields platform objects indicate how much they moved, so whenever an object's "standing on" field points to a moving platform, the displacement of the platform is added to the object's position, in addition to its own displacement.


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 7:54 pm 
Offline

Joined: Wed May 19, 2010 6:12 pm
Posts: 2238
tokumaru wrote:
Rahsennor wrote:
1) update all platforms first, storing a delta of how far each one moves
2) any entity that collides with the top of a platform gets moved by the delta amount, without changing its velocity

That's pretty much my approach. The "speed" fields platform objects indicate how much they moved, so whenever an object's "standing on" field points to a moving platform, the displacement of the platform is added to the object's position, in addition to its own displacement.


Hey, that sounds like how I did it.

Also, in my game I allow enemies to walk on platforms.


Top
 Profile  
 
PostPosted: Mon Jun 19, 2017 9:12 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 9900
Location: Rio de Janeiro - Brazil
psycopathicteen wrote:
Also, in my game I allow enemies to walk on platforms.

Yeah, if each object remembers where it's standing, multiple objects can ride the same platform, even items and other typically passive objects.


Top
 Profile  
 
PostPosted: Tue Jun 20, 2017 3:05 am 
Offline

Joined: Tue Feb 07, 2017 2:03 am
Posts: 214
Another factor is speed of your platforms.

If you have a platform that moves quickly up and down and you jump on it while it goes up, if you just do a jump you can end up with the platform catching up to you and "catching" you again.. I'm sure we have all had this happen to us in a game before. In some cases you can then fall through the platform XD

Typically I do the following ( if I can't get away with janky just add Velocity code ;) )

Place Player in to "on platform/continuous collision mode" and record the entity that I'm on
When I update the player, detect I'm in that state, update "other" entity first, then get its movement deltas/velocity
Inject these extra values into the players movement system depending upon state. <- also handy to misuse for those moment when you want the player to move, end of level walk, shot out of a cannon, "feared", "demo" mode, "bug repoduction/tests"


Top
 Profile  
 
PostPosted: Mon Jun 26, 2017 3:58 am 
Offline
User avatar

Joined: Thu Sep 15, 2016 6:29 am
Posts: 248
Location: Denmark (PAL)
Oziphantom wrote:
In some cases you can then fall through the platform XD

Never jump on to a platform moving upwards in Super Mario Bros...


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: Yahoo [Bot] and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group