Hextris

Hex puzzle, engine test for touch input (GPLv3 upstream).

▶ Run in browser

Upstream: https://github.com/Hextris/hextris

Tags: port tier-0

Hextris: SimVX port

Engine test only. Upstream is GPLv3, do not promote this to a SimVX example.

Run (desktop)

uv run python ported_games/hextris/simvx_port/main.py

Controls

  • Left arrow / A rotate hex left

  • Right arrow / D rotate hex right

  • Down / S speed up falling blocks

  • Enter / R restart (when game over)

  • Tap left half rotate left (mouse + touch)

  • Tap right half rotate right (mouse + touch)

Web export (touch test)

uv run simvx export web ported_games/hextris/simvx_port/main.py \
    -o ported_games/hextris/simvx_port/web/index.html

Open web/index.html in Chrome 113+ or Edge 113+.

See ../NOTES.md for the touch-input validation findings; that is the headline of this port.

Upstream

../source/ is a shallow clone of https://github.com/Hextris/hextris (GPLv3). JavaScript was used as a design reference; all Python here was written from scratch.

Source

 1#!/usr/bin/env python3
 2"""Hextris: Hex puzzle, engine test for touch input (GPLv3 upstream).
 3
 4# /// simvx
 5# tags = ["port", "tier-0"]
 6# upstream = "https://github.com/Hextris/hextris"
 7# web = { width = 800, height = 800, responsive = true }
 8# ///
 9
10Upstream: https://github.com/Hextris/hextris (GPLv3).
11Port goal: smoke-test SimVX touch input + mobile web export.
12
13Run desktop:
14    uv run python ported_games/hextris/simvx_port/main.py
15
16Web export:
17    uv run simvx export web ported_games/hextris/simvx_port/main.py         -o ported_games/hextris/simvx_port/web/index.html
18"""
19
20import math
21import random
22import sys
23from pathlib import Path
24
25# Allow `uv run python main.py` from this folder by adding the parent on path.
26sys.path.insert(0, str(Path(__file__).parent))
27
28from simvx.core import Input, InputMap, Key, Node, Node2D, Property, Vec2  # noqa: E402
29from simvx.graphics import App  # noqa: E402
30
31from nodes.game import HextrisGame  # noqa: E402
32
33WIDTH, HEIGHT = 800, 800
34
35
36class HextrisRoot(Node):
37    """Root node: registers actions and hosts the game scene."""
38
39    def on_ready(self):
40        # Per CLAUDE.md: InputMap.add_action MUST live in root on_ready
41        # (web exporter skips main(), and module-time actions are silently lost).
42        InputMap.add_action("rotate_left", [Key.LEFT, Key.A])
43        InputMap.add_action("rotate_right", [Key.RIGHT, Key.D])
44        InputMap.add_action("speed_up", [Key.DOWN, Key.S])
45        InputMap.add_action("restart", [Key.ENTER, Key.R])
46        InputMap.add_action("pause", [Key.P, Key.SPACE])
47        self.add_child(HextrisGame(name="HextrisGame"))
48
49
50if __name__ == "__main__":
51    App(width=WIDTH, height=HEIGHT, title="Hextris (SimVX port)").run(HextrisRoot())