Skip to content

Getting Started

magmacrunchmedia edited this page Aug 24, 2026 · 3 revisions

Getting Started

We will build a small game: a player that walks around a walled room, with a camera that follows and a HUD. Every snippet here runs as written.

Install

pip install texastoast

texastoast needs only the standard library plus tkinter. If import tkinter fails, install your platform's tk package (sudo apt install python3-tk on Debian/Ubuntu; it ships with the python.org installers on macOS and Windows).

1. A window

from texastoast import Game

game = Game(title="My Game", width=400, height=300, fps=30)
game.start()

That is a working game: an empty window that closes cleanly. start() blocks until the window is closed.

2. Something on screen

CanvasRenderer draws onto the game's canvas. Give it an update and a render:

from texastoast import Game, CanvasRenderer

game = Game(title="My Game", width=400, height=300, fps=30)
renderer = CanvasRenderer(game.canvas, 400, 300)

def update(dt):
    pass

def render():
    renderer.clear()
    renderer.draw_rect(50, 50, 20, 20, "#e94560")

game.set_update(update)
game.set_render(render)
game.start()

clear() every frame, then draw. The canvas keeps whatever you put on it otherwise.

3. A map

A TileMap is a grid of integers plus a tile size. Which ids block movement is up to you:

from texastoast import TileMap

GRID = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 1, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
]
tilemap = TileMap(GRID, tile_size=32, solid_tiles={1})

TILE_COLORS = {0: "#7cb342", 1: "#5d4037"}   # grass, wall

Draw it with draw_tilemap. A tile is drawn when its id appears in the color map; ids you leave out stay transparent:

def render():
    renderer.clear()
    renderer.draw_tilemap(tilemap, TILE_COLORS)

4. A player that moves

Entity holds a position, a size and a speed in pixels per second. move() takes the frame's dt and, optionally, a tile map to collide against:

from texastoast import Entity, KeyboardInput

keyboard = KeyboardInput(game.root)
player = Entity(x=48, y=48, width=20, height=20, speed=120)

def update(dt):
    state = keyboard.poll()
    player.move(state.dx, state.dy, dt, tilemap)

Spawn the player somewhere walkable. x=48, y=48 with tile_size=32 puts it in tile (1, 1), which is 0 in the grid above. Dropping an entity inside a solid tile leaves it stuck — nothing can push it out.

Collision handles the rest: the player slides along walls instead of catching on them, stops flush against them, and cannot tunnel through one at high speed.

5. A camera

For a map larger than the window, follow the player:

def update(dt):
    state = keyboard.poll()
    player.move(state.dx, state.dy, dt, tilemap)
    renderer.camera.follow(
        player.center_x, player.center_y,
        map_width=tilemap.width, map_height=tilemap.height, dt=dt,
    )

map_width/map_height clamp the camera so it never shows past the map edge. Every draw_* call except draw_hud_text is camera-relative.

6. A HUD

HUD elements are screen-space and ignore the camera:

from texastoast.ui import HUD

hud = HUD(renderer)
hud.add_stat("hp", "HP", value=100, max_value=100, color="#e94560")
hud.add_text("score", "Score: 0", 300, 8, fill="#fdd835")

def render():
    renderer.clear()
    renderer.draw_tilemap(tilemap, TILE_COLORS)
    renderer.draw_rect(player.x, player.y, player.width, player.height, "#e94560")
    hud.render()   # last, so it draws on top

Update values with hud.set_stat("hp", 75) and hud.set_text("score", "Score: 10").

The whole thing

from texastoast import Game, CanvasRenderer, TileMap, Entity, KeyboardInput
from texastoast.ui import HUD

GRID = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 1, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
]
TILE_COLORS = {0: "#7cb342", 1: "#5d4037"}

game = Game(title="My Game", width=400, height=300, fps=30)
renderer = CanvasRenderer(game.canvas, 400, 300)
keyboard = KeyboardInput(game.root)
hud = HUD(renderer)
game.on_close(keyboard.destroy)

tilemap = TileMap(GRID, tile_size=32, solid_tiles={1})
player = Entity(x=48, y=48, width=20, height=20, speed=120)
hud.add_stat("hp", "HP", value=100, max_value=100, color="#e94560")

def update(dt):
    state = keyboard.poll()
    player.move(state.dx, state.dy, dt, tilemap)
    renderer.camera.follow(
        player.center_x, player.center_y,
        map_width=tilemap.width, map_height=tilemap.height, dt=dt,
    )

def render():
    renderer.clear()
    renderer.draw_tilemap(tilemap, TILE_COLORS)
    renderer.draw_rect(player.x, player.y, player.width, player.height, "#e94560")
    hud.render()

game.set_update(update)
game.set_render(render)
game.start()

Arrow keys or WASD to move.

Adding dialogue or a menu

The same shape extends to the other widgets, with one rule: they are frame-driven. Construct them from the renderer, advance the dialogue from update, and draw all of them from render:

from texastoast.ui import DialogueBox

dialogue = DialogueBox(renderer)
dialogue.show("Welcome, traveler!", speaker="Old Wizard")

def update(dt):
    dialogue.update(dt)      # advances the typewriter
    ...

def render():
    renderer.clear()
    ...
    hud.render()
    dialogue.render()        # after clear(), every frame

Miss the render() call and the box never appears; miss update(dt) and the text never types. See UI Components.

Next

  • Core Concepts — why dt matters and how the loop behaves
  • Scenes and Game Structure — pause menus and dialogue without flag soup; the step to take as soon as your game has more than one screen
  • Tile Maps and Collision — map files, collision rules
  • UI Components — dialogue boxes, menus, theming
  • Audio — sound that degrades gracefully
  • Hardware Dev Kit — controllers, without owning any
  • examples/game_template.py in the repo — the reference wiring: world, pause and dialogue as scenes, an entity group, stats

Clone this wiki locally