mirror of
https://github.com/csd4ni3l/aim-trainer.git
synced 2025-11-05 02:57:56 +01:00
Fix credits and settings dropdowns, add high score, fps counter
This commit is contained in:
3
CREDITS
3
CREDITS
@@ -3,7 +3,8 @@ Thanks to OpenGameArt and:
|
||||
TinyWorlds for the death sound effect: https://opengameart.org/content/explosion-0
|
||||
|
||||
The gun icons used in this project are from game-icons.net.
|
||||
Licensed under the Creative Commons Attribution 3.0 International License (CC BY 3.0): https://creativecommons.org/licenses/by/3.0/
|
||||
Licensed under the Creative Commons Attribution 3.0 International License (CC BY 3.0):
|
||||
https://creativecommons.org/licenses/by/3.0/
|
||||
|
||||
Huge Thanks to Python for being the programming language used in this game.
|
||||
https://www.python.org/
|
||||
|
||||
16
game/game.py
16
game/game.py
@@ -4,7 +4,7 @@ from game.enemy import Enemy
|
||||
from utils.constants import weapons, min_enemy_y, max_enemy_y
|
||||
from ursina import *
|
||||
from ursina.shaders import lit_with_shadows_shader
|
||||
import os
|
||||
import os, json
|
||||
|
||||
enemy_file_names = os.listdir("assets/graphics/enemy")
|
||||
|
||||
@@ -12,6 +12,12 @@ class Game():
|
||||
def __init__(self, pypresence_client) -> None:
|
||||
self.pypresence_client = pypresence_client
|
||||
|
||||
if os.path.exists("data.json"):
|
||||
with open("data.json", "r") as file:
|
||||
self.high_score = json.load(file)["high_score"]
|
||||
else:
|
||||
self.high_score = 0
|
||||
|
||||
pypresence_client.update(state='Training Aim', details=f'Hits: 0/0 Accuracy: 0%')
|
||||
|
||||
self.ground = Entity(model='plane', collider='box', scale=64, texture='grass', texture_scale=(4,4), shader=lit_with_shadows_shader)
|
||||
@@ -23,7 +29,7 @@ class Game():
|
||||
for n, weapon in enumerate(weapons):
|
||||
self.inventory.append(weapons[weapon]["image"], weapon, n)
|
||||
|
||||
self.player = Player(self.info_label, self.inventory, pypresence_client)
|
||||
self.player = Player(self.high_score, self.info_label, self.inventory, pypresence_client)
|
||||
|
||||
self.shootables_parent = Entity()
|
||||
mouse.traverse_target = self.shootables_parent
|
||||
@@ -40,6 +46,7 @@ class Game():
|
||||
|
||||
self.sky = Sky()
|
||||
self.sky.update = self.update
|
||||
|
||||
|
||||
def summon_enemy(self):
|
||||
if not len(self.enemies) >= 50:
|
||||
@@ -50,7 +57,7 @@ class Game():
|
||||
|
||||
if held_keys["escape"]:
|
||||
self.back_to_main_menu()
|
||||
elif held_keys["space"]:
|
||||
elif held_keys["n"]:
|
||||
self.summon_enemy()
|
||||
|
||||
def back_to_main_menu(self):
|
||||
@@ -70,3 +77,6 @@ class Game():
|
||||
|
||||
for enemy in self.enemies:
|
||||
destroy(enemy)
|
||||
|
||||
with open("data.json", "w") as file:
|
||||
file.write(json.dumps({"high_score": self.player.high_score}, indent=4))
|
||||
|
||||
@@ -7,8 +7,8 @@ from utils.preload import death_sound
|
||||
import json
|
||||
|
||||
class Player(FirstPersonController):
|
||||
def __init__(self, info_label, inventory, pypresence_client) -> None:
|
||||
super().__init__(model='cube', z=16, color=color.orange, origin_y=-.5, speed=8, collider='box', gravity=False, shader=lit_with_shadows_shader)
|
||||
def __init__(self, high_score, info_label, inventory, pypresence_client) -> None:
|
||||
super().__init__(model='cube', z=16, color=color.orange, origin_y=-.5, speed=8, collider='box', gravity=True, shader=lit_with_shadows_shader)
|
||||
|
||||
self.collider = BoxCollider(self, Vec3(0,1,0), Vec3(1,2,1))
|
||||
|
||||
@@ -19,7 +19,7 @@ class Player(FirstPersonController):
|
||||
self.info_label = info_label
|
||||
self.inventory = inventory
|
||||
self.pypresence_client = pypresence_client
|
||||
|
||||
self.high_score = high_score
|
||||
self.last_presence_update = time.perf_counter()
|
||||
self.shots_fired = 0
|
||||
self.shots_hit = 0
|
||||
@@ -40,15 +40,18 @@ class Player(FirstPersonController):
|
||||
|
||||
self.x = max(-16, min(self.x, 16))
|
||||
self.z = max(-16, min(self.z, 16))
|
||||
self.info_label.text = f"Score: {self.score} Hits: {self.shots_fired}/{self.shots_hit} Accuracy: {round(self.accuracy, 2)}%"
|
||||
self.info_label.text = f"High Score: {self.high_score} Score: {self.score} Hits: {self.shots_fired}/{self.shots_hit} Accuracy: {round(self.accuracy, 2)}%"
|
||||
|
||||
weapon_name = self.inventory.slot_names[self.inventory.current_slot]
|
||||
self.weapon_attack_speed = weapons[weapon_name]["atk_speed"]
|
||||
self.weapon_dmg = weapons[weapon_name]["dmg"]
|
||||
|
||||
if self.score > self.high_score:
|
||||
self.high_score = self.score
|
||||
|
||||
if time.perf_counter() - self.last_presence_update >= 3:
|
||||
self.last_presence_update = time.perf_counter()
|
||||
self.pypresence_client.update(state='Training Aim', details=f"Score: {self.score} Hits: {self.shots_fired}/{self.shots_hit} Accuracy: {round(self.accuracy, 2)}%")
|
||||
self.pypresence_client.update(state='Training Aim', details=f"High Score: {self.high_score} Score: {self.score} Hits: {self.shots_fired}/{self.shots_hit} Accuracy: {round(self.accuracy, 2)}%")
|
||||
|
||||
def summon_enemy(self):
|
||||
pass
|
||||
|
||||
@@ -46,14 +46,21 @@ class Main():
|
||||
self.pypresence_client = FakePyPresence()
|
||||
self.pypresence_client.start_time = time.time()
|
||||
|
||||
if os.path.exists("data.json"):
|
||||
with open("data.json", "r") as file:
|
||||
self.high_score = json.load(file)["high_score"]
|
||||
else:
|
||||
self.high_score = 0
|
||||
|
||||
self.pypresence_client.update(state='In Main Menu', details='In Main Menu')
|
||||
|
||||
button_spacing = .075 * 1.25
|
||||
base_y = -2
|
||||
|
||||
self.menu_parent = Entity(parent=camera.ui, y=.15)
|
||||
self.main_menu = Entity(parent=self.menu_parent)
|
||||
|
||||
self.title_label = Text("Aim Trainer", parent=self.main_menu, y=-0.25 * button_spacing, scale=3, x=-.2)
|
||||
self.title_label = Text("Aim Trainer", parent=self.main_menu, y=-0.01 * button_spacing, scale=3, x=-.2)
|
||||
self.high_score_label = Text(f"High Score: {self.high_score}", parent=self.main_menu, scale=1.25, y=-1 * button_spacing, x=-.12)
|
||||
self.play_button = MenuButton('Play', on_click=Func(self.play), parent=self.main_menu, y=-2 * button_spacing)
|
||||
self.settings_button = MenuButton('Settings', on_click=Func(self.settings), parent=self.main_menu, y=-3 * button_spacing)
|
||||
self.quit_button = MenuButton('Quit', on_click=Sequence(Wait(.01), Func(application.quit)), parent=self.main_menu, y=-4 * button_spacing)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from ursina import *
|
||||
from ursina.prefabs.slider import ThinSlider
|
||||
from ursina.prefabs.dropdown_menu import DropdownMenu, DropdownMenuButton
|
||||
from ursina.prefabs.dropdown_menu import DropdownMenuButton
|
||||
from ursina.prefabs.button_group import ButtonGroup
|
||||
import pypresence, json, copy
|
||||
from utils.utils import FakePyPresence
|
||||
from utils.utils import FakePyPresence, Dropdown
|
||||
from utils.constants import discord_presence_id, settings, settings_start_category
|
||||
from utils.preload import music_sound
|
||||
|
||||
@@ -58,20 +58,29 @@ class Settings:
|
||||
self.ui.append(slider)
|
||||
|
||||
else:
|
||||
items = []
|
||||
menu_buttons = []
|
||||
for opt in info['options']:
|
||||
b = DropdownMenuButton(opt)
|
||||
b.on_click = lambda btn, n=name: self.update(n, btn.text)
|
||||
items.append(b)
|
||||
dm = DropdownMenu(val, buttons=tuple(items))
|
||||
dm.position = (.2, y)
|
||||
self.ui.append(dm)
|
||||
menu_button = DropdownMenuButton(opt)
|
||||
menu_buttons.append(menu_button)
|
||||
|
||||
dropdown_menu = Dropdown(val, buttons=tuple(menu_buttons))
|
||||
|
||||
for menu_button in menu_buttons:
|
||||
menu_button.on_click = lambda dropdown_menu=dropdown_menu, btn=menu_button, n=name: self.dropdown_update(n, dropdown_menu, btn)
|
||||
|
||||
dropdown_menu.position = (.2, y)
|
||||
self.ui.append(dropdown_menu)
|
||||
|
||||
y -= .08
|
||||
|
||||
self.apply_button = Button('Apply', parent=camera.ui, color=color.green, scale=(.15, .08), position=(.6, -.4), on_click=self.apply_changes)
|
||||
self.ui.append(self.apply_button)
|
||||
|
||||
def dropdown_update(self, n, dropdown_menu, btn):
|
||||
dropdown_menu.text = btn.text
|
||||
|
||||
self.update(n, btn.text)
|
||||
|
||||
def update(self, name, value):
|
||||
self.edits[settings[self.category][name]['config_key']] = value
|
||||
|
||||
@@ -146,15 +155,15 @@ class Settings:
|
||||
text = file.read()
|
||||
|
||||
if window.size.x >= 3840:
|
||||
font_size = 2.4
|
||||
font_size = 2.3
|
||||
elif window.size.x >= 2560:
|
||||
font_size = 1.9
|
||||
font_size = 1.8
|
||||
elif window.size.x >= 1920:
|
||||
font_size = 1.6
|
||||
font_size = 1.5
|
||||
elif window.size.x >= 1440:
|
||||
font_size = 1.3
|
||||
font_size = 1.2
|
||||
else:
|
||||
font_size = 1.1
|
||||
font_size = 1.0
|
||||
|
||||
self.credits_label = Text(text=text, parent=camera.ui, position=(0, 0), origin=(0, 0), scale=font_size, color=color.white)
|
||||
self.credits_label.type = 'credits_text'
|
||||
|
||||
5
run.py
5
run.py
@@ -1,7 +1,8 @@
|
||||
import os, pypresence, json
|
||||
import os, json
|
||||
from ursina import Ursina
|
||||
from menus.main import Main
|
||||
from utils.utils import get_closest_resolution
|
||||
from ursina import window
|
||||
|
||||
if os.path.exists('settings.json'):
|
||||
with open('settings.json', 'r') as settings_file:
|
||||
@@ -32,6 +33,8 @@ if not args["fullscreen"]:
|
||||
args["size"] = list(map(int, settings['resolution'].split('x')))
|
||||
|
||||
app = Ursina(title="Aim Trainer", development_mode=False, **args)
|
||||
window.editor_ui.enabled = True
|
||||
window.fps_counter.enabled = True
|
||||
|
||||
if settings.get("music", True):
|
||||
from utils.preload import music_sound
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from panda3d.core import GraphicsPipeSelection
|
||||
from ursina.prefabs.dropdown_menu import DropdownMenu
|
||||
|
||||
def get_closest_resolution():
|
||||
allowed_resolutions = [(1366, 768), (1440, 900), (1600,900), (1920,1080), (2560,1440), (3840,2160)]
|
||||
@@ -24,6 +25,25 @@ def get_closest_resolution():
|
||||
)
|
||||
return closest_resolution
|
||||
|
||||
class Dropdown(DropdownMenu):
|
||||
def __init__(self, text='', buttons = None, **kwargs):
|
||||
super().__init__(text, buttons, **kwargs)
|
||||
|
||||
self.scale = (.4,.04)
|
||||
|
||||
|
||||
def on_mouse_enter(self):
|
||||
...
|
||||
|
||||
def input(self, key):
|
||||
super().input(key)
|
||||
|
||||
if key == 'left mouse down' and self.hovered:
|
||||
if not self.buttons[0].enabled:
|
||||
self.open()
|
||||
else:
|
||||
self.close()
|
||||
|
||||
class FakePyPresence():
|
||||
def __init__(self):
|
||||
...
|
||||
|
||||
Reference in New Issue
Block a user