Compare commits

...

34 Commits

Author SHA1 Message Date
1bd3ebe2f6 Added name in corner 2025-07-16 15:21:37 +01:00
bd3a986699 Added expansion manager implementation 2025-07-16 12:08:22 +01:00
ceca244290 Improved gun fire animation 2025-07-05 00:46:26 +01:00
72f1891c87 Changed nextPlayer() call to happen after new animations 2025-06-25 12:29:46 +01:00
4dc7d0dda5 Updated fire animation & re-enabled looping for better previews 2025-06-25 12:27:41 +01:00
e5b8316409 Removed TODO 2025-06-25 12:19:37 +01:00
45123c39b6 Implemented extra animations 2025-06-25 12:15:55 +01:00
e932c88cc3 Added / modified (maybe) gun animations 2025-06-25 12:12:29 +01:00
5a62ca10d0 Moved away from deprecated gameUtils.RoundTable() 2025-06-25 08:01:50 +01:00
ccf08724ab Switched from importing randint to importing random 2025-06-25 08:00:32 +01:00
2deb001322 Removed comments
Muzzle flash will be done in animation,
BG music was done in commit a6a64cdf69
2025-06-24 14:46:44 +01:00
c155e11d87 Added motivational comment 2025-06-24 14:45:16 +01:00
0a2305f4cc Added basic popup code 2025-06-24 14:36:57 +01:00
2e59e718e6 Added timeout ID check 2025-06-24 10:16:13 +01:00
647d230fe0 Removed important line
FOR I CAN SEE THE FUTURE, THAT BASTARD WILL PUSH AN UPDATE THAT REMOVES THE NEED FOR THIS (I've lost it, team)
2025-06-24 10:02:44 +01:00
f258cf8982 Updated TODO because I forgot how Russian Roulette works 2025-06-24 05:54:46 +00:00
39045c3882 Oh my god I'm stupid, fixed game not launching 2025-06-23 20:19:32 +01:00
a6a64cdf69 Added background music, background music is currently randomly selected between 2 audio files on startup 2025-06-23 20:16:43 +01:00
7b0338c092 Added more example turn code 2025-06-23 14:45:56 +01:00
7628c59b36 Added TODO 2025-06-23 14:45:43 +01:00
c41f863205 Started to implement turn based system from GameUtils 2025-06-23 12:31:05 +01:00
d0284cc578 You'll never guess 2025-06-22 20:02:50 +01:00
26b0363764 Updated TODO, again 2025-06-22 20:00:25 +01:00
e2ed74b92a Updated delay 2025-06-22 19:58:43 +01:00
6023b9a2b5 Updated TODO 2025-06-22 19:57:45 +01:00
655edc25ee Merge branch 'main' of https://git.personal.imadumbass.dog/Brosef/RussianRoulette 2025-06-22 18:37:30 +01:00
5be3d93e52 Added gun cyclinder stop sfx 2025-06-22 18:37:27 +01:00
90388fc661 Added / updated TODO 2025-06-22 18:36:22 +01:00
c0727b2f02 Added random delay to the firing 2025-06-22 18:26:41 +01:00
decb36295d Removed redundant variables 2025-06-22 00:00:05 +01:00
22c6903783 Updated to use v1.0.0 of GameUtils 2025-06-21 23:32:09 +01:00
d38eadd6c3 Removed redundant __main__.py 2025-06-21 23:05:06 +01:00
894ac59038 Unlocked to the gun from the framerate. I told you lot to do this from the beginning. Fuck every last one of you. 2025-06-20 19:27:42 +01:00
4abb2353e1 Moved assets to ./assets/ 2025-06-20 18:21:23 +01:00
15 changed files with 88 additions and 109 deletions

View File

@ -1,58 +0,0 @@
# Import the game code
import __init__
import argparse
import tomllib
import pathlib
import pygame
import os
# Store the current working directory
# This is used to revert the cd change
originalCWD = os.getcwd()
# Get the path of the game
basePath = pathlib.Path(__file__).parent.resolve()
# Set the current working directory
# to the base path of the game
os.chdir(basePath)
# Load the game.toml data
with open('game.toml', 'r') as f:
gameData = tomllib.loads(f.read())
# Parse command line arguments
parser = argparse.ArgumentParser(prog=gameData['name'])
parser.add_argument('-sw', '--width', type=int, default=1280)
parser.add_argument('-sh', '--height', type=int, default=720)
parser.add_argument('-f', '--fullscreen', action='store_true')
args = parser.parse_args()
# Initialise screen
flags = 0
if args.fullscreen: flags |= pygame.FULLSCREEN
screen = pygame.display.set_mode((args.width, args.height), flags)
pygame.display.set_caption(gameData['name'])
# Initialise game
game = __init__.Game(screen, screen.size)
# Set to False when the game should exit
run = True
while run:
# Event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
game.onEvent(event)
# Draw loop
game.draw()
# Clean up
os.chdir(originalCWD)
game.close()
pygame.quit()

BIN
assets/gun-base.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

BIN
assets/gun-blank.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

BIN
assets/gun-fire.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

BIN
assets/gun-spin.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB

View File

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

BIN
assets/surrounded.ogg Normal file

Binary file not shown.

BIN
assets/twiceoritsluck.ogg Normal file

Binary file not shown.

139
game.py
View File

@ -1,10 +1,17 @@
import logging import logging
import pygame import pygame
from random import randint import random
import gameUtils import gameUtils
import NoPELib
#Oh god here we go. I'm gonna screw up this entire thing #Oh god here we go. I'm gonna screw up this entire thing
def transform(value, minA, maxA, minB, maxB):
"""
Translates `value` from `minA`-`maxA` to `minB`-`maxB`.
"""
return ((value - minA) / (maxA - minA)) * (maxB - minB) + minB
class Game(gameUtils.Game): class Game(gameUtils.Game):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
""" """
@ -18,56 +25,96 @@ class Game(gameUtils.Game):
# Don't remove this. It does important things. :3 # Don't remove this. It does important things. :3
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.em = NoPELib.ExpansionsManager(self.pm, includeExpansions=['ShockColar1'])
self.clock = pygame.time.Clock() # TODO: Utilise the following new sounds:
# TODO: Add a random delay between the spin and fire
# TODO: Utiles the following new sounds:
# gun-load: Should be played at the beginning of the game, # gun-load: Should be played at the beginning of the game,
# and should have an animation accompanying it. # and should have an animation accompanying it.
# see Brosef for the animation. # see Brosef for the animation.
# gun-cylinder-stop: Plays directly after the load
# animation is complete. # TODO: Add a hook to see if the current player has become inactive.
# gun-spin/blank/shot are all used in their original ways. playerName = random.choice(list(self.pm.keys()))
self.currentlyPlaying = self.pm[playerName]
#Sounds for the gun :3 #Sounds for the gun :3
self.playSound = pygame.mixer.Sound.play self.playSound = pygame.mixer.Sound.play
self.gunBlank = pygame.mixer.Sound("sfx/gun-blank.mp3") self.gunBlank = pygame.mixer.Sound("./assets/gun-blank.mp3")
self.gunShot = pygame.mixer.Sound("sfx/gun-shot.mp3") self.gunShot = pygame.mixer.Sound("./assets/gun-shot.mp3")
self.gunSpin = pygame.mixer.Sound("sfx/gun-spin.mp3") self.gunSpin = pygame.mixer.Sound("./assets/gun-spin.mp3")
self.gunLoad = pygame.mixer.Sound("sfx/gun-load.mp3") self.gunLoad = pygame.mixer.Sound("./assets/gun-load.mp3")
self.gunCyclinder = pygame.mixer.Sound("sfx/gun-cylinder-stop.mp3") self.gunCyclinderStop = pygame.mixer.Sound("./assets/gun-cylinder-stop.mp3")
self.gun = pygame.image.load_animation("gun.webp") #Background Music commands
self.gunFlash = pygame.image.load("images/muzzleflash.png") self.unloadMusic = pygame.mixer.music.unload
self.stopMusic = pygame.mixer.music.stop
self.playMusic = pygame.mixer.music.play
#self.gun = pygame.load_animation('./assets/gun-spin.webp')
self.gunFlash = pygame.image.load("./assets/muzzleflash.png")
self.gun = self.createAnimObj('gun', './assets/gun-base.png')
self.gun.addAnimation(gameUtils.AnimationHandler('spin', './assets/gun-spin.webp', 60))
self.gun.addAnimation(gameUtils.AnimationHandler('blank', './assets/gun-blank.webp', 60))
self.gun.addAnimation(gameUtils.AnimationHandler('fire', './assets/gun-fire.webp', 60))
self.shockScale = 0 #controls shock level sent to PDO (on a scale of 0 to 1) self.shockScale = 0 #controls shock level sent to PDO (on a scale of 0 to 1)
#gun variables
self.startSpin = False
self.spinInc = 0
#render variables #render variables
self.gunw=self.gun[0][0].size[0] #calculates width of gun anim self.gunw=self.gun.size[0] #calculates width of gun anim
self.gunh=self.gun[0][0].size[1] #calculates height of gun anim self.gunh=self.gun.size[1] #calculates height of gun anim
#NOTE: Brosef, istg you better not make the gun webm #NOTE: Brosef, istg you better not make the gun webm
# change sizes mid file, or so help me # change sizes mid file, or so help me
#
# :3
# - Brosef
self.screenMidx = self.size[0]/2 #calculates horizontal midpoint of screen self.screenMidx = self.size[0]/2 #calculates horizontal midpoint of screen
self.screenMidy = self.size[1]/2 #calculates verticle midpoint of screen self.screenMidy = self.size[1]/2 #calculates verticle midpoint of screen
self.gunScale = min(self.size[1]/self.gunh,self.size[0]/self.gunw) #calculates how to scale the gun so that it stays on the screen self.gunScale = min(self.size[1]/self.gunh,self.size[0]/self.gunw) #calculates how to scale the gun so that it stays on the screen
self.gunMidx = self.screenMidx-(self.gunw*self.gunScale/2) #gun midpoint on the x axis self.font = pygame.font.SysFont('', 64)
self.gunMidy = self.screenMidy-(self.gunh*self.gunScale/2) #gun midpoint on the y axis
#Selects random music to play at the start of the game, might change because I just threw this together.
#I feel horrible writing this code this feels super unoptimised :c
# Bro I'm gonna be honest, there's not much I'd change about that, you're good.
# The only thing I can think if just moving `set_volume()` to after both if statements.
self.musicNumber = random.randint(1,2)
if self.musicNumber == 1:
pygame.mixer.music.load("./assets/surrounded.ogg")
self.playMusic(-1)
pygame.mixer.music.set_volume(0.5)
if self.musicNumber == 2:
pygame.mixer.music.load("./assets/twiceoritsluck.ogg")
self.playMusic(-1)
pygame.mixer.music.set_volume(0.5)
def nextPlayer(self):
playerIndex = list(self.pm.keys()).index(self.currentlyPlaying.name)
playerIndex += 1
if playerIndex >= len(self.pm):
playerIndex = 0
playerName = list(self.pm.keys())[playerIndex]
self.currentlyPlaying = self.pm[playerName]
self.popup('Next player', f'Pass shocker to {self.currentlyPlaying.name},\nthen press R-CTRL+ENTER to continue.')
def fire(self):#LETS GO GAMBLING def fire(self):#LETS GO GAMBLING
if randint(1,6) == 6: if random.randint(1,6) == 6:
self.playSound(self.gunShot) self.playSound(self.gunShot)
self.gun.playAnim('fire')
expansionIDs = self.em.lookupPlayer(self.currentlyPlaying.name)
shocker = self.em[expansionIDs[0]]
iMin, iMax = self.currentlyPlaying.expansions['ShockCollar1']['shcokRange']
v = round(transform(self.shockScale, 0, 1, iMin, iMax))
print(f'Shocking {self.currentlyPlaying.name} with intensity {v}')
shocker.step((False, 0.5, v))
print(f'{self.currentlyPlaying.name} is fucking dead.')
return 0.04 return 0.04
#remember to add shock #remember to add shock
else: else:
self.playSound(self.gunBlank) self.playSound(self.gunBlank)
self.gun.playAnim('blank')
return 0 return 0
def onEvent(self, event): def onEvent(self, event):
@ -85,42 +132,32 @@ class Game(gameUtils.Game):
self.playSound(self.gunShot) self.playSound(self.gunShot)
elif event.key == pygame.K_3: elif event.key == pygame.K_3:
self.playSound(self.gunSpin) self.playSound(self.gunSpin)
elif event.key == pygame.K_SPACE: elif event.key == pygame.K_SPACE and not self.awaitingTimeout("FireDelay"):
self.startSpin = True self.gun.playAnim('spin')
elif event.type == gameUtils.AnimStart:
if event.objectID == self.gun.objectID and event.animationID == 'spin':
self.playSound(self.gunSpin)
elif event.type == gameUtils.AnimFinish:
if event.objectID == self.gun.objectID and event.animationID == 'spin':
self.timeout("FireDelay",random.randint(750,2000)/1000)
self.playSound(self.gunCyclinderStop)
elif event.objectID == self.gun.objectID and event.animationID in ['blank', 'fire']:
self.nextPlayer()
elif event.type == gameUtils.Timeout and event.timeoutID == 'FireDelay':
self.shockScale += self.fire() #check if the user gets shot
self.shockScale = min(self.shockScale, 1) #keeps shockScale in bounds
def update(self): def update(self):
""" """
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.
""" """
#gun code WOO
if self.startSpin == True:#check if space was pressed or if the gun is already spinning
if self.spinInc == 0:
self.playSound(self.gunSpin)
self.spinInc += 1 #next gun frame
if self.spinInc == len(self.gun): #if we've reached the end
self.spinInc = 0 #reset frame count
self.startSpin = False #what did i say bitch? stop spinning
self.shockScale += self.fire() #check if the user gets shot
self.shockScale = min(self.shockScale, 1) #keeps shockScale in bounds
#screen code #screen code
self.surf.fill("black") self.surf.fill("black")
self.surf.blit(pygame.transform.scale_by(self.gun[self.spinInc][0],self.gunScale),(self.gunMidx,self.gunMidy))#draw the gun self.surf.blit(gameUtils.centre(pygame.transform.scale_by(self.gun.getFrame(), self.gunScale), self.size))
#screen.blit(pygame.transform.scale_by(MainSurface,1),(0,yOffset))#renders the main surface to the screen, while also scaling it for the required display resolution self.surf.blit(self.font.render(f'Current player: {self.currentlyPlaying.name}', True, (255, 255, 255)), (0, 0))
# TODO:
# I've removed the whole "main surface" thing for now,
# because I'm not sure how we're going to deal with it
# from now on right now. I'll fix this later when it's
# a bit clearer on how NoPE-Lib will draw the players
# and how the base game should draw that.
# - Brosef
pygame.display.flip()
self.clock.tick(60)
def close(self): def close(self):
""" """

BIN
gun.webp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 MiB