Skip to content

Commit 94ce033

Browse files
authored
Merge pull request #3007 from makermelissa/main
Add Chips Challenge for guide
2 parents dc254f0 + 1f143ab commit 94ce033

37 files changed

+3887
-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
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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+
#import supervisor
15+
#supervisor.runtime.autoreload = False
16+
17+
# Change this to use a different data file
18+
DATA_FILE = "CHIPS.DAT"
19+
20+
displayio.release_displays()
21+
22+
audio_settings = {
23+
'bit_clock': board.D9,
24+
'word_select': board.D10,
25+
'data': board.D11
26+
}
27+
28+
fb = picodvi.Framebuffer(320, 240, clk_dp=board.CKP, clk_dn=board.CKN,
29+
red_dp=board.D0P, red_dn=board.D0N,
30+
green_dp=board.D1P, green_dn=board.D1N,
31+
blue_dp=board.D2P, blue_dn=board.D2N,
32+
color_depth=8)
33+
display = framebufferio.FramebufferDisplay(fb)
34+
35+
game = Game(display, DATA_FILE, **audio_settings)
36+
tick_length = SECOND_LENGTH / 1000 / TICKS_PER_SECOND
37+
while True:
38+
start = time.monotonic()
39+
game.tick()
40+
while time.monotonic() - start < tick_length:
41+
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)