Creating a World Map Similar to Shovel Knight or SMB3

jkocker18

Member
Hello, I am starting a new video game similar to SMBs, and I was wondering what the best way to set up a level selection world where you can move from each level like a little map?

I can get a character to jump to the next selection, but I would like it to look like it is walking over there.

I have very limited code for this project as I was just starting today.

Thank you!

(Similar to These: )
 

Attachments

Yal

šŸ§ *penguin noises*
GMC Elder
In SMB1 you always move the same amount (2 tiles) each time you press a button, so you could use 4 paths (up, down, left, right) for movement, but only move if there's no collision in that direction (e.g. place_meeting collision check at the coordinates obtained from path_get_x() / path_get_y() at the end of the path).

Also, only start moving if you're not already on a path. (You want to start the path in non-looping mode with the path end behavior set to "stop", relative to the current position instead of absolute)
 

jkocker18

Member
Thank you, I started reading up on paths as they are new to me, do you mean to create a new path each time a key is pressed if there is no collision that way?

So setting a variable = path_add(); and then having it move that move and the deleting the path with path_end();

Also how do I reference when the player is or isn't on a path?

Thank you
 
In SMB1 you always move the same amount (2 tiles) each time you press a button, so you could use 4 paths (up, down, left, right) for movement, but only move if there's no collision in that direction (e.g. place_meeting collision check at the coordinates obtained from path_get_x() / path_get_y() at the end of the path).

Also, only start moving if you're not already on a path. (You want to start the path in non-looping mode with the path end behavior set to "stop", relative to the current position instead of absolute)
Why would you use a path? That's overengineering it a bit, don't you think? I would understand for something like Super Mario World's map, since that uses more complex movements, but in Mario 3 and Shovel Knight, they both just move in straight cardinal directions until reaching the next node in the path. Using a path just to move in a straight line would be like using an excavator to dig a hole for a sapling.
EDIT: BTW, it's not always 2 tiles. You're forgetting this ;)
1614812136755.png

The way I learned it years back would be to use a simple collision check and make your maps in the room editor. Make the sprite for the overworld player have a square collision mask the same size as your tileset. Both SMB3 and Shovel Knight use 16x16. Then, have a variable in the player object called moving. You use it to check if the player is already moving. You need to know this because otherwise the player can input any direction whenever and change direction with no regards to the map's limitations. In the events where you check for key presses to move, you will need something like this:
GML:
if (not moving) {
    moving = true;
    speed = 2; // Make sure the grid size is evenly divisible by the movement speed or checking for collisions will not work properly!
    direction = 0; // Direction uses degrees. 0 is right, and each subsequent cardinal direction is +90 degrees counterclockwise
}
This prevents the player from being able to push buttons while they're still moving. Then, you need to set up your map nodes. SMB3 uses small coin icons as well as levels, while SK uses circles and levels. Every step, you check whether the player is currently overlapping a node and stop moving if so.
GML:
if (position_meeting(x, y, obj_node)) { // Make sure the node object's sprite also has a square collision mask the same size as the player's!
    moving = false;
    speed = 0;
}
...but wait! What if the player moves a direction that is invalid? You need to add some blocks that prevent invalid moves. They should just be invisible objects with a sprite that is--you guessed it--a square the same size as the player collision mask. If the player should only be able to move left and right, place them above and below the player. If the player can move up, left, and down, place one to the right of the player. And so on. Then, in the movement checking code, you need to amend it slightly:
GML:
if (not moving) {
    // The following position meeting check assumes you are attempting to move right
    // You will need to change it for checking different directions
    // Left = (x - 16, y)
    // Up   = (x, y - 16)
    // Down = (x, y + 16)
    if (not position_meeting(x + 16, y, obj_block)) {
        moving = true;
        speed = 2;
        direction = 0;
    }
}
 
Last edited:
Yeah, but I figured it'd be easier to understand than state machines for a total newbie :p
It's just a single variable written in such a way that it's in plain English. If you can kludge your way through an overly-complicated solution using paths, you're more than capable of doing it the simpler, ideal way. Not to mention, still need to do collision detection like I suggest when blocking off invalid moves.
 
Last edited:

Roman P.

Member
Static and moving state.
Input only on static state (or possibly during the moving state as well if you want to be able to reverse directions).
Keep track of node you're in, possible directions from the node and distances to next node.
Run the moving state for long enough to cover the distance between the two nodes.

That's how I would do it.

The node data could be hardcoded or generated by checking the available paths and their lengths in all directions.
 
Last edited:
Top