Skip to content

Commit 24bee75

Browse files
committed
Add MagicEightBall game.
1 parent 38364f4 commit 24bee75

File tree

3 files changed

+241
-0
lines changed

3 files changed

+241
-0
lines changed

MagicEightBall/MagicEightBall.py

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
# Magic Eight Ball for Thumby
2+
# A fortune-telling game with immersive animations
3+
4+
import thumby
5+
import time
6+
import random
7+
import math
8+
9+
# Initialize the display
10+
thumby.display.setFPS(30)
11+
thumby.display.fill(0)
12+
13+
# Game states
14+
STATE_START = 0
15+
STATE_SHAKE = 1
16+
STATE_FORTUNE = 2
17+
18+
# Current game state
19+
current_state = STATE_START
20+
21+
# List of possible fortunes
22+
fortunes = [
23+
"IT IS\nCERTAIN",
24+
"IT IS\nDECIDEDLY\nSO",
25+
"WITHOUT A\nDOUBT",
26+
"YES\nDEFINITELY",
27+
"YOU MAY\nRELY ON IT",
28+
"AS I SEE\nIT, YES",
29+
"MOST\nLIKELY",
30+
"OUTLOOK\nGOOD",
31+
"YES",
32+
"SIGNS POINT\nTO YES",
33+
"REPLY HAZY\nTRY AGAIN",
34+
"ASK AGAIN\nLATER",
35+
"BETTER NOT\nTELL YOU\nNOW",
36+
"CANNOT\nPREDICT\nNOW",
37+
"CONCENTRATE\nAND ASK\nAGAIN",
38+
"DON'T\nCOUNT\nON IT",
39+
"MY REPLY\nIS NO",
40+
"MY SOURCES\nSAY NO",
41+
"OUTLOOK NOT\nSO GOOD",
42+
"VERY\nDOUBTFUL"
43+
]
44+
45+
# Current fortune and previous fortune
46+
current_fortune = ""
47+
previous_fortune = ""
48+
49+
# Animation variables
50+
shake_frames = 0
51+
shake_counter = 0
52+
fade_counter = 0
53+
noise_level = 0
54+
bubble_positions = []
55+
56+
# Draw the start screen
57+
def draw_start_screen():
58+
# Draw eight ball border to make it look like we're looking through the window
59+
thumby.display.drawRectangle(0, 0, 72, 40, 1)
60+
thumby.display.drawRectangle(1, 1, 70, 38, 1)
61+
62+
# Draw title text
63+
thumby.display.setFont("/lib/font5x7.bin", 5, 7, 1)
64+
thumby.display.drawText("MAGIC", 18, 5, 1)
65+
thumby.display.drawText("EIGHT BALL", 8, 15, 1)
66+
67+
# Draw the number 8 with a simple background (using lines instead of a triangle)
68+
thumby.display.drawLine(28, 30, 50, 30, 1)
69+
thumby.display.drawLine(28, 30, 39, 18, 1)
70+
thumby.display.drawLine(50, 30, 39, 18, 1)
71+
#thumby.display.setFont("/lib/font3x5.bin", 3, 5, 1)
72+
thumby.display.drawText("8", 37, 22, 1)
73+
74+
# Draw instructions
75+
thumby.display.setFont("/lib/font3x5.bin", 3, 5, 1)
76+
thumby.display.drawText("A/B to shake", 12, 32, 1)
77+
78+
# Draw the fortune with word wrapping
79+
def draw_fortune(text, alpha=1.0):
80+
thumby.display.setFont("/lib/font5x7.bin", 5, 7, 1)
81+
lines = text.split('\n')
82+
y = max(0, (40 - len(lines) * 10) // 2)
83+
84+
for line in lines:
85+
x = max(0, (72 - len(line) * 6) // 2)
86+
87+
# Only draw the text if random value is less than alpha (for fade effect)
88+
if random.random() < alpha:
89+
thumby.display.drawText(line, x, y, 1)
90+
y += 10
91+
92+
# Create bubble effect
93+
def initialize_bubbles():
94+
global bubble_positions
95+
bubble_positions = []
96+
97+
# Create random bubbles
98+
for _ in range(10):
99+
x = random.randint(5, 67)
100+
y = random.randint(5, 35)
101+
size = random.randint(1, 3)
102+
speed = random.uniform(0.2, 0.8)
103+
bubble_positions.append([x, y, size, speed])
104+
105+
# Update and draw bubbles
106+
def update_bubbles():
107+
global bubble_positions
108+
109+
for i, bubble in enumerate(bubble_positions):
110+
# Move bubble up
111+
bubble[1] -= bubble[3]
112+
113+
# If bubble goes off screen, reset at bottom
114+
if bubble[1] < -5:
115+
bubble[0] = random.randint(5, 67)
116+
bubble[1] = 45
117+
118+
# Draw bubble
119+
thumby.display.drawFilledRectangle(int(bubble[0]), int(bubble[1]), bubble[2], bubble[2], 1)
120+
121+
# Update in the list
122+
bubble_positions[i] = bubble
123+
124+
# Generate random noise pattern for shaking effect
125+
def generate_noise(intensity):
126+
for y in range(0, 40, 2):
127+
for x in range(0, 72, 2):
128+
if random.random() < intensity / 10.0:
129+
thumby.display.setPixel(x, y, 1)
130+
131+
# Shake animation - simulates the fluid becoming cloudy and bubbling
132+
def animate_shake():
133+
global shake_frames, shake_counter, bubble_positions, noise_level
134+
135+
shake_frames += 1
136+
137+
# Draw the eight ball window border
138+
thumby.display.drawRectangle(0, 0, 72, 40, 1)
139+
140+
# Calculate noise intensity - increases then decreases
141+
if shake_frames < 30:
142+
noise_level = min(10, shake_frames // 3)
143+
else:
144+
noise_level = max(0, 10 - (shake_frames - 30) // 3)
145+
146+
# Generate noise pattern with current intensity
147+
generate_noise(noise_level)
148+
149+
# Update and draw bubbles
150+
update_bubbles()
151+
152+
# Occasionally show the previous fortune fading out
153+
if shake_frames < 30 and previous_fortune and random.random() < 0.3:
154+
fade_alpha = max(0, 1.0 - (shake_frames / 30.0))
155+
draw_fortune(previous_fortune, fade_alpha)
156+
157+
# Shake the screen slightly
158+
shake_offset = random.randint(-2, 2)
159+
thumby.display.drawLine(0, 0 + shake_offset, 71, 0 + shake_offset, 1)
160+
thumby.display.drawLine(0, 39 + shake_offset, 71, 39 + shake_offset, 1)
161+
162+
# Check if shake animation is complete
163+
if shake_frames >= 60:
164+
return True
165+
return False
166+
167+
# Animate the fortune appearing from the cloudy fluid
168+
def animate_fortune_reveal():
169+
global fade_counter
170+
171+
fade_counter += 1
172+
173+
# Draw the eight ball window border
174+
thumby.display.drawRectangle(0, 0, 72, 40, 1)
175+
176+
# Calculate fade-in alpha
177+
alpha = min(1.0, fade_counter / 30.0)
178+
179+
# Generate decreasing noise as the text becomes clearer
180+
noise_intensity = max(0, 10 - fade_counter // 3)
181+
generate_noise(noise_intensity)
182+
183+
# Update and draw bubbles (they continue throughout)
184+
update_bubbles()
185+
186+
# Draw the fortune with current alpha
187+
draw_fortune(current_fortune, alpha)
188+
189+
# Check if fade animation is complete
190+
if fade_counter >= 30:
191+
return True
192+
return False
193+
194+
# Initialize the game
195+
initialize_bubbles()
196+
197+
# Main game loop
198+
while True:
199+
thumby.display.fill(0)
200+
201+
# Handle button inputs
202+
if thumby.buttonA.justPressed() or thumby.buttonB.justPressed():
203+
if current_state == STATE_START or current_state == STATE_FORTUNE:
204+
current_state = STATE_SHAKE
205+
shake_frames = 0
206+
shake_counter = 0
207+
# Store previous fortune before selecting a new one
208+
previous_fortune = current_fortune
209+
# Select a random fortune
210+
current_fortune = random.choice(fortunes)
211+
# Reset bubbles for shake animation
212+
initialize_bubbles()
213+
214+
# Update and render based on current state
215+
if current_state == STATE_START:
216+
draw_start_screen()
217+
218+
elif current_state == STATE_SHAKE:
219+
# Run shake animation
220+
if animate_shake():
221+
current_state = STATE_FORTUNE
222+
fade_counter = 0
223+
224+
elif current_state == STATE_FORTUNE:
225+
# Run fortune transition animation or show fortune
226+
if fade_counter < 30:
227+
animate_fortune_reveal()
228+
else:
229+
# Draw the eight ball window border
230+
thumby.display.drawRectangle(0, 0, 72, 40, 1)
231+
# Draw fully revealed fortune
232+
draw_fortune(current_fortune)
233+
# Still show some occasional bubbles
234+
update_bubbles()
235+
236+
# Update the display
237+
thumby.display.update()
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Yet another Magic Eight Ball game.
2+
3+
This one has animations for bubbles and fading in and out between answers to
4+
give the appearance of messages floating up and down in murky liquid.
355 KB
Binary file not shown.

0 commit comments

Comments
 (0)