In order to learn some of the new features before I make my game for college, I decided to make some practice projects (in GM7, college is way-ay-ay-ay behind). Today's little success is a Tile-Based Movement engine scripted in GML.
What this does:
-Allows square objects to move one tile (32 square pixel sprites) at a time.
-Prevents objects from moving onto impassable tiles (invisible objects)
This is very similar to how some tutorials show you how to prevent the player from falling through tiles by using a collision mask.
First, create a player sprite (spr_player, a 32x32 circle) and a wall sprite (a 32x32 square). Next, create their objects (obj_player and obj_wall). obj_wall does not need anything. DO NOT MAKE IT SOLID! DO NOT GIVE IT CODE! Just leave it alone.
obj_player will only have two events; Create and Step.
Code:
<div class="gml" id="{CB}" style="font-family: monospace;"><ol>
Information about object: obj_player
Sprite: spr_player
Solid: <span style="color: #663300;">false
Visible: <span style="color: #663300;">true
Depth: <span style="color: #cc66cc;">0
Persistent: <span style="color: #663300;">false
Parent: <no parent>
Mask: <same as sprite>
Create Event:
execute code:
{
move_speed = <span style="color: #cc66cc;">4;
tile_x = <span style="font-weight: bold; color: #000000;">x / <span style="color: #cc66cc;">32;
tile_y = <span style="font-weight: bold; color: #000000;">y / <span style="color: #cc66cc;">32;
}
Step Event:
execute code:
{
UP = [url=http://www.zonamakers.com/gmlreference/keyboard_check.html]<span style="color: navy;">keyboard_check[/url](<span style="color: #663300;">vk_up);
DOWN = [url=http://www.zonamakers.com/gmlreference/keyboard_check.html]<span style="color: navy;">keyboard_check[/url](<span style="color: #663300;">vk_down);
LEFT = [url=http://www.zonamakers.com/gmlreference/keyboard_check.html]<span style="color: navy;">keyboard_check[/url](<span style="color: #663300;">vk_left);
RIGHT = [url=http://www.zonamakers.com/gmlreference/keyboard_check.html]<span style="color: navy;">keyboard_check[/url](<span style="color: #663300;">vk_right);
SELECT = [url=http://www.zonamakers.com/gmlreference/keyboard_check.html]<span style="color: navy;">keyboard_check[/url](<span style="color: #663300;">vk_space) || [url=http://www.zonamakers.com/gmlreference/keyboard_check.html]<span style="color: navy;">keyboard_check[/url](<span style="color: #663300;">vk_enter);
CANCEL = [url=http://www.zonamakers.com/gmlreference/keyboard_check.html]<span style="color: navy;">keyboard_check[/url](<span style="color: #663300;">vk_escape) || [url=http://www.zonamakers.com/gmlreference/keyboard_check.html]<span style="color: navy;">keyboard_check[/url]([url=http://www.zonamakers.com/gmlreference/ord.html]<span style="color: navy;">ord[/url]('X'));
<span style="font-weight: bold; color: #000000;">if (tile_x * <span style="color: #cc66cc;">32 > <span style="font-weight: bold; color: #000000;">x) { <span style="font-weight: bold; color: #000000;">x += move_speed; <span style="font-weight: bold; color: #000000;">exit; }
<span style="font-weight: bold; color: #000000;">else <span style="font-weight: bold; color: #000000;">if (tile_x * <span style="color: #cc66cc;">32 < <span style="font-weight: bold; color: #000000;">x) { <span style="font-weight: bold; color: #000000;">x -= move_speed; <span style="font-weight: bold; color: #000000;">exit; }
<span style="font-weight: bold; color: #000000;">else <span style="font-weight: bold; color: #000000;">if (tile_y * <span style="color: #cc66cc;">32 > <span style="font-weight: bold; color: #000000;">y) { <span style="font-weight: bold; color: #000000;">y += move_speed; <span style="font-weight: bold; color: #000000;">exit; }
<span style="font-weight: bold; color: #000000;">else <span style="font-weight: bold; color: #000000;">if (tile_y * <span style="color: #cc66cc;">32 < <span style="font-weight: bold; color: #000000;">y) { <span style="font-weight: bold; color: #000000;">y -= move_speed; <span style="font-weight: bold; color: #000000;">exit; }
<span style="font-weight: bold; color: #000000;">if (UP) { [url=http://www.zonamakers.com/gmlreference/script_execute.html]<span style="color: navy;">script_execute[/url](scr_move, c_dir_up); }
<span style="font-weight: bold; color: #000000;">else <span style="font-weight: bold; color: #000000;">if (DOWN) { [url=http://www.zonamakers.com/gmlreference/script_execute.html]<span style="color: navy;">script_execute[/url](scr_move, c_dir_down); }
<span style="font-weight: bold; color: #000000;">else <span style="font-weight: bold; color: #000000;">if (LEFT) { [url=http://www.zonamakers.com/gmlreference/script_execute.html]<span style="color: navy;">script_execute[/url](scr_move, c_dir_left); }
<span style="font-weight: bold; color: #000000;">else <span style="font-weight: bold; color: #000000;">if (RIGHT) { [url=http://www.zonamakers.com/gmlreference/script_execute.html]<span style="color: navy;">script_execute[/url](scr_move, c_dir_right); }
}
This code starts in the Create Event by declaring our instance variables. This is good practice, and when you make your player more complicated later, you can add more declarations here, such as animation_speed. The Step event is next. Here you must first collect the Input from the keyboard, so we grab some essential stuff, up/down/left/right, and some stuff for later (though this tutorial will not cover the SELECT or CANCEL branches of the system).
Next the tile is moved closer to its proper location. This would be the current Tile Position multiplied by 32. This code will prevent the player from switching the direction until the Real X (x) and the Tile X (tile_x * 32) are equal. The same goes for the Ys.
Next, based on the Input, a call is made to a script you are about to write, called scr_move.
Code:
<div class="gml" id="{CB}" style="font-family: monospace;"><ol>
<span style="font-style: italic; color: green;">// Moves the character based on tile position in direction argument0
{
<span style="font-style: italic; color: green;">// This set of conditionals is strictly for Movement!
<span style="font-weight: bold; color: #000000;">if (argument0 == c_dir_up) { <span style="font-weight: bold; color: #000000;">if (![url=http://www.zonamakers.com/gmlreference/place_meeting.html]<span style="color: navy;">place_meeting[/url](tile_x * <span style="color: #cc66cc;">32, (tile_y - <span style="color: #cc66cc;">1) * <span style="color: #cc66cc;">32, obj_wall)) tile_y -= <span style="color: #cc66cc;">1; }
<span style="font-weight: bold; color: #000000;">else <span style="font-weight: bold; color: #000000;">if (argument0 == c_dir_down) { <span style="font-weight: bold; color: #000000;">if (![url=http://www.zonamakers.com/gmlreference/place_meeting.html]<span style="color: navy;">place_meeting[/url](tile_x * <span style="color: #cc66cc;">32, (tile_y + <span style="color: #cc66cc;">1) * <span style="color: #cc66cc;">32, obj_wall)) tile_y += <span style="color: #cc66cc;">1; }
<span style="font-weight: bold; color: #000000;">else <span style="font-weight: bold; color: #000000;">if (argument0 == c_dir_left) { <span style="font-weight: bold; color: #000000;">if (![url=http://www.zonamakers.com/gmlreference/place_meeting.html]<span style="color: navy;">place_meeting[/url]((tile_x - <span style="color: #cc66cc;">1) * <span style="color: #cc66cc;">32, tile_y * <span style="color: #cc66cc;">32, obj_wall)) tile_x -= <span style="color: #cc66cc;">1; }
<span style="font-weight: bold; color: #000000;">else <span style="font-weight: bold; color: #000000;">if (argument0 == c_dir_right) { <span style="font-weight: bold; color: #000000;">if (![url=http://www.zonamakers.com/gmlreference/place_meeting.html]<span style="color: navy;">place_meeting[/url]((tile_x + <span style="color: #cc66cc;">1) * <span style="color: #cc66cc;">32, tile_y * <span style="color: #cc66cc;">32, obj_wall)) tile_x += <span style="color: #cc66cc;">1; }
}
This code checks the direction passed in argument0 and changes the tile_x/y accordingly unless their is an obj_wall in the way. We have this code in a script so that we don't have to rewrite it for our NPCs and other moving objects. Notice that I use custom constants c_dir_*. All you have to do is put them in your Constants and give them any values (that are unique). Mine are 0 through 4 because I have no other constants.
Now, you should be able to create a map. Open up a Room and surround it with obj_wall objects. Feel free to build a maze. Place your obj_player object in the room, and run it.
WARNING: You need to place tiles on the 32x32 grid.
NOTE: You can replace all of the instances of 32 in the above code with a constant. Try changing the value of the constant to 16 or 64. Resize your sprites, and check it out.
Hope that was helpful. If ya'll have any questions, corrections, or suggestions, lemme know, yo.
~Optimist Shadow