Ready to build AI
This commit is contained in:
parent
b0a925292e
commit
ba0cc46841
10 changed files with 170 additions and 48 deletions
|
@ -19,7 +19,7 @@
|
|||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,390,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,390,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,394,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,400,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,395,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,393,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,390,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||
-1,-1,-1,-1,-1,-1,390,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
||||
|
|
|
|
@ -6,7 +6,7 @@ asset_path = os.path.join(
|
|||
script_dir, '../../..', 'assets')
|
||||
|
||||
monster_data = {
|
||||
'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}}
|
||||
'squid': {'id': 1, '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': {'id': 2, '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': {'id': 3, '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': {'id': 4, '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}}
|
||||
|
|
|
@ -1,4 +1,23 @@
|
|||
stats = {
|
||||
tank_stats = {
|
||||
'role_id': 1,
|
||||
'health': 150,
|
||||
'energy': 40,
|
||||
'attack': 7,
|
||||
'magic': 3,
|
||||
'speed': 3
|
||||
}
|
||||
|
||||
mage_stats = {
|
||||
'role_id': 2,
|
||||
'health': 70,
|
||||
'energy': 80,
|
||||
'attack': 3,
|
||||
'magic': 6,
|
||||
'speed': 5
|
||||
}
|
||||
|
||||
warrior_stats = {
|
||||
'role_id': 3,
|
||||
'health': 100,
|
||||
'energy': 60,
|
||||
'attack': 10,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# game setup
|
||||
WIDTH = 1280
|
||||
HEIGHT = 720
|
||||
FPS = 60
|
||||
FPS = 500
|
||||
TILESIZE = 64
|
||||
HITBOX_OFFSET = {
|
||||
'player': (-6, -26),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import pygame
|
||||
from random import randint
|
||||
from random import randint, choice
|
||||
|
||||
from configs.game.spell_config import magic_data
|
||||
from configs.game.weapon_config import weapon_data
|
||||
|
@ -11,7 +11,7 @@ from .combat import CombatHandler
|
|||
class InputHandler:
|
||||
|
||||
# , status):
|
||||
def __init__(self, sprite_type, animation_player):
|
||||
def __init__(self, sprite_type, animation_player, ai_controller=False):
|
||||
self.status = 'down'
|
||||
self.sprite_type = sprite_type
|
||||
|
||||
|
@ -41,27 +41,27 @@ class InputHandler:
|
|||
|
||||
keys = pygame.key.get_pressed()
|
||||
|
||||
# button = randint(0, 5)
|
||||
button = randint(0, 4)
|
||||
|
||||
self.move_time = pygame.time.get_ticks()
|
||||
|
||||
# Movement Input
|
||||
if keys[pygame.K_w]: # button == 0: # keys[pygame.K_w]:
|
||||
if button == 0: # keys[pygame.K_w]:
|
||||
self.movement.direction.y = -1
|
||||
self.status = 'up'
|
||||
self.can_move = False
|
||||
elif keys[pygame.K_s]: # button == 1: # keys[pygame.K_s]:
|
||||
elif 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 keys[pygame.K_a]: # button == 2: # keys[pygame.K_a]:
|
||||
if button == 2: # keys[pygame.K_a]:
|
||||
self.movement.direction.x = -1
|
||||
self.status = 'left'
|
||||
self.can_move = False
|
||||
elif keys[pygame.K_d]: # keys[pygame.K_d]:
|
||||
elif button == 3: # keys[pygame.K_d]:
|
||||
self.movement.direction.x = 1
|
||||
self.status = 'right'
|
||||
self.can_move = False
|
||||
|
@ -72,14 +72,14 @@ class InputHandler:
|
|||
|
||||
if self.sprite_type == 'player':
|
||||
# Combat Input
|
||||
if keys[pygame.K_e] and not self.attacking: # keys[pygame.K_e]
|
||||
if button == 4 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.combat.weapon_attack_sound.play()
|
||||
|
||||
# Magic Input
|
||||
if keys[pygame.K_q]: # keys[pygame.K_q]:
|
||||
if button == 5: # keys[pygame.K_q]:
|
||||
self.attacking = True
|
||||
self.attack_time = pygame.time.get_ticks()
|
||||
|
||||
|
@ -96,7 +96,7 @@ class InputHandler:
|
|||
|
||||
# Rotating Weapons
|
||||
# keys[pygame.K_LSHIFT]
|
||||
if keys[pygame.K_LSHIFT] and self.can_rotate_weapon:
|
||||
if button == 6 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:
|
||||
|
@ -109,7 +109,7 @@ class InputHandler:
|
|||
|
||||
# Swap Spells
|
||||
# keys[pygame.K_LCTRL] :
|
||||
if keys[pygame.K_LCTRL] and self.can_swap_magic:
|
||||
if button == 7 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:
|
||||
|
|
|
@ -1,29 +1,32 @@
|
|||
from configs.game.player_config import stats, max_stats, upgrade_costs
|
||||
from configs.game.player_config import warrior_stats, mage_stats, tank_stats
|
||||
from configs.game.monster_config import monster_data
|
||||
|
||||
|
||||
class StatsHandler:
|
||||
|
||||
def __init__(self, sprite_type, monster_name=None):
|
||||
def __init__(self, sprite_type, role=None, monster_name=None):
|
||||
|
||||
if sprite_type == 'player':
|
||||
|
||||
self.stats = stats
|
||||
|
||||
self.max_stats = max_stats
|
||||
|
||||
self.upgrade_costs = upgrade_costs
|
||||
if role == 'warrior':
|
||||
self.stats = warrior_stats
|
||||
elif role == 'tank':
|
||||
self.stats = tank_stats
|
||||
elif role == 'mage':
|
||||
self.stats = mage_stats
|
||||
|
||||
self.role_id = self.stats['role_id']
|
||||
self.health = self.stats['health']
|
||||
self.energy = self.stats['energy']
|
||||
self.attack = self.stats['attack']
|
||||
self.magic = self.stats['magic']
|
||||
self.speed = self.stats['speed']
|
||||
self.exp = 10000
|
||||
self.exp = 0
|
||||
|
||||
if sprite_type == 'enemy':
|
||||
|
||||
self.monster_info = monster_data[monster_name]
|
||||
self.monster_id = self.monster_info['id']
|
||||
self.health = self.monster_info['health']
|
||||
self.attack = self.monster_info['attack']
|
||||
self.attack_type = self.monster_info['attack_type']
|
||||
|
|
|
@ -22,7 +22,6 @@ class Enemy(pygame.sprite.Sprite):
|
|||
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
|
||||
|
||||
|
@ -31,13 +30,11 @@ class Enemy(pygame.sprite.Sprite):
|
|||
self.sprite_type, self.animation_player)
|
||||
|
||||
# Setup Stats
|
||||
self.stats = StatsHandler(self.sprite_type, self.name)
|
||||
self.stats = StatsHandler(self.sprite_type, monster_name=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]
|
||||
|
@ -83,9 +80,9 @@ class Enemy(pygame.sprite.Sprite):
|
|||
def update(self):
|
||||
|
||||
self.get_action()
|
||||
self.status = self.animation.status
|
||||
|
||||
self.animation.animate(self.status, self._input.combat.vulnerable)
|
||||
self.animation.animate(self.animation.status,
|
||||
self._input.combat.vulnerable)
|
||||
self.image = self.animation.image
|
||||
self.rect = self.animation.rect
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ from effects.particle_effects import AnimationPlayer
|
|||
|
||||
class Player(pygame.sprite.Sprite):
|
||||
|
||||
def __init__(self, position, groups, obstacle_sprites, visible_sprites, attack_sprites, attackable_sprites):
|
||||
def __init__(self, position, groups, obstacle_sprites, visible_sprites, attack_sprites, attackable_sprites, role):
|
||||
super().__init__(groups)
|
||||
|
||||
# Setup Sprites
|
||||
|
@ -35,7 +35,8 @@ class Player(pygame.sprite.Sprite):
|
|||
self.sprite_type, self.animation_player) # , self.status)
|
||||
|
||||
# Setup Stats
|
||||
self.stats = StatsHandler(self.sprite_type)
|
||||
self.role = role
|
||||
self.stats = StatsHandler(self.sprite_type, self.role)
|
||||
|
||||
self.distance_direction_from_enemy = None
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ class Level:
|
|||
|
||||
# UI setup
|
||||
self.ui = UI()
|
||||
self.upgrade = Upgrade(self.player)
|
||||
# self.upgrade = Upgrade(self.player)
|
||||
|
||||
self.get_players_enemies()
|
||||
self.get_distance_direction()
|
||||
|
@ -86,10 +86,20 @@ class Level:
|
|||
self.observer = Observer(
|
||||
(x, y), [self.visible_sprites])
|
||||
|
||||
elif col == '394':
|
||||
elif col == '400':
|
||||
# Player Generation
|
||||
self.player = Player(
|
||||
(x, y), [self.visible_sprites], self.obstacle_sprites, self.visible_sprites, self.attack_sprites, self.attackable_sprites)
|
||||
Player(
|
||||
(x, y), [self.visible_sprites], self.obstacle_sprites, self.visible_sprites, self.attack_sprites, self.attackable_sprites, 'tank')
|
||||
|
||||
elif col == '401':
|
||||
# Player Generation
|
||||
Player(
|
||||
(x, y), [self.visible_sprites], self.obstacle_sprites, self.visible_sprites, self.attack_sprites, self.attackable_sprites, 'warrior')
|
||||
|
||||
elif col == '402':
|
||||
# Player Generation
|
||||
Player(
|
||||
(x, y), [self.visible_sprites], self.obstacle_sprites, self.visible_sprites, self.attack_sprites, self.attackable_sprites, 'mage')
|
||||
|
||||
else:
|
||||
# Monster Generation
|
||||
|
@ -154,7 +164,9 @@ class Level:
|
|||
elif who == 'player':
|
||||
self.visible_sprites.custom_draw(self.player)
|
||||
self.ui.display(self.player)
|
||||
debug('v0.5')
|
||||
|
||||
debug('v0.6')
|
||||
|
||||
if not self.game_paused:
|
||||
# Update the game
|
||||
for player in self.player_sprites:
|
||||
|
@ -168,7 +180,8 @@ class Level:
|
|||
# self.visible_sprites.enemy_update(self.player)
|
||||
# self.player_attack_logic()
|
||||
else:
|
||||
self.upgrade.display()
|
||||
debug('PAUSED')
|
||||
|
||||
if self.player.stats.health <= 0:
|
||||
self.__init__()
|
||||
for player in self.player_sprites:
|
||||
if player.stats.health <= 0:
|
||||
player.kill()
|
||||
|
|
101
game/main.py
101
game/main.py
|
@ -1,13 +1,12 @@
|
|||
import pygame
|
||||
import sys
|
||||
import numpy as np
|
||||
import torch
|
||||
import pygame
|
||||
|
||||
from configs.system.window_config import WIDTH, HEIGHT, WATER_COLOR, FPS
|
||||
|
||||
from level.level import Level
|
||||
|
||||
import os
|
||||
import psutil
|
||||
|
||||
|
||||
class Game:
|
||||
|
||||
|
@ -27,6 +26,90 @@ class Game:
|
|||
main_sound.set_volume(0.4)
|
||||
main_sound.play(loops=-1)
|
||||
|
||||
def extract_features(self):
|
||||
self.features = []
|
||||
for i, player in enumerate(self.level.player_sprites):
|
||||
|
||||
player_features = {
|
||||
"player_position": player.rect.center,
|
||||
"player role": player.stats.role_id,
|
||||
"player_health": player.stats.health,
|
||||
"player_energy": player.stats.energy,
|
||||
"player_attack": player.stats.attack,
|
||||
"player_magic": player.stats.magic,
|
||||
"player_speed": player.stats.speed,
|
||||
"player_exp": player.stats.exp,
|
||||
"player_vulnerable": int(player._input.combat.vulnerable),
|
||||
"player_can_move": int(player._input.can_move),
|
||||
"player_attacking": int(player._input.attacking),
|
||||
"player_can_rotate_weapon": int(player._input.can_rotate_weapon),
|
||||
"playercan_swap_magic": int(player._input.can_swap_magic)
|
||||
}
|
||||
|
||||
distances_directions = []
|
||||
|
||||
for distance, direction, enemy in player.distance_direction_from_enemy:
|
||||
distances_directions.append({
|
||||
"enemy_id": enemy.stats.monster_id,
|
||||
"enemy_status": 0 if enemy.animation.status == "idle" else (1 if enemy.animation.status == "move" else 2),
|
||||
"enemy_health": enemy.stats.health,
|
||||
"enemy_attack": enemy.stats.attack,
|
||||
"enemy_speed": enemy.stats.speed,
|
||||
"enemy_attack_radius": enemy.stats.attack_radius,
|
||||
"enemy_notice_radius": enemy.stats.notice_radius,
|
||||
"enemy_exp": enemy.stats.exp,
|
||||
"enemy_distance": distance,
|
||||
"enemy_direction": direction
|
||||
})
|
||||
|
||||
player_features["enemies"] = distances_directions
|
||||
self.features.append(player_features)
|
||||
|
||||
def convert_features_to_tensor(self):
|
||||
|
||||
self.tensors = []
|
||||
for player_features in self.features:
|
||||
info_array = []
|
||||
|
||||
# Adding player features to tensor
|
||||
player_info = [
|
||||
player_features['player_position'][0],
|
||||
player_features['player_position'][1],
|
||||
player_features['player role'],
|
||||
player_features['player_health'],
|
||||
player_features['player_energy'],
|
||||
player_features['player_attack'],
|
||||
player_features['player_magic'],
|
||||
player_features['player_speed'],
|
||||
player_features['player_exp'],
|
||||
player_features['player_vulnerable'],
|
||||
player_features['player_can_move'],
|
||||
player_features['player_attacking'],
|
||||
player_features['player_can_rotate_weapon'],
|
||||
player_features['playercan_swap_magic'],
|
||||
]
|
||||
info_array.extend(player_info)
|
||||
|
||||
for enemy in player_features['enemies']:
|
||||
enemy_info = [
|
||||
enemy['enemy_id'],
|
||||
enemy['enemy_status'],
|
||||
enemy['enemy_health'],
|
||||
enemy['enemy_attack'],
|
||||
enemy['enemy_speed'],
|
||||
enemy['enemy_attack_radius'],
|
||||
enemy['enemy_notice_radius'],
|
||||
enemy['enemy_exp'],
|
||||
enemy['enemy_distance'],
|
||||
enemy['enemy_direction'][0],
|
||||
enemy['enemy_direction'][1]
|
||||
]
|
||||
info_array.extend(enemy_info)
|
||||
|
||||
player_tensor = torch.tensor(
|
||||
np.array(info_array, dtype=np.float32))
|
||||
self.tensors.append(player_tensor)
|
||||
|
||||
def run(self):
|
||||
|
||||
for event in pygame.event.get():
|
||||
|
@ -38,7 +121,11 @@ class Game:
|
|||
self.level.toggle_menu()
|
||||
|
||||
self.screen.fill(WATER_COLOR)
|
||||
self.level.run('player')
|
||||
|
||||
self.extract_features()
|
||||
self.convert_features_to_tensor()
|
||||
|
||||
self.level.run('observer')
|
||||
pygame.display.update()
|
||||
self.clock.tick(FPS)
|
||||
|
||||
|
@ -46,5 +133,7 @@ class Game:
|
|||
if __name__ == '__main__':
|
||||
|
||||
game = Game()
|
||||
while True:
|
||||
for _ in range(0, 10000):
|
||||
game.run()
|
||||
game.extract_features()
|
||||
game.convert_features_to_tensor()
|
||||
|
|
Loading…
Reference in a new issue