Skip to content

Commit b4a7cf8

Browse files
committed
Add Chips Challenge for guide
1 parent d2abcbf commit b4a7cf8

37 files changed

+3911
-0
lines changed
106 KB
Binary file not shown.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# SPDX-FileCopyrightText: 2025 Melissa LeBlanc-Williams
2+
#
3+
# SPDX-License-Identifier: MIT
4+
import audiocore
5+
import audiobusio
6+
from definitions import PLAY_SOUNDS
7+
8+
class Audio:
9+
def __init__(self, *, bit_clock, word_select, data):
10+
self._audio = audiobusio.I2SOut(bit_clock, word_select, data)
11+
self._wav_files = {}
12+
13+
def add_sound(self, sound_name, file):
14+
self._wav_files[sound_name] = file
15+
16+
def play(self, sound_name, wait=False):
17+
if not PLAY_SOUNDS:
18+
return
19+
if sound_name in self._wav_files:
20+
with open(self._wav_files[sound_name], "rb") as wave_file:
21+
wav = audiocore.WaveFile(wave_file)
22+
self._audio.play(wav)
23+
if wait:
24+
while self._audio.playing:
25+
pass
47 KB
Binary file not shown.
46.6 KB
Binary file not shown.
9.68 KB
Binary file not shown.
22.1 KB
Binary file not shown.
Binary file not shown.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# SPDX-FileCopyrightText: 2025 Melissa LeBlanc-Williams
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
import time
6+
import board
7+
import picodvi
8+
import framebufferio
9+
import displayio
10+
from game import Game
11+
from definitions import SECOND_LENGTH, TICKS_PER_SECOND
12+
13+
# Disable auto-reload to prevent the game from restarting
14+
# TODO: Enable after testing
15+
#import supervisor
16+
#supervisor.runtime.autoreload = False
17+
18+
# Change this to use a different data file
19+
DATA_FILE = "CHIPS.DAT"
20+
21+
displayio.release_displays()
22+
23+
audio_settings = {
24+
'bit_clock': board.D9,
25+
'word_select': board.D10,
26+
'data': board.D11
27+
}
28+
29+
fb = picodvi.Framebuffer(320, 240, clk_dp=board.CKP, clk_dn=board.CKN,
30+
red_dp=board.D0P, red_dn=board.D0N,
31+
green_dp=board.D1P, green_dn=board.D1N,
32+
blue_dp=board.D2P, blue_dn=board.D2N,
33+
color_depth=8)
34+
display = framebufferio.FramebufferDisplay(fb)
35+
36+
game = Game(display, DATA_FILE, **audio_settings)
37+
tick_length = SECOND_LENGTH / 1000 / TICKS_PER_SECOND
38+
while True:
39+
start = time.monotonic()
40+
game.tick()
41+
while time.monotonic() - start < tick_length:
42+
pass
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# SPDX-FileCopyrightText: 2025 Melissa LeBlanc-Williams
2+
#
3+
# SPDX-License-Identifier: MIT
4+
from point import Point
5+
from definitions import NONE, TYPE_BLOCK, TYPE_CHIP, NORTH, SOUTH, WEST, EAST
6+
7+
DIR_UP = 0
8+
DIR_LEFT = 1
9+
DIR_DOWN = 2
10+
DIR_RIGHT = 3
11+
12+
# creatures should move based on chip, tiles near them, and their own AI
13+
# creatures should be able to move in any direction assuming they are not blocked
14+
15+
# Abstract class
16+
class Creature:
17+
def __init__(self, *, position=None, direction=NONE, creature_type=NONE):
18+
self.cur_pos = position or Point(0, 0)
19+
self.type = creature_type or TYPE_BLOCK
20+
self.direction = direction
21+
self.state = 0x00
22+
self.hidden = False
23+
self.on_slip_list = False
24+
self.to_direction = NONE
25+
26+
def move(self, destination):
27+
if destination.y < self.cur_pos.y:
28+
self.direction = NORTH
29+
elif destination.x < self.cur_pos.x:
30+
self.direction = WEST
31+
elif destination.y > self.cur_pos.y:
32+
self.direction = SOUTH
33+
elif destination.x > self.cur_pos.x:
34+
self.direction = EAST
35+
else:
36+
self.direction = NONE
37+
self.cur_pos = destination
38+
39+
def image_number(self):
40+
tile_index = 0
41+
if self.type == TYPE_CHIP:
42+
tile_index = 0x6C
43+
elif self.type == TYPE_BLOCK:
44+
tile_index = 0x0A
45+
else:
46+
tile_index = 0x40 + ((self.type - 1) * 4)
47+
48+
if self.direction == WEST:
49+
tile_index += DIR_LEFT
50+
elif self.direction == EAST:
51+
tile_index += DIR_RIGHT
52+
elif self.direction == NORTH:
53+
tile_index += DIR_UP
54+
elif self.direction in (SOUTH, NONE):
55+
tile_index += DIR_DOWN
56+
return tile_index
57+
58+
def get_tile_in_dir(self, direction):
59+
pt_dir = Point(self.cur_pos.x, self.cur_pos.y)
60+
if direction == WEST:
61+
pt_dir.x -= 1
62+
elif direction == EAST:
63+
pt_dir.x += 1
64+
elif direction == NORTH:
65+
pt_dir.y -= 1
66+
elif direction == SOUTH:
67+
pt_dir.y += 1
68+
return pt_dir
69+
70+
def left(self):
71+
# return the point to the left of the creature
72+
pt_dest = Point(self.cur_pos.x, self.cur_pos.y)
73+
if self.direction == NORTH:
74+
pt_dest.x -= 1
75+
elif self.direction == WEST:
76+
pt_dest.y += 1
77+
elif self.direction == SOUTH:
78+
pt_dest.x += 1
79+
elif self.direction == EAST:
80+
pt_dest.y -= 1
81+
return pt_dest
82+
83+
def right(self):
84+
# Return point to the right of the creature
85+
pt_dest = Point(self.cur_pos.x, self.cur_pos.y)
86+
if self.direction == NORTH:
87+
pt_dest.x += 1
88+
elif self.direction == WEST:
89+
pt_dest.y -= 1
90+
elif self.direction == SOUTH:
91+
pt_dest.x -= 1
92+
elif self.direction == EAST:
93+
pt_dest.y += 1
94+
return pt_dest
95+
96+
def back(self):
97+
# Return point behind the creature
98+
pt_dest = Point(self.cur_pos.x, self.cur_pos.y)
99+
if self.direction == NORTH:
100+
pt_dest.y += 1
101+
elif self.direction == WEST:
102+
pt_dest.x += 1
103+
elif self.direction == SOUTH:
104+
pt_dest.y -= 1
105+
elif self.direction == EAST:
106+
pt_dest.x -= 1
107+
return pt_dest
108+
109+
def front(self):
110+
# Return point in front of the creature
111+
pt_dest = Point(self.cur_pos.x, self.cur_pos.y)
112+
if self.direction == NORTH:
113+
pt_dest.y -= 1
114+
elif self.direction == WEST:
115+
pt_dest.x -= 1
116+
elif self.direction == SOUTH:
117+
pt_dest.y += 1
118+
elif self.direction == EAST:
119+
pt_dest.x += 1
120+
return pt_dest
121+
122+
def reverse(self):
123+
if self.direction == NORTH:
124+
return SOUTH
125+
elif self.direction == SOUTH:
126+
return NORTH
127+
elif self.direction == WEST:
128+
return EAST
129+
elif self.direction == EAST:
130+
return WEST
131+
else:
132+
return self.direction
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# SPDX-FileCopyrightText: 2023 Melissa LeBlanc-Williams for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
class DataBuffer:
6+
def __init__(self):
7+
self._dataset = {}
8+
self._default_data = {}
9+
10+
def set_data_structure(self, data_structure):
11+
self._default_data = data_structure
12+
self.reset()
13+
14+
def reset(self, field=None):
15+
# Copy the default data to the dataset
16+
if field is not None:
17+
if not isinstance(field, (tuple, list)):
18+
field = [field]
19+
for item in field:
20+
self._dataset[item] = self.deepcopy(self._default_data[item])
21+
else:
22+
self._dataset = self.deepcopy(self._default_data)
23+
24+
def deepcopy(self, data):
25+
# Iterate through the data and copy each element
26+
new_data = {}
27+
if isinstance(data, (dict)):
28+
for key, value in data.items():
29+
if isinstance(value, (dict, list)):
30+
new_data[key] = self.deepcopy(value)
31+
else:
32+
new_data[key] = value
33+
elif isinstance(data, (list)):
34+
for idx, item in enumerate(data):
35+
if isinstance(item, (dict, list)):
36+
new_data[idx] = self.deepcopy(item)
37+
else:
38+
new_data[idx] = item
39+
return new_data
40+
41+
@property
42+
def dataset(self):
43+
return self._dataset

0 commit comments

Comments
 (0)