Top-Down Racing Game

Main Skills: Acceleration, steering, friction, checkpoints, collision detection, variables, and basic racing game logic.

In this lesson, you will create a top-down racing game in GameMaker. Instead of the car immediately moving at full speed, it will gradually accelerate, slow down using friction, and steer around a race track.

Lesson Objectives

By the end of this lesson, you should be able to:

Game Requirements

Requirement Description
Player Car A car controlled by the keyboard.
Acceleration The car gradually speeds up.
Braking The car can slow down and reverse.
Steering The car turns left and right.
Friction The car gradually slows when the accelerator is released.
Maximum Speed The car cannot accelerate forever.
Race Track A visible area for the player to drive.
Checkpoints At least four checkpoints.
Checkpoint Order Checkpoints must be reached in the correct order.
Lap Counter The game keeps track of completed laps.

Part 1 - Create the Project

Create a new GameMaker project named:

PX_lastname_Top-DownRacing
  • Verify your 2 files you will need to create at the end and where to drop them:
  • file one: PX_lastname_Top-DownRacing.png (Screen print of the program inside the game maker ide)
  • file two: PX_lastname_Top-DownRacing.mp4 (Video of you playing the game. I need at least 7 seconds)
  • Be sure to drop off the two file into your google drive for class under 2026_27KleinCollins\your class name
  • Drop your two files into google classroom.
  • Create the following assets:

    spr_car
    obj_car
    
    spr_checkpoint
    obj_checkpoint
    
    spr_wall
    obj_wall
    
    rm_race

    Part 2 - Create the Car

    Create a sprite named:

    spr_car

    The car should be viewed from above. A simple rectangle is fine.

    Set the sprite origin to:

    Middle Center

    Create an object named:

    obj_car

    Assign spr_car to the object.

    Part 3 - Create the Car Variables

    Add a Create Event to obj_car.

    car_speed = 0;
    
    acceleration = 0.15;
    brake_power = 0.20;
    
    max_speed = 6;
    max_reverse = -2;
    
    friction = 0.05;
    
    turn_speed = 3;
    
    next_checkpoint = 0;
    lap = 0;

    What Do These Variables Mean?

    Variable Purpose
    car_speed Current speed of the car.
    acceleration How quickly the car speeds up.
    brake_power How quickly the car slows down.
    max_speed Maximum forward speed.
    max_reverse Maximum reverse speed.
    friction Natural slowing of the car.
    turn_speed How quickly the car turns.
    next_checkpoint The checkpoint the player must reach next.
    lap The number of completed laps.

    Part 4 - Add Acceleration

    Add a Step Event to obj_car.

    if (keyboard_check(vk_up))
    {
        car_speed += acceleration;
    }

    Holding the Up Arrow gradually increases the car's speed.

    Important: The car does not instantly jump to maximum speed. This is acceleration.

    Part 5 - Add Braking and Reverse

    if (keyboard_check(vk_down))
    {
        car_speed -= brake_power;
    }

    The Down Arrow slows the car. If the player continues holding Down, the car can move backward.

    Part 6 - Limit the Speed

    car_speed = clamp(car_speed, max_reverse, max_speed);

    The clamp() function keeps a value between a minimum and maximum.

    Minimum = -2
    Maximum = 6

    Part 7 - Add Friction

    if (!keyboard_check(vk_up) && !keyboard_check(vk_down))
    {
        if (car_speed > 0)
        {
            car_speed -= friction;
            car_speed = max(car_speed, 0);
        }
    
        if (car_speed < 0)
        {
            car_speed += friction;
            car_speed = min(car_speed, 0);
        }
    }

    Release the accelerator. The car should gradually slow down instead of stopping instantly.

    Part 8 - Add Steering

    if (abs(car_speed) > 0.1)
    {
        if (keyboard_check(vk_left))
        {
            image_angle += turn_speed;
        }
    
        if (keyboard_check(vk_right))
        {
            image_angle -= turn_speed;
        }
    }

    The car can turn only when it is moving. This makes the controls feel more like a real vehicle.

    Part 9 - Move the Car

    x += lengthdir_x(car_speed, image_angle);
    y += lengthdir_y(car_speed, image_angle);

    These functions use the direction of the car to calculate horizontal and vertical movement.

    Complete Step Event

    // ACCELERATE
    
    if (keyboard_check(vk_up))
    {
        car_speed += acceleration;
    }
    
    
    // BRAKE / REVERSE
    
    if (keyboard_check(vk_down))
    {
        car_speed -= brake_power;
    }
    
    
    // LIMIT SPEED
    
    car_speed = clamp(car_speed, max_reverse, max_speed);
    
    
    // FRICTION
    
    if (!keyboard_check(vk_up) && !keyboard_check(vk_down))
    {
        if (car_speed > 0)
        {
            car_speed -= friction;
            car_speed = max(car_speed, 0);
        }
    
        if (car_speed < 0)
        {
            car_speed += friction;
            car_speed = min(car_speed, 0);
        }
    }
    
    
    // STEERING
    
    if (abs(car_speed) > 0.1)
    {
        if (keyboard_check(vk_left))
        {
            image_angle += turn_speed;
        }
    
        if (keyboard_check(vk_right))
        {
            image_angle -= turn_speed;
        }
    }
    
    
    // MOVE
    
    x += lengthdir_x(car_speed, image_angle);
    y += lengthdir_y(car_speed, image_angle);

    Part 10 - Test the Car

    Place obj_car inside:

    rm_race

    Run the game and test the controls.

    Up Arrow = Accelerate
    Down Arrow = Brake / Reverse
    Left Arrow = Turn Left
    Right Arrow = Turn Right
    SHOW YOUR TEACHER

    Demonstrate that your car:

    Part 11 - Create the Race Track

    Create your race track inside rm_race.

    You can use:

    The track should form a complete circuit.

            +-----------------------+
            |                       |
            |     +-----------+     |
            |     |           |     |
            |     |           |     |
            |     +-----------+     |
            |                       |
            +-----------------------+

    Part 12 - Create Checkpoints

    Create:

    spr_checkpoint

    A checkpoint can be a rectangle placed across the road.

    Create:

    obj_checkpoint

    Add a Create Event:

    checkpoint_number = 0;

    Each checkpoint should have a different number.

    Checkpoint 0
    Checkpoint 1
    Checkpoint 2
    Checkpoint 3

    Part 13 - Number the Checkpoints

    Starting Line = 0
    
    Checkpoint 1 = 1
    
    Checkpoint 2 = 2
    
    Checkpoint 3 = 3

    The player should drive through them in this order:

    0 -> 1 -> 2 -> 3 -> 0
    This prevents the player from repeatedly crossing the finish line without driving around the track.

    Part 14 - Detect Checkpoints

    In obj_car, add a Collision Event with obj_checkpoint.

    if (other.checkpoint_number == next_checkpoint)
    {
        next_checkpoint += 1;
    }

    The car only accepts the correct checkpoint.

    Part 15 - Complete a Lap

    If you have four checkpoints numbered 0 through 3, use:

    if (other.checkpoint_number == next_checkpoint)
    {
        next_checkpoint += 1;
    
        if (next_checkpoint >= 4)
        {
            next_checkpoint = 0;
            lap += 1;
        }
    }

    When the player reaches all four checkpoints, the lap counter increases.

    Part 16 - Display Race Information

    Add a Draw GUI Event to obj_car.

    draw_text(20, 20, "Lap: " + string(lap));
    draw_text(20, 50, "Next Checkpoint: " + string(next_checkpoint));
    draw_text(20, 80, "Speed: " + string(round(car_speed)));

    Your game should display information similar to:

    Lap: 2
    Next Checkpoint: 3
    Speed: 5

    Challenge 1 - Better Steering

    Make steering depend on the speed of the car.

    var steering_amount = turn_speed * abs(car_speed / max_speed);
    if (keyboard_check(vk_left))
    {
        image_angle += steering_amount;
    }
    
    if (keyboard_check(vk_right))
    {
        image_angle -= steering_amount;
    }

    Challenge 2 - Wall Collisions

    Create:

    obj_wall

    Place walls around the edge of your race track.

    When the car hits a wall:

    car_speed *= -0.3;

    This reduces the speed and creates a small bounce.

    Challenge 3 - Off-Road Penalty

    Create grass or another off-road area.

    When the player leaves the road, reduce the car's speed.

    car_speed *= 0.95;

    Challenge 4 - Add a Timer

    Create a timer variable:

    race_time = 0;

    Increase the timer every Step:

    race_time += 1 / room_speed;

    Display the timer:

    draw_text(20, 110,
        "Time: " + string_format(race_time, 0, 2));

    Challenge 5 - Three-Lap Race

    total_laps = 3;

    Check:

    if (lap >= total_laps)

    Display:

    RACE COMPLETE!

    Final Game Checklist

    Student Reflection

    1. What variable controls how quickly the car accelerates?
    2. What is the purpose of friction?
    3. Why do we use clamp()?
    4. Why should checkpoints have numbers?
    5. What would happen if the player could cross checkpoints in any order?
    6. What change did you make that improved your game the most?

    Extension Goal

    After completing the basic game, try adding one or more advanced features:

    FINAL SHOW YOUR TEACHER CHECKPOINT

    Run your completed game and demonstrate one complete lap. Your teacher should be able to see acceleration, steering, checkpoint detection, and the lap counter working.