Skip to content

Add Chips Challenge for guide #3007

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Metro/Metro_RP2350_Chips_Challenge/CHIPS.DAT
Binary file not shown.
25 changes: 25 additions & 0 deletions Metro/Metro_RP2350_Chips_Challenge/audio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# SPDX-FileCopyrightText: 2025 Melissa LeBlanc-Williams
#
# SPDX-License-Identifier: MIT
import audiocore
import audiobusio
from definitions import PLAY_SOUNDS

class Audio:
def __init__(self, *, bit_clock, word_select, data):
self._audio = audiobusio.I2SOut(bit_clock, word_select, data)
self._wav_files = {}

def add_sound(self, sound_name, file):
self._wav_files[sound_name] = file

def play(self, sound_name, wait=False):
if not PLAY_SOUNDS:
return
if sound_name in self._wav_files:
with open(self._wav_files[sound_name], "rb") as wave_file:
wav = audiocore.WaveFile(wave_file)
self._audio.play(wav)
if wait:
while self._audio.playing:
pass
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
41 changes: 41 additions & 0 deletions Metro/Metro_RP2350_Chips_Challenge/code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# SPDX-FileCopyrightText: 2025 Melissa LeBlanc-Williams
#
# SPDX-License-Identifier: MIT

import time
import board
import picodvi
import framebufferio
import displayio
from game import Game
from definitions import SECOND_LENGTH, TICKS_PER_SECOND

# Disable auto-reload to prevent the game from restarting
#import supervisor
#supervisor.runtime.autoreload = False

# Change this to use a different data file
DATA_FILE = "CHIPS.DAT"

displayio.release_displays()

audio_settings = {
'bit_clock': board.D9,
'word_select': board.D10,
'data': board.D11
}

fb = picodvi.Framebuffer(320, 240, clk_dp=board.CKP, clk_dn=board.CKN,
red_dp=board.D0P, red_dn=board.D0N,
green_dp=board.D1P, green_dn=board.D1N,
blue_dp=board.D2P, blue_dn=board.D2N,
color_depth=8)
display = framebufferio.FramebufferDisplay(fb)

game = Game(display, DATA_FILE, **audio_settings)
tick_length = SECOND_LENGTH / 1000 / TICKS_PER_SECOND
while True:
start = time.monotonic()
game.tick()
while time.monotonic() - start < tick_length:
pass
132 changes: 132 additions & 0 deletions Metro/Metro_RP2350_Chips_Challenge/creature.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# SPDX-FileCopyrightText: 2025 Melissa LeBlanc-Williams
#
# SPDX-License-Identifier: MIT
from point import Point
from definitions import NONE, TYPE_BLOCK, TYPE_CHIP, NORTH, SOUTH, WEST, EAST

DIR_UP = 0
DIR_LEFT = 1
DIR_DOWN = 2
DIR_RIGHT = 3

# creatures should move based on chip, tiles near them, and their own AI
# creatures should be able to move in any direction assuming they are not blocked

# Abstract class
class Creature:
def __init__(self, *, position=None, direction=NONE, creature_type=NONE):
self.cur_pos = position or Point(0, 0)
self.type = creature_type or TYPE_BLOCK
self.direction = direction
self.state = 0x00
self.hidden = False
self.on_slip_list = False
self.to_direction = NONE

def move(self, destination):
if destination.y < self.cur_pos.y:
self.direction = NORTH
elif destination.x < self.cur_pos.x:
self.direction = WEST
elif destination.y > self.cur_pos.y:
self.direction = SOUTH
elif destination.x > self.cur_pos.x:
self.direction = EAST
else:
self.direction = NONE
self.cur_pos = destination

def image_number(self):
tile_index = 0
if self.type == TYPE_CHIP:
tile_index = 0x6C
elif self.type == TYPE_BLOCK:
tile_index = 0x0A
else:
tile_index = 0x40 + ((self.type - 1) * 4)

if self.direction == WEST:
tile_index += DIR_LEFT
elif self.direction == EAST:
tile_index += DIR_RIGHT
elif self.direction == NORTH:
tile_index += DIR_UP
elif self.direction in (SOUTH, NONE):
tile_index += DIR_DOWN
return tile_index

def get_tile_in_dir(self, direction):
pt_dir = Point(self.cur_pos.x, self.cur_pos.y)
if direction == WEST:
pt_dir.x -= 1
elif direction == EAST:
pt_dir.x += 1
elif direction == NORTH:
pt_dir.y -= 1
elif direction == SOUTH:
pt_dir.y += 1
return pt_dir

def left(self):
# return the point to the left of the creature
pt_dest = Point(self.cur_pos.x, self.cur_pos.y)
if self.direction == NORTH:
pt_dest.x -= 1
elif self.direction == WEST:
pt_dest.y += 1
elif self.direction == SOUTH:
pt_dest.x += 1
elif self.direction == EAST:
pt_dest.y -= 1
return pt_dest

def right(self):
# Return point to the right of the creature
pt_dest = Point(self.cur_pos.x, self.cur_pos.y)
if self.direction == NORTH:
pt_dest.x += 1
elif self.direction == WEST:
pt_dest.y -= 1
elif self.direction == SOUTH:
pt_dest.x -= 1
elif self.direction == EAST:
pt_dest.y += 1
return pt_dest

def back(self):
# Return point behind the creature
pt_dest = Point(self.cur_pos.x, self.cur_pos.y)
if self.direction == NORTH:
pt_dest.y += 1
elif self.direction == WEST:
pt_dest.x += 1
elif self.direction == SOUTH:
pt_dest.y -= 1
elif self.direction == EAST:
pt_dest.x -= 1
return pt_dest

def front(self):
# Return point in front of the creature
pt_dest = Point(self.cur_pos.x, self.cur_pos.y)
if self.direction == NORTH:
pt_dest.y -= 1
elif self.direction == WEST:
pt_dest.x -= 1
elif self.direction == SOUTH:
pt_dest.y += 1
elif self.direction == EAST:
pt_dest.x += 1
return pt_dest

def reverse(self):
if self.direction == NORTH:
return SOUTH
elif self.direction == SOUTH:
return NORTH
elif self.direction == WEST:
return EAST
elif self.direction == EAST:
return WEST
else:
return self.direction
43 changes: 43 additions & 0 deletions Metro/Metro_RP2350_Chips_Challenge/databuffer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# SPDX-FileCopyrightText: 2023 Melissa LeBlanc-Williams for Adafruit Industries
#
# SPDX-License-Identifier: MIT

class DataBuffer:
def __init__(self):
self._dataset = {}
self._default_data = {}

def set_data_structure(self, data_structure):
self._default_data = data_structure
self.reset()

def reset(self, field=None):
# Copy the default data to the dataset
if field is not None:
if not isinstance(field, (tuple, list)):
field = [field]
for item in field:
self._dataset[item] = self.deepcopy(self._default_data[item])
else:
self._dataset = self.deepcopy(self._default_data)

def deepcopy(self, data):
# Iterate through the data and copy each element
new_data = {}
if isinstance(data, (dict)):
for key, value in data.items():
if isinstance(value, (dict, list)):
new_data[key] = self.deepcopy(value)
else:
new_data[key] = value
elif isinstance(data, (list)):
for idx, item in enumerate(data):
if isinstance(item, (dict, list)):
new_data[idx] = self.deepcopy(item)
else:
new_data[idx] = item
return new_data

@property
def dataset(self):
return self._dataset
Loading