Metagrid is a simple game engine for 2D Grid Games
Project description
Metagrid
Description
Metagrid is a Python library for creating simple 2D grid games. Each cell in the grid can display:
- a solid color
- an image
- a character
Installation
pip install metagrid
Tutorial
Program structure
Every metagrid program follows the same three-step pattern:
- Declare the game state variables (globals).
- Write the callback functions (
on_init,on_update,on_draw,on_click,on_key). - In the
if __name__ == "__main__"block: create the engine, register the callbacks, then start the loop withgame.start().
1. Create the engine
import metagrid
game = metagrid.create(rows, cols, cell_size, margin)
| Parameter | Role |
|---|---|
rows |
Number of rows in the grid |
cols |
Number of columns in the grid |
cell_size |
Size in pixels of each cell |
margin |
Thickness in pixels of the border between cells |
2. Callbacks
Callbacks are plain functions passed to the engine. Metagrid calls them automatically at the right time.
on_init — initialization
Called once at startup, before the first frame. Reset all game state here.
def init():
print("Game initialized")
game.on_init(init)
on_update — game logic
Called every frame, before drawing. Advance the game state here.
game.frame_no holds the current frame number (starts at 0, increments by 1 per frame). Useful for triggering periodic actions without an external timer.
def update():
if game.frame_no % 120 == 0: # every 2 seconds at 60 fps
print("tick")
game.on_update(update)
on_draw — drawing
Called every frame, after update. Translate the game state into colors / images / characters here.
def draw():
for i in range(5):
for j in range(5):
val = grid[i][j]
if val == 1:
game.set_cell_color(i, j, "#135683")
elif val == 2:
game.set_cell_char(i, j, "X", "#000000")
game.on_draw(draw)
on_click — mouse click
Called when the user clicks on a cell.
def click(i: int, j: int, button: str):
# i, j : coordinates of the clicked cell
# button : "left", "right" or "middle"
print(f"Cell ({i}, {j}) clicked with {button}")
game.on_click(click)
on_key — keyboard
Called when the user presses a key.
def key(k: str):
# k : character ('a', 'z', ' ', …) or special key name
print(f"Key {k} pressed")
game.on_key(key)
3. Drawing in cells
Three functions change the appearance of cell (i, j) (row i, column j, both starting at 0 from the top-left):
Solid color
game.set_cell_color(i, j, "#RRGGBB")
Character
game.set_cell_char(i, j, "A", "#RRGGBB")
One character per cell, centered on top of the background.
Image
Load an image once (before game.start()), then display it:
game.load_image("image_name", "path/to/image.png")
# …
game.set_cell_image(i, j, "image_name")
4. Start the loop
game.start() # blocks until the window is closed
Full example
import metagrid
from metagrid import AbstractEngine
grid: list[list[int]] = [
[0, 1, 0, 0, 0],
[0, 0, 2, 1, 0],
[2, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 0, 1],
]
game: AbstractEngine
def init():
print("Game initialized")
def click(i: int, j: int, button: str):
print(f"Cell ({i}, {j}) clicked with {button}")
def key(k: str):
print(f"Key {k} pressed")
def update():
if game.frame_no % 120 == 0:
print("Update every 2 seconds")
def draw():
for i in range(5):
for j in range(5):
val = grid[i][j]
if val == 1:
game.set_cell_color(i, j, "#135683")
elif val == 2:
game.set_cell_char(i, j, "X", "#000000")
if __name__ == "__main__":
game = metagrid.create(5, 5, 50, 1)
game.on_init(init)
game.on_click(click)
game.on_key(key)
game.on_update(update)
game.on_draw(draw)
game.start()
The full source is available in examples/full_example.py.
Networked turn-based games
Metagrid supports 2-player networked games over WebSocket. Each player runs the same script; the server matches them and relays moves.
For teachers — hosting the server
Teachers can self-host the game server using the open-source repository MMarchand-NSI/game-server. Once deployed, share the server URL and access token with your students so they can fill in their .env file.
Configuration
Create a .env file at the root of your project (fill in the values provided by your teacher):
METAGRID_URL=wss://...
METAGRID_TOKEN=your_token
The credentials are loaded automatically — you never write them in the Python file.
Create the engine
import metagrid
game = metagrid.create_networked(rows, cols, cell_size, margin)
Extra callbacks
on_game_start — both players connected
def start(i_go_first: bool):
# i_go_first is True for the player who created the game
pass
game.on_game_start(start)
on_opponent_move — opponent sent a move
def opponent_move(state):
# state is whatever was passed to game.send_move() by the opponent
pass
game.on_opponent_move(opponent_move)
on_opponent_left — opponent disconnected
def opponent_left():
pass
game.on_opponent_left(opponent_left)
Extra methods
| Method | Description |
|---|---|
game.send_move(state) |
Send the current game state to the opponent (any JSON-serialisable value) |
game.disconnect() |
Close the connection (call when the game is over) |
Program structure
game.start() automatically asks whether to create or join a game before launching the loop.
if __name__ == "__main__":
game = metagrid.create_networked(rows, cols, cell_size, margin)
game.on_init(init)
game.on_draw(draw)
game.on_game_start(start)
game.on_opponent_move(opponent_move)
game.on_opponent_left(opponent_left)
game.on_click(click)
game.start()
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file metagrid-0.6.0.tar.gz.
File metadata
- Download URL: metagrid-0.6.0.tar.gz
- Upload date:
- Size: 142.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
41dd24367c4dea21eb9fea8d06d0489d1f8d2975fb6d9ac42ea42cf5cca0b06b
|
|
| MD5 |
11c1063f3d44ddcaa0270761b2ee780e
|
|
| BLAKE2b-256 |
97517000d289483200d7a9fc52d3c8aa8e2255512419305156c4c8bfac8a39a1
|
Provenance
The following attestation bundles were made for metagrid-0.6.0.tar.gz:
Publisher:
publish.yml on MMarchand-NSI/metagrid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
metagrid-0.6.0.tar.gz -
Subject digest:
41dd24367c4dea21eb9fea8d06d0489d1f8d2975fb6d9ac42ea42cf5cca0b06b - Sigstore transparency entry: 1684520921
- Sigstore integration time:
-
Permalink:
MMarchand-NSI/metagrid@4ffdbc0a014cc0340898e16487ec9c753850bf3e -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/MMarchand-NSI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4ffdbc0a014cc0340898e16487ec9c753850bf3e -
Trigger Event:
push
-
Statement type:
File details
Details for the file metagrid-0.6.0-py3-none-any.whl.
File metadata
- Download URL: metagrid-0.6.0-py3-none-any.whl
- Upload date:
- Size: 139.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34e59d3e926e4693cfc925e0f2ee8570a45a0b4ca7e2777aff9f7acd80661128
|
|
| MD5 |
8bc08b4ec15bca8a84267aa16a196b68
|
|
| BLAKE2b-256 |
c9914a70dbae2828ca55a6d7c07b476d3860cb810cd5be3c97c748bd41384297
|
Provenance
The following attestation bundles were made for metagrid-0.6.0-py3-none-any.whl:
Publisher:
publish.yml on MMarchand-NSI/metagrid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
metagrid-0.6.0-py3-none-any.whl -
Subject digest:
34e59d3e926e4693cfc925e0f2ee8570a45a0b4ca7e2777aff9f7acd80661128 - Sigstore transparency entry: 1684521066
- Sigstore integration time:
-
Permalink:
MMarchand-NSI/metagrid@4ffdbc0a014cc0340898e16487ec9c753850bf3e -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/MMarchand-NSI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@4ffdbc0a014cc0340898e16487ec9c753850bf3e -
Trigger Event:
push
-
Statement type: