-
Notifications
You must be signed in to change notification settings - Fork 0
/
catapult.py
165 lines (152 loc) · 6.49 KB
/
catapult.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 Sam Blenny
#
from displayio import Group, TileGrid
import gc
from micropython import const
class Catapult:
# This class manages animation cycles for the catapult and pumpkin.
# The spritesheet tile numbers used here come from the annotations in
# sprites-with-grid.jpeg. The x,y coordinates for screen positions come
# from bkgnd-with-grid.jpeg.
# Names of catapult animation cycle frames (public, for state machine)
# CAUTION: these must match row indexes of _C_TILES
LOAD = const(0)
TOSS1 = const(1)
TOSS2 = const(2)
TOSS3 = const(3)
# Names of pumpkin animation cycle frames (public, for state machine)
# CAUTION: these must match indexes of _P_TILES
HIDE = const(0)
FLY = const(1)
SPLAT1 = const(2)
SPLAT2 = const(3)
SPLAT3 = const(4)
# Tile tuples for the catapult sprite. Catapult sprite is 16x16 px. Tiles
# in the spritesheet are 8x8. So, each frame of the catapult animation
# cycle uses 4 tiles: (top-left, top-right, bottom-left, bottom-right).
_C_TILES = (
(12, 13, 22, 23), # LOAD: stopped, arm at 30°, pumpkin in basket
(14, 15, 24, 25), # TOSS1: moving, arm at 45°, pumpkin in basket
(16, 17, 26, 27), # TOSS2: moving, arm at 60°, pumpkin in basket
(18, 19, 28, 29), # TOSS3: stopped, arm at 60°, basket empty
)
# Tiles for the pumpkin sprite (in flight and splatted). Pumpkin sprite is
# 8x8. So, each frame of the pumpkin flight-splat animation cycle uses 1
# tile of the spritesheet.
_P_TILES = (
0, # HIDE: in-flight sprite is hidden (pumpkin is in the catapult)
10, # FLY: pumpkin is flying (catapult basket empty)
11, # SPLAT1: partial splat at 3/4 height
20, # SPLAT2: partial splat at 1/2 height
21, # SPLAT3: full splat
)
# Catapult charge-up power limits (public)
CHARGE_ZERO = const(0) # hide the charge-up bar
CHARGE_MAX = const(20) # 100% power
# Tiles for the catapult charge-up indicator bar. The indicator bar goes
# from 0% to 100% in 20 increments (bars) of 5% each. The charge bar is
# seven 8x8 tiles wide. The leftmost and rightmost tiles are the ends of
# the rounded rectangle. The 5 inner 8x8 tiles can each represent 4 bars of
# charge (1 bar == 2 px).
_CHG_TILES = (
(0, 0, 0, 0, 0, 0, 0), # CHARGE_ZERO: transparent (hide charge bar)
(1, 3, 2, 2, 2, 2, 7), # 1/20
(1, 4, 2, 2, 2, 2, 7), # 2/20
(1, 5, 2, 2, 2, 2, 7), # 3/20
(1, 6, 2, 2, 2, 2, 7), # 4/20
(1, 6, 3, 2, 2, 2, 7), # 5/20
(1, 6, 4, 2, 2, 2, 7), # 6/20
(1, 6, 5, 2, 2, 2, 7), # 7/20
(1, 6, 6, 2, 2, 2, 7), # 8/20
(1, 6, 6, 3, 2, 2, 7), # 9/20
(1, 6, 6, 4, 2, 2, 7), # 10/20
(1, 6, 6, 5, 2, 2, 7), # 11/20
(1, 6, 6, 6, 2, 2, 7), # 12/20
(1, 6, 6, 6, 3, 2, 7), # 13/20
(1, 6, 6, 6, 4, 2, 7), # 14/20
(1, 6, 6, 6, 5, 2, 7), # 15/20
(1, 6, 6, 6, 6, 2, 7), # 16/20
(1, 6, 6, 6, 6, 3, 7), # 17/20
(1, 6, 6, 6, 6, 4, 7), # 18/20
(1, 6, 6, 6, 6, 5, 7), # 19/20
(1, 6, 6, 6, 6, 6, 7), # 20/20 = CHARGE_MAX
)
def __init__(self, bitmap, palette, x, y, splat_y, chg_x, chg_y):
# This sets up catapult and pumpkin sprites.
# Args:
# - bitmap, palette: Shared spritesheet from adafruit_imageload
# - x, y: Coordinate of top left corner of catapult sprite
# - splat_y: Ground height in pumpkin splat zone
#
# The spritesheet has 8x8 tiles. The pumpkin sprite is 8x8. The
# catapult sprite is 16x16 (4 tiles per sprite/frame).
#
gc.collect()
# Make catapult TileGrid
tgc = TileGrid(
bitmap, pixel_shader=palette, width=2, height=2,
tile_width=8, tile_height=8, x=x, y=y)
gc.collect()
# Make catapult charge-up indicator TileGrid
tgchg = TileGrid(
bitmap, pixel_shader=palette, width=7, height=1,
tile_width=8, tile_height=8, x=chg_x, y=chg_y)
gc.collect()
# Make pumpkin TileGrid
tgp = TileGrid(
bitmap, pixel_shader=palette, width=1, height=1,
tile_width=8, tile_height=8, x=x, y=y)
gc.collect()
# Arrange TileGrids into a group
grp = Group(scale=1)
grp.append(tgc)
grp.append(tgchg)
grp.append(tgp)
# Save arguments and object references
self.x = x
self.y = y
self.splat_y = y
self.tgc = tgc
self.tgchg = tgchg
self.tgp = tgp
self.grp = grp
# Set sprite tiles for initial animation frame
self.set_catapult(LOAD)
self.set_charge(CHARGE_ZERO)
self.set_pumpkin(HIDE, 0, 0)
def group(self):
# Return the displayio.Group object for catapult and pumpkin TileGrids
return self.grp
def set_charge(self, power):
# Set catapult charge-up indicator bar
if (CHARGE_ZERO <= power) and (power <= CHARGE_MAX):
for (i, tile) in enumerate(self._CHG_TILES[power]):
self.tgchg[i] = tile
else:
raise Exception(f"charge power out of range: {power}")
def set_catapult(self, frame):
# Set catapult sprite tiles for the specified animation cycle frame
if (LOAD <= frame) and (frame <= TOSS3):
(topL, topR, botL, botR) = self._C_TILES[frame]
self.tgc[0] = topL
self.tgc[1] = topR
self.tgc[2] = botL
self.tgc[3] = botR
else:
raise Exception(f"catapult frame out of range: {frame}")
def set_pumpkin(self, frame, x, y):
# Set pumpkin sprite tile and relative position for the specified
# animation cycle frame. Pumpkin (x,y) is relative to catapult (x,y).
# Returns:
# - (x, y) coordinate of pumpkin in absolute screen px (vs x, y args
# to this method which are relative to the catapult coordinates)
if (HIDE <= frame) and (frame <= SPLAT3):
self.tgp[0] = self._P_TILES[frame]
pumpkin_x = self.x + round(x) # x argument can be float
pumpkin_y = self.y + round(y) # y argument can be float
self.tgp.x = pumpkin_x
self.tgp.y = pumpkin_y
return (pumpkin_x, pumpkin_y)
else:
raise Exception(f"pumpkin frame out of range: {frame}")