pix8 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pix8-0.0.1/PKG-INFO +5 -0
- pix8-0.0.1/README.md +77 -0
- pix8-0.0.1/pix8/__main__.py +164 -0
- pix8-0.0.1/pix8.egg-info/PKG-INFO +5 -0
- pix8-0.0.1/pix8.egg-info/SOURCES.txt +9 -0
- pix8-0.0.1/pix8.egg-info/dependency_links.txt +1 -0
- pix8-0.0.1/pix8.egg-info/entry_points.txt +2 -0
- pix8-0.0.1/pix8.egg-info/requires.txt +1 -0
- pix8-0.0.1/pix8.egg-info/top_level.txt +1 -0
- pix8-0.0.1/pyproject.toml +8 -0
- pix8-0.0.1/setup.cfg +4 -0
pix8-0.0.1/PKG-INFO
ADDED
pix8-0.0.1/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# **๐ฆ PIX-8 โ Tiny Fantasy Console**
|
|
2
|
+
|
|
3
|
+
PIX-8 is a minimal, retro-style fantasy console written in Python.
|
|
4
|
+
It lets you create **tiny games** with a simple PEP-8-inspired Python cartridge format.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## **โก Features**
|
|
9
|
+
|
|
10
|
+
* 128ร128 pixel display
|
|
11
|
+
|
|
12
|
+
* 16-color palette
|
|
13
|
+
|
|
14
|
+
* Simple drawing API: `cls()`, `pset()`, `rectfill()`
|
|
15
|
+
|
|
16
|
+
* Input: arrow keys \+ `Z/X` as buttons
|
|
17
|
+
|
|
18
|
+
* PEP-8โstyle cartridges (`init(pix)`, `update(pix)`, `draw(pix)`)
|
|
19
|
+
|
|
20
|
+
* Runs as a single Python file (`pix8.py`)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## **๐ Installation**
|
|
25
|
+
|
|
26
|
+
`git clone <repo-url>`
|
|
27
|
+
`cd pix8`
|
|
28
|
+
`pip install .`
|
|
29
|
+
|
|
30
|
+
Or if you just want to run it locally without pip:
|
|
31
|
+
|
|
32
|
+
`python pix8.py game.py`
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## **๐ฎ Writing a Cartridge**
|
|
37
|
+
|
|
38
|
+
Create a Python file, for example `game.py`:
|
|
39
|
+
|
|
40
|
+
`metadata = {"title": "Tiny Demo"}`
|
|
41
|
+
|
|
42
|
+
`def init(pix):`
|
|
43
|
+
`pix.x = 60`
|
|
44
|
+
`pix.y = 60`
|
|
45
|
+
|
|
46
|
+
`def update(pix):`
|
|
47
|
+
`if pix.btn("left"):`
|
|
48
|
+
`pix.x -= 1`
|
|
49
|
+
`if pix.btn("right"):`
|
|
50
|
+
`pix.x += 1`
|
|
51
|
+
|
|
52
|
+
`def draw(pix):`
|
|
53
|
+
`pix.cls(1)`
|
|
54
|
+
`pix.rectfill(pix.x, pix.y, 8, 8, 8)`
|
|
55
|
+
|
|
56
|
+
Run it:
|
|
57
|
+
|
|
58
|
+
`pix8 game.py`
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## **๐ API Reference**
|
|
63
|
+
|
|
64
|
+
| Function | Description |
|
|
65
|
+
| ----- | ----- |
|
|
66
|
+
| `pix.cls(color=0)` | Clear the screen |
|
|
67
|
+
| `pix.pset(x, y, color=7)` | Draw a single pixel |
|
|
68
|
+
| `pix.rectfill(x, y, w, h, color=7)` | Draw a filled rectangle |
|
|
69
|
+
| `pix.btn("left")` | Check if a button is pressed (`left`, `right`, `up`, `down`, `a`, `b`) |
|
|
70
|
+
| `pix.flip()` | Update the screen and tick FPS |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## **๐ License**
|
|
75
|
+
|
|
76
|
+
MIT License โ free to use, modify, and share.
|
|
77
|
+
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PIX-8 Fantasy Console
|
|
3
|
+
One-file edition
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
import pygame
|
|
8
|
+
import importlib.util
|
|
9
|
+
|
|
10
|
+
# ======================
|
|
11
|
+
# HARDWARE SPEC
|
|
12
|
+
# ======================
|
|
13
|
+
|
|
14
|
+
WIDTH = 128
|
|
15
|
+
HEIGHT = 128
|
|
16
|
+
SCALE = 4
|
|
17
|
+
FPS = 30
|
|
18
|
+
|
|
19
|
+
PALETTE = [
|
|
20
|
+
(0, 0, 0), # 0 black
|
|
21
|
+
(29, 43, 83), # 1 dark blue
|
|
22
|
+
(126, 37, 83), # 2 dark purple
|
|
23
|
+
(0, 135, 81), # 3 dark green
|
|
24
|
+
(171, 82, 54), # 4 brown
|
|
25
|
+
(95, 87, 79), # 5 dark gray
|
|
26
|
+
(194, 195, 199), # 6 light gray
|
|
27
|
+
(255, 241, 232), # 7 white
|
|
28
|
+
(255, 0, 77), # 8 red
|
|
29
|
+
(255, 163, 0), # 9 orange
|
|
30
|
+
(255, 236, 39), # 10 yellow
|
|
31
|
+
(0, 228, 54), # 11 green
|
|
32
|
+
(41, 173, 255), # 12 blue
|
|
33
|
+
(131, 118, 156), # 13 indigo
|
|
34
|
+
(255, 119, 168), # 14 pink
|
|
35
|
+
(255, 204, 170), # 15 peach
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
KEYMAP = {
|
|
39
|
+
"left": pygame.K_LEFT,
|
|
40
|
+
"right": pygame.K_RIGHT,
|
|
41
|
+
"up": pygame.K_UP,
|
|
42
|
+
"down": pygame.K_DOWN,
|
|
43
|
+
"a": pygame.K_z,
|
|
44
|
+
"b": pygame.K_x,
|
|
45
|
+
"start": pygame.K_RETURN,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# ======================
|
|
49
|
+
# PIX-8 CONSOLE
|
|
50
|
+
# ======================
|
|
51
|
+
|
|
52
|
+
class Pix8:
|
|
53
|
+
"""
|
|
54
|
+
Fantasy console object passed to cartridges.
|
|
55
|
+
Cartridges may attach arbitrary state to this object.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def __init__(self):
|
|
59
|
+
pygame.init()
|
|
60
|
+
self.window = pygame.display.set_mode(
|
|
61
|
+
(WIDTH * SCALE, HEIGHT * SCALE)
|
|
62
|
+
)
|
|
63
|
+
pygame.display.set_caption("PIX-8")
|
|
64
|
+
|
|
65
|
+
self.surface = pygame.Surface((WIDTH, HEIGHT))
|
|
66
|
+
self.clock = pygame.time.Clock()
|
|
67
|
+
self.keys = None
|
|
68
|
+
|
|
69
|
+
# ---- VIDEO API ----
|
|
70
|
+
|
|
71
|
+
def cls(self, color=0):
|
|
72
|
+
self.surface.fill(PALETTE[color % 16])
|
|
73
|
+
|
|
74
|
+
def pset(self, x, y, color=7):
|
|
75
|
+
if 0 <= x < WIDTH and 0 <= y < HEIGHT:
|
|
76
|
+
self.surface.set_at((int(x), int(y)), PALETTE[color % 16])
|
|
77
|
+
|
|
78
|
+
def rect(self, x, y, w, h, color=7):
|
|
79
|
+
pygame.draw.rect(
|
|
80
|
+
self.surface,
|
|
81
|
+
PALETTE[color % 16],
|
|
82
|
+
(x, y, w, h),
|
|
83
|
+
1,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
def rectfill(self, x, y, w, h, color=7):
|
|
87
|
+
pygame.draw.rect(
|
|
88
|
+
self.surface,
|
|
89
|
+
PALETTE[color % 16],
|
|
90
|
+
(x, y, w, h),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# ---- INPUT API ----
|
|
94
|
+
|
|
95
|
+
def btn(self, name):
|
|
96
|
+
if self.keys is None:
|
|
97
|
+
return False
|
|
98
|
+
key = KEYMAP.get(name)
|
|
99
|
+
return bool(self.keys[key]) if key else False
|
|
100
|
+
|
|
101
|
+
# ---- FRAME END ----
|
|
102
|
+
|
|
103
|
+
def flip(self):
|
|
104
|
+
scaled = pygame.transform.scale(
|
|
105
|
+
self.surface,
|
|
106
|
+
self.window.get_size(),
|
|
107
|
+
)
|
|
108
|
+
self.window.blit(scaled, (0, 0))
|
|
109
|
+
pygame.display.flip()
|
|
110
|
+
self.clock.tick(FPS)
|
|
111
|
+
|
|
112
|
+
# ======================
|
|
113
|
+
# CARTRIDGE LOADER
|
|
114
|
+
# ======================
|
|
115
|
+
|
|
116
|
+
def load_cartridge(path):
|
|
117
|
+
spec = importlib.util.spec_from_file_location("cartridge", path)
|
|
118
|
+
module = importlib.util.module_from_spec(spec)
|
|
119
|
+
spec.loader.exec_module(module)
|
|
120
|
+
return module
|
|
121
|
+
|
|
122
|
+
# ======================
|
|
123
|
+
# RUNTIME
|
|
124
|
+
# ======================
|
|
125
|
+
|
|
126
|
+
def run(cart_path):
|
|
127
|
+
pix = Pix8()
|
|
128
|
+
cart = load_cartridge(cart_path)
|
|
129
|
+
|
|
130
|
+
if hasattr(cart, "metadata"):
|
|
131
|
+
title = cart.metadata.get("title", "PIX-8")
|
|
132
|
+
pygame.display.set_caption(title)
|
|
133
|
+
|
|
134
|
+
if hasattr(cart, "init"):
|
|
135
|
+
cart.init(pix)
|
|
136
|
+
|
|
137
|
+
running = True
|
|
138
|
+
while running:
|
|
139
|
+
pix.keys = pygame.key.get_pressed()
|
|
140
|
+
|
|
141
|
+
for event in pygame.event.get():
|
|
142
|
+
if event.type == pygame.QUIT:
|
|
143
|
+
running = False
|
|
144
|
+
|
|
145
|
+
if hasattr(cart, "update"):
|
|
146
|
+
cart.update(pix)
|
|
147
|
+
|
|
148
|
+
if hasattr(cart, "draw"):
|
|
149
|
+
cart.draw(pix)
|
|
150
|
+
|
|
151
|
+
pix.flip()
|
|
152
|
+
|
|
153
|
+
pygame.quit()
|
|
154
|
+
|
|
155
|
+
# ======================
|
|
156
|
+
# CLI ENTRY
|
|
157
|
+
# ======================
|
|
158
|
+
|
|
159
|
+
if __name__ == "__main__":
|
|
160
|
+
if len(sys.argv) < 2:
|
|
161
|
+
print("Usage: python pix8.py cartridge.py")
|
|
162
|
+
sys.exit(1)
|
|
163
|
+
|
|
164
|
+
run(sys.argv[1])
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pygame
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pix8
|
pix8-0.0.1/setup.cfg
ADDED