Video Game Design and Coding

Week 13 packet

Student instructions, tasks, and checks. The answer key is not in this packet. Links stay as text. This page does not embed a clip or run a file.

# Week 13 — A first platformer

## VGC-L061 — Understand platform coordinates and acceleration

**Objective:** Distinguish horizontal control, vertical velocity and gravity.

**Time:** 55 minutes

### Instruction
Relay Runner is a short delivery platformer. Horizontal input directly selects a sideways velocity, while gravity accelerates the player downward over time. In 2D positive y is down, so a jump begins with negative y velocity. Acceleration changes velocity; velocity changes position through move_and_slide. Do not add gravity directly to position. Draw the expected vertical-velocity signs for rising, peak and falling. Keeping these ideas separate helps diagnose a jump that moves backward or falls upward.

### Worked example
A ball thrown upward begins with negative y velocity. Gravity adds a positive amount each physics step, slowing the rise and eventually producing downward motion.

### Assignment
1. Sketch a jump arc and label y-velocity signs.
2. Predict what doubling gravity does if jump speed is unchanged.

### Acceptance checks
- Rising is negative y velocity and falling is positive.
- Prediction distinguishes initial jump impulse from continuing acceleration.

**Submit:** Annotated jump diagram and prediction note.

**Question:** What is vertical velocity near the top of a jump?

**Support:** Use C-PLATFORM with one wide floor and no hazards. Verify floor contact before adding platforms. Start with the first assigned task and re-run its acceptance test before adding the remaining feature.

**Optional extension:** Compare two gravity/jump-speed pairs while keeping horizontal speed fixed. Document one changed parameter, your prediction, and the observed effect; optional, not required for completion.

**Optional free reading:** [Your first 2D game](https://docs.godotengine.org/en/stable/getting_started/first_2d_game/index.html)

---

## VGC-L062 — Implement a grounded jump

**Objective:** Use is_on_floor and just-pressed input to restrict jumping.

**Time:** 55 minutes

### Instruction
Build C-PLATFORM with a rectangular player collider and a StaticBody2D floor. _physics_process sets horizontal velocity, adds gravity when airborne, and applies the jump impulse only when jump is just pressed and the prior motion established floor contact. move_and_slide resolves the movement. Begin above the floor rather than overlapping it. Holding Space should not create repeated jumps in midair. A player can still jump again after landing and pressing again; this is a deliberate one-jump rule.

### Worked example
A ball thrown upward begins with negative y velocity. Gravity adds a positive amount each physics step, slowing the rise and eventually producing downward motion.

Scaffold C-PLATFORM — A gravity-and-jump platform player
Setup: CharacterBody2D root Player, child CollisionShape2D RectangleShape2D size (24,32), no scale changes. Layer 1 mask 2. StaticBody2D floor layer 2 mask 1 with rectangular collider. Add Input Map move_left, move_right and jump bound to Space. Place player above floor, not intersecting it. Coordinates use positive y downward. Attach script to Player.
```gdscript
extends CharacterBody2D
@export var speed: float = 160.0
@export var gravity: float = 900.0
@export var jump_speed: float = 340.0
func _draw() -> void:
    draw_rect(Rect2(-12, -16, 24, 32), Color.SKY_BLUE)
    draw_line(Vector2(-8, -4), Vector2(8, -4), Color.BLACK, 2.0)
func _physics_process(delta: float) -> void:
    velocity.x = Input.get_axis("move_left", "move_right") * speed
    if not is_on_floor():
        velocity.y += gravity * delta
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = -jump_speed
    move_and_slide()
```

### Assignment
1. Build the player and one floor using C-PLATFORM.
2. Test tap, hold, airborne press and press after landing.

### Acceptance checks
- Only grounded just-presses start a jump.
- The player lands on top of the floor without sinking.

**Submit:** Platform baseline project and four-input test record.

**Question:** Why check is_on_floor rather than y velocity equal to zero?

**Support:** Use C-PLATFORM with one wide floor and no hazards. Verify floor contact before adding platforms. Start with the first assigned task and re-run its acceptance test before adding the remaining feature.

**Optional extension:** Compare two gravity/jump-speed pairs while keeping horizontal speed fixed. Document one changed parameter, your prediction, and the observed effect; optional, not required for completion.

**Optional free reading:** [Your first 2D game](https://docs.godotengine.org/en/stable/getting_started/first_2d_game/index.html)

---

## VGC-L063 — Tune a reachable gap

**Objective:** Estimate jump range and then verify it experimentally.

**Time:** 55 minutes

### Instruction
A jump’s rough airtime back to the same height is two times jump_speed divided by gravity, ignoring collision details. With 340 and 900, that is about 0.76 seconds. At horizontal speed 160, the rough same-height range is about 121 pixels. This is an estimate, not a promise: collider width, takeoff position and input affect the result. Start with a 70-pixel gap and test several runs. Design required gaps with margin instead of demanding a mathematically perfect edge jump.

### Worked example
A ball thrown upward begins with negative y velocity. Gravity adds a positive amount each physics step, slowing the rise and eventually producing downward motion.

Scaffold C-PLATFORM — A gravity-and-jump platform player
Setup: CharacterBody2D root Player, child CollisionShape2D RectangleShape2D size (24,32), no scale changes. Layer 1 mask 2. StaticBody2D floor layer 2 mask 1 with rectangular collider. Add Input Map move_left, move_right and jump bound to Space. Place player above floor, not intersecting it. Coordinates use positive y downward. Attach script to Player.
```gdscript
extends CharacterBody2D
@export var speed: float = 160.0
@export var gravity: float = 900.0
@export var jump_speed: float = 340.0
func _draw() -> void:
    draw_rect(Rect2(-12, -16, 24, 32), Color.SKY_BLUE)
    draw_line(Vector2(-8, -4), Vector2(8, -4), Color.BLACK, 2.0)
func _physics_process(delta: float) -> void:
    velocity.x = Input.get_axis("move_left", "move_right") * speed
    if not is_on_floor():
        velocity.y += gravity * delta
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = -jump_speed
    move_and_slide()
```

### Assignment
1. Calculate the approximate airtime and horizontal range.
2. Build and test 70-, 90- and 110-pixel same-height gaps in a practice scene.

### Acceptance checks
- The written units are seconds and pixels.
- Required course route uses a gap the learner can clear reliably.

**Submit:** Gap test scene and calculation/observation table.

**Question:** Why leave a margin below the estimated maximum range?

**Support:** Use C-PLATFORM with one wide floor and no hazards. Verify floor contact before adding platforms. Start with the first assigned task and re-run its acceptance test before adding the remaining feature.

**Optional extension:** Compare two gravity/jump-speed pairs while keeping horizontal speed fixed. Document one changed parameter, your prediction, and the observed effect; optional, not required for completion.

**Optional free reading:** [Your first 2D game](https://docs.godotengine.org/en/stable/getting_started/first_2d_game/index.html)

---

## VGC-L064 — Build a readable three-jump route

**Objective:** Teach one skill at a time through level layout.

**Time:** 55 minutes

### Instruction
A good introductory level demonstrates, lets the player practice and then combines the skill. Build a wide safe first jump, a moderate second gap and a final raised platform. Show the destination before the player commits. Avoid a blind drop or a hazard immediately after an unseen landing. Use consistent visual shapes for solid platforms. You do not need a tilemap yet; a few StaticBody2D rectangles make collision behavior easier to inspect and understand.

### Worked example
A ball thrown upward begins with negative y velocity. Gravity adds a positive amount each physics step, slowing the rise and eventually producing downward motion.

Scaffold C-PLATFORM — A gravity-and-jump platform player
Setup: CharacterBody2D root Player, child CollisionShape2D RectangleShape2D size (24,32), no scale changes. Layer 1 mask 2. StaticBody2D floor layer 2 mask 1 with rectangular collider. Add Input Map move_left, move_right and jump bound to Space. Place player above floor, not intersecting it. Coordinates use positive y downward. Attach script to Player.
```gdscript
extends CharacterBody2D
@export var speed: float = 160.0
@export var gravity: float = 900.0
@export var jump_speed: float = 340.0
func _draw() -> void:
    draw_rect(Rect2(-12, -16, 24, 32), Color.SKY_BLUE)
    draw_line(Vector2(-8, -4), Vector2(8, -4), Color.BLACK, 2.0)
func _physics_process(delta: float) -> void:
    velocity.x = Input.get_axis("move_left", "move_right") * speed
    if not is_on_floor():
        velocity.y += gravity * delta
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = -jump_speed
    move_and_slide()
```

### Assignment
1. Sketch and build a three-jump route with safe start and visible goal.
2. Complete it three times and record where failures occur.

### Acceptance checks
- Every required landing is visible before takeoff.
- The route is completable without pixel-perfect input.

**Submit:** Route sketch, runnable level and three-run notes.

**Question:** Why not introduce a moving hazard on the first required jump?

**Support:** Use C-PLATFORM with one wide floor and no hazards. Verify floor contact before adding platforms. Start with the first assigned task and re-run its acceptance test before adding the remaining feature.

**Optional extension:** Compare two gravity/jump-speed pairs while keeping horizontal speed fixed. Document one changed parameter, your prediction, and the observed effect; optional, not required for completion.

**Optional free reading:** [Your first 2D game](https://docs.godotengine.org/en/stable/getting_started/first_2d_game/index.html)

---

## VGC-L065 — Reset safely after a fall

**Objective:** Implement a fall-zone trigger and a deliberate spawn point.

**Time:** 55 minutes

### Instruction
A fall should return the player to a valid point rather than leave them outside the level. Place an Area2D fall zone below the platforms, with a wide rectangle collider and mask for Player. Its body_entered handler checks the player group and calls the level’s respawn method. C-CHECKPOINT defers the actual move and clears velocity. Put the spawn above a safe floor with enough collider clearance. Do not put it inside the fall zone or another hazard, which creates a reset loop.

### Worked example
A ball thrown upward begins with negative y velocity. Gravity adds a positive amount each physics step, slowing the rise and eventually producing downward motion.

Scaffold C-CHECKPOINT — A safe checkpoint respawn
Setup: Add this pattern to a separate Node2D level root with child Player using C-PLATFORM. Call set_checkpoint with a safe global position when a player reaches a checkpoint Area2D; call respawn when entering a fall zone. This code does not connect Area2D automatically; select the area body_entered signal in editor and call these methods from its handler after checking the player group. Respawn is deferred because a physics callback may be active.
```gdscript
extends Node2D
@onready var player: CharacterBody2D = $Player
var checkpoint: Vector2
func _ready() -> void:
    checkpoint = player.global_position
func set_checkpoint(safe_position: Vector2) -> void:
    checkpoint = safe_position
func respawn() -> void:
    _apply_respawn.call_deferred()
func _apply_respawn() -> void:
    player.global_position = checkpoint
    player.velocity = Vector2.ZERO
```

Scaffold C-PLATFORM — A gravity-and-jump platform player
Setup: CharacterBody2D root Player, child CollisionShape2D RectangleShape2D size (24,32), no scale changes. Layer 1 mask 2. StaticBody2D floor layer 2 mask 1 with rectangular collider. Add Input Map move_left, move_right and jump bound to Space. Place player above floor, not intersecting it. Coordinates use positive y downward. Attach script to Player.
```gdscript
extends CharacterBody2D
@export var speed: float = 160.0
@export var gravity: float = 900.0
@export var jump_speed: float = 340.0
func _draw() -> void:
    draw_rect(Rect2(-12, -16, 24, 32), Color.SKY_BLUE)
    draw_line(Vector2(-8, -4), Vector2(8, -4), Color.BLACK, 2.0)
func _physics_process(delta: float) -> void:
    velocity.x = Input.get_axis("move_left", "move_right") * speed
    if not is_on_floor():
        velocity.y += gravity * delta
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = -jump_speed
    move_and_slide()
```

### Assignment
1. Add the fall zone and C-CHECKPOINT respawn pattern.
2. Fall while moving sideways and test the restored velocity and position.

### Acceptance checks
- Player returns to a safe floor.
- Falling momentum does not immediately cause another failure.

**Submit:** Respawn-capable level and fall test note.

**Question:** Why clear velocity during respawn?

**Support:** Use C-PLATFORM with one wide floor and no hazards. Verify floor contact before adding platforms. Start with the first assigned task and re-run its acceptance test before adding the remaining feature.

**Optional extension:** Compare two gravity/jump-speed pairs while keeping horizontal speed fixed. Document one changed parameter, your prediction, and the observed effect; optional, not required for completion.

**Optional free reading:** [Your first 2D game](https://docs.godotengine.org/en/stable/getting_started/first_2d_game/index.html)

---