PVG
3. Creating the Player — Program Video Games

3. Creating the Player

[[programvideogames]]In this lecture we'll create and display a collider for the player.

But first, I'd like to introduce a couple of type aliases.

At the top of the file, after imports:

// Type aliases
Vec2 :: rl.Vector2
Rect :: rl.Rectangle

These aliases allow us to use the easier Vec2 and Rect.

Next, we'll create a Player struct to store data about the player.

Player :: struct {
    // Allows us to use .x, .y, .width and .height directly
    // e.g. player.x += 10, same as player.collider.x += 10
    using collider: Rect,
}

The using keyword allows easy access to the commonly used collider fields.

using has other uses in Odin which we'll take advantage of later.

If you want to read ahead: https://odin-lang.org/docs/overview/#using-statement

Let's instantiate our player instance just before our game loop.

player: Player = {
    x = 100, y = 100,
    width = 16, height = 38
}

for !rl.WindowShouldclose() { // ...

Finally, we'll draw the player after our solid_tiles.

rl.DrawRectangleLinesEx(player.collider, 1, rl.GREEN)

Note that for now our "player" is just a green rectangle.

This is enough to get us started on movement and physics.

After that's all sorted, we can work on sprites and animations.

Full code:

package main

import "core:os"
import rl "vendor:raylib"

// Type aliases
Vec2 :: rl.Vector2
Rect :: rl.Rectangle

Player :: struct {
    // Allows us to use .x, .y, .width and .height directly
    // e.g. player.x += 10, same as player.collider.rect += 10
    using collider: Rect,
}

WINDOW_WIDTH :: 1280
WINDOW_HEIGHT :: 720
TILE_SIZE :: 16
ZOOM :: 2
BG_COLOR :: rl.BLACK

main :: proc() {
    rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Program Video Games!")

    camera := rl.Camera2D {
        zoom = ZOOM,
    }

    // Allocated using the context's allocator
    // unless otherwise specified
    solid_tiles: [dynamic]rl.Rectangle
    {
        level_data, ok := os.read_entire_file("data/simple_level.dat")
        assert(ok, "Failed to load level data")

        x, y: f32
        for v in level_data {
            if v == '
' {
                y += TILE_SIZE
                x = 0
                continue
            }
            if v == '#' {
                append(&solid_tiles, rl.Rectangle{x, y, TILE_SIZE, TILE_SIZE})
            }
            x += TILE_SIZE
        }
    }

    player: Player = {
        x      = 100,
        y      = 100,
        width  = 16,
        height = 38,
    }

    for !rl.WindowShouldClose() {
        rl.BeginDrawing()
        rl.BeginMode2D(camera)
        rl.ClearBackground(BG_COLOR)

        for rect in solid_tiles {
            rl.DrawRectangleRec(rect, rl.WHITE)
            rl.DrawRectangleLinesEx(rect, 1, rl.GRAY)
        }

        rl.DrawRectangleLinesEx(player.collider, 1, rl.GREEN)

        rl.EndMode2D()
        rl.EndDrawing()
    }
}