Finished refactoring code

This commit is contained in:
Vasilis Valatsos 2023-10-04 04:37:28 +02:00
parent cd0333cbff
commit b0a925292e
25 changed files with 429 additions and 194 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/audio/death.wav Normal file

Binary file not shown.

BIN
assets/audio/flame.wav Normal file

Binary file not shown.

BIN
assets/audio/heal.wav Normal file

Binary file not shown.

BIN
assets/audio/hit.wav Normal file

Binary file not shown.

BIN
assets/audio/main.ogg Normal file

Binary file not shown.

BIN
assets/audio/sword.wav Normal file

Binary file not shown.

View file

@ -1,5 +1,12 @@
import os
script_dir = os.path.dirname(os.path.abspath(__file__))
asset_path = os.path.join(
script_dir, '../../..', 'assets')
monster_data = {
'squid': {'health': 100,'exp':100,'damage':20,'attack_type': 'slash', 'attack_sound':'../Graphics/audio/attack/slash.wav', 'speed': 3, 'resistance': 3, 'attack_radius': 80, 'notice_radius': 360},
'raccoon': {'health': 300,'exp':250,'damage':40,'attack_type': 'claw', 'attack_sound':'../Graphics/audio/attack/claw.wav','speed': 2, 'resistance': 3, 'attack_radius': 120, 'notice_radius': 400},
'spirit': {'health': 100,'exp':110,'damage':8,'attack_type': 'thunder', 'attack_sound':'../Graphics/audio/attack/fireball.wav', 'speed': 4, 'resistance': 3, 'attack_radius': 60, 'notice_radius': 350},
'bamboo': {'health': 70,'exp':120,'damage':6,'attack_type': 'leaf_attack', 'attack_sound':'../Graphics/audio/attack/slash.wav', 'speed': 3, 'resistance': 3, 'attack_radius': 50, 'notice_radius': 300}}
'squid': {'health': 100, 'exp': 100, 'attack': 20, 'attack_type': 'slash', 'attack_sound': f'{asset_path}/audio/attack/slash.wav', 'speed': 3, 'knockback': 20, 'attack_radius': 80, 'notice_radius': 360},
'raccoon': {'health': 300, 'exp': 250, 'attack': 40, 'attack_type': 'claw', 'attack_sound': f'{asset_path}/audio/attack/claw.wav', 'speed': 2, 'knockback': 20, 'attack_radius': 120, 'notice_radius': 400},
'spirit': {'health': 100, 'exp': 110, 'attack': 8, 'attack_type': 'thunder', 'attack_sound': f'{asset_path}/audio/attack/fireball.wav', 'speed': 4, 'knockback': 20, 'attack_radius': 60, 'notice_radius': 350},
'bamboo': {'health': 70, 'exp': 120, 'attack': 6, 'attack_type': 'leaf_attack', 'attack_sound': f'{asset_path}/audio/attack/slash.wav', 'speed': 3, 'knockback': 20, 'attack_radius': 50, 'notice_radius': 300}}

View file

@ -0,0 +1,23 @@
stats = {
'health': 100,
'energy': 60,
'attack': 10,
'magic': 4,
'speed': 5
}
max_stats = {
'health': 300,
'energy': 150,
'attack': 20,
'magic': 10,
'speed': 10
}
upgrade_costs = {
'health': 100,
'energy': 100,
'attack': 100,
'magic': 100,
'speed': 100
}

View file

@ -13,37 +13,3 @@ HITBOX_OFFSET = {
# general colors
WATER_COLOR = '#71ddee'
UI_BG_COLOR = '#222222'
UI_BORDER_COLOR = '#111111'
TEXT_COLOR = '#EEEEEE'
# ui colors
HEALTH_COLOR = 'red'
ENERGY_COLOR = 'blue'
UI_BORDER_COLOR_ACTIVE = 'gold'
# Upgrade menu
TEXT_COLOR_SELECTED = '#111111'
BAR_COLOR = '#EEEEEE'
BAR_COLOR_SELECTED = '#111111'
UPGRADE_BG_COLOR_SELECTED = '#EEEEEE'
# # weapons
# weapon_data = {
# 'sword': {'cooldown': 100, 'damage': 15,'graphic':'../Graphics/graphics/weapons/sword/full.png'},
# 'lance': {'cooldown': 400, 'damage': 30,'graphic':'../Graphics/graphics/weapons/lance/full.png'},
# 'axe': {'cooldown': 300, 'damage': 20, 'graphic':'../Graphics/graphics/weapons/axe/full.png'},
# 'rapier':{'cooldown': 50, 'damage': 8, 'graphic':'../Graphics/graphics/weapons/rapier/full.png'},
# 'sai':{'cooldown': 80, 'damage': 10, 'graphic':'../Graphics/graphics/weapons/sai/full.png'}}
#
# # magic
# magic_data = {
# 'flame': {'strength': 5,'cost': 20,'graphic':'../Graphics/graphics/particles/flame/fire.png'},
# 'heal' : {'strength': 20,'cost': 10,'graphic':'../Graphics/graphics/particles/heal/heal.png'}}
#
# # enemy
# monster_data = {
# 'squid': {'health': 100,'exp':100,'damage':20,'attack_type': 'slash', 'attack_sound':'../Graphics/audio/attack/slash.wav', 'speed': 3, 'resistance': 3, 'attack_radius': 80, 'notice_radius': 360},
# 'raccoon': {'health': 300,'exp':250,'damage':40,'attack_type': 'claw', 'attack_sound':'../Graphics/audio/attack/claw.wav','speed': 2, 'resistance': 3, 'attack_radius': 120, 'notice_radius': 400},
# 'spirit': {'health': 100,'exp':110,'damage':8,'attack_type': 'thunder', 'attack_sound':'../Graphics/audio/attack/fireball.wav', 'speed': 4, 'resistance': 3, 'attack_radius': 60, 'notice_radius': 350},
# 'bamboo': {'health': 70,'exp':120,'damage':6,'attack_type': 'leaf_attack', 'attack_sound':'../Graphics/audio/attack/slash.wav', 'speed': 3, 'resistance': 3, 'attack_radius': 50, 'notice_radius': 300}}

View file

@ -1,24 +1,26 @@
import os
import pygame
from random import randint
from configs.system.window_config import TILESIZE
from configs.game.spell_config import *
class MagicPlayer:
def __init__(self, animation_player):
self.animation_player = animation_player
script_dir = os.path.dirname(os.path.abspath(__file__))
asset_path = os.path.join(
script_dir, '../..', 'assets')
# Sound Setup
# self.sounds = {
# 'heal': pygame.mixer.Sound('../Graphics/audio/heal.wav'),
# 'flame': pygame.mixer.Sound('../Graphics/audio/flame.wav')
# }
self.sounds = {
'heal': pygame.mixer.Sound(f'{asset_path}/audio/heal.wav'),
'flame': pygame.mixer.Sound(f'{asset_path}/audio/flame.wav')
}
def heal(self, player, strength, cost, groups):
if player.stats.energy >= cost:
# self.sounds['heal'].play()
self.sounds['heal'].play()
player.stats.health += strength
player.stats.energy -= cost
if player.stats.health >= player.stats.stats['health']:
@ -31,13 +33,13 @@ class MagicPlayer:
def flame(self, player, cost, groups):
if player.stats.energy >= cost:
player.stats.energy -= cost
# self.sounds['flame'].play()
self.sounds['flame'].play()
if player.status.split('_')[0] == 'right':
if player._input.status.split('_')[0] == 'right':
direction = pygame.math.Vector2(1, 0)
elif player.status.split('_')[0] == 'left':
elif player._input.status.split('_')[0] == 'left':
direction = pygame.math.Vector2(-1, 0)
elif player.status.split('_')[0] == 'up':
elif player._input.status.split('_')[0] == 'up':
direction = pygame.math.Vector2(0, -1)
else:
direction = pygame.math.Vector2(0, 1)

View file

@ -12,7 +12,7 @@ class Weapon(pygame.sprite.Sprite):
script_dir, '../..', 'assets')
self.sprite_type = 'weapon'
direction = player.status.split('_')[0]
direction = player._input.status.split('_')[0]
# Graphic
full_path = f"{asset_path}/graphics/weapons/{player._input.combat.weapon}/{direction}.png"

View file

@ -10,21 +10,22 @@ from .combat import CombatHandler
class InputHandler:
def __init__(self, sprite_type, status):
self.status = status
# , status):
def __init__(self, sprite_type, animation_player):
self.status = 'down'
self.sprite_type = sprite_type
# Setup Movement
self.movement = MovementHandler(sprite_type)
self.movement = MovementHandler(self.sprite_type)
self.move_cooldown = 15
self.can_move = True
self.move_time = None
# Setup Combat
self.combat = CombatHandler()
self.combat = CombatHandler(animation_player)
self.attacking = False
self.attack_cooldown = 400
self.attack_time = None
self.can_move = True
# Setup Special Actions
self.can_rotate_weapon = True
@ -37,28 +38,30 @@ class InputHandler:
def check_input(self, speed, hitbox, obstacle_sprites, rect, player):
if not self.attacking and self.can_move:
keys = pygame.key.get_pressed()
button = randint(0, 7)
# button = randint(0, 5)
self.move_time = pygame.time.get_ticks()
# Movement Input
if button == 0: # keys[pygame.K_w]:
if keys[pygame.K_w]: # button == 0: # keys[pygame.K_w]:
self.movement.direction.y = -1
self.status = 'up'
self.can_move = False
elif button == 1: # keys[pygame.K_s]:
elif keys[pygame.K_s]: # button == 1: # keys[pygame.K_s]:
self.movement.direction.y = 1
self.status = 'down'
self.can_move = False
else:
self.movement.direction.y = 0
if button == 2: # keys[pygame.K_a]:
if keys[pygame.K_a]: # button == 2: # keys[pygame.K_a]:
self.movement.direction.x = -1
self.status = 'left'
self.can_move = False
elif button == 3: # keys[pygame.K_d]:
elif keys[pygame.K_d]: # keys[pygame.K_d]:
self.movement.direction.x = 1
self.status = 'right'
self.can_move = False
@ -67,15 +70,16 @@ class InputHandler:
self.movement.move(speed, hitbox, obstacle_sprites, rect)
if self.sprite_type == 'player':
# Combat Input
if button == 4 and not self.attacking: # keys[pygame.K_e]
if keys[pygame.K_e] and not self.attacking: # keys[pygame.K_e]
self.attacking = True
self.attack_time = pygame.time.get_ticks()
self.combat.create_attack_sprite(player)
# self.weapon_attack_sound.play()
self.combat.weapon_attack_sound.play()
# Magic Input
if button == 5: # keys[pygame.K_q]:
if keys[pygame.K_q]: # keys[pygame.K_q]:
self.attacking = True
self.attack_time = pygame.time.get_ticks()
@ -87,12 +91,12 @@ class InputHandler:
cost = list(magic_data.values())[
self.combat.magic_index]['cost']
print(self.combat.magic)
self.combat.create_magic_sprite(
player, self.combat.magic, strength, cost)
# Rotating Weapons
if button == 6 and self.can_rotate_weapon: # keys[pygame.K_LSHIFT]
# keys[pygame.K_LSHIFT]
if keys[pygame.K_LSHIFT] and self.can_rotate_weapon:
self.can_rotate_weapon = False
self.weapon_rotation_time = pygame.time.get_ticks()
if self.combat.weapon_index < len(list(weapon_data.keys())) - 1:
@ -104,7 +108,8 @@ class InputHandler:
self.combat.weapon_index]
# Swap Spells
if button == 7 and self.can_swap_magic: # keys[pygame.K_LCTRL] :
# keys[pygame.K_LCTRL] :
if keys[pygame.K_LCTRL] and self.can_swap_magic:
self.can_swap_magic = False
self.magic_swap_time = pygame.time.get_ticks()
if self.combat.magic_index < len(list(magic_data.keys())) - 1:
@ -114,6 +119,7 @@ class InputHandler:
def cooldowns(self, vulnerable):
current_time = pygame.time.get_ticks()
self.vulnerable = vulnerable
if self.attacking:
if current_time - self.attack_time > self.attack_cooldown + weapon_data[self.combat.weapon]['cooldown']:
@ -130,8 +136,8 @@ class InputHandler:
self.can_swap_magic = True
if not vulnerable:
if current_time - self.hurt_time >= self.invulnerability_duration:
vulnerable = True
if current_time - self.combat.hurt_time >= self.combat.invulnerability_duration:
self.combat.vulnerable = True
if not self.can_move:
if current_time - self.move_time >= self.move_cooldown:

View file

@ -3,20 +3,25 @@ import pygame
from math import sin
from utils.resource_loader import import_folder
from configs.system.window_config import HITBOX_OFFSET
class AnimationHandler:
def __init__(self):
def __init__(self, sprite_type, name=None):
self.frame_index = 0
self.animation_speed = 0.15
def import_assets(self, sprite_type, position, name=None):
self.sprite_type = sprite_type
self.name = name
def import_assets(self, position):
script_dir = os.path.dirname(os.path.abspath(__file__))
asset_path = os.path.join(
script_dir, '../../..', 'assets', 'graphics')
if sprite_type == 'player':
if self.sprite_type == 'player':
character_path = f"{asset_path}/player"
@ -24,7 +29,8 @@ class AnimationHandler:
self.image = pygame.image.load(
f"{character_path}/down/down_0.png").convert_alpha()
self.rect = self.image.get_rect(topleft=position)
self.hitbox = self.rect.inflate(HITBOX_OFFSET[sprite_type])
self.hitbox = self.rect.inflate(HITBOX_OFFSET[self.sprite_type])
self.animations = {
'up': [], 'down': [], 'left': [], 'right': [],
'up_idle': [], 'down_idle': [], 'left_idle': [], 'right_idle': [],
@ -34,21 +40,30 @@ class AnimationHandler:
full_path = f"{character_path}/{animation}"
self.animations[animation] = import_folder(full_path)
elif sprite_type == 'enemy':
elif self.sprite_type == 'enemy':
self.status = 'idle'
character_path = f"{asset_path}/monsters/{self.name}"
character_path = f"{asset_path}/monsters/{name}"
self.animations = {'idle': [], 'move': [], 'attack': []}
main_path = f"{asset_path}/monsters/{name}"
for animation in self.animations.keys():
self.animations[animation] = import_folder(
f"{main_path}/{animation}")
f"{character_path}/{animation}")
self.image = self.animations[self.status][self.frame_index]
self.rect = self.image.get_rect(topleft=position)
self.hitbox = self.rect.inflate(0, -10)
def animate(self, status, vulnerable=True, can_attack=False):
def animate(self, status, vulnerable):
animation = self.animations[status]
self.frame_index += self.animation_speed
if self.frame_index >= len(animation):
if self.sprite_type == 'enemy':
if status == 'attack':
self.can_attack = False
self.frame_index = 0
# Set the image
@ -61,6 +76,10 @@ class AnimationHandler:
else:
self.image.set_alpha(255)
def trigger_death_particles(self, animation_player, position, particle_type, groups):
animation_player.generate_particles(
particle_type, position, groups)
def wave_value(self):
value = sin(pygame.time.get_ticks())
if value >= 0:

View file

@ -0,0 +1,27 @@
import os
import pygame
from configs.game.monster_config import monster_data
class AudioHandler:
def __init__(self, sprite_type, monster_name=None):
script_dir = os.path.dirname(os.path.abspath(__file__))
asset_path = os.path.join(
script_dir, '../../..', 'assets', 'audio')
if sprite_type == 'player':
pass
elif sprite_type == 'enemy':
# Sounds
self.attack_sound = pygame.mixer.Sound(
monster_data[monster_name]['attack_sound'])
self.death_sound = pygame.mixer.Sound(
f'{asset_path}/death.wav')
self.hit_sound = pygame.mixer.Sound(f'{asset_path}/hit.wav')
self.death_sound.set_volume(0.2)
self.hit_sound.set_volume(0.2)
self.attack_sound.set_volume(0.2)

View file

@ -3,7 +3,6 @@ import pygame
from effects.weapon_effects import Weapon
from effects.magic_effects import MagicPlayer
from effects.particle_effects import AnimationPlayer
from configs.game.weapon_config import weapon_data
from configs.game.spell_config import magic_data
@ -11,11 +10,12 @@ from configs.game.spell_config import magic_data
class CombatHandler:
def __init__(self):
def __init__(self, animation_player):
self.animation_player = animation_player
# Setup Combat
self.animation_player = AnimationPlayer()
self.magic_player = MagicPlayer(self.animation_player)
self.magic_player = MagicPlayer(animation_player)
self.current_attack = None
# Spell and Weapon Rotation
@ -31,13 +31,13 @@ class CombatHandler:
self.invulnerability_duration = 300
# Import Sounds
# script_dir = os.path.dirname(os.path.abspath(__file__))
# asset_path = os.path.join(
# script_dir, '../../..', 'assets', 'audio')
#
# self.weapon_attack_sound = pygame.mixer.Sound(
# f"{asset_path}/sword.wav")
# self.weapon_attack_sound.set_volume(0.2)
script_dir = os.path.dirname(os.path.abspath(__file__))
asset_path = os.path.join(
script_dir, '../../..', 'assets', 'audio')
self.weapon_attack_sound = pygame.mixer.Sound(
f"{asset_path}/sword.wav")
self.weapon_attack_sound.set_volume(0.2)
def create_attack_sprite(self, player):
self.current_attack = Weapon(
@ -49,7 +49,6 @@ class CombatHandler:
self.current_attack = None
def create_magic_sprite(self, player, style, strength, cost):
print(style)
if style == 'heal':
self.magic_player.heal(player, strength, cost, [
player.visible_sprites])

View file

@ -1,29 +1,18 @@
from configs.game.player_config import stats, max_stats, upgrade_costs
from configs.game.monster_config import monster_data
class StatsHandler:
def __init__(self):
self.stats = {
'health': 100,
'energy': 60,
'attack': 10,
'magic': 4,
'speed': 5
}
def __init__(self, sprite_type, monster_name=None):
self.max_stats = {
'health': 300,
'energy': 150,
'attack': 20,
'magic': 10,
'speed': 10
}
if sprite_type == 'player':
self.upgrade_costs = {
'health': 100,
'energy': 100,
'attack': 100,
'magic': 100,
'speed': 100
}
self.stats = stats
self.max_stats = max_stats
self.upgrade_costs = upgrade_costs
self.health = self.stats['health']
self.energy = self.stats['energy']
@ -32,9 +21,21 @@ class StatsHandler:
self.speed = self.stats['speed']
self.exp = 10000
if sprite_type == 'enemy':
self.monster_info = monster_data[monster_name]
self.health = self.monster_info['health']
self.attack = self.monster_info['attack']
self.attack_type = self.monster_info['attack_type']
self.attack_radius = self.monster_info['attack_radius']
self.speed = self.monster_info['speed']
self.knockback = self.monster_info['knockback']
self.notice_radius = self.monster_info['notice_radius']
self.exp = self.monster_info['exp']
def energy_recovery(self):
if self.energy < self.stats['energy']:
self.energy += 0.01 * self.stats['magic']
self.energy += 0.01 * self.magic
else:
self.energy = self.stats['energy']

92
game/entities/enemy.py Normal file
View file

@ -0,0 +1,92 @@
import pygame
from .components.animaton import AnimationHandler
from .components.stats import StatsHandler
from .components._input import InputHandler
from effects.particle_effects import AnimationPlayer
from .components.audio import AudioHandler
class Enemy(pygame.sprite.Sprite):
def __init__(self, name, position, groups, visible_sprites, obstacle_sprites):
super().__init__(groups)
self.sprite_type = "enemy"
self.name = name
self.visible_sprites = visible_sprites
# Setup Graphics
self.audio = AudioHandler(self.sprite_type, self.name)
self.animation_player = AnimationPlayer()
self.animation = AnimationHandler(self.sprite_type, self.name)
self.animation.import_assets(position)
self.status = self.animation.status
self.image = self.animation.image
self.rect = self.animation.rect
# Setup Inputs
self._input = InputHandler(
self.sprite_type, self.animation_player)
# Setup Stats
self.stats = StatsHandler(self.sprite_type, self.name)
self.obstacle_sprites = obstacle_sprites
self.distance_direction_from_player = None
self.kills = 0
def get_action(self):
player_distance = sorted(
self.distance_direction_from_player, key=lambda x: x[0])[0]
if player_distance[0] < self.stats.notice_radius and player_distance[0] >= self.stats.attack_radius:
self._input.movement.direction = player_distance[1]
self.animation.status = "move"
self._input.movement.move(
self.stats.speed, self.animation.hitbox, self.obstacle_sprites, self.animation.rect)
elif player_distance[0] <= self.stats.attack_radius:
self.animation.status = 'attack'
else:
self.animation.status = 'idle'
def add_exp(self, player):
player.stats.exp += self.stats.exp
def check_death(self, player):
if self.stats.health <= 0:
self.add_exp(player)
self.animation.trigger_death_particles(
self.animation_player, self.rect.center, self.name, self.visible_sprites)
self.audio.death_sound.play()
self.kill()
def get_damaged(self, player, attack_type):
if self._input.combat.vulnerable:
self.audio.hit_sound.play()
for _, direction, attacking_player in self.distance_direction_from_player:
if attacking_player == player:
self._input.movement.direction = -direction
self._input.movement.move(
self.stats.speed * self.stats.knockback, self.animation.hitbox, self.obstacle_sprites, self.animation.rect)
break
if attack_type == 'weapon':
self.stats.health -= player.get_full_weapon_damage()
else:
self.stats.health -= player.get_full_magic_damage()
self.check_death(player)
self._input.combat.hurt_time = pygame.time.get_ticks()
self._input.combat.vulnerable = False
def update(self):
self.get_action()
self.status = self.animation.status
self.animation.animate(self.status, self._input.combat.vulnerable)
self.image = self.animation.image
self.rect = self.animation.rect
self._input.cooldowns(self._input.combat.vulnerable)

View file

@ -1,14 +1,19 @@
import pygame
from random import randint
from configs.game.weapon_config import weapon_data
from configs.game.spell_config import magic_data
from .components.combat import CombatHandler
from .components.stats import StatsHandler
from .components._input import InputHandler
from .components.animaton import AnimationHandler
from effects.particle_effects import AnimationPlayer
class Player(pygame.sprite.Sprite):
def __init__(self, position, groups, obstacle_sprites, visible_sprites, attack_sprites):
def __init__(self, position, groups, obstacle_sprites, visible_sprites, attack_sprites, attackable_sprites):
super().__init__(groups)
# Setup Sprites
@ -16,32 +21,33 @@ class Player(pygame.sprite.Sprite):
self.visible_sprites = visible_sprites
self.attack_sprites = attack_sprites
self.obstacle_sprites = obstacle_sprites
self.status = 'down'
self.attackable_sprites = attackable_sprites
# Setup Graphics
self.animation_player = AnimationPlayer()
self.animation = AnimationHandler(self.sprite_type)
self.animation.import_assets(position)
self.image = self.animation.image
self.rect = self.animation.rect
# Setup Inputs
self._input = InputHandler(
self.sprite_type, self.status)
# Setup Graphics
self.animation = AnimationHandler()
self.animation.import_assets(self.sprite_type, position)
self.animate = self.animation.animate
self.image = self.animation.image
self.animate(self.status, self._input.combat.vulnerable)
self.rect = self.animation.rect
self.sprite_type, self.animation_player) # , self.status)
# Setup Stats
self.stats = StatsHandler()
self.stats = StatsHandler(self.sprite_type)
self.distance_direction_from_enemy = None
def get_status(self):
if self._input.movement.direction.x == 0 and self._input.movement.direction.y == 0:
if not 'idle' in self.status and not 'attack' in self.status:
if 'idle' not in self.status and 'attack' not in self.status:
self.status += '_idle'
if self._input.attacking:
self._input.movement.direction.x = 0
self._input.movement.direction.y = 0
if not 'attack' in self.status:
if 'attack' not in self.status:
if 'idle' in self.status:
self.status = self.status.replace('idle', 'attack')
else:
@ -50,10 +56,38 @@ class Player(pygame.sprite.Sprite):
if 'attack' in self.status:
self.status = self.status.replace('_attack', '')
def attack_logic(self):
if self.attack_sprites:
for attack_sprite in self.attack_sprites:
collision_sprites = pygame.sprite.spritecollide(
attack_sprite, self.attackable_sprites, False)
if collision_sprites:
for target_sprite in collision_sprites:
if target_sprite.sprite_type == 'grass':
pos = target_sprite.rect.center
offset = pygame.math.Vector2(0, 75)
for leaf in range(randint(3, 6)):
self.animation_player.create_grass_particles(
position=pos - offset, groups=[self.visible_sprites])
target_sprite.kill()
else:
target_sprite.get_damaged(
self, attack_sprite.sprite_type)
def get_full_weapon_damage(self):
base_damage = self.stats.attack
weapon_damage = weapon_data[self._input.combat.weapon]['damage']
return (base_damage + weapon_damage)
def get_full_magic_damage(self):
base_damage = self.stats.magic
spell_damage = magic_data[self._input.combat.magic]['strength']
return (base_damage + spell_damage)
def update(self):
# Refresh objects based on input
self._input.check_input(
self.stats.stats['speed'], self.animation.hitbox, self.obstacle_sprites, self.animation.rect, self)
self.stats.speed, self.animation.hitbox, self.obstacle_sprites, self.animation.rect, self)
self.status = self._input.status
# Animate

View file

@ -1,6 +1,6 @@
import pygame
from .ui_settings import *
from .ui_settings import UI_FONT, UI_FONT_SIZE, TEXT_COLOR, TEXT_COLOR_SELECTED, UPGRADE_BG_COLOR_SELECTED, UI_BORDER_COLOR, UI_BG_COLOR, BAR_COLOR_SELECTED, BAR_COLOR
class Upgrade:

View file

@ -1,11 +1,8 @@
import os
import pygame
from random import choice, randint
from random import choice
from configs.game.spell_config import magic_data
from configs.game.weapon_config import weapon_data
from configs.game.monster_config import monster_data
from configs.system.window_config import TILESIZE
from utils.debug import debug
@ -14,12 +11,9 @@ from utils.resource_loader import import_csv_layout, import_folder
from interface.ui import UI
from interface.upgrade import Upgrade
from effects.magic_effects import MagicPlayer
from effects.particle_effects import AnimationPlayer
from effects.weapon_effects import Weapon
from entities.observer import Observer
from entities.player import Player
from entities.enemy import Enemy
from .terrain import Tile
from .camera import Camera
@ -48,6 +42,9 @@ class Level:
self.ui = UI()
self.upgrade = Upgrade(self.player)
self.get_players_enemies()
self.get_distance_direction()
def create_map(self):
script_dir = os.path.dirname(os.path.abspath(__file__))
asset_path = os.path.join(
@ -92,28 +89,85 @@ class Level:
elif col == '394':
# Player Generation
self.player = Player(
(x, y), [self.visible_sprites], self.obstacle_sprites, self.visible_sprites, self.attack_sprites)
(x, y), [self.visible_sprites], self.obstacle_sprites, self.visible_sprites, self.attack_sprites, self.attackable_sprites)
else:
pass
# monster generation
# Monster Generation
if col == '390':
monster_name = 'bamboo'
elif col == '391':
monster_name = 'spirit'
elif col == '392':
monster_name = 'raccoon'
else:
monster_name = 'squid'
Enemy(monster_name, (x, y), [
self.visible_sprites, self.attackable_sprites], self.visible_sprites, self.obstacle_sprites)
def get_players_enemies(self):
self.player_sprites = [sprite for sprite in self.visible_sprites.sprites(
) if hasattr(sprite, 'sprite_type') and sprite.sprite_type in ('player')]
self.enemy_sprites = [sprite for sprite in self.visible_sprites.sprites(
) if hasattr(sprite, 'sprite_type') and sprite.sprite_type in ('enemy')]
def get_distance_direction(self):
for player in self.player_sprites:
player.distance_direction_from_enemy = []
for enemy in self.enemy_sprites:
enemy.distance_direction_from_player = []
for player in self.player_sprites:
player_vector = pygame.math.Vector2(player.rect.center)
for enemy in self.enemy_sprites:
enemy_vector = pygame.math.Vector2(enemy.rect.center)
distance = (player_vector - enemy_vector).magnitude()
if distance > 0:
direction = (player_vector - enemy_vector).normalize()
else:
direction = pygame.math.Vector2()
enemy.distance_direction_from_player.append(
(distance, direction, player))
player.distance_direction_from_enemy.append(
(distance, -direction, enemy))
def apply_damage_to_player(self):
for enemy in self.enemy_sprites:
for distance, _, player in enemy.distance_direction_from_player:
if distance < enemy.stats.attack_radius and player._input.combat.vulnerable:
player.stats.health -= enemy.stats.attack
player._input.combat.vulnerable = False
player._input.combat.hurt_time = pygame.time.get_ticks()
def toggle_menu(self):
self.game_paused = not self.game_paused
def run(self):
def run(self, who='observer'):
# Draw the game
if who == 'observer':
self.visible_sprites.custom_draw(self.observer)
self.ui.display(self.observer)
elif who == 'player':
self.visible_sprites.custom_draw(self.player)
self.ui.display(self.player)
debug(self.player.status)
debug('v0.5')
if not self.game_paused:
# Update the game
# self.player.distance_direction_to_player = self.get_state()
for player in self.player_sprites:
player.attack_logic()
self.get_players_enemies()
self.get_distance_direction()
self.apply_damage_to_player()
self.visible_sprites.update()
# self.visible_sprites.enemy_update(self.player)
# self.player_attack_logic()
else:
if self.visible_sprites.sprite_type == 'player':
self.upgrade.display()
if self.player.stats.health <= 0:

View file

@ -2,10 +2,12 @@ import pygame
import sys
from configs.system.window_config import WIDTH, HEIGHT, WATER_COLOR, FPS
from utils.debug import debug
from level.level import Level
import os
import psutil
class Game:
@ -13,16 +15,17 @@ class Game:
pygame.init()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
self.screen = pygame.display.set_mode(
(WIDTH, HEIGHT))
pygame.display.set_caption('Pneuma')
self.clock = pygame.time.Clock()
self.level = Level()
# # Sound
# main_sound = pygame.mixer.Sound('../assets/audio/main.ogg')
# main_sound.set_volume(0.4)
# main_sound.play(loops=-1)
# Sound
main_sound = pygame.mixer.Sound('../assets/audio/main.ogg')
main_sound.set_volume(0.4)
main_sound.play(loops=-1)
def run(self):
@ -35,7 +38,7 @@ class Game:
self.level.toggle_menu()
self.screen.fill(WATER_COLOR)
self.level.run()
self.level.run('player')
pygame.display.update()
self.clock.tick(FPS)

View file

@ -1,5 +1,6 @@
import pygame
import sys
import os
from utils.settings import *
from utils.debug import debug
@ -7,13 +8,15 @@ from utils.debug import debug
from objects.level import Level
class Game:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
self.screen = pygame.display.set_mode(
(WIDTH, HEIGHT))
pygame.display.set_caption('Pneuma')
self.clock = pygame.time.Clock()
@ -43,6 +46,5 @@ class Game:
if __name__ == '__main__':
game = Game()
figure_file = 'rl/plots/pneuma.png'
while True:
game.run()