Compare commits

...

3 Commits

Author SHA1 Message Date
95e4df2810 Implemented spinner ticking sound 2025-06-26 12:32:11 +01:00
23d0ca1ee2 Changed how the spinner is rendered 2025-06-26 12:32:03 +01:00
de4749cac9 Removed debug line 2025-06-26 10:12:15 +01:00
2 changed files with 37 additions and 10 deletions

47
game.py
View File

@ -66,17 +66,23 @@ class Game(gameUtils.Game):
# How long (in seconds) it takes for the wheel to get to full speed # How long (in seconds) it takes for the wheel to get to full speed
self.WHEEL_SPIN_FADE_IN = 0.25 self.WHEEL_SPIN_FADE_IN = 0.25
# How long (in seconds) it takes for the wheel to go back to stationary # How long (in seconds) it takes for the wheel to go back to stationary
self.WHEEL_SPIN_FADE_OUT = 2.5 self.WHEEL_SPIN_FADE_OUT = 3
# The minimum and maximum speeds of the wheel # The minimum and maximum speeds of the wheel
self.WHEEL_SPEED_RANGE = [360, 550] self.WHEEL_SPEED_RANGE = [360, 1000]
# Holds the decided speed of the wheel # Holds the decided speed of the wheel
self.wheelSpinSpeed = 0 self.wheelSpinSpeed = 0
# When the wheel started its spin animation # When the wheel started its spin animation
self.wheelAnimStart = 0 self.wheelAnimStart = 0
# The ticker sound effect
self.tickSfx = pygame.mixer.Sound("./assets/spinner-tick.mp3")
# The last time (in time.perf_counter()) the ticker was played
self.lastTickTime = 0
# The last index the ticker ticked on
self.lastTickItem = -1
font = pygame.font.SysFont('', 32) font = pygame.font.SysFont('', 32)
items = [f'Example item {i+1}' for i in range(17)] self.items = [f'Example item {i+1}' for i in range(13)]
# How many pixels away from the outer side of the # How many pixels away from the outer side of the
# circle the text should be # circle the text should be
textMargin = 5 textMargin = 5
@ -86,13 +92,17 @@ class Game(gameUtils.Game):
# Draw the base circle # Draw the base circle
pygame.draw.circle(self.wheelSurf, (25, 25, 25), (circleR, circleR), circleR) pygame.draw.circle(self.wheelSurf, (25, 25, 25), (circleR, circleR), circleR)
# Calculate the gap, in radians, between each item # Calculate the gap, in radians, between each item
gap = maths.pi * 2 / len(items) gap = maths.pi * 2 / len(self.items)
for idx, item in enumerate(items): for idx, item in enumerate(self.items):
# Calculate the radians of this item # Calculate the radians of this item
rad = (idx / len(items)) * maths.pi * 2 rad = (idx / len(self.items)) * maths.pi * 2
# Calculate the vector from that # Rotate it CCW be 90deg so the first item is on the top
vector = maths.cos(rad), maths.sin(rad) rad -= maths.pi / 2
# Calculate the vector offset by half the item gap
# This is because the text should be in the middle,
# and the lines (which is what this is used by) on the edges
vector = maths.cos(rad+gap/2), maths.sin(rad+gap/2)
# Calculate the end position of a line based on the vector # Calculate the end position of a line based on the vector
endPos = np.add(np.multiply(vector, circleR), circleR) endPos = np.add(np.multiply(vector, circleR), circleR)
# Draw the dividing line # Draw the dividing line
@ -109,10 +119,17 @@ class Game(gameUtils.Game):
#pygame.draw.line(textSurf, (255, 0, 0), (circleR, circleR), (textSurf.size[0], circleR)) #pygame.draw.line(textSurf, (255, 0, 0), (circleR, circleR), (textSurf.size[0], circleR))
#pygame.draw.line(textSurf, (0, 255, 0), (circleR, circleR), (circleR, textSurf.size[1])) #pygame.draw.line(textSurf, (0, 255, 0), (circleR, circleR), (circleR, textSurf.size[1]))
# Rotate the text surface # Rotate the text surface
textSurf = rotateRad(textSurf, rad+gap/2) textSurf = rotateRad(textSurf, rad)
# Blit the text surface to the wheel surface # Blit the text surface to the wheel surface
self.wheelSurf.blit(textSurf, (0, 0)) self.wheelSurf.blit(textSurf, (0, 0))
def spinnerTick(self):
# If there's a tick already playing
if time.perf_counter() - self.lastTickTime < self.tickSfx.get_length():
return
self.tickSfx.play()
self.lastTickTime = time.perf_counter()
def onEvent(self, event): def onEvent(self, event):
""" """
@ -130,6 +147,7 @@ class Game(gameUtils.Game):
Ran once per frame, put your drawing code and any Ran once per frame, put your drawing code and any
game logic that should be ran once per frame in here. game logic that should be ran once per frame in here.
""" """
self.surf.fill((0, 0, 0))
self.surf.blit(rotateDeg(gameUtils.centre(self.wheelSurf, self.size), self.wheelRotation), (0, 0)) self.surf.blit(rotateDeg(gameUtils.centre(self.wheelSurf, self.size), self.wheelRotation), (0, 0))
animTime = time.perf_counter() - self.wheelAnimStart animTime = time.perf_counter() - self.wheelAnimStart
@ -141,7 +159,16 @@ class Game(gameUtils.Game):
self.wheelRotation += speed * self.timeDelta self.wheelRotation += speed * self.timeDelta
self.wheelRotation %= 360 self.wheelRotation %= 360
print(self.wheelRotation)
# Calculates the current item index with... I don't know, magic?
currentItemIdx = round((self.wheelRotation / 360) * len(self.items)) % len(self.items)
# If the last tick was on a different index,
if currentItemIdx != self.lastTickItem:
# Click again
self.spinnerTick()
# And set the last tick index to the current one
self.lastTickItem = currentItemIdx
def close(self): def close(self):
""" """