Compare commits

..

45 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
09ae4c8d7e Renamed __init__.py to game.py 2025-06-20 17:34:58 +01:00
108f99af5b Updated to follow the new new base game 2025-06-20 17:34:35 +01:00
e78b07dcb9 Made gun scale and center on vertical axis now, made a variable gun width and height once near start so we don't need to keep retyping the same 5 mile long bullshit 2025-06-17 23:54:09 +01:00
5fa732b4cf once again I have attained peak efficiency 2025-06-17 23:33:27 +01:00
8986a46ce3 Removed spinning variable and any checks for it as they were actually completely fucking useless 2025-06-17 23:31:44 +01:00
cc5f12ce63 Merge branch 'main' of https://git.personal.imadumbass.dog/Brosef/RussianRoulette 2025-06-17 19:00:17 +01:00
2dcbe5e201 Slightly optimised code (maybe idk) 2025-06-17 19:00:15 +01:00
efc0d2fd0c Merge branch 'main' of https://git.personal.imadumbass.dog/Brosef/RussianRoulette 2025-06-17 18:46:13 +01:00
67c6c5158b Merge branch 'main' of https://git.personal.imadumbass.dog/Brosef/RussianRoulette 2025-06-17 17:40:20 +01:00
6b8ceb885f Stopped tracking .vscode directory 2025-06-17 17:39:16 +01:00
8a2cbf6529 Fixed some dumbass typo that stopped code from working 2025-06-16 21:18:03 +01:00
18 changed files with 170 additions and 186 deletions

4
.gitignore vendored
View File

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

View File

@ -1,127 +0,0 @@
import logging
import pygame
from random import randint
#import NoPELib
#import PDOLib
#Oh god here we go. I'm gonna screw up this entire thing
class Game:
def __init__(self, surface, size):
"""
Ran when the game starts.
Args:
surface (pygame.Surface): The surface you draw to.
size (list[int, int]): The size of the surface.
"""
pygame.init()
self.surface = surface
self.size = size
self.clock = pygame.time.Clock()
# 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,
# and should have an animation accompanying it.
# see Brosef for the animation.
# gun-cylinder-stop: Plays directly after the load
# animation is complete.
# gun-spin/blank/shot are all used in their original ways.
#Sounds for the gun :3
self.playSound = pygame.mixer.Sound.play
self.gunBlank = pygame.mixer.Sound("sfx/gun-blank.mp3")
self.gunShot = pygame.mixer.Sound("sfx/gun-shot.mp3")
self.gunSpin = pygame.mixer.Sound("sfx/gun-spin.mp3")
self.gunLoad = pygame.mixer.Sound("sfx/gun-load.mp3")
self.gunCyclinder = pygame.mixer.Sound("sfx/gun-cylinder-stop")
self.gun = pygame.image.load_animation("gun.webp")
self.gunFlash = pygame.image.load("images/muzzleflash.png")
self.shockScale = 0 #controls shock level sent to PDO (on a scale of 0 to 1)
#gun variables
self.startSpin = False
self.spinning = False
self.spinInc = 0
#render variables
self.screenMid = self.size[0]/2
self.gunScale = self.size[1]/1080
self.gunMid = self.screenMid-(self.gun[0][0].size[0]*self.gunScale/2)
# TODO
# Make the gun scale based on width of screen as well as height
def fire(self):#LETS GO GAMBLING
if randint(1,6) == 6:
self.playSound(self.gunShot)
return 0.04
#remember to add shock
else:
self.playSound(self.gunBlank)
return 0
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_1:
self.playSound(self.gunBlank)
elif event.key == pygame.K_2:
self.playSound(self.gunShot)
elif event.key == pygame.K_3:
self.playSound(self.gunSpin)
elif event.key == pygame.K_SPACE:
self.startSpin = True
def draw(self):
"""
Ran once per frame, put your drawing code in here
"""
#gun code WOO
if self.startSpin == True or self.spinning == True:#check if space was pressed or if the gun is already spinning
self.spinning = True #keep the gun 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.spinning = False #stop spinning
self.startSpin = False #what did i say bitch? stop spinning
self.shockScale += self.fire() #check if the user gets shot
if self.shockScale > 1: self.shockScale=1 #keeps shockScale in bounds
#screen code
self.surface.fill("black")
self.surface.blit(pygame.transform.scale_by(self.gun[self.spinInc][0],self.gunScale),(self.gunMid,0))#draw the gun
#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
# 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
# TODO:
# Actually scale the gun with self.size, and centre it
pygame.display.flip()
self.clock.tick(60)
def close(self):
"""
Ran when the game closes
"""
pass

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.

166
game.py Normal file
View File

@ -0,0 +1,166 @@
import logging
import pygame
import random
import gameUtils
import NoPELib
#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):
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.em = NoPELib.ExpansionsManager(self.pm, includeExpansions=['ShockColar1'])
# TODO: Utilise the following new sounds:
# gun-load: Should be played at the beginning of the game,
# and should have an animation accompanying it.
# see Brosef for the animation.
# TODO: Add a hook to see if the current player has become inactive.
playerName = random.choice(list(self.pm.keys()))
self.currentlyPlaying = self.pm[playerName]
#Sounds for the gun :3
self.playSound = pygame.mixer.Sound.play
self.gunBlank = pygame.mixer.Sound("./assets/gun-blank.mp3")
self.gunShot = pygame.mixer.Sound("./assets/gun-shot.mp3")
self.gunSpin = pygame.mixer.Sound("./assets/gun-spin.mp3")
self.gunLoad = pygame.mixer.Sound("./assets/gun-load.mp3")
self.gunCyclinderStop = pygame.mixer.Sound("./assets/gun-cylinder-stop.mp3")
#Background Music commands
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)
#render variables
self.gunw=self.gun.size[0] #calculates width of gun anim
self.gunh=self.gun.size[1] #calculates height of gun anim
#NOTE: Brosef, istg you better not make the gun webm
# change sizes mid file, or so help me
#
# :3
# - Brosef
self.screenMidx = self.size[0]/2 #calculates horizontal 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.font = pygame.font.SysFont('', 64)
#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
if random.randint(1,6) == 6:
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
#remember to add shock
else:
self.playSound(self.gunBlank)
self.gun.playAnim('blank')
return 0
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_1:
self.playSound(self.gunBlank)
elif event.key == pygame.K_2:
self.playSound(self.gunShot)
elif event.key == pygame.K_3:
self.playSound(self.gunSpin)
elif event.key == pygame.K_SPACE and not self.awaitingTimeout("FireDelay"):
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):
"""
Ran once per frame, put your drawing code and any
game logic that should be ran once per frame in here.
"""
#screen code
self.surf.fill("black")
self.surf.blit(gameUtils.centre(pygame.transform.scale_by(self.gun.getFrame(), self.gunScale), self.size))
self.surf.blit(self.font.render(f'Current player: {self.currentlyPlaying.name}', True, (255, 255, 255)), (0, 0))
def close(self):
"""
Ran when the game closes
"""
pass

BIN
gun.webp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 MiB

View File

@ -1,3 +1,4 @@
../NoPELib/ ../NoPELib/
../PDOLib/ ../PDOLib/
../GameUtils/
pygame-ce pygame-ce