├── requirements.txt ├── audio └── track.mp3 ├── graphics ├── 0 │ ├── bg.png │ ├── gridline.png │ ├── gridline2.png │ ├── gridline3.png │ ├── gridline4.png │ └── symbols │ │ ├── 0_floppy.png │ │ ├── 0_seven.png │ │ ├── 0_diamond.png │ │ ├── 0_hourglass.png │ │ └── 0_telephone.png └── font │ └── PLACE_FONT_HERE ├── player.py ├── wins.py ├── settings.py ├── main.py ├── ui.py ├── README.md ├── .gitignore ├── reel.py └── machine.py /requirements.txt: -------------------------------------------------------------------------------- 1 | pygame>=2.1.2 -------------------------------------------------------------------------------- /audio/track.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notaSWE/pygameslots/HEAD/audio/track.mp3 -------------------------------------------------------------------------------- /graphics/0/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notaSWE/pygameslots/HEAD/graphics/0/bg.png -------------------------------------------------------------------------------- /graphics/0/gridline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notaSWE/pygameslots/HEAD/graphics/0/gridline.png -------------------------------------------------------------------------------- /graphics/0/gridline2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notaSWE/pygameslots/HEAD/graphics/0/gridline2.png -------------------------------------------------------------------------------- /graphics/0/gridline3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notaSWE/pygameslots/HEAD/graphics/0/gridline3.png -------------------------------------------------------------------------------- /graphics/0/gridline4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notaSWE/pygameslots/HEAD/graphics/0/gridline4.png -------------------------------------------------------------------------------- /graphics/font/PLACE_FONT_HERE: -------------------------------------------------------------------------------- 1 | # I downloaded the kidspace.ttf font from https://dl.dafont.com/dl/?f=kidspace -------------------------------------------------------------------------------- /graphics/0/symbols/0_floppy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notaSWE/pygameslots/HEAD/graphics/0/symbols/0_floppy.png -------------------------------------------------------------------------------- /graphics/0/symbols/0_seven.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notaSWE/pygameslots/HEAD/graphics/0/symbols/0_seven.png -------------------------------------------------------------------------------- /graphics/0/symbols/0_diamond.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notaSWE/pygameslots/HEAD/graphics/0/symbols/0_diamond.png -------------------------------------------------------------------------------- /graphics/0/symbols/0_hourglass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notaSWE/pygameslots/HEAD/graphics/0/symbols/0_hourglass.png -------------------------------------------------------------------------------- /graphics/0/symbols/0_telephone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notaSWE/pygameslots/HEAD/graphics/0/symbols/0_telephone.png -------------------------------------------------------------------------------- /player.py: -------------------------------------------------------------------------------- 1 | from settings import * 2 | 3 | class Player(): 4 | def __init__(self): 5 | self.balance = 1000.00 6 | self.bet_size = 10.00 7 | self.last_payout = 0.00 8 | self.total_won = 0.00 9 | self.total_wager = 0.00 10 | 11 | def get_data(self): 12 | player_data = {} 13 | player_data['balance'] = "{:.2f}".format(self.balance) 14 | player_data['bet_size'] = "{:.2f}".format(self.bet_size) 15 | player_data['last_payout'] = "{:.2f}".format(self.last_payout) if self.last_payout else "N/A" 16 | player_data['total_won'] = "{:.2f}".format(self.total_won) 17 | player_data['total_wager'] = "{:.2f}".format(self.total_wager) 18 | return player_data 19 | 20 | def place_bet(self): 21 | bet = self.bet_size 22 | self.balance -= bet 23 | self.total_wager += bet -------------------------------------------------------------------------------- /wins.py: -------------------------------------------------------------------------------- 1 | # Helper functions to detect wins 2 | 3 | def flip_horizontal(result): 4 | # Flip results horizontally to keep them in a more readable list 5 | horizontal_values = [] 6 | for value in result.values(): 7 | horizontal_values.append(value) 8 | # 'Rotate' 90 degrees to get text representation of spin in order 9 | rows, cols = len(horizontal_values), len(horizontal_values[0]) 10 | hvals2 = [[""] * rows for _ in range(cols)] 11 | for x in range(rows): 12 | for y in range(cols): 13 | hvals2[y][rows - x - 1] = horizontal_values[x][y] 14 | hvals3 = [item[::-1] for item in hvals2] 15 | return hvals3 16 | 17 | def longest_seq(hit): 18 | subSeqLength, longest = 1, 1 19 | start, end = 0, 0 20 | for i in range(len(hit) - 1): 21 | # Check to see if indices in hit parameter are sequential 22 | if hit[i] == hit[i + 1] - 1: 23 | subSeqLength += 1 24 | if subSeqLength > longest: 25 | longest = subSeqLength 26 | start = i + 2 - subSeqLength 27 | end = i + 2 28 | else: 29 | subSeqLength = 1 30 | return hit[start:end] -------------------------------------------------------------------------------- /settings.py: -------------------------------------------------------------------------------- 1 | # Display settings 2 | DEFAULT_IMAGE_SIZE = (300, 300) 3 | FPS = 120 4 | HEIGHT = 1000 5 | WIDTH = 1600 6 | START_X, START_Y = 0, -300 7 | X_OFFSET, Y_OFFSET = 20, 0 8 | 9 | # Images 10 | BG_IMAGE_PATH = 'graphics/0/bg.png' 11 | GRID_IMAGE_PATH = 'graphics/0/gridline.png' 12 | GAME_INDICES = [1, 2, 3] # 0 and 4 are outside of play area 13 | SYM_PATH = 'graphics/0/symbols' 14 | 15 | # Text 16 | TEXT_COLOR = 'White' 17 | # You need to provide your own font in the below directory 18 | # I downloaded Kidspace font from https://www.dafont.com/kidspace.font 19 | UI_FONT = 'graphics/font/kidspace.ttf' 20 | UI_FONT_SIZE = 30 21 | WIN_FONT_SIZE = 110 22 | 23 | # 5 Symbols for demo 24 | # symbols = { 25 | # 'diamond': f"{SYM_PATH}/0_diamond.png", 26 | # 'floppy': f"{SYM_PATH}/0_floppy.png", 27 | # 'hourglass': f"{SYM_PATH}/0_hourglass.png", 28 | # 'seven': f"{SYM_PATH}/0_seven.png", 29 | # 'telephone': f"{SYM_PATH}/0_telephone.png" 30 | # } 31 | 32 | # 4 Symbols for more wins 33 | symbols = { 34 | 'diamond': f"{SYM_PATH}/0_diamond.png", 35 | 'floppy': f"{SYM_PATH}/0_floppy.png", 36 | 'hourglass': f"{SYM_PATH}/0_hourglass.png", 37 | 'hourglass2': f"{SYM_PATH}/0_hourglass.png", 38 | 'telephone': f"{SYM_PATH}/0_telephone.png" 39 | } -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from machine import Machine 2 | from settings import * 3 | import ctypes, pygame, sys 4 | 5 | # Maintain resolution regardless of Windows scaling settings 6 | ctypes.windll.user32.SetProcessDPIAware() 7 | 8 | class Game: 9 | def __init__(self): 10 | 11 | # General setup 12 | pygame.init() 13 | self.screen = pygame.display.set_mode((WIDTH, HEIGHT)) 14 | pygame.display.set_caption('Slot Machine Demo') 15 | self.clock = pygame.time.Clock() 16 | self.bg_image = pygame.image.load(BG_IMAGE_PATH).convert_alpha() 17 | self.grid_image = pygame.image.load(GRID_IMAGE_PATH).convert_alpha() 18 | self.machine = Machine() 19 | self.delta_time = 0 20 | 21 | # Sound 22 | main_sound = pygame.mixer.Sound('audio/track.mp3') 23 | main_sound.play(loops = -1) 24 | 25 | def run(self): 26 | 27 | self.start_time = pygame.time.get_ticks() 28 | 29 | while True: 30 | # Handle quit operation 31 | for event in pygame.event.get(): 32 | if event.type == pygame.QUIT: 33 | pygame.quit() 34 | sys.exit() 35 | 36 | # Time variables 37 | self.delta_time = (pygame.time.get_ticks() - self.start_time) / 1000 38 | self.start_time = pygame.time.get_ticks() 39 | 40 | pygame.display.update() 41 | self.screen.blit(self.bg_image, (0, 0)) 42 | self.machine.update(self.delta_time) 43 | self.screen.blit(self.grid_image, (0, 0)) 44 | self.clock.tick(FPS) 45 | 46 | if __name__ == '__main__': 47 | game = Game() 48 | game.run() -------------------------------------------------------------------------------- /ui.py: -------------------------------------------------------------------------------- 1 | from player import Player 2 | from settings import * 3 | import pygame, random 4 | 5 | class UI: 6 | def __init__(self, player): 7 | self.player = player 8 | self.display_surface = pygame.display.get_surface() 9 | try: 10 | self.font, self.bet_font = pygame.font.Font(UI_FONT, UI_FONT_SIZE), pygame.font.Font(UI_FONT, UI_FONT_SIZE) 11 | self.win_font = pygame.font.Font(UI_FONT, WIN_FONT_SIZE) 12 | except: 13 | print("Error loading font!") 14 | print(f"Currently, the UI_FONT variable is set to {UI_FONT}") 15 | print("Does the file exist?") 16 | quit() 17 | self.win_text_angle = random.randint(-4, 4) 18 | 19 | def display_info(self): 20 | player_data = self.player.get_data() 21 | 22 | # Balance and bet size 23 | balance_surf = self.font.render("Balance: $" + player_data['balance'], True, TEXT_COLOR, None) 24 | x, y = 20, self.display_surface.get_size()[1] - 30 25 | balance_rect = balance_surf.get_rect(bottomleft = (x, y)) 26 | 27 | bet_surf = self.bet_font.render("Wager: $" + player_data['bet_size'], True, TEXT_COLOR, None) 28 | x = self.display_surface.get_size()[0] - 20 29 | bet_rect = bet_surf.get_rect(bottomright = (x, y)) 30 | 31 | # Draw player data 32 | pygame.draw.rect(self.display_surface, False, balance_rect) 33 | pygame.draw.rect(self.display_surface, False, bet_rect) 34 | self.display_surface.blit(balance_surf, balance_rect) 35 | self.display_surface.blit(bet_surf, bet_rect) 36 | 37 | # Print last win if applicable 38 | if self.player.last_payout: 39 | last_payout = player_data['last_payout'] 40 | win_surf = self.win_font.render("WIN! $" + last_payout, True, TEXT_COLOR, None) 41 | x1 = 800 42 | y1 = self.display_surface.get_size()[1] - 60 43 | win_surf = pygame.transform.rotate(win_surf, self.win_text_angle) 44 | win_rect = win_surf.get_rect(center = (x1, y1)) 45 | self.display_surface.blit(win_surf, win_rect) 46 | 47 | def update(self): 48 | pygame.draw.rect(self.display_surface, 'Black', pygame.Rect(0, 900, 1600, 100)) 49 | self.display_info() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pygame Slots 2 | #### Pygame-based slot machine with easily changeable symbols, sound effects, and music. 3 | 4 | ## Demos 5 | #### Graphics/music included in this Github repo: 6 | 7 | https://user-images.githubusercontent.com/98667270/189539691-6cc22c1d-d719-4339-9889-77163738a07d.mp4 8 | 9 | #### Licensed symbols via Adobe Stock and additional sound effects via Google search: 10 | 11 | https://user-images.githubusercontent.com/98667270/189508033-ac361229-e493-44d3-a441-e075d22c3ddb.mp4 12 | 13 | ## Features 14 | 15 | - Five reels, each with three symbols in play at any given time 16 | - 300x300 png image symbols that are easy to change via Python dictionary 17 | - Easy-to-import audio (commented out by default) 18 | - Basic win animation 19 | - Basic UI 20 | 21 | ## Tech 22 | 23 | Basically just Pygame: 24 | 25 | - [Pygame] - Python game library 26 | - Images/Music/Sound effects 27 | 28 | ## Installation 29 | 30 | Pygame and Python3 are required, as well as the [kidspace.ttf] font in graphics/font/ 31 | 32 | ```sh 33 | pip install -r requirements.txt 34 | ``` 35 | 36 | From cmd/PowerShell: 37 | 38 | ```sh 39 | python main.py 40 | ``` 41 | 42 | ## Media 43 | 44 | I have provided some basic symbols that don't look great but they work well enough. You can simply add a new directory and create a new symbol dictionary in settings.py to replace them. Same with audio files! See comments throughout for more info. 45 | 46 | ## Win Data 47 | win_data is formatted as such: 48 | `{1: ['symbol_1', [1, 2, 3]], 3: ['symbol_2', [0, 1, 2]]}` 49 | 50 | ## Future Development 51 | I will probably try to recreate this in an actual game engine at some point. Potential future work includes: 52 | - Better animations 53 | - More win scenarios 54 | - Simulations 55 | - Web version 56 | 57 | ## Thanks 58 | [Clear Code]: If you are new to Pygame, you need to watch Clear Code's videos. They are incredible! 59 | Additionally, I had some help on delta_time/animation staggering as well as the music from two of my friends - thank you! 60 | ## License 61 | 62 | [Creative Commons 0 License] 63 | 64 | [//]: # (These are reference links used in the body of this note and get stripped out when the markdown processor does its job. There is no need to format nicely because it shouldn't be seen. Thanks SO - http://stackoverflow.com/questions/4823468/store-comments-in-markdown-syntax) 65 | [Pygame]: 66 | [Creative Commons 0 License]: 67 | [Clear Code]: 68 | [kidspace.ttf]: 69 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | *.pyc 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | pip-wheel-metadata/ 25 | share/python-wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .nox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *.cover 51 | *.py,cover 52 | .hypothesis/ 53 | .pytest_cache/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | .python-version 87 | 88 | # pipenv 89 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 90 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 91 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 92 | # install all needed dependencies. 93 | #Pipfile.lock 94 | 95 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 96 | __pypackages__/ 97 | 98 | # Celery stuff 99 | celerybeat-schedule 100 | celerybeat.pid 101 | 102 | # SageMath parsed files 103 | *.sage.py 104 | 105 | # Environments 106 | .env 107 | .venv 108 | env/ 109 | venv/ 110 | ENV/ 111 | env.bak/ 112 | venv.bak/ 113 | 114 | # Spyder project settings 115 | .spyderproject 116 | .spyproject 117 | 118 | # Rope project settings 119 | .ropeproject 120 | 121 | # mkdocs documentation 122 | /site 123 | 124 | # mypy 125 | .mypy_cache/ 126 | .dmypy.json 127 | dmypy.json 128 | 129 | # Pyre type checker 130 | .pyre/ 131 | 132 | # Licensed media 133 | audio/win*.wav 134 | audio/stop.mp3 135 | audio/spin.mp3 136 | audio/spinclip.mp3 137 | graphics/font/kidspace.ttf 138 | graphics/neon/* 139 | graphics/neon 140 | graphics/test/* 141 | graphics/test 142 | 143 | # Clear Code debug file 144 | debug.py -------------------------------------------------------------------------------- /reel.py: -------------------------------------------------------------------------------- 1 | from settings import * 2 | import pygame, random 3 | 4 | class Reel: 5 | def __init__(self, pos): 6 | self.symbol_list = pygame.sprite.Group() 7 | self.shuffled_keys = list(symbols.keys()) 8 | random.shuffle(self.shuffled_keys) 9 | self.shuffled_keys = self.shuffled_keys[:5] # Only matters when there are more than 5 symbols 10 | 11 | self.reel_is_spinning = False 12 | 13 | # Sounds 14 | # self.stop_sound = pygame.mixer.Sound('audio/stop.mp3') 15 | # self.stop_sound.set_volume(0.5) 16 | 17 | for idx, item in enumerate(self.shuffled_keys): 18 | self.symbol_list.add(Symbol(symbols[item], pos, idx)) 19 | pos = list(pos) 20 | pos[1] += 300 21 | pos = tuple(pos) 22 | 23 | def animate(self, delta_time): 24 | if self.reel_is_spinning: 25 | self.delay_time -= (delta_time * 1000) 26 | self.spin_time -= (delta_time * 1000) 27 | reel_is_stopping = False 28 | 29 | if self.spin_time < 0: 30 | reel_is_stopping = True 31 | 32 | # Stagger reel spin start animation 33 | if self.delay_time <= 0: 34 | 35 | # Iterate through all 5 symbols in reel; truncate; add new random symbol on top of stack 36 | for symbol in self.symbol_list: 37 | symbol.rect.bottom += 100 38 | 39 | # Correct spacing is dependent on the above addition eventually hitting 1200 40 | if symbol.rect.top == 1200: 41 | if reel_is_stopping: 42 | self.reel_is_spinning = False 43 | # self.stop_sound.play() 44 | 45 | symbol_idx = symbol.idx 46 | symbol.kill() 47 | # Spawn random symbol in place of the above 48 | self.symbol_list.add(Symbol(symbols[random.choice(self.shuffled_keys)], ((symbol.x_val), -300), symbol_idx)) 49 | 50 | def start_spin(self, delay_time): 51 | self.delay_time = delay_time 52 | self.spin_time = 1000 + delay_time 53 | self.reel_is_spinning = True 54 | 55 | def reel_spin_result(self): 56 | # Get and return text representation of symbols in a given reel 57 | spin_symbols = [] 58 | for i in GAME_INDICES: 59 | spin_symbols.append(self.symbol_list.sprites()[i].sym_type) 60 | return spin_symbols[::-1] 61 | 62 | class Symbol(pygame.sprite.Sprite): 63 | def __init__(self, pathToFile, pos, idx): 64 | super().__init__() 65 | 66 | # Friendly name 67 | self.sym_type = pathToFile.split('/')[3].split('.')[0] 68 | 69 | self.pos = pos 70 | self.idx = idx 71 | self.image = pygame.image.load(pathToFile).convert_alpha() 72 | self.rect = self.image.get_rect(topleft = pos) 73 | self.x_val = self.rect.left 74 | 75 | # Used for win animations 76 | self.size_x = 300 77 | self.size_y = 300 78 | self.alpha = 255 79 | self.fade_out = False 80 | self.fade_in = False 81 | 82 | def update(self): 83 | # Slightly increases size of winning symbols 84 | if self.fade_in: 85 | if self.size_x < 320: 86 | self.size_x += 1 87 | self.size_y += 1 88 | self.image = pygame.transform.scale(self.image, (self.size_x, self.size_y)) 89 | 90 | # Fades out non-winning symbols 91 | elif not self.fade_in and self.fade_out: 92 | if self.alpha > 115: 93 | self.alpha -= 7 94 | self.image.set_alpha(self.alpha) -------------------------------------------------------------------------------- /machine.py: -------------------------------------------------------------------------------- 1 | from player import Player 2 | from reel import * 3 | from settings import * 4 | from ui import UI 5 | from wins import * 6 | import pygame 7 | 8 | class Machine: 9 | def __init__(self): 10 | self.display_surface = pygame.display.get_surface() 11 | self.machine_balance = 10000.00 12 | self.reel_index = 0 13 | self.reel_list = {} 14 | self.can_toggle = True 15 | self.spinning = False 16 | self.can_animate = False 17 | self.win_animation_ongoing = False 18 | 19 | # Results 20 | self.prev_result = {0: None, 1: None, 2: None, 3: None, 4: None} 21 | self.spin_result = {0: None, 1: None, 2: None, 3: None, 4: None} 22 | 23 | self.spawn_reels() 24 | self.currPlayer = Player() 25 | self.ui = UI(self.currPlayer) 26 | 27 | # Import sounds 28 | # self.spin_sound = pygame.mixer.Sound('audio/spinclip.mp3') 29 | # self.spin_sound.set_volume(0.15) 30 | # self.win_three = pygame.mixer.Sound('audio/winthree.wav') 31 | # self.win_three.set_volume(0.6) 32 | # self.win_four = pygame.mixer.Sound('audio/winfour.wav') 33 | # self.win_four.set_volume(0.7) 34 | # self.win_five = pygame.mixer.Sound('audio/winfive.wav') 35 | # self.win_five.set_volume(0.8) 36 | 37 | def cooldowns(self): 38 | # Only lets player spin if all reels are NOT spinning 39 | for reel in self.reel_list: 40 | if self.reel_list[reel].reel_is_spinning: 41 | self.can_toggle = False 42 | self.spinning = True 43 | 44 | if not self.can_toggle and [self.reel_list[reel].reel_is_spinning for reel in self.reel_list].count(False) == 5: 45 | self.can_toggle = True 46 | self.spin_result = self.get_result() 47 | 48 | if self.check_wins(self.spin_result): 49 | self.win_data = self.check_wins(self.spin_result) 50 | # Play the win sound 51 | # self.play_win_sound(self.win_data) 52 | self.pay_player(self.win_data, self.currPlayer) 53 | self.win_animation_ongoing = True 54 | self.ui.win_text_angle = random.randint(-4, 4) 55 | 56 | def input(self): 57 | keys = pygame.key.get_pressed() 58 | 59 | # Checks for space key, ability to toggle spin, and balance to cover bet size 60 | if keys[pygame.K_SPACE] and self.can_toggle and self.currPlayer.balance >= self.currPlayer.bet_size: 61 | self.toggle_spinning() 62 | self.spin_time = pygame.time.get_ticks() 63 | self.currPlayer.place_bet() 64 | self.machine_balance += self.currPlayer.bet_size 65 | self.currPlayer.last_payout = None 66 | 67 | def draw_reels(self, delta_time): 68 | for reel in self.reel_list: 69 | self.reel_list[reel].animate(delta_time) 70 | 71 | def spawn_reels(self): 72 | if not self.reel_list: 73 | x_topleft, y_topleft = 10, -300 74 | while self.reel_index < 5: 75 | if self.reel_index > 0: 76 | x_topleft, y_topleft = x_topleft + (300 + X_OFFSET), y_topleft 77 | 78 | self.reel_list[self.reel_index] = Reel((x_topleft, y_topleft)) # Need to create reel class 79 | self.reel_index += 1 80 | 81 | def toggle_spinning(self): 82 | if self.can_toggle: 83 | self.spin_time = pygame.time.get_ticks() 84 | self.spinning = not self.spinning 85 | self.can_toggle = False 86 | 87 | for reel in self.reel_list: 88 | self.reel_list[reel].start_spin(int(reel) * 200) 89 | # self.spin_sound.play() 90 | self.win_animation_ongoing = False 91 | 92 | def get_result(self): 93 | for reel in self.reel_list: 94 | self.spin_result[reel] = self.reel_list[reel].reel_spin_result() 95 | return self.spin_result 96 | 97 | def check_wins(self, result): 98 | hits = {} 99 | horizontal = flip_horizontal(result) 100 | for row in horizontal: 101 | for sym in row: 102 | if row.count(sym) > 2: # Potential win 103 | possible_win = [idx for idx, val in enumerate(row) if sym == val] 104 | 105 | # Check possible_win for a subsequence longer than 2 and add to hits 106 | if len(longest_seq(possible_win)) > 2: 107 | hits[horizontal.index(row) + 1] = [sym, longest_seq(possible_win)] 108 | if hits: 109 | self.can_animate = True 110 | return hits 111 | 112 | def pay_player(self, win_data, curr_player): 113 | multiplier = 0 114 | spin_payout = 0 115 | for v in win_data.values(): 116 | multiplier += len(v[1]) 117 | spin_payout = (multiplier * curr_player.bet_size) 118 | curr_player.balance += spin_payout 119 | self.machine_balance -= spin_payout 120 | curr_player.last_payout = spin_payout 121 | curr_player.total_won += spin_payout 122 | 123 | # You need to provide sounds and load them in the Machine init function for this to work! 124 | def play_win_sound(self, win_data): 125 | sum = 0 126 | for item in win_data.values(): 127 | sum += len(item[1]) 128 | if sum == 3: self.win_three.play() 129 | elif sum == 4: self.win_four.play() 130 | elif sum > 4: self.win_five.play() 131 | 132 | def win_animation(self): 133 | if self.win_animation_ongoing and self.win_data: 134 | for k, v in list(self.win_data.items()): 135 | if k == 1: 136 | animationRow = 3 137 | elif k == 3: 138 | animationRow = 1 139 | else: 140 | animationRow = 2 141 | animationCols = v[1] 142 | for reel in self.reel_list: 143 | if reel in animationCols and self.can_animate: 144 | self.reel_list[reel].symbol_list.sprites()[animationRow].fade_in = True 145 | for symbol in self.reel_list[reel].symbol_list: 146 | if not symbol.fade_in: 147 | symbol.fade_out = True 148 | 149 | def update(self, delta_time): 150 | self.cooldowns() 151 | self.input() 152 | self.draw_reels(delta_time) 153 | for reel in self.reel_list: 154 | self.reel_list[reel].symbol_list.draw(self.display_surface) 155 | self.reel_list[reel].symbol_list.update() 156 | self.ui.update() 157 | self.win_animation() 158 | 159 | # Balance/payout debugger 160 | # debug_player_data = self.currPlayer.get_data() 161 | # machine_balance = "{:.2f}".format(self.machine_balance) 162 | # if self.currPlayer.last_payout: 163 | # last_payout = "{:.2f}".format(self.currPlayer.last_payout) 164 | # else: 165 | # last_payout = "N/A" 166 | # debug(f"Player balance: {debug_player_data['balance']} | Machine balance: {machine_balance} | Last payout: {last_payout}") --------------------------------------------------------------------------------