mirror of
https://github.com/csd4ni3l/game-of-life.git
synced 2026-01-01 04:23:42 +01:00
Add settings, credits, sound, add background color
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -179,3 +179,4 @@ test*.py
|
|||||||
.zed/
|
.zed/
|
||||||
logs/
|
logs/
|
||||||
logs
|
logs
|
||||||
|
settings.json
|
||||||
|
|||||||
11
CREDITS
Normal file
11
CREDITS
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Thanks to Pixabay for the sound effects and the music!
|
||||||
|
|
||||||
|
Huge Thanks to Python for being the programming language used in this game.
|
||||||
|
https://www.python.org/
|
||||||
|
|
||||||
|
Huge thanks to Arcade and Pyglet for being the graphical engines used in this game.
|
||||||
|
https://arcade.academy/
|
||||||
|
https://pyglet.readthedocs.io/en/latest/
|
||||||
|
|
||||||
|
Thanks to the following other libraries used in this game:
|
||||||
|
pypresence - https://github.com/qwertyquerty/pypresence - Used for Discord Rich Presence
|
||||||
BIN
assets/sound/create.mp3
Normal file
BIN
assets/sound/create.mp3
Normal file
Binary file not shown.
BIN
assets/sound/destroy.mp3
Normal file
BIN
assets/sound/destroy.mp3
Normal file
Binary file not shown.
BIN
assets/sound/music.mp3
Normal file
BIN
assets/sound/music.mp3
Normal file
Binary file not shown.
34
game/play.py
34
game/play.py
@@ -1,5 +1,6 @@
|
|||||||
import arcade, arcade.gui, random, math, copy
|
import arcade, arcade.gui, random, math, copy, time, json
|
||||||
from utils.constants import COLS, ROWS, CELL_SIZE, SPACING, NEIGHBORS
|
from utils.constants import COLS, ROWS, CELL_SIZE, SPACING, NEIGHBORS, button_style
|
||||||
|
from utils.preload import create_sound, destroy_sound, button_texture, button_hovered_texture
|
||||||
|
|
||||||
class Game(arcade.gui.UIView):
|
class Game(arcade.gui.UIView):
|
||||||
def __init__(self, pypresence_client=None):
|
def __init__(self, pypresence_client=None):
|
||||||
@@ -14,10 +15,14 @@ class Game(arcade.gui.UIView):
|
|||||||
|
|
||||||
self.pypresence_client = pypresence_client
|
self.pypresence_client = pypresence_client
|
||||||
self.spritelist = arcade.SpriteList()
|
self.spritelist = arcade.SpriteList()
|
||||||
|
self.last_create_sound = time.perf_counter()
|
||||||
|
|
||||||
self.start_x = self.window.width / 2 - ((COLS * (CELL_SIZE + SPACING)) / 2)
|
self.start_x = self.window.width / 2 - ((COLS * (CELL_SIZE + SPACING)) / 2)
|
||||||
self.start_y = self.window.height / 2 - ((ROWS * (CELL_SIZE + SPACING)) / 2)
|
self.start_y = self.window.height / 2 - ((ROWS * (CELL_SIZE + SPACING)) / 2)
|
||||||
|
|
||||||
|
with open("settings.json", "r") as file:
|
||||||
|
self.settings_dict = json.load(file)
|
||||||
|
|
||||||
def on_show_view(self):
|
def on_show_view(self):
|
||||||
super().on_show_view()
|
super().on_show_view()
|
||||||
self.setup_grid()
|
self.setup_grid()
|
||||||
@@ -34,8 +39,16 @@ class Game(arcade.gui.UIView):
|
|||||||
self.fps_label = arcade.gui.UILabel(text="FPS: 10", font_name="Protest Strike", font_size=16)
|
self.fps_label = arcade.gui.UILabel(text="FPS: 10", font_name="Protest Strike", font_size=16)
|
||||||
self.info_box.add(self.fps_label)
|
self.info_box.add(self.fps_label)
|
||||||
|
|
||||||
|
self.back_button = arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='<--', style=button_style, width=100, height=50)
|
||||||
|
self.back_button.on_click = lambda e: self.main_exit()
|
||||||
|
self.anchor.add(self.back_button, anchor_x="left", anchor_y="top", align_x=5, align_y=-5)
|
||||||
|
|
||||||
arcade.schedule(self.update_generation, 1 / self.generation_fps)
|
arcade.schedule(self.update_generation, 1 / self.generation_fps)
|
||||||
|
|
||||||
|
def main_exit(self):
|
||||||
|
from menus.main import Main
|
||||||
|
self.window.show_view(Main(self.pypresence_client))
|
||||||
|
|
||||||
def setup_grid(self, randomized=False):
|
def setup_grid(self, randomized=False):
|
||||||
self.spritelist.clear()
|
self.spritelist.clear()
|
||||||
|
|
||||||
@@ -72,7 +85,7 @@ class Game(arcade.gui.UIView):
|
|||||||
self.pypresence_generation_count = 0
|
self.pypresence_generation_count = 0
|
||||||
self.pypresence_client.update(state='In Game', details=f'Generation: {self.generation} Population: {self.population}', start=self.pypresence_client.start_time)
|
self.pypresence_client.update(state='In Game', details=f'Generation: {self.generation} Population: {self.population}', start=self.pypresence_client.start_time)
|
||||||
|
|
||||||
next_grid = {y: {x: cell for x, cell in row.items()} for y, row in self.cell_grid.items()}
|
next_grid = copy.deepcopy(self.cell_grid) # create a copy of the old grid so we dont modify it in-place
|
||||||
|
|
||||||
grid = self.cell_grid
|
grid = self.cell_grid
|
||||||
|
|
||||||
@@ -111,6 +124,10 @@ class Game(arcade.gui.UIView):
|
|||||||
self.running = not self.running
|
self.running = not self.running
|
||||||
elif symbol == arcade.key.C:
|
elif symbol == arcade.key.C:
|
||||||
self.population = 0
|
self.population = 0
|
||||||
|
self.generation = 0
|
||||||
|
|
||||||
|
self.population_label.text = f"Population: {self.population}"
|
||||||
|
self.generation_label.text = f"Generation: {self.generation}"
|
||||||
|
|
||||||
arcade.unschedule(self.update_generation)
|
arcade.unschedule(self.update_generation)
|
||||||
self.setup_grid()
|
self.setup_grid()
|
||||||
@@ -137,6 +154,12 @@ class Game(arcade.gui.UIView):
|
|||||||
|
|
||||||
if self.cell_grid[grid_row][grid_col] == 0:
|
if self.cell_grid[grid_row][grid_col] == 0:
|
||||||
self.population += 1
|
self.population += 1
|
||||||
|
|
||||||
|
if time.perf_counter() - self.last_create_sound >= 0.05:
|
||||||
|
self.last_create_sound = time.perf_counter()
|
||||||
|
if self.settings_dict.get("sfx", True):
|
||||||
|
create_sound.play(volume=self.settings_dict.get("sfx_volume", 50) / 100, loop=True)
|
||||||
|
|
||||||
self.sprite_grid[grid_row][grid_col].visible = True
|
self.sprite_grid[grid_row][grid_col].visible = True
|
||||||
self.cell_grid[grid_row][grid_col] = 1
|
self.cell_grid[grid_row][grid_col] = 1
|
||||||
|
|
||||||
@@ -144,8 +167,13 @@ class Game(arcade.gui.UIView):
|
|||||||
grid_col = math.ceil((self.window.mouse.data["x"] - self.start_x + (CELL_SIZE / 2)) // (CELL_SIZE + SPACING)) # type: ignore
|
grid_col = math.ceil((self.window.mouse.data["x"] - self.start_x + (CELL_SIZE / 2)) // (CELL_SIZE + SPACING)) # type: ignore
|
||||||
grid_row = math.ceil((self.window.mouse.data["y"] - self.start_y + (CELL_SIZE / 2)) // (CELL_SIZE + SPACING)) # type: ignore
|
grid_row = math.ceil((self.window.mouse.data["y"] - self.start_y + (CELL_SIZE / 2)) // (CELL_SIZE + SPACING)) # type: ignore
|
||||||
|
|
||||||
|
if grid_col < 0 or grid_row < 0 or grid_row >= ROWS or grid_col >= COLS:
|
||||||
|
return
|
||||||
|
|
||||||
if self.cell_grid[grid_row][grid_col] == 1:
|
if self.cell_grid[grid_row][grid_col] == 1:
|
||||||
self.population -= 1
|
self.population -= 1
|
||||||
|
if self.settings_dict.get("sfx", True):
|
||||||
|
destroy_sound.play(volume=self.settings_dict.get("sfx_volume", 50) / 100, loop=True)
|
||||||
self.sprite_grid[grid_row][grid_col].visible = False
|
self.sprite_grid[grid_row][grid_col].visible = False
|
||||||
self.cell_grid[grid_row][grid_col] = 0
|
self.cell_grid[grid_row][grid_col] = 0
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import arcade, arcade.gui, asyncio, pypresence, time
|
import arcade, arcade.gui, asyncio, pypresence, time, json
|
||||||
from utils.preload import button_texture, button_hovered_texture
|
from utils.preload import button_texture, button_hovered_texture, theme_sound
|
||||||
from utils.constants import button_style
|
from utils.constants import button_style
|
||||||
from utils.utils import FakePyPresence
|
from utils.utils import FakePyPresence
|
||||||
|
|
||||||
@@ -41,9 +41,18 @@ class Main(arcade.gui.UIView):
|
|||||||
def on_show_view(self):
|
def on_show_view(self):
|
||||||
super().on_show_view()
|
super().on_show_view()
|
||||||
|
|
||||||
|
self.title_label = self.box.add(arcade.gui.UILabel(text="Game Of Life", font_name="Protest Strike", font_size=48))
|
||||||
|
|
||||||
self.play_button = self.box.add(arcade.gui.UITextureButton(text="Play", texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 2, height=150, style=button_style))
|
self.play_button = self.box.add(arcade.gui.UITextureButton(text="Play", texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 2, height=150, style=button_style))
|
||||||
self.play_button.on_click = lambda event: self.play()
|
self.play_button.on_click = lambda event: self.play()
|
||||||
|
|
||||||
|
self.settings_button = self.box.add(arcade.gui.UITextureButton(text="Settings", texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 2, height=150, style=button_style))
|
||||||
|
self.settings_button.on_click = lambda event: self.settings()
|
||||||
|
|
||||||
def play(self):
|
def play(self):
|
||||||
from game.play import Game
|
from game.play import Game
|
||||||
self.window.show_view(Game(self.pypresence_client))
|
self.window.show_view(Game(self.pypresence_client))
|
||||||
|
|
||||||
|
def settings(self):
|
||||||
|
from menus.settings import Settings
|
||||||
|
self.window.show_view(Settings(self.pypresence_client))
|
||||||
|
|||||||
294
menus/settings.py
Normal file
294
menus/settings.py
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
import copy, pypresence, json, os
|
||||||
|
|
||||||
|
import arcade, arcade.gui
|
||||||
|
|
||||||
|
from utils.constants import button_style, dropdown_style, slider_style, settings
|
||||||
|
from utils.utils import FakePyPresence
|
||||||
|
from utils.preload import button_texture, button_hovered_texture, theme_sound
|
||||||
|
|
||||||
|
from arcade.gui import UIBoxLayout, UIAnchorLayout
|
||||||
|
from arcade.gui.experimental.focus import UIFocusGroup
|
||||||
|
|
||||||
|
class Settings(arcade.gui.UIView):
|
||||||
|
def __init__(self, pypresence_client):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
with open("settings.json", "r") as file:
|
||||||
|
self.settings_dict = json.load(file)
|
||||||
|
|
||||||
|
self.pypresence_client = pypresence_client
|
||||||
|
self.pypresence_client.update(state='In Settings', details='Modifying Settings', start=self.pypresence_client.start_time)
|
||||||
|
|
||||||
|
self.slider_labels = {}
|
||||||
|
self.sliders = {}
|
||||||
|
|
||||||
|
self.on_radiobuttons = {}
|
||||||
|
self.off_radiobuttons = {}
|
||||||
|
|
||||||
|
self.current_category = "Graphics"
|
||||||
|
|
||||||
|
self.modified_settings = {}
|
||||||
|
|
||||||
|
def create_layouts(self):
|
||||||
|
self.anchor = self.add_widget(UIAnchorLayout(size_hint=(1, 1)))
|
||||||
|
|
||||||
|
self.box = UIBoxLayout(space_between=50, align="center", vertical=False)
|
||||||
|
self.anchor.add(self.box, anchor_x="center", anchor_y="top", align_x=10, align_y=-75)
|
||||||
|
|
||||||
|
self.top_box = UIBoxLayout(space_between=self.window.width / 160, vertical=False)
|
||||||
|
self.anchor.add(self.top_box, anchor_x="left", anchor_y="top", align_x=10, align_y=-10)
|
||||||
|
|
||||||
|
self.key_layout = self.box.add(UIBoxLayout(space_between=20, align='left'))
|
||||||
|
self.value_layout = self.box.add(UIBoxLayout(space_between=13, align='left'))
|
||||||
|
|
||||||
|
def on_show_view(self):
|
||||||
|
super().on_show_view()
|
||||||
|
|
||||||
|
self.create_layouts()
|
||||||
|
|
||||||
|
self.ui.push_handlers(self)
|
||||||
|
|
||||||
|
self.back_button = arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='<--', style=button_style, width=100, height=50)
|
||||||
|
self.back_button.on_click = lambda e: self.main_exit()
|
||||||
|
self.top_box.add(self.back_button)
|
||||||
|
|
||||||
|
self.display_categories()
|
||||||
|
|
||||||
|
self.display_category("Graphics")
|
||||||
|
|
||||||
|
def display_categories(self):
|
||||||
|
for category in settings:
|
||||||
|
category_button = arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text=category, style=button_style, width=self.window.width / 10, height=50)
|
||||||
|
|
||||||
|
if not category == "Credits":
|
||||||
|
category_button.on_click = lambda e, category=category: self.display_category(category)
|
||||||
|
else:
|
||||||
|
category_button.on_click = lambda e: self.credits()
|
||||||
|
|
||||||
|
self.top_box.add(category_button)
|
||||||
|
|
||||||
|
def display_category(self, category):
|
||||||
|
if hasattr(self, 'apply_button'):
|
||||||
|
self.anchor.remove(self.apply_button)
|
||||||
|
del self.apply_button
|
||||||
|
|
||||||
|
if hasattr(self, 'credits_label'):
|
||||||
|
self.anchor.remove(self.credits_label)
|
||||||
|
del self.credits_label
|
||||||
|
|
||||||
|
self.current_category = category
|
||||||
|
|
||||||
|
self.key_layout.clear()
|
||||||
|
self.value_layout.clear()
|
||||||
|
|
||||||
|
for setting in settings[category]:
|
||||||
|
label = arcade.gui.UILabel(text=setting, font_name="Protest Strike", font_size=28, text_color=arcade.color.WHITE )
|
||||||
|
self.key_layout.add(label)
|
||||||
|
|
||||||
|
setting_dict = settings[category][setting]
|
||||||
|
|
||||||
|
if setting_dict['type'] == "option":
|
||||||
|
dropdown = arcade.gui.UIDropdown(options=setting_dict['options'], width=200, height=50, default=self.settings_dict.get(setting_dict["config_key"], setting_dict["options"][0]), active_style=dropdown_style, dropdown_style=dropdown_style, primary_style=dropdown_style)
|
||||||
|
dropdown.on_change = lambda _, setting=setting, dropdown=dropdown: self.update(setting, dropdown.value, "option")
|
||||||
|
self.value_layout.add(dropdown)
|
||||||
|
|
||||||
|
elif setting_dict['type'] == "bool":
|
||||||
|
button_layout = self.value_layout.add(arcade.gui.UIBoxLayout(space_between=50, vertical=False))
|
||||||
|
|
||||||
|
on_radiobutton = arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text="ON", style=button_style, width=150, height=50)
|
||||||
|
self.on_radiobuttons[setting] = on_radiobutton
|
||||||
|
on_radiobutton.on_click = lambda _, setting=setting: self.update(setting, True, "bool")
|
||||||
|
button_layout.add(on_radiobutton)
|
||||||
|
|
||||||
|
off_radiobutton = arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text="OFF", style=button_style, width=150, height=50)
|
||||||
|
self.off_radiobuttons[setting] = off_radiobutton
|
||||||
|
off_radiobutton.on_click = lambda _, setting=setting: self.update(setting, False, "bool")
|
||||||
|
button_layout.add(off_radiobutton)
|
||||||
|
|
||||||
|
if self.settings_dict.get(setting_dict["config_key"], setting_dict["default"]):
|
||||||
|
self.set_highlighted_style(on_radiobutton)
|
||||||
|
self.set_normal_style(off_radiobutton)
|
||||||
|
else:
|
||||||
|
self.set_highlighted_style(off_radiobutton)
|
||||||
|
self.set_normal_style(on_radiobutton)
|
||||||
|
|
||||||
|
elif setting_dict['type'] == "slider":
|
||||||
|
if setting == "FPS Limit":
|
||||||
|
if self.settings_dict.get(setting_dict["config_key"]) == 0:
|
||||||
|
label_text = "FPS Limit: Disabled"
|
||||||
|
else:
|
||||||
|
label_text = f"FPS Limit: {self.settings_dict.get(setting_dict["config_key"], setting_dict["default"])}"
|
||||||
|
else:
|
||||||
|
label_text = f"{setting}: {int(self.settings_dict.get(setting_dict["config_key"], setting_dict["default"]))}"
|
||||||
|
|
||||||
|
label.text = label_text
|
||||||
|
|
||||||
|
self.slider_labels[setting] = label
|
||||||
|
|
||||||
|
slider = arcade.gui.UISlider(width=400, height=50, value=self.settings_dict.get(setting_dict["config_key"], setting_dict["default"]), min_value=setting_dict['min'], max_value=setting_dict['max'], style=slider_style)
|
||||||
|
slider.on_change = lambda _, setting=setting, slider=slider: self.update(setting, slider.value, "slider")
|
||||||
|
|
||||||
|
self.sliders[setting] = slider
|
||||||
|
self.value_layout.add(slider)
|
||||||
|
|
||||||
|
self.apply_button = arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='Apply', style=button_style, width=200, height=100)
|
||||||
|
self.apply_button.on_click = lambda e: self.apply_settings()
|
||||||
|
self.anchor.add(self.apply_button, anchor_x="right", anchor_y="bottom", align_x=-10, align_y=10)
|
||||||
|
|
||||||
|
def apply_settings(self):
|
||||||
|
for config_key, value in self.modified_settings.items():
|
||||||
|
self.settings_dict[config_key] = value
|
||||||
|
|
||||||
|
if self.settings_dict['window_mode'] == "Fullscreen":
|
||||||
|
self.window.set_fullscreen(True)
|
||||||
|
else:
|
||||||
|
self.window.set_fullscreen(False)
|
||||||
|
width, height = map(int, self.settings_dict['resolution'].split('x'))
|
||||||
|
self.window.set_size(width, height)
|
||||||
|
|
||||||
|
if self.settings_dict['music']:
|
||||||
|
if not theme_sound.source._players:
|
||||||
|
theme_sound.play(volume=self.settings_dict.get("music_volume", 50) / 100, loop=True)
|
||||||
|
else:
|
||||||
|
for n, sound in enumerate(theme_sound.source._players):
|
||||||
|
sound.volume = self.settings_dict.get("music_volume", 50) / 100
|
||||||
|
else:
|
||||||
|
for n, sound in enumerate(theme_sound.source._players): # stop all theme sounds
|
||||||
|
sound.delete()
|
||||||
|
del theme_sound.source._players[n]
|
||||||
|
|
||||||
|
if self.settings_dict['vsync']:
|
||||||
|
self.window.set_vsync(True)
|
||||||
|
display_mode = self.window.display.get_default_screen().get_mode()
|
||||||
|
refresh_rate = display_mode.rate
|
||||||
|
self.window.set_update_rate(1 / refresh_rate)
|
||||||
|
self.window.set_draw_rate(1 / refresh_rate)
|
||||||
|
|
||||||
|
elif not self.settings_dict['fps_limit'] == 0:
|
||||||
|
self.window.set_vsync(False)
|
||||||
|
self.window.set_update_rate(1 / self.settings_dict['fps_limit'])
|
||||||
|
self.window.set_draw_rate(1 / self.settings_dict['fps_limit'])
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.window.set_vsync(False)
|
||||||
|
self.window.set_update_rate(1 / 99999999)
|
||||||
|
self.window.set_draw_rate(1 / 99999999)
|
||||||
|
|
||||||
|
if self.settings_dict['discord_rpc']:
|
||||||
|
if isinstance(self.pypresence_client, FakePyPresence): # the user has enabled RPC in the settings in this session.
|
||||||
|
start_time = copy.deepcopy(self.pypresence_client.start_time)
|
||||||
|
self.pypresence_client.close()
|
||||||
|
del self.pypresence_client
|
||||||
|
try:
|
||||||
|
self.pypresence_client = pypresence.Presence(1363780625928028200)
|
||||||
|
self.pypresence_client.connect()
|
||||||
|
self.pypresence_client.update(state='In Settings', details='Modifying Settings', start=start_time)
|
||||||
|
self.pypresence_client.start_time = start_time
|
||||||
|
except:
|
||||||
|
self.pypresence_client = FakePyPresence()
|
||||||
|
self.pypresence_client.start_time = start_time
|
||||||
|
else:
|
||||||
|
if not isinstance(self.pypresence_client, FakePyPresence):
|
||||||
|
start_time = copy.deepcopy(self.pypresence_client.start_time)
|
||||||
|
self.pypresence_client.update()
|
||||||
|
self.pypresence_client.close()
|
||||||
|
del self.pypresence_client
|
||||||
|
self.pypresence_client = FakePyPresence()
|
||||||
|
self.pypresence_client.start_time = start_time
|
||||||
|
|
||||||
|
self.ui_cleanup()
|
||||||
|
|
||||||
|
self.ui = arcade.gui.UIManager()
|
||||||
|
self.ui.enable()
|
||||||
|
|
||||||
|
self.create_layouts()
|
||||||
|
|
||||||
|
self.back_button = arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='<--', style=button_style, width=100, height=50)
|
||||||
|
self.back_button.on_click = lambda e: self.main_exit()
|
||||||
|
self.top_box.add(self.back_button)
|
||||||
|
|
||||||
|
self.display_categories()
|
||||||
|
|
||||||
|
self.display_category(self.current_category)
|
||||||
|
|
||||||
|
with open("settings.json", "w") as file:
|
||||||
|
file.write(json.dumps(self.settings_dict, indent=4))
|
||||||
|
|
||||||
|
def update(self, setting=None, button_state=None, setting_type="bool"):
|
||||||
|
setting_dict = settings[self.current_category][setting]
|
||||||
|
config_key = settings[self.current_category][setting]["config_key"]
|
||||||
|
|
||||||
|
if setting_type == "option":
|
||||||
|
self.modified_settings[config_key] = button_state
|
||||||
|
|
||||||
|
elif setting_type == "bool":
|
||||||
|
self.modified_settings[config_key] = button_state
|
||||||
|
|
||||||
|
if button_state:
|
||||||
|
self.set_highlighted_style(self.on_radiobuttons[setting])
|
||||||
|
self.set_normal_style(self.off_radiobuttons[setting])
|
||||||
|
else:
|
||||||
|
self.set_highlighted_style(self.off_radiobuttons[setting])
|
||||||
|
self.set_normal_style(self.on_radiobuttons[setting])
|
||||||
|
|
||||||
|
elif setting_type == "slider":
|
||||||
|
new_value = int(button_state)
|
||||||
|
|
||||||
|
self.modified_settings[config_key] = new_value
|
||||||
|
self.sliders[setting].value = new_value
|
||||||
|
|
||||||
|
if setting == "FPS Limit":
|
||||||
|
if new_value == 0:
|
||||||
|
label_text = "FPS Limit: Disabled"
|
||||||
|
else:
|
||||||
|
label_text = f"FPS Limit: {str(new_value).rjust(8)}"
|
||||||
|
else:
|
||||||
|
label_text = f"{setting}: {str(new_value).rjust(8)}"
|
||||||
|
|
||||||
|
self.slider_labels[setting].text = label_text
|
||||||
|
|
||||||
|
def credits(self):
|
||||||
|
if hasattr(self, 'apply_button'):
|
||||||
|
self.anchor.remove(self.apply_button)
|
||||||
|
del self.apply_button
|
||||||
|
|
||||||
|
if hasattr(self, 'credits_label'):
|
||||||
|
self.anchor.remove(self.credits_label)
|
||||||
|
del self.credits_label
|
||||||
|
|
||||||
|
self.key_layout.clear()
|
||||||
|
self.value_layout.clear()
|
||||||
|
|
||||||
|
with open('CREDITS', 'r') as file:
|
||||||
|
text = file.read()
|
||||||
|
|
||||||
|
if self.window.width == 3840:
|
||||||
|
font_size = 30
|
||||||
|
elif self.window.width == 2560:
|
||||||
|
font_size = 20
|
||||||
|
elif self.window.width == 1920:
|
||||||
|
font_size = 17
|
||||||
|
elif self.window.width >= 1440:
|
||||||
|
font_size = 14
|
||||||
|
else:
|
||||||
|
font_size = 12
|
||||||
|
|
||||||
|
self.credits_label = arcade.gui.UILabel(text=text, text_color=arcade.color.WHITE, font_name="Protest Strike", font_size=font_size, align="center", multiline=True)
|
||||||
|
|
||||||
|
self.key_layout.add(self.credits_label)
|
||||||
|
|
||||||
|
def set_highlighted_style(self, element):
|
||||||
|
element.texture = button_hovered_texture
|
||||||
|
element.texture_hovered = button_texture
|
||||||
|
|
||||||
|
def set_normal_style(self, element):
|
||||||
|
element.texture_hovered = button_hovered_texture
|
||||||
|
element.texture = button_texture
|
||||||
|
|
||||||
|
def main_exit(self):
|
||||||
|
from menus.main import Main
|
||||||
|
self.window.show_view(Main(pypresence_client=self.pypresence_client))
|
||||||
|
|
||||||
|
def ui_cleanup(self):
|
||||||
|
self.ui.clear()
|
||||||
|
del self.ui
|
||||||
26
run.py
26
run.py
@@ -5,10 +5,9 @@ pyglet.options.debug_gl = False
|
|||||||
import logging, datetime, os, json, sys, arcade
|
import logging, datetime, os, json, sys, arcade
|
||||||
|
|
||||||
from utils.utils import get_closest_resolution, print_debug_info, on_exception
|
from utils.utils import get_closest_resolution, print_debug_info, on_exception
|
||||||
from utils.constants import log_dir
|
from utils.constants import log_dir, menu_background_color
|
||||||
from menus.main import Main
|
from menus.main import Main
|
||||||
import utils.preload # type: ignore # needed for preload
|
from utils.preload import theme_sound # type: ignore # needed for preload
|
||||||
from arcade.experimental.controller_window import ControllerWindow
|
|
||||||
|
|
||||||
sys.excepthook = on_exception
|
sys.excepthook = on_exception
|
||||||
|
|
||||||
@@ -49,6 +48,17 @@ if os.path.exists('settings.json'):
|
|||||||
vsync = settings['vsync']
|
vsync = settings['vsync']
|
||||||
fps_limit = settings['fps_limit']
|
fps_limit = settings['fps_limit']
|
||||||
else:
|
else:
|
||||||
|
settings = {
|
||||||
|
"music": True,
|
||||||
|
"music_volume": 50,
|
||||||
|
"resolution": f"{resolution[0]}x{resolution[1]}",
|
||||||
|
"antialiasing": "4x MSAA",
|
||||||
|
"window_mode": "Windowed",
|
||||||
|
"vsync": True,
|
||||||
|
"fps_limit": 60,
|
||||||
|
"discord_rpc": True
|
||||||
|
}
|
||||||
|
|
||||||
resolution = get_closest_resolution()
|
resolution = get_closest_resolution()
|
||||||
antialiasing = 4
|
antialiasing = 4
|
||||||
fullscreen = False
|
fullscreen = False
|
||||||
@@ -56,7 +66,13 @@ else:
|
|||||||
vsync = True
|
vsync = True
|
||||||
fps_limit = 0
|
fps_limit = 0
|
||||||
|
|
||||||
window = ControllerWindow(width=resolution[0], height=resolution[1], title='ShatterStack', samples=antialiasing, antialiasing=antialiasing > 0, fullscreen=fullscreen, vsync=vsync, resizable=False, style=style)
|
with open("settings.json", "w") as file:
|
||||||
|
file.write(json.dumps(settings))
|
||||||
|
|
||||||
|
if settings.get("music", True):
|
||||||
|
theme_sound.play(volume=settings.get("music_volume", 50) / 100, loop=True)
|
||||||
|
|
||||||
|
window = arcade.Window(width=resolution[0], height=resolution[1], title='Game Of Life', samples=antialiasing, antialiasing=antialiasing > 0, fullscreen=fullscreen, vsync=vsync, resizable=False, style=style)
|
||||||
|
|
||||||
if vsync:
|
if vsync:
|
||||||
window.set_vsync(True)
|
window.set_vsync(True)
|
||||||
@@ -71,6 +87,8 @@ else:
|
|||||||
window.set_update_rate(1 / 99999999)
|
window.set_update_rate(1 / 99999999)
|
||||||
window.set_draw_rate(1 / 99999999)
|
window.set_draw_rate(1 / 99999999)
|
||||||
|
|
||||||
|
arcade.set_background_color(menu_background_color)
|
||||||
|
|
||||||
print_debug_info()
|
print_debug_info()
|
||||||
main = Main()
|
main = Main()
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import arcade.color
|
import arcade.color
|
||||||
from arcade.types import Color
|
from arcade.types import Color
|
||||||
from arcade.gui.widgets.buttons import UITextureButtonStyle
|
from arcade.gui.widgets.buttons import UITextureButtonStyle, UIFlatButtonStyle
|
||||||
|
from arcade.gui.widgets.slider import UISliderStyle
|
||||||
|
|
||||||
COLS = 80
|
COLS = 80
|
||||||
ROWS = 60
|
ROWS = 60
|
||||||
@@ -9,7 +10,34 @@ SPACING = 2
|
|||||||
NEIGHBORS = [(-1, 0), (-1, 1), (-1, -1),(0, 0), (0, 1), (0, -1), (1, 0), (1, 1), (1, -1)]
|
NEIGHBORS = [(-1, 0), (-1, 1), (-1, -1),(0, 0), (0, 1), (0, -1), (1, 0), (1, 1), (1, -1)]
|
||||||
|
|
||||||
log_dir = 'logs'
|
log_dir = 'logs'
|
||||||
menu_background_color = Color(28, 28, 28)
|
menu_background_color = arcade.color.DARK_SLATE_GRAY
|
||||||
|
|
||||||
button_style = {'normal': UITextureButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK), 'hover': UITextureButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK),
|
button_style = {'normal': UITextureButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK), 'hover': UITextureButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK),
|
||||||
'press': UITextureButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK), 'disabled': UITextureButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK)}
|
'press': UITextureButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK), 'disabled': UITextureButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK)}
|
||||||
|
dropdown_style = {'normal': UIFlatButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK, bg=Color(128, 128, 128)), 'hover': UIFlatButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK, bg=Color(49, 154, 54)),
|
||||||
|
'press': UIFlatButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK, bg=Color(128, 128, 128)), 'disabled': UIFlatButtonStyle(font_name="Protest Strike", font_color=arcade.color.BLACK, bg=Color(128, 128, 128))}
|
||||||
|
|
||||||
|
slider_default_style = UISliderStyle(bg=Color(128, 128, 128), unfilled_track=Color(128, 128, 128), filled_track=Color(49, 154, 54))
|
||||||
|
slider_hover_style = UISliderStyle(bg=Color(49, 154, 54), unfilled_track=Color(128, 128, 128), filled_track=Color(49, 154, 54))
|
||||||
|
|
||||||
|
slider_style = {'normal': slider_default_style, 'hover': slider_hover_style, 'press': slider_hover_style, 'disabled': slider_default_style}
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
"Graphics": {
|
||||||
|
"Window Mode": {"type": "option", "options": ["Windowed", "Fullscreen", "Borderless"], "config_key": "window_mode", "default": "Windowed"},
|
||||||
|
"Resolution": {"type": "option", "options": ["1366x768", "1440x900", "1600x900", "1920x1080", "2560x1440", "3840x2160"], "config_key": "resolution"},
|
||||||
|
"Anti-Aliasing": {"type": "option", "options": ["None", "2x MSAA", "4x MSAA", "8x MSAA", "16x MSAA"], "config_key": "anti_aliasing", "default": "4x MSAA"},
|
||||||
|
"VSync": {"type": "bool", "config_key": "vsync", "default": True},
|
||||||
|
"FPS Limit": {"type": "slider", "min": 0, "max": 480, "config_key": "fps_limit", "default": 60},
|
||||||
|
},
|
||||||
|
"Sound": {
|
||||||
|
"Music": {"type": "bool", "config_key": "music", "default": True},
|
||||||
|
"SFX": {"type": "bool", "config_key": "sfx", "default": True},
|
||||||
|
"Music Volume": {"type": "slider", "min": 0, "max": 100, "config_key": "music_volume", "default": 50},
|
||||||
|
"SFX Volume": {"type": "slider", "min": 0, "max": 100, "config_key": "sfx_volume", "default": 50},
|
||||||
|
},
|
||||||
|
"Miscellaneous": {
|
||||||
|
"Discord RPC": {"type": "bool", "config_key": "discord_rpc", "default": True},
|
||||||
|
},
|
||||||
|
"Credits": {}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,3 +2,7 @@ import arcade.gui, arcade
|
|||||||
|
|
||||||
button_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture("assets/graphics/button.png"))
|
button_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture("assets/graphics/button.png"))
|
||||||
button_hovered_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture("assets/graphics/button_hovered.png"))
|
button_hovered_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture("assets/graphics/button_hovered.png"))
|
||||||
|
|
||||||
|
create_sound = arcade.Sound("assets/sound/create.mp3")
|
||||||
|
destroy_sound = arcade.Sound("assets/sound/destroy.mp3")
|
||||||
|
theme_sound = arcade.Sound("assets/sound/music.mp3")
|
||||||
|
|||||||
Reference in New Issue
Block a user