generated from pimoroni/boilerplate-micropython
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
97efb8d
commit f935375
Showing
2 changed files
with
328 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
import math | ||
from machine import I2C | ||
from qwstpad import QwSTPad, ADDRESSES | ||
from picographics import PicoGraphics, DISPLAY_PICO_DISPLAY_2, PEN_RGB565 | ||
|
||
# Constants | ||
WHITE = const(65535) | ||
BLACK = const(0) | ||
CYAN = const(65287) | ||
MAGENTA = const(8184) | ||
YELLOW = const(57599) | ||
GREEN = const(57351) | ||
RED = const(248) | ||
BLUE = const(7936) | ||
|
||
|
||
# Classes | ||
class Projectile(object): | ||
def __init__(self, x, y, direction): | ||
self.x = x | ||
self.y = y | ||
self.direction = direction | ||
|
||
def update(self): | ||
self.x += int(5 * math.cos(self.direction)) | ||
self.y += int(5 * math.sin(self.direction)) | ||
|
||
|
||
class Game(object): | ||
def __init__(self, i2c): | ||
self.player = [Player(30, 50, 10, GREEN), Player(280, 50, 10, MAGENTA), | ||
Player(30, 200, 10, CYAN), Player(280, 200, 10, BLUE)] | ||
|
||
# Store the player pad objects | ||
self.pad = [QwSTPad(i2c, address=ADDRESSES[0]), | ||
QwSTPad(i2c, address=ADDRESSES[1]), | ||
QwSTPad(i2c, address=ADDRESSES[2]), | ||
QwSTPad(i2c, address=ADDRESSES[3])] | ||
|
||
self.xmin = 10 | ||
self.xmax = WIDTH | ||
self.ymin = 10 | ||
self.ymax = HEIGHT | ||
self.winner = False | ||
|
||
def draw(self, display): | ||
|
||
# Clear the screen | ||
display.set_pen(BLACK) | ||
display.clear() | ||
|
||
# Draw a grid for the background | ||
display.set_pen(GREY) | ||
for x in range(0, WIDTH, 20): | ||
for y in range(0, HEIGHT, 20): | ||
display.pixel(x, y) | ||
|
||
# Draw players | ||
for p in self.player: | ||
display.set_pen(WHITE) | ||
display.circle(p.x, p.y, p.size) | ||
display.set_pen(BLACK) if not p.was_hit else display.set_pen(RED) | ||
display.circle(p.x, p.y, p.size - 1) | ||
p.was_hit = False | ||
display.set_pen(p.colour) | ||
display.line(p.x, p.y, int(p.x + (p.line_length * math.cos(p.direction))), int(p.y + (p.line_length * math.sin(p.direction)))) | ||
|
||
for i in p.projectiles: | ||
display.set_pen(p.colour) | ||
display.pixel(i.x, i.y) | ||
|
||
for i, p in enumerate(self.player): | ||
display.set_pen(p.colour) | ||
display.text(f"P{i + 1}: {p.score}", 5 + i * 80, 227, WIDTH, 2) | ||
|
||
# Update the screen | ||
display.update() | ||
|
||
def update(self): | ||
for i, p in enumerate(self.pad): | ||
|
||
button = p.read_buttons() | ||
|
||
if button['L']: | ||
self.player[i].direction -= 0.1 | ||
|
||
if button['R']: | ||
self.player[i].direction += 0.1 | ||
|
||
if button['U']: | ||
self.player[i].x += int(5 * math.cos(self.player[i].direction)) | ||
self.player[i].y += int(5 * math.sin(self.player[i].direction)) | ||
|
||
if button['D']: | ||
self.player[i].x -= int(5 * math.cos(self.player[i].direction)) | ||
self.player[i].y -= int(5 * math.sin(self.player[i].direction)) | ||
|
||
if button['A']: | ||
self.player[i].new_projectile() | ||
|
||
self.player[i].x = min(self.player[i].x, self.xmax - self.player[i].size) | ||
self.player[i].x = max(self.player[i].x, self.xmin + self.player[i].size) | ||
|
||
self.player[i].y = min(self.player[i].y, self.ymax - self.player[i].size) | ||
self.player[i].y = max(self.player[i].y, self.ymin + self.player[i].size) | ||
|
||
for p in self.player: | ||
p.update() | ||
|
||
for i, p in enumerate(self.player): | ||
for j in range(len(self.player)): | ||
if not i == j: | ||
p2 = self.player[j] | ||
|
||
for projectile in p.projectiles: | ||
|
||
xdif = projectile.x - p2.x | ||
ydif = projectile.y - p2.y | ||
|
||
sqdist = xdif ** 2 + ydif ** 2 | ||
|
||
if sqdist < p2.size ** 2: | ||
p2.was_hit = True | ||
p.score += 1 | ||
|
||
|
||
class Player(object): | ||
def __init__(self, x, y, size, colour): | ||
self.direction = math.radians(20) | ||
self.x = x | ||
self.y = y | ||
self.size = size | ||
self.colour = colour | ||
self.line_length = 25 | ||
self.projectiles = [] | ||
self.was_hit = False | ||
self.score = 0 | ||
|
||
def new_projectile(self): | ||
if len(self.projectiles) < 15: | ||
self.projectiles.append(Projectile(self.x, self.y, self.direction)) | ||
|
||
def update(self): | ||
if self.projectiles: | ||
new_proj = [] | ||
for i, projectile in enumerate(self.projectiles): | ||
projectile.update() | ||
if projectile.x > WIDTH or projectile.x < 0 or projectile.y < 0 or projectile.y > HEIGHT: | ||
pass | ||
else: | ||
new_proj.append(projectile) | ||
self.projectiles = new_proj | ||
|
||
|
||
# Variables | ||
display = PicoGraphics(display=DISPLAY_PICO_DISPLAY_2, pen_type=PEN_RGB565) | ||
display.set_backlight(1.0) | ||
|
||
WIDTH, HEIGHT = display.get_bounds() | ||
GREY = display.create_pen(115, 115, 115) | ||
|
||
i2c = I2C(0, scl=5, sda=4) | ||
g = Game(i2c) | ||
|
||
while True: | ||
g.update() | ||
g.draw(display) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import time | ||
from machine import I2C | ||
from qwstpad import QwSTPad, DEFAULT_ADDRESS | ||
from picographics import PicoGraphics, DISPLAY_PICO_DISPLAY_2, PEN_RGB565 | ||
|
||
# Constants | ||
WHITE = const(65535) | ||
BLACK = const(0) | ||
GREEN = const(57351) | ||
|
||
# Classes | ||
|
||
class Game(object): | ||
def __init__(self, i2c): | ||
|
||
self.complete = False | ||
|
||
# The square the player must get to. | ||
self.end_location = (1, 30) | ||
|
||
# Our maze, 1's are solid walls and 0's are the path we can move along. | ||
# Try changing some 1s and 0s and see how the maze changes! :) | ||
|
||
self.maze = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], | ||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], | ||
[1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1], | ||
[1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1], | ||
[1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1], | ||
[1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1], | ||
[1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1], | ||
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1], | ||
[1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1], | ||
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1], | ||
[1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1], | ||
[1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1], | ||
[1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1], | ||
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1], | ||
[1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], | ||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], | ||
[1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1], | ||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], | ||
[1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], | ||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], | ||
[1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1], | ||
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], | ||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] | ||
|
||
# Store the player pad objects | ||
self.pad = QwSTPad(i2c, address=DEFAULT_ADDRESS) | ||
|
||
# Our player object. Stores the current location and the colour of the player square. | ||
self.player = Player(1, 21, PLAYER) | ||
|
||
def draw(self, display): | ||
|
||
# Clear the screen | ||
display.set_pen(PATH) | ||
display.clear() | ||
display.set_pen(WHITE) | ||
|
||
# Draw the maze we have stored above. | ||
# Each '1' in the array is drawn as a 10x10 pixel square. | ||
for row in range(len(self.maze)): | ||
for col in range(len(self.maze[row])): | ||
if self.maze[row][col] == 1: | ||
display.set_pen(BLACK) | ||
display.rectangle(col * 10 + 2, row * 10 + 2, 10, 10) | ||
display.set_pen(WALL) | ||
display.rectangle(col * 10, row * 10, 9, 9) | ||
|
||
if self.maze[row][col] == 2: | ||
display.set_pen(GREEN) | ||
display.rectangle(col * 10, row * 10, 9, 9) | ||
display.set_pen(WALL) | ||
|
||
# Draw the player. | ||
display.set_pen(self.player.colour) | ||
display.rectangle(self.player.x * 10, self.player.y * 10, self.player.size - 1, self.player.size - 1) | ||
|
||
# Draw the end location square | ||
display.set_pen(GREEN) | ||
display.rectangle(self.end_location[1] * 10, self.end_location[0] * 10, 9, 9) | ||
|
||
if self.complete: | ||
# Draw banner shadow | ||
display.set_pen(BLACK) | ||
display.rectangle(4, 94, WIDTH, 50) | ||
# Draw banner | ||
display.set_pen(PLAYER) | ||
display.rectangle(0, 90, WIDTH, 50) | ||
|
||
# Draw text shadow | ||
display.set_pen(BLACK) | ||
display.text("Maze Complete!", WIDTH // 6 + 2, 107, WIDTH, 3) | ||
|
||
# Draw text | ||
display.set_pen(WHITE) | ||
display.text("Maze Complete!", WIDTH // 6, 105, WIDTH, 3) | ||
|
||
# Update the screen | ||
display.update() | ||
|
||
def update(self): | ||
|
||
button = self.pad.read_buttons() | ||
|
||
if button['L']: | ||
if self.maze[self.player.y][self.player.x - 1] == 0: | ||
self.player.x -= 1 | ||
time.sleep(0.1) | ||
|
||
if button['R']: | ||
if self.maze[self.player.y][self.player.x + 1] == 0: | ||
self.player.x += 1 | ||
time.sleep(0.1) | ||
|
||
if button['U']: | ||
if self.maze[self.player.y - 1][self.player.x] == 0: | ||
self.player.y -= 1 | ||
time.sleep(0.1) | ||
|
||
if button['D']: | ||
if self.maze[self.player.y + 1][self.player.x] == 0: | ||
self.player.y += 1 | ||
time.sleep(0.1) | ||
|
||
if self.player.x == self.end_location[1] and self.player.y == self.end_location[0]: | ||
self.complete = True | ||
|
||
|
||
class Player(object): | ||
# The player object. | ||
# Stores the current location of the player in the maze. | ||
def __init__(self, x, y, colour): | ||
self.x = x | ||
self.y = y | ||
self.size = 10 | ||
self.colour = colour | ||
|
||
|
||
display = PicoGraphics(display=DISPLAY_PICO_DISPLAY_2, pen_type=PEN_RGB565) | ||
display.set_backlight(1.0) | ||
|
||
WIDTH, HEIGHT = display.get_bounds() | ||
|
||
# Set some colours to use later. | ||
WALL = display.create_pen(127, 125, 244) | ||
PATH = display.create_pen(60, 57, 169) | ||
PLAYER = display.create_pen(227, 231, 110) | ||
|
||
display.set_pen(BLACK) | ||
display.clear() | ||
|
||
|
||
i2c = I2C(0, scl=5, sda=4) | ||
g = Game(i2c) | ||
|
||
while True: | ||
if not g.complete: | ||
g.update() | ||
g.draw(display) |