Snake (raylib classic)

Grid logic, tap-to-turn touch controls, resize-aware HUD.

▶ Run in browser

Upstream: https://github.com/raysan5/raylib-games/tree/master/classics/src

Licence: this port's own code is offered under Zlib, not the SimVX Examples Licence the rest of the gallery carries. See ATTRIBUTION.md for the upstream it re-implements, the terms of anything it bundles, and the credit each one requires.

Ports live in the repository only, not in the simvx-examples distribution, because each is a derivative work licensed individually against the game it re-implements. Read it with git clone https://git.simvx.com/simvx/simvx.

Tags: port tier-0

Snake (raylib classic): SimVX port

A re-implementation of snake.c from raylib-games/classics by Ian Eito, Albert Martos and Ramon Santamaria. The gameplay follows the C original: a snake that grows on fruit pickup, the allow_move latch that blocks 180-degree reversals, and a step every five physics frames. The board here is 31 by 24 cells.

Everything is drawn procedurally, so the port bundles no upstream art, audio or fonts. See ATTRIBUTION.md and UPSTREAM_LICENSE.md.

What it shows

  • The whole game is one Node2D: grid state, the menu / play / game-over flow and the drawing all live in nodes/snake_game.py.

  • Fixed-timestep logic in on_fixed_update, so the snake steps at the same cadence whatever the frame rate.

  • Immediate-mode 2D drawing: the board, the snake and the HUD come out of one on_draw on a dynamic node, with no scene node per cell.

  • Typed input actions shared by keyboard and touch, so the same logic serves desktop and the web export.

  • Resize-aware layout: the cell size, the board origin and every text scale are recomputed from tree.screen_size each frame, fitted with renderer.fit_scale.

  • died and ate signals, so a scoreboard or an audio node can react without the game node knowing about it.

Run

# from the repo root
uv run python examples/ports/raylib_snake/main.py

Controls

Action

Keyboard

Touch

Steer

Arrow keys or WASD

Tap ahead of the head, in the direction you want

Pause / resume

P

Tap the middle of the score strip above the board

Start / restart

SPACE or ENTER (also any arrow key to start)

Tap anywhere

Quit

ESC

-

Web export

uv run simvx export web examples/ports/raylib_snake/main.py \
    -o /tmp/raylib_snake.html

Source files

File

Summary

Lines

main.py

Snake (raylib classic): Grid logic, tap-to-turn touch controls, resize-aware HUD.

59

__init__.py

0

nodes/__init__.py

0

nodes/snake_game.py

Snake: gameplay node.

363

Source

 1#!/usr/bin/env python3
 2# /// script
 3# requires-python = ">=3.14"
 4# dependencies = ["simvx-core", "simvx-graphics"]
 5# ///
 6"""Snake (raylib classic): Grid logic, tap-to-turn touch controls, resize-aware HUD.
 7
 8# /// simvx
 9# tags = ["port", "tier-0"]
10# upstream = "https://github.com/raysan5/raylib-games/tree/master/classics/src"
11# web = { width = 620, height = 480, responsive = true }
12# ///
13
14A re-implementation of raylib's classic ``snake.c`` as a single SimVX
15``Node2D``. It follows the upstream design (the ``allow_move`` latch that
16blocks 180-degree reversals, a step every five physics frames) on a 31 by 24
17board, and
18around that shows fixed-timestep logic in ``on_fixed_update``, immediate-mode
19board drawing in ``on_draw`` on a ``dynamic`` node, ``InputMap`` actions shared
20by keyboard and touch, text that fits itself to the window with
21``renderer.fit_scale``, and ``died`` / ``ate`` signals other nodes can connect
22to.
23
24Controls: arrow keys or WASD steer, P pauses, SPACE or ENTER starts and
25restarts, ESC quits. By touch, tap to start and restart, tap ahead of the head
26to steer, and tap the middle of the score strip to pause.
27
28Run::
29
30    uv run python examples/ports/raylib_snake/main.py
31
32Web export::
33
34    uv run simvx export web examples/ports/raylib_snake/main.py -o /tmp/raylib_snake.html
35
36Attribution and upstream licence: see ``ATTRIBUTION.md`` and
37``UPSTREAM_LICENSE.md`` beside this file.
38"""
39
40import os
41import sys
42
43_HERE = os.path.abspath(os.path.dirname(__file__))
44if _HERE not in sys.path:
45    sys.path.insert(0, _HERE)
46
47from nodes.snake_game import SnakeGame  # noqa: E402
48
49from simvx.graphics import App  # noqa: E402
50
51WIDTH, HEIGHT = 620, 480
52
53
54def main():
55    App(title="Snake (raylib classic)", width=WIDTH, height=HEIGHT).run(SnakeGame())
56
57
58if __name__ == "__main__":
59    main()