Skip to content

Quick Start Guide

Lojemiru edited this page Sep 13, 2021 · 1 revision

TODO: Images

So, you just want to get rolling with some quick and easy pixel-perfect collisions? This Quick Start guide will walk you through setting up basic collisions for a player object.

In your GameMaker Studio 2.3 project, create a new script for functions to run on game startup (if you haven't already). You can name it whatever you like, but mine's usually called scr_setup. You'll need to type in the following code outside of a function so that it runs on startup:

lhc_init();

lhc_create_interface("ISolid");

lhc_assign_interface("ISolid", obj_solid);

lhc_init() prepares the entire system. This MUST be run before any other LHC functions can be safely called.

lhc_create_interface("ISolid") defines a new Interface called ISolid. We can assign this to objects and later use it to check for collisions.

Speaking of assigning Interfaces to objects, we do that with lhc_assign_interface("ISolid", obj_solid).

Under the hood, Interfaces are little more than a fancy wrapper for tags and function names. In context of the LHC, however, they give us the ability to detect collisions as a group and provide a common interface (woah, that's the name!) for collision function calls. I'll explain that a more properly in their dedicated section of the documentation, but for right now you should just think of them as the ability to assign multiple parent objects to an object that are used exclusively for collision checking.


Now that we've got the prep work out of the way, let's make two new objects. We'll name the first obj_solid and assign it a 16x16 sprite with the origin set to "Top Left." This will be our example collision object. We'll name the second obj_player and give it an 8x28 sprite with the origin set to "Bottom Centre."

Open obj_player and add a Create and Step event.

lhc_activate() needs to be called in the Create event of every object you want to use LHC collisions. lhc_add(interface, function) sets a function that should be run when the LHC detects a collision with the specified Interface, and should generally only be used in the Create event. Add the following code to the Create event:

/// CREATE

// Create movement variables.
xVel = 0;
yVel = 0;
onGround = false;

// Initialize the LHC for this object.
lhc_activate();

// Add collision with Interface ISolid.
lhc_add("ISolid", function() {
    // Check for horizontal collision.
    if (lhc_collision_horizontal()) {
        // Stop further x-axis movement this step...
        lhc_stop_x();
        // AND stop our x velocity.
        xVel = 0;
    }

    // Check for vertical collision.
    if (lhc_collision_vertical()) {
        // Stop further y-axis movement this step...
        lhc_stop_y();
        // AND stop our y velocity.
        yVel = 0;
    }
});

lhc_collision_* functions return the direction of the current collision - up, down, left, right, horizontal (left OR right), and vertical (up OR down). lhc_stop_* functions will stop movement on the given axis for the current step at the point of collision. They do NOT reset your x/yVel variables, as those are not controlled by the LHC; take care to handle them manually as necessary. (Here, we set them to 0 when we're colliding in their direction to stop the player from "sticking" to the colliding ISolid.) These functions are collision-event only and will result in undefined behavior if called outside of an LHC collision event. lhc_colliding() is another collision-event only function that returns the colliding instance's ID.

In the Step event, we merely need to call lhc_move(xVel, yVel) to move and run our collision events! Add the following code to the Step event:

/// STEP

// Get keyboard input for left/right movement.
xVel = (keyboard_check(vk_right) - keyboard_check(vk_left)) * 2.2;

// These two lines handle jumping and gravity.
// Don't pay too much attention to them, this isn't the point of the example!
onGround = place_meeting(x, y + 2, obj_solid);
yVel += (onGround * keyboard_check(vk_up) * 7) - 0.5;

// Move using the LHC.
lhc_move(xVel, yVel);

I've added some additional code here to actually give our player the ability to run and jump. You don't need to pay too much attention to it; your input code can be anything you like so long as you feed the x and y velocities into the LHC with lhc_move(xVel, yVel).

- IMPORTANT: You should always call lhc_cleanup() in the Cleanup event of all LHC-enabled objects to prevent memory leaks! -

Due to GameMaker limitations, I am forced to use a ds_list internally. This must be removed on cleanup or it will produce a memory leak.


Open Room1 (you may set your room size to whatever you please, but I chose 256x144 to keep things simple) and drag obj_solid from the asset tree into the room three times, stretching one to cover the floor and the other two to cover the left and right sides of the room. You can add a few extras as test platforms, if you like. Next, drag obj_player into the middle of the room. It should now look something like this:

[IMAGE MISSING]

Hit the Run (F5) button to build the game, and use the arrow keys to make our player object run around. Congrats, you've set up basic collisions! Let's try something a little more funky to spice things up.

The LHC provides a few basic collision behaviors for quick implementation of simple behaviors. Let's use one to try out multiple collisions: lhc_behavior_push_horizontal.

First, let's create a new object. Name it obj_pushblock, and add it to the ISolid Interface assignment in our setup script. We'll also need to create and assign a new Interface for it called IPushableH. Your setup script should now look something like this:

lhc_init();

lhc_create_interface("ISolid");

lhc_create_interface("IPushableH");

lhc_assign_interface("ISolid", obj_solid, obj_pushblock);

lhc_assign_interface("IPushableH", obj_pushblock);

Assign obj_pushblock a 16x16 sprite, add a call to lhc_activate() in its Create event, and place it on the floor in Room1 to the side of obj_player.

Back in obj_player's Create event, add the following block of code above the collision function for ISolid. I'll explain why it needs to be above the ISolid collision event later.

lhc_add("IPushableH", lhc_behavior_push_horizontal);

Build the game again, and walk into the pushblock. Unlike most things I program, it does exactly as we'd expect! ...aside from it being able to be pushed into walls, but that should be fairly easy for you to figure out. Hint: lhc_behavior_push_horizontal runs the LHC movement script on the colliding instance. How would you make it stop on collision?


Now let's try something slightly different to illustrate an important concept of the LHC. In obj_player's Create event, move the line we just added to be after the collision event for ISolid, build the game, and try to push the pushblock again.

Why can't we push the block anymore? Because the LHC has built-in collision event priority. Collision events are evaluated in the order they are defined. When we put the collision with IPushableH first, we check and run its collision (pushing) before we check and run the collision with its parent, ISolid (stopping the player). Since we inverted that, we stop movement before we can check to push the pushblock!

Armed with this knowledge, you should be set for basic use of the LHC and have a good starting point for understanding the rest of the collision functions.

Clone this wiki locally