Compare commits

...

32 Commits

Author SHA1 Message Date
36d646a26f Slightly cleaned up arraw draw 2025-06-27 07:22:37 +01:00
32c33ae613 Added TODOs 2025-06-27 07:18:50 +01:00
97bd53e491 Moved wheel config to its own class 2025-06-26 18:19:45 +01:00
0dc6555499 Changed text margin 2025-06-26 16:55:15 +01:00
8b47026f0e Added arrow 2025-06-26 16:55:06 +01:00
097dd7486a Fixed bug in text rendering 2025-06-26 16:54:58 +01:00
6adb31f466 Updated debug line code 2025-06-26 16:54:49 +01:00
db4f7d05f7 Added wheel margin 2025-06-26 16:54:33 +01:00
dafeb80b77 Fixed typo 2025-06-26 16:44:40 +01:00
3e4907f192 Moved wheel drawing into its own function 2025-06-26 16:44:27 +01:00
1366c10fd7 Added item shuffling 2025-06-26 16:43:40 +01:00
a12a583444 Linted 2 lines 2025-06-26 14:53:57 +01:00
dce162ba4a Made the first item appear on the right 2025-06-26 14:53:46 +01:00
c8b25ff53b Fixed big with which way the text rendered 2025-06-26 14:52:56 +01:00
94fa33ebd0 Made KEYDOWN event more flexible 2025-06-26 14:51:06 +01:00
a1c5641eee Added global font & render current item 2025-06-26 14:50:41 +01:00
471de3ef6e Created WheelItem class 2025-06-26 14:48:33 +01:00
e8ee151267 Removed TODO 2025-06-26 14:47:11 +01:00
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
f2b9ab4d26 Added spinner audio file & relevant TODO 2025-06-26 08:01:44 +01:00
b2cc7a996f Did the "LEGO Island fix" 2025-06-26 07:29:31 +01:00
b0c752f946 Added TODOs 2025-06-26 07:22:09 +01:00
71693518a8 Added text margins 2025-06-26 07:21:57 +01:00
a8814fdfe1 Added basic spin animation 2025-06-26 07:21:41 +01:00
585c54f205 Fixed bug, and changed colours 2025-06-26 06:15:09 +01:00
54f9d8bc88 Added item text to wheel 2025-06-26 06:14:08 +01:00
914ad5e0ce Created a pi(e) in literally 10 minutes, I'm fucking balling lads 2025-06-25 14:48:03 +01:00
9643baa093 Updated game details 2025-06-25 14:47:42 +01:00
a6f6f56843 Added test.py and .vscode to .gitignore 2025-06-20 19:35:19 +01:00
ea7ed8be07 Added boilerplate 2025-06-20 19:35:04 +01:00
5 changed files with 236 additions and 0 deletions

3
.gitignore vendored
View File

@ -174,3 +174,6 @@ cython_debug/
# PyPI configuration file
.pypirc
# ---> Other
/test.py
/.vscode/

BIN
assets/spinner-tick.mp3 Normal file

Binary file not shown.

220
game.py Normal file
View File

@ -0,0 +1,220 @@
import math as maths
import logging
import random
import time
import gameUtils
import NoPELib
import numpy as np
import pygame
# TODO: Prevent another animation from starting when the wheel's spinning
# TODO: Convert fade in / out time to be random
# TODO: Make random finer (to prevent a range of 4-5 only having two possible speeds)
def translate(value, aMin, aMax, bMin, bMax):
"""
Translates `value` to go from `aMin`-`aMax` to `bMin`-`bMax`
Stolen from StackOverflow because we don't have time to do shit
properly here.
"""
aRange = aMax - aMin
bRange = bMax - bMin
return (((value - aMin) * bRange) / aRange) + bMin
def rotateRad(surface: pygame.Surface, radians: float) -> pygame.Surface:
"""
Rotates a surface clockwise in radians and re-centres it.
"""
# Calculate the degrees
deg = radians*(180/maths.pi)
# Rotate the surface re-centre
return rotateDeg(surface, deg)
def rotateDeg(surface: pygame.Surface, degrees: float) -> pygame.Surface:
"""
Rotates a surface clockwise in degrees and re-centres it.
"""
# Convert to CCW becaus for some reason that's what Pygame uses?
degrees *= -1
# Rotate surface which will expand it
rotSurface = pygame.transform.rotate(surface, degrees)
# re-centre it to the orinal surface bounding box
rotSurface = gameUtils.centre(rotSurface, surface.size)
return rotSurface
class WCfg:
"""
Holds all the Wheel Configurations.
"""
# The background colour of the wheel
bgColour = (25, 25, 25)
# The colour of the dividing lines
divColour = (75, 75, 75)
# The colour of the text
txtColour = (255, 255, 255)
# How much space is between the wheel and the screen
margin = 50
# The minimum and maximum time it takes (in seconds)
# for the wheel to get to full speed.
spinFadeInTimes = [0.25, 0.25]
# The minimum and maximum time it takes (in seconds)
# for the wheel to get to go back to being stationary.
spinFadeOutTimes = [3, 4]
# The minimum and maximum speeds of the wheel in deg/s
spinSpeedRange = [360, 1000]
# How many pixels away from the outer side of the
# circle the text should be
textMargin = 10
# The font to use for drawing the item text
font = pygame.font.SysFont('', 32)
class WheelItem:
# TODO: Add integration with NoPE-Lib
# TODO: Allow this to modify game attributes so it can hide the wheel and respin
def __init__(self, text):
self.text = text
class Game(gameUtils.Game):
def __init__(self, *args, **kwargs):
"""
Ran when the game starts.
You have access to the following variables:
self.surf (pygame.Surface): This is the surface you draw onto.
self.pm (NoPELib.PlayerManager): This is where your players are stored.
self.cfg (dict): Everything from the `game.toml` file. You can access it like this: self.details['title']
"""
# Don't remove this. It does important things. :3
super().__init__(*args, **kwargs)
self.wheelSurf = pygame.Surface([min(self.size)-WCfg.margin*2]*2) # Don't ask.
self.wheelRotation = 0
# Holds the decided speed of the wheel
self.wheelSpinSpeed = 0
# Holds the decided fade in time
self.animFadeIn = 0
# Holds the decided fade out time
self.animFadeOut = 0
# When the wheel started its spin animation
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
self.items = []
self.items.append(WheelItem('Drink 1 shot'))
self.items.append(WheelItem('Drink 2 shots'))
self.items.append(WheelItem('Get shocked at 50%'))
self.items.append(WheelItem('Get shocked at 100%'))
self.items.append(WheelItem('Get slapped by\neveryone in the room'))
self.items.append(WheelItem('Respin, wheel hidden'))
random.shuffle(self.items)
self.font = pygame.font.SysFont('', 50)
self.drawWheel()
def drawWheel(self):
# Calculate circle radius
circleR = self.wheelSurf.size[0] / 2
# Draw the base circle
pygame.draw.circle(self.wheelSurf, WCfg.bgColour, (circleR, circleR), circleR)
# Calculate the gap, in radians, between each item
gap = maths.pi * 2 / len(self.items)
for idx, item in enumerate(self.items):
# Calculate the radians of this item
rad = (idx / len(self.items)) * 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
endPos = np.add(np.multiply(vector, circleR), circleR)
# Draw the dividing line
pygame.draw.line(self.wheelSurf, WCfg.divColour, (circleR, circleR), endPos)
# Create a surface that our text will be rendered onto
textSurf = pygame.Surface(self.wheelSurf.size, pygame.SRCALPHA)
# Render the item text
text = WCfg.font.render(item.text, True, WCfg.txtColour)
# Draw the item text onto the text surface, centred to the right
textSurf.blit(text, (textSurf.size[0]-text.get_width()-WCfg.textMargin, textSurf.size[1]//2 - text.get_height()//2))
# Draw debug lines
#if idx < 1:
# pygame.draw.rect(textSurf, (0, 128, 255), (0, 0, textSurf.size[0], textSurf.size[1]), 1)
# 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]))
# Rotate the text surface
textSurf = rotateRad(textSurf, -rad)
# Blit the text surface to the wheel surface
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):
"""
Ran when an event is fired.
Args:
event (pygame.Event): The event that was fired.
"""
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
self.wheelSpinSpeed = random.randint(*WCfg.spinSpeedRange)
self.wheelAnimStart = time.perf_counter()
def update(self):
"""
Ran once per frame, put your drawing code and any
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))
arrowX = (self.size[0] - self.wheelSurf.size[0]) // 2 + self.wheelSurf.size[0]
arrowY = self.size[1] // 2
arrowSize = 20
arrowPollys = ((arrowX, arrowY), (arrowX+arrowSize, arrowY-arrowSize//2), (arrowX+arrowSize, arrowY+arrowSize//2))
pygame.draw.polygon(self.surf, (255, 255, 255), arrowPollys)
animTime = time.perf_counter() - self.wheelAnimStart
if animTime < WCfg.spinFadeInTimes[0] + WCfg.spinFadeOutTimes[0]:
if animTime < WCfg.spinFadeInTimes[0]:
speed = translate(animTime, 0, WCfg.spinFadeInTimes[0], 0, self.wheelSpinSpeed)
else:
speed = translate(animTime, WCfg.spinFadeInTimes[0], WCfg.spinFadeInTimes[0]+WCfg.spinFadeOutTimes[0], self.wheelSpinSpeed, 0)
self.wheelRotation += speed * self.timeDelta
self.wheelRotation %= 360
# 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
self.surf.blit(self.font.render(self.items[currentItemIdx].text, True, (255, 255, 255)), (0, 0))
def close(self):
"""
Ran when the game closes.
"""
pass

8
game.toml Normal file
View File

@ -0,0 +1,8 @@
# The ID used for logging
# TODO: Filter things like '\', '{}', '\n' etc.-
id = "spinTheSin"
# The name used for setting the windows
# title, and for displaying in the launcher
name = "Spin The Sin"
# The description displayed by the launcher
description = "Write something about this game.\nNew lines are supported."

5
requirements.txt Normal file
View File

@ -0,0 +1,5 @@
../GameUtils/
../NoPELib/
../PDOLib/
pygame-ce
numpy