Add working inventory, textures, add classes for IRS agents and the Player, add mana, draw UI on top of other things, make shooting automatic in direction of mouse, fix bugs

This commit is contained in:
csd4ni3l
2025-10-10 19:01:31 +02:00
parent bca585bc45
commit aab2ebc513
8 changed files with 150 additions and 60 deletions

View File

@@ -1,5 +1,11 @@
The Roboto Black font used in this project is licensed under the Open Font License. Read assets/fonts/OFL.txt for more information. The Roboto Black font used in this project is licensed under the Open Font License. Read assets/fonts/OFL.txt for more information.
Thanks to OpenGameArt and AntumDeluge for the mage textures/animations/spritesheets. (Licensed under CC0)
https://opengameart.org/content/mages-rework (Created by Sollision & Jordan Irwin (AntumDeluge))
Thanks to OpenGameArt and Kenney.nl for the blue shirt man, which was redesigned to be the IRS agent texture.
https://opengameart.org/content/topdown-shooter (This is a full pack, Created by Kenney.nl, link is https://www.kenney.nl)
Huge Thanks to Python for being the programming language used in this game. Huge Thanks to Python for being the programming language used in this game.
https://www.python.org/ https://www.python.org/

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -4,16 +4,16 @@ from utils.constants import button_style
class Inventory(arcade.gui.UIBoxLayout): class Inventory(arcade.gui.UIBoxLayout):
def __init__(self, items, window_width): def __init__(self, items, window_width):
super().__init__(size_hint=(0.75, 0.1), vertical=False, space_between=5) super().__init__(size_hint=(0.5, 0.1), vertical=False, space_between=5)
self.items = items self.items = items
self.current_inventory_item = 0 self.current_inventory_item = 0
self.inventory_buttons: list[arcade.gui.UITextureButton] = [] self.inventory_buttons: list[arcade.gui.UITextureButton] = []
for n, item in enumerate(items): for n, item in enumerate(items):
self.inventory_buttons.append(self.add(arcade.gui.UIFlatButton(text=f"{item[0]} ({n + 1})", style=button_style, width=(window_width * 0.75) / len(items) + 1))) self.inventory_buttons.append(self.add(arcade.gui.UIFlatButton(text=f"{item[0]} ({n + 1})", style=button_style, width=(window_width * 0.5) / len(items) + 1)))
self.pay_tax_button = self.add(arcade.gui.UIFlatButton(text="Pay Tax (1000$)", style=button_style, width=(window_width * 0.75) / len(items) + 1)) self.pay_tax_button = self.add(arcade.gui.UIFlatButton(text="Pay Tax (1000$)", style=button_style, width=(window_width * 0.5) / len(items) + 1))
self.pay_tax_button.style["normal"]["bg"] = arcade.color.GRAY self.pay_tax_button.style["normal"]["bg"] = arcade.color.GRAY
self.pay_tax_button.style["normal"]["bg"] = arcade.color.GRAY self.pay_tax_button.style["normal"]["bg"] = arcade.color.GRAY

View File

@@ -1,18 +1,48 @@
import arcade, arcade.gui, random, math, time, json, os import arcade, arcade.gui, random, math, time, json, os
from utils.constants import BULLET_SPEED, TAX_EVASION_LEVELS, INVENTORY_ITEMS, IRS_AGENT_SPEED, TAX_PER_IRS_AGENT, IRS_AGENT_SPAWN_INTERVAL, SPAWN_INTERVAL_DECREASE_PER_LEVEL, SPEED_INCREASE_PER_LEVEL, TAX_EVASION_NAMES, TAX_INCREASE_PER_LEVEL, menu_background_color from utils.constants import BULLET_SPEED, IRS_AGENT_HEALTH, HEALTH_INCREASE_PER_LEVEL, PLAYER_SPEED, IRS_AGENT_SPEED, TAX_PER_IRS_AGENT, IRS_AGENT_ATTACK_SPEED
from utils.preload import wizard_texture, irs_agent_texture from utils.constants import IRS_AGENT_SPAWN_INTERVAL, SPAWN_INTERVAL_DECREASE_PER_LEVEL, SPEED_INCREASE_PER_LEVEL
from utils.constants import TAX_EVASION_LEVELS, TAX_EVASION_NAMES, TAX_INCREASE_PER_LEVEL, menu_background_color, INVENTORY_ITEMS, INVENTORY_TRIGGER_KEYS
from utils.preload import irs_agent_texture
from utils.preload import light_wizard_left_animation, light_wizard_right_animation, light_wizard_standing_animation, light_wizard_up_animation
from utils.preload import dark_wizard_left_animation, dark_wizard_right_animation, dark_wizard_standing_animation, dark_wizard_up_animation
from game.inventory import Inventory from game.inventory import Inventory
class Bullet(arcade.Sprite): class Bullet(arcade.SpriteCircle):
def __init__(self, x, y, direction, color, **kwargs): def __init__(self, radius, x, y, direction, color):
super().__init__(arcade.texture.make_circle_texture(20, color), center_x=x, center_y=y) super().__init__(radius=radius, color=color)
self.center_x = x
self.center_y = y
self.radius = radius
self.direction = direction self.direction = direction
def move(self): def move(self):
self.position += self.direction * BULLET_SPEED self.position += self.direction * BULLET_SPEED
class IRSAgent(arcade.Sprite):
def __init__(self, x, y):
super().__init__(irs_agent_texture, center_x=x, center_y=y, scale=1.25)
self.damaged = False
self.last_damage = time.perf_counter()
self.last_attack = time.perf_counter()
self.health = 0
def update(self):
if self.damaged:
if time.perf_counter() - self.last_damage >= 0.3:
self.damaged = False
self.color = arcade.color.RED
else:
self.color = (255, 255, 255, 255)
class Player(arcade.TextureAnimationSprite):
def __init__(self, x, y): # x, y here because we dont know window width and height
super().__init__(animation=dark_wizard_standing_animation, center_x=x, center_y=y, scale=1.5)
class Game(arcade.gui.UIView): class Game(arcade.gui.UIView):
def __init__(self, pypresence_client): def __init__(self, pypresence_client):
super().__init__() super().__init__()
@@ -43,9 +73,10 @@ class Game(arcade.gui.UIView):
self.anchor = self.add_widget(arcade.gui.UIAnchorLayout(size_hint=(1, 1))) self.anchor = self.add_widget(arcade.gui.UIAnchorLayout(size_hint=(1, 1)))
self.spritelist = arcade.SpriteList() self.spritelist = arcade.SpriteList()
self.irs_agents = [] self.irs_agents: list[IRSAgent] = []
self.last_irs_agent_spawn = time.perf_counter() self.last_irs_agent_spawn = time.perf_counter()
self.last_mana = time.perf_counter() self.last_mana = time.perf_counter()
self.last_shoot = time.perf_counter()
self.evaded_tax = 0 self.evaded_tax = 0
self.mana = 0 self.mana = 0
@@ -53,8 +84,8 @@ class Game(arcade.gui.UIView):
self.bullets: list[Bullet] = [] self.bullets: list[Bullet] = []
self.highscore_evaded_tax = self.data["high_score"] self.highscore_evaded_tax = self.data["high_score"]
self.wizard_sprite = arcade.Sprite(wizard_texture, center_x=self.window.width / 2, center_y=self.window.height / 2) self.player = Player(self.window.width / 2, self.window.height / 2)
self.spritelist.append(self.wizard_sprite) self.spritelist.append(self.player)
self.info_box = self.anchor.add(arcade.gui.UIBoxLayout(space_between=0, align="left"), anchor_x="left", anchor_y="top") self.info_box = self.anchor.add(arcade.gui.UIBoxLayout(space_between=0, align="left"), anchor_x="left", anchor_y="top")
self.evaded_tax_label = self.info_box.add(arcade.gui.UILabel(text="Evaded Tax: 0$", font_size=14, text_color=arcade.color.BLACK)) self.evaded_tax_label = self.info_box.add(arcade.gui.UILabel(text="Evaded Tax: 0$", font_size=14, text_color=arcade.color.BLACK))
@@ -74,7 +105,7 @@ class Game(arcade.gui.UIView):
self.inventory.pay_tax_button.on_click = lambda event: self.pay_tax() self.inventory.pay_tax_button.on_click = lambda event: self.pay_tax()
def spawn_bullet(self, direction): def spawn_bullet(self, direction):
bullet = Bullet(self.window.width / 2, self.window.height / 2, direction, arcade.color.BLUE) bullet = Bullet(INVENTORY_ITEMS[self.inventory.current_inventory_item][3], self.player.center_x, self.player.center_y, direction, arcade.color.BLUE)
self.bullets.append(bullet) self.bullets.append(bullet)
self.spritelist.append(bullet) self.spritelist.append(bullet)
@@ -83,11 +114,11 @@ class Game(arcade.gui.UIView):
closest_direction = None closest_direction = None
for irs_agent in self.irs_agents: for irs_agent in self.irs_agents:
distance = arcade.math.Vec2(self.wizard_sprite.center_x, self.wizard_sprite.center_y).distance((irs_agent.center_x, irs_agent.center_y)) distance = arcade.math.Vec2(self.player.center_x, self.player.center_y).distance((irs_agent.center_x, irs_agent.center_y))
if distance < closest_dist: if distance < closest_dist:
closest_dist = distance closest_dist = distance
closest_direction = (arcade.math.Vec2(irs_agent.center_x, irs_agent.center_y) - (self.wizard_sprite.center_x, self.wizard_sprite.center_y)).normalize() closest_direction = (arcade.math.Vec2(irs_agent.center_x, irs_agent.center_y) - (self.player.center_x, self.player.center_y)).normalize()
if not closest_dist or not closest_direction: if not closest_dist or not closest_direction:
return return
@@ -116,7 +147,10 @@ class Game(arcade.gui.UIView):
self.tax_evasion_level_notice.visible = True self.tax_evasion_level_notice.visible = True
self.last_tax_evasion_notice = time.perf_counter() self.last_tax_evasion_notice = time.perf_counter()
if not self.get_current_level_int() == len(TAX_EVASION_NAMES) - 1:
self.progress_bar.value = ((self.evaded_tax - TAX_EVASION_LEVELS[self.tax_evasion_level]) / (TAX_EVASION_LEVELS[TAX_EVASION_NAMES[self.get_current_level_int() + 1]] - TAX_EVASION_LEVELS[self.tax_evasion_level])) * 100 self.progress_bar.value = ((self.evaded_tax - TAX_EVASION_LEVELS[self.tax_evasion_level]) / (TAX_EVASION_LEVELS[TAX_EVASION_NAMES[self.get_current_level_int() + 1]] - TAX_EVASION_LEVELS[self.tax_evasion_level])) * 100
else:
self.progress_bar.value = 100
self.tax_evasion_label.text = f"Tax Evasion Level: {self.tax_evasion_level}" self.tax_evasion_label.text = f"Tax Evasion Level: {self.tax_evasion_level}"
@@ -135,16 +169,42 @@ class Game(arcade.gui.UIView):
x = base_x + (math.cos(angle) * amount) x = base_x + (math.cos(angle) * amount)
y = base_y + (math.sin(angle) * amount) y = base_y + (math.sin(angle) * amount)
irs_agent = arcade.Sprite(irs_agent_texture, center_x=x, center_y=y) irs_agent = IRSAgent(x, y)
irs_agent.health = IRS_AGENT_HEALTH + (HEALTH_INCREASE_PER_LEVEL * self.get_current_level_int())
self.irs_agents.append(irs_agent) self.irs_agents.append(irs_agent)
self.spritelist.append(irs_agent) self.spritelist.append(irs_agent)
def on_update(self, delta_time): def on_update(self, delta_time):
self.player.update_animation()
if self.window.keyboard[arcade.key.W]:
self.player.center_y += PLAYER_SPEED
if not self.player.animation == dark_wizard_up_animation: # this is needed because the animation property will reset to the first frame, so animation doesnt work.
self.player.animation = dark_wizard_up_animation
elif self.window.keyboard[arcade.key.S]:
self.player.center_y -= PLAYER_SPEED
if not self.player.animation == dark_wizard_standing_animation: # this is needed because the animation property will reset to the first frame, so animation doesnt work.
self.player.animation = dark_wizard_standing_animation
if self.window.keyboard[arcade.key.D]:
self.player.center_x += PLAYER_SPEED
if not self.player.animation == dark_wizard_right_animation: # this is needed because the animation property will reset to the first frame, so animation doesnt work.
self.player.animation = dark_wizard_right_animation
elif self.window.keyboard[arcade.key.A]:
self.player.center_x -= PLAYER_SPEED
if not self.player.animation == dark_wizard_left_animation: # this is needed because the animation property will reset to the first frame, so animation doesnt work.
self.player.animation = dark_wizard_left_animation
if time.perf_counter() - self.last_shoot >= INVENTORY_ITEMS[self.inventory.current_inventory_item][1]:
self.last_shoot = time.perf_counter()
direction = ((self.window.mouse.data.get("x", 0), self.window.mouse.data.get("y", 0)) - arcade.math.Vec2(self.player.center_x, self.player.center_y)).normalize()
self.spawn_bullet(direction)
if self.tax_evasion_level_notice.visible and time.perf_counter() - self.last_tax_evasion_notice >= 2.5: if self.tax_evasion_level_notice.visible and time.perf_counter() - self.last_tax_evasion_notice >= 2.5:
self.tax_evasion_level_notice.visible = False self.tax_evasion_level_notice.visible = False
if time.perf_counter() - self.last_mana >= 0.1: if time.perf_counter() - self.last_mana >= 0.5:
self.last_mana = time.perf_counter() self.last_mana = time.perf_counter()
self.mana += 5 self.mana += 5
@@ -154,19 +214,22 @@ class Game(arcade.gui.UIView):
self.camera_shake.update(delta_time) self.camera_shake.update(delta_time)
for irs_agent in self.irs_agents: for irs_agent in self.irs_agents:
wizard_pos_vec = arcade.math.Vec2(self.wizard_sprite.center_x, self.wizard_sprite.center_y) irs_agent.update()
direction = (wizard_pos_vec - irs_agent.position).normalize()
irs_agent.position += direction * (IRS_AGENT_SPEED + (SPEED_INCREASE_PER_LEVEL * self.get_current_level_int())) wizard_pos_vec = arcade.math.Vec2(self.player.center_x, self.player.center_y)
if wizard_pos_vec.distance(irs_agent.position) <= self.player.width / 2:
if time.perf_counter() - irs_agent.last_attack >= IRS_AGENT_ATTACK_SPEED:
irs_agent.last_attack = time.perf_counter()
if wizard_pos_vec.distance(irs_agent.position) <= self.wizard_sprite.width / 2:
self.camera_shake.start() self.camera_shake.start()
self.evaded_tax -= TAX_PER_IRS_AGENT + (TAX_INCREASE_PER_LEVEL * self.get_current_level_int()) self.evaded_tax -= TAX_PER_IRS_AGENT + (TAX_INCREASE_PER_LEVEL * self.get_current_level_int())
self.update_evasion_level() self.update_evasion_level()
else:
self.spritelist.remove(irs_agent) direction = (wizard_pos_vec - irs_agent.position).normalize()
self.irs_agents.remove(irs_agent) irs_agent.angle = -math.degrees(direction.heading())
irs_agent.position += direction * (IRS_AGENT_SPEED + (SPEED_INCREASE_PER_LEVEL * self.get_current_level_int()))
for bullet in self.bullets: for bullet in self.bullets:
bullet.move() bullet.move()
@@ -174,22 +237,25 @@ class Game(arcade.gui.UIView):
hit = False hit = False
for irs_agent in self.irs_agents: for irs_agent in self.irs_agents:
if arcade.math.Vec2(bullet.center_x, bullet.center_y).distance((irs_agent.center_x, irs_agent.center_y)) <= irs_agent.width: if arcade.math.Vec2(bullet.center_x, bullet.center_y).distance((irs_agent.center_x, irs_agent.center_y)) <= (irs_agent.width / 2 + bullet.radius):
irs_agent.damaged = True
irs_agent.last_damage = time.perf_counter()
irs_agent.position += bullet.direction * INVENTORY_ITEMS[self.inventory.current_inventory_item][2] * 1.5
irs_agent.health -= INVENTORY_ITEMS[self.inventory.current_inventory_item][2]
if irs_agent.health <= 0:
self.spritelist.remove(irs_agent) self.spritelist.remove(irs_agent)
self.irs_agents.remove(irs_agent) self.irs_agents.remove(irs_agent)
hit = True self.evaded_tax += (TAX_PER_IRS_AGENT / 2) + ((TAX_INCREASE_PER_LEVEL / 2) * self.get_current_level_int())
self.update_evasion_level()
break self.camera_shake.start()
hit = True
if hit: if hit:
self.spritelist.remove(bullet) self.spritelist.remove(bullet)
self.bullets.remove(bullet) self.bullets.remove(bullet)
self.camera_shake.start()
self.evaded_tax += 100
self.update_evasion_level()
if time.perf_counter() - self.last_irs_agent_spawn >= IRS_AGENT_SPAWN_INTERVAL - (SPAWN_INTERVAL_DECREASE_PER_LEVEL * self.get_current_level_int()): if time.perf_counter() - self.last_irs_agent_spawn >= IRS_AGENT_SPAWN_INTERVAL - (SPAWN_INTERVAL_DECREASE_PER_LEVEL * self.get_current_level_int()):
self.last_irs_agent_spawn = time.perf_counter() self.last_irs_agent_spawn = time.perf_counter()
@@ -203,18 +269,13 @@ class Game(arcade.gui.UIView):
def on_show_view(self): def on_show_view(self):
super().on_show_view() super().on_show_view()
def on_mouse_press(self, x, y, button, modifiers):
direction = ((x, y) - arcade.math.Vec2(self.wizard_sprite.center_x, self.wizard_sprite.center_y)).normalize()
self.spawn_bullet(direction)
def on_key_press(self, symbol, modifiers): def on_key_press(self, symbol, modifiers):
if symbol == arcade.key.ESCAPE: if symbol == arcade.key.ESCAPE:
arcade.set_background_color(menu_background_color) arcade.set_background_color(menu_background_color)
from menus.main import Main from menus.main import Main
self.window.show_view(Main(self.pypresence_client)) self.window.show_view(Main(self.pypresence_client))
elif chr(symbol).isnumeric() and int(chr(symbol)) <= len(INVENTORY_ITEMS): elif symbol in INVENTORY_TRIGGER_KEYS:
self.inventory.select_item(int(chr(symbol)) - 1) self.inventory.select_item(int(chr(symbol)) - 1)
elif symbol == arcade.key.P: elif symbol == arcade.key.P:
self.pay_tax() self.pay_tax()
@@ -224,8 +285,11 @@ class Game(arcade.gui.UIView):
self.camera.match_window() self.camera.match_window()
def on_draw(self): def on_draw(self):
super().on_draw() self.window.clear()
self.camera_shake.update_camera() self.camera_shake.update_camera()
self.camera.use() self.camera.use()
self.spritelist.draw() self.spritelist.draw()
self.camera_shake.readjust_camera() self.camera_shake.readjust_camera()
self.ui.draw() # draw after, so UI is on top

View File

@@ -1,4 +1,4 @@
import arcade.color import arcade.color, arcade.key
from arcade.types import Color from arcade.types import Color
from arcade.gui.widgets.buttons import UITextureButtonStyle, UIFlatButtonStyle from arcade.gui.widgets.buttons import UITextureButtonStyle, UIFlatButtonStyle
from arcade.gui.widgets.slider import UISliderStyle from arcade.gui.widgets.slider import UISliderStyle
@@ -8,26 +8,34 @@ log_dir = 'logs'
discord_presence_id = 1424784736726945915 discord_presence_id = 1424784736726945915
IRS_AGENT_SPAWN_INTERVAL = 1 IRS_AGENT_SPAWN_INTERVAL = 1
IRS_AGENT_SPEED = 1 IRS_AGENT_ATTACK_SPEED = 1
TAX_PER_IRS_AGENT = 200 IRS_AGENT_SPEED = 1.5
IRS_AGENT_HEALTH = 15
TAX_PER_IRS_AGENT = 100
TAX_EVASION_LEVELS = {"Compliant Citizen": 0, "Suspicious": 1, "Under Review": 1500, "Flagged": 3500, "Audited": 10000, "Criminal Case": 20000, "Most Wanted": 50000, "Legendary": 100000} TAX_EVASION_LEVELS = {"Compliant Citizen": 0, "Suspicious": 1, "Under Review": 2500, "Flagged": 5000, "Audited": 10000, "Criminal Case": 20000, "Most Wanted": 50000, "Legendary": 100000}
TAX_EVASION_NAMES = list(TAX_EVASION_LEVELS.keys()) TAX_EVASION_NAMES = list(TAX_EVASION_LEVELS.keys())
BULLET_SPEED = 5 BULLET_SPEED = 10
SPEED_INCREASE_PER_LEVEL = 0.5 SPEED_INCREASE_PER_LEVEL = 0.3
SPAWN_INTERVAL_DECREASE_PER_LEVEL = 0.1 SPAWN_INTERVAL_DECREASE_PER_LEVEL = 0.075
TAX_INCREASE_PER_LEVEL = 50 HEALTH_INCREASE_PER_LEVEL = 2
TAX_INCREASE_PER_LEVEL = 100
ATTACK_INTERVAL_DECREASE_PER_LEVEL = .1
SHOP_ITEMS = [] SHOP_ITEMS = []
PLAYER_SPEED = 4
INVENTORY_ITEMS = [ INVENTORY_ITEMS = [
["Fireball"], ["Fireball", 0.2, 10, 10],
["Lightning Bolt"], ["Lightning Bolt", 0.4, 20, 20],
["Ice Blast"], ["Ice Blast", 0.1, 5, 7.5],
["Arcane Beam"], ["Arcane Beam", 0.2, 20, 15],
] ]
INVENTORY_TRIGGER_KEYS = [getattr(arcade.key, f"KEY_{n+1}") for n in range(len(INVENTORY_ITEMS))]
button_style = {'normal': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), 'hover': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), button_style = {'normal': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), 'hover': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK),
'press': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), 'disabled': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK)} 'press': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK), 'disabled': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK)}
big_button_style = {'normal': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK, font_size=26), 'hover': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK, font_size=26), big_button_style = {'normal': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK, font_size=26), 'hover': UITextureButtonStyle(font_name="Roboto", font_color=arcade.color.BLACK, font_size=26),

View File

@@ -2,5 +2,17 @@ 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"))
wizard_texture = arcade.texture.make_soft_square_texture(100, arcade.color.BLACK, outer_alpha=255)
irs_agent_texture = arcade.texture.make_soft_square_texture(30, arcade.color.RED, outer_alpha=255) light_wizard_spritesheet = arcade.load_spritesheet("assets/graphics/mage-light.png").get_texture_grid((48, 64), 3, 12)
light_wizard_up_animation = arcade.TextureAnimation([arcade.TextureKeyframe(texture, 300) for texture in light_wizard_spritesheet[0:2]])
light_wizard_right_animation = arcade.TextureAnimation([arcade.TextureKeyframe(texture, 300) for texture in light_wizard_spritesheet[3:5]])
light_wizard_standing_animation = arcade.TextureAnimation([arcade.TextureKeyframe(texture, 300) for texture in light_wizard_spritesheet[6:8]])
light_wizard_left_animation = arcade.TextureAnimation([arcade.TextureKeyframe(texture, 300) for texture in light_wizard_spritesheet[9:11]])
dark_wizard_spritesheet = arcade.load_spritesheet("assets/graphics/mage-dark.png").get_texture_grid((48, 64), 3, 12)
dark_wizard_up_animation = arcade.TextureAnimation([arcade.TextureKeyframe(texture, 300) for texture in dark_wizard_spritesheet[0:2]])
dark_wizard_right_animation = arcade.TextureAnimation([arcade.TextureKeyframe(texture, 300) for texture in dark_wizard_spritesheet[3:5]])
dark_wizard_standing_animation = arcade.TextureAnimation([arcade.TextureKeyframe(texture, 300) for texture in dark_wizard_spritesheet[6:8]])
dark_wizard_left_animation = arcade.TextureAnimation([arcade.TextureKeyframe(texture, 300) for texture in dark_wizard_spritesheet[9:11]])
irs_agent_texture = arcade.load_texture("assets/graphics/irs_agent.png")