Found huge bug, updated some basic stuff
BIN
.DS_Store
vendored
BIN
agents/ppo/.DS_Store
vendored
Normal file
BIN
assets/.DS_Store
vendored
Normal file
BIN
assets/graphics/.DS_Store
vendored
Normal file
BIN
assets/graphics/particles/.DS_Store
vendored
Normal file
BIN
assets/map/.DS_Store
vendored
Normal file
|
@ -18,8 +18,8 @@
|
|||
-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,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,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,500,-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,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,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,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,-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,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
|
||||
|
|
|
63
camera.py
|
@ -11,9 +11,7 @@ class Camera(pygame.sprite.Group):
|
|||
|
||||
# General Setup
|
||||
self.display_surface = pygame.display.get_surface()
|
||||
self.half_width = self.display_surface.get_size()[0] // 2
|
||||
self.half_height = self.display_surface.get_size()[1] // 2
|
||||
self.offset = pygame.math.Vector2(100, 200)
|
||||
self.display_size = self.display_surface.get_size()
|
||||
|
||||
self.floor_surf = pygame.image.load(
|
||||
import_assets(
|
||||
|
@ -25,32 +23,45 @@ class Camera(pygame.sprite.Group):
|
|||
|
||||
self.floor_rect = self.floor_surf.get_rect(topleft=(0, 0))
|
||||
|
||||
def custom_draw(self, entity):
|
||||
self.calculate_scale()
|
||||
|
||||
self.sprite_type = entity.sprite_type
|
||||
# Getting the offset
|
||||
if hasattr(entity, 'animation'):
|
||||
self.offset.x = entity.animation.rect.centerx - self.half_width
|
||||
def calculate_scale(self):
|
||||
map_width, map_height = self.floor_rect.size
|
||||
screen_width, screen_height = self.display_size
|
||||
|
||||
self.offset.y = entity.animation.rect.centery - self.half_height
|
||||
# Calculating the scale to fit the map on the screen
|
||||
self.scale = min(screen_width / map_width, screen_height / map_height)
|
||||
self.scaled_floor_surf = pygame.transform.scale(self.floor_surf,
|
||||
(int(map_width * self.scale),
|
||||
int(map_height * self.scale)))
|
||||
self.scaled_floor_rect = self.scaled_floor_surf.get_rect()
|
||||
|
||||
else:
|
||||
self.offset.x = entity.rect.centerx - self.half_width
|
||||
|
||||
self.offset.y = entity.rect.centery - self.half_height
|
||||
|
||||
# Drawing the floor
|
||||
floor_offset_pos = self.floor_rect.topleft - self.offset
|
||||
self.display_surface.blit(self.floor_surf, floor_offset_pos)
|
||||
|
||||
for sprite in sorted(self.sprites(),
|
||||
key=lambda sprite: sprite.animation.rect.centery
|
||||
if hasattr(sprite, 'animation')
|
||||
else sprite.rect.centery):
|
||||
def custom_draw(self):
|
||||
# Drawing the scaled floor
|
||||
self.display_surface.blit(
|
||||
self.scaled_floor_surf, self.scaled_floor_rect.topleft)
|
||||
|
||||
for sprite in sorted(self.sprites(), key=lambda sprite: sprite.rect.centery if not hasattr(sprite, 'animation') else sprite.animation.rect.centery):
|
||||
# Check for sprites with 'animation' attribute
|
||||
if hasattr(sprite, 'animation'):
|
||||
offset_pos = sprite.animation.rect.topleft - self.offset
|
||||
self.display_surface.blit(sprite.animation.image, offset_pos)
|
||||
scaled_sprite_image = pygame.transform.scale(sprite.animation.image,
|
||||
(int(sprite.animation.rect.width * self.scale),
|
||||
int(sprite.animation.rect.height * self.scale)))
|
||||
scaled_position = (int(sprite.animation.rect.x * self.scale),
|
||||
int(sprite.animation.rect.y * self.scale))
|
||||
for sprite in sorted(self.sprites(), key=lambda sprite: sprite.rect.centery if not hasattr(sprite, 'animation') else sprite.animation.rect.centery):
|
||||
# Check for sprites with 'animation' attribute
|
||||
if hasattr(sprite, 'animation'):
|
||||
scaled_sprite_image = pygame.transform.scale(sprite.animation.image,
|
||||
(int(sprite.animation.rect.width * self.scale),
|
||||
int(sprite.animation.rect.height * self.scale)))
|
||||
scaled_position = (int(sprite.animation.rect.x * self.scale),
|
||||
int(sprite.animation.rect.y * self.scale))
|
||||
else:
|
||||
offset_pos = sprite.rect.topleft - self.offset
|
||||
self.display_surface.blit(sprite.image, offset_pos)
|
||||
scaled_sprite_image = pygame.transform.scale(sprite.image,
|
||||
(int(sprite.rect.width * self.scale),
|
||||
int(sprite.rect.height * self.scale)))
|
||||
scaled_position = (int(sprite.rect.x * self.scale),
|
||||
int(sprite.rect.y * self.scale))
|
||||
|
||||
self.display_surface.blit(scaled_sprite_image, scaled_position)
|
||||
|
|
BIN
configs/.DS_Store
vendored
Normal file
BIN
effects/.DS_Store
vendored
Normal file
BIN
entities/.DS_Store
vendored
Normal file
|
@ -148,14 +148,6 @@ class Player(pygame.sprite.Sprite):
|
|||
|
||||
def get_current_state(self):
|
||||
|
||||
def fermi(x, a):
|
||||
# Used for rescaling features
|
||||
return 1 / (np.exp((x - a)) + 1)
|
||||
|
||||
def maxwell(x, a):
|
||||
# Used for rescaling features
|
||||
return 1 / np.exp((x - a) / a)
|
||||
|
||||
if self.distance_direction_from_enemy != []:
|
||||
sorted_distances = sorted(
|
||||
self.distance_direction_from_enemy, key=lambda x: x[0])
|
||||
|
@ -166,32 +158,11 @@ class Player(pygame.sprite.Sprite):
|
|||
|
||||
self.action_features = [self._input.action]
|
||||
|
||||
self.reward = [
|
||||
np.log(1 + self.stats.exp) if self.stats.exp >= 0 else -10,
|
||||
|
||||
fermi(nearest_dist, 300),
|
||||
|
||||
fermi(
|
||||
nearest_enemy.stats.health,
|
||||
nearest_enemy.stats.monster_info['health']
|
||||
),
|
||||
|
||||
maxwell(
|
||||
len(self.distance_direction_from_enemy),
|
||||
self.max_num_enemies
|
||||
) - 1,
|
||||
|
||||
- fermi(
|
||||
self.stats.health,
|
||||
self.stats.stats['health']
|
||||
)
|
||||
]
|
||||
|
||||
# self.reward = self.stats.exp\
|
||||
# + self.stats.health/self.stats.stats['health'] - 1\
|
||||
# - nearest_dist/np.sqrt(np.sum(self.map_edge))\
|
||||
# - nearest_enemy.stats.health/nearest_enemy.stats.monster_info['health']\
|
||||
# - 2*len(self.distance_direction_from_enemy)/self.max_num_enemies
|
||||
self.reward = self.stats.exp\
|
||||
+ self.stats.health/self.stats.stats['health'] - 1\
|
||||
- nearest_dist/np.sqrt(np.sum(self.map_edge))\
|
||||
- nearest_enemy.stats.health/nearest_enemy.stats.monster_info['health']\
|
||||
- 2*len(self.distance_direction_from_enemy)/self.max_num_enemies
|
||||
|
||||
self.state_features = [
|
||||
self.animation.rect.center[0]/self.map_edge[0],
|
||||
|
@ -204,10 +175,8 @@ class Player(pygame.sprite.Sprite):
|
|||
|
||||
]
|
||||
|
||||
enemy_states = []
|
||||
|
||||
for distance, direction, enemy in self.distance_direction_from_enemy:
|
||||
enemy_states.extend([
|
||||
self.state_features.extend([
|
||||
|
||||
distance/np.sqrt(np.sum(self.map_edge)),
|
||||
|
||||
|
@ -215,14 +184,12 @@ class Player(pygame.sprite.Sprite):
|
|||
|
||||
direction[1],
|
||||
|
||||
nearest_enemy.stats.health /
|
||||
nearest_enemy.stats.monster_info['health'],
|
||||
enemy.stats.health /
|
||||
enemy.stats.monster_info['health'],
|
||||
|
||||
enemy.stats.exp,
|
||||
])
|
||||
|
||||
self.state_features.extend(enemy_states)
|
||||
|
||||
if hasattr(self, 'num_features'):
|
||||
while len(self.state_features) < self.num_features:
|
||||
self.state_features.append(0)
|
||||
|
@ -255,7 +222,7 @@ class Player(pygame.sprite.Sprite):
|
|||
self)
|
||||
|
||||
self.agent.remember(self.state_features, action,
|
||||
probs, value, self.stats.exp, self.is_dead())
|
||||
probs, value, self.reward, self.is_dead())
|
||||
|
||||
self.get_current_state()
|
||||
|
||||
|
|
|
@ -27,4 +27,5 @@ class Terrain(pygame.sprite.Sprite):
|
|||
topleft=(position[0], position[1] - TILESIZE))
|
||||
else:
|
||||
self.rect = self.image.get_rect(topleft=position)
|
||||
|
||||
self.hitbox = self.rect.inflate(HITBOX_OFFSET[sprite_type])
|
||||
|
|
BIN
figures/.DS_Store
vendored
Normal file
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
20
game.py
|
@ -1,16 +1,13 @@
|
|||
import os
|
||||
|
||||
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
|
||||
|
||||
import sys
|
||||
import pygame
|
||||
|
||||
from level import Level
|
||||
|
||||
from configs.system.window_config import WIDTH,\
|
||||
HEIGHT,\
|
||||
WATER_COLOR,\
|
||||
FPS
|
||||
from level import Level
|
||||
import pygame
|
||||
import sys
|
||||
import os
|
||||
|
||||
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
|
||||
|
||||
|
||||
class Game:
|
||||
|
@ -44,8 +41,6 @@ class Game:
|
|||
|
||||
def run(self):
|
||||
|
||||
self.clock = pygame.time.Clock()
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
self.quit()
|
||||
|
@ -55,10 +50,9 @@ class Game:
|
|||
|
||||
self.screen.fill(WATER_COLOR)
|
||||
|
||||
self.level.run('observer', self.clock.get_fps())
|
||||
self.level.run()
|
||||
|
||||
pygame.display.update()
|
||||
self.clock.tick(FPS)
|
||||
|
||||
def quit(self):
|
||||
pygame.quit()
|
||||
|
|
|
@ -108,24 +108,5 @@ class UI:
|
|||
|
||||
self.display_surface.blit(magic_surf, magic_rect)
|
||||
|
||||
def display(self, player):
|
||||
if player.sprite_type == 'player':
|
||||
self.show_bar(
|
||||
player.stats.health,
|
||||
player.stats.stats['health'],
|
||||
self.health_bar_rect,
|
||||
HEALTH_COLOR)
|
||||
|
||||
self.show_bar(
|
||||
player.stats.energy,
|
||||
player.stats.stats['energy'],
|
||||
self.energy_bar_rect,
|
||||
ENERGY_COLOR)
|
||||
|
||||
self.show_exp(player.stats.exp)
|
||||
self.weapon_overlay(player._input.combat.weapon_index,
|
||||
player._input.can_rotate_weapon)
|
||||
self.magic_overlay(player._input.combat.magic_index,
|
||||
player._input.can_swap_magic)
|
||||
if player.sprite_type == 'camera':
|
||||
self.show_exp(player.exp)
|
||||
def display(self):
|
||||
self.show_exp(-1)
|
||||
|
|
95
level.py
|
@ -85,50 +85,41 @@ class Level:
|
|||
|
||||
elif col != '700':
|
||||
Terrain((x, y),
|
||||
[self.obstacle_sprites,
|
||||
self.visible_sprites],
|
||||
[self.obstacle_sprites],
|
||||
'invisible')
|
||||
elif col == '700' and self.n_players > 1:
|
||||
print(f"Prison set at:{(x, y)}")
|
||||
# Generate grass
|
||||
# if style == 'grass':
|
||||
# random_grass_image = choice(self.graphics['grass'])
|
||||
#
|
||||
# Terrain((x, y), [
|
||||
# self.visible_sprites,
|
||||
# self.obstacle_sprites,
|
||||
# self.attackable_sprites
|
||||
# ],
|
||||
# 'grass',
|
||||
# random_grass_image)
|
||||
if style == 'grass':
|
||||
random_grass_image = choice(self.graphics['grass'])
|
||||
|
||||
Terrain((x, y), [
|
||||
self.visible_sprites,
|
||||
self.obstacle_sprites,
|
||||
self.attackable_sprites
|
||||
],
|
||||
'grass',
|
||||
random_grass_image)
|
||||
|
||||
# Generate objects like trees and statues
|
||||
# if style == 'objects':
|
||||
# surface = self.graphics['objects'][int(col)]
|
||||
# Terrain((x, y), [
|
||||
# self.visible_sprites,
|
||||
# self.obstacle_sprites
|
||||
# ],
|
||||
# 'object',
|
||||
# surface)
|
||||
if style == 'objects':
|
||||
surface = self.graphics['objects'][int(col)]
|
||||
Terrain((x, y), [
|
||||
self.visible_sprites,
|
||||
self.obstacle_sprites
|
||||
],
|
||||
'object',
|
||||
surface)
|
||||
|
||||
# Generate observer, players and monsters
|
||||
if style == 'entities':
|
||||
|
||||
# Generate observer
|
||||
if col == '500':
|
||||
self.observer = Observer(
|
||||
(x, y),
|
||||
[self.visible_sprites]
|
||||
)
|
||||
|
||||
# Generate player(s)
|
||||
# TODO: Make a way to generate players in random locations
|
||||
elif col == '400':
|
||||
if col == '400':
|
||||
self.possible_player_locations.append((x, y))
|
||||
# Monster generation
|
||||
|
||||
else:
|
||||
# Monster generation
|
||||
elif col in ['390', '391', '392', '393']:
|
||||
if col == '390':
|
||||
monster_name = 'bamboo'
|
||||
elif col == '391':
|
||||
|
@ -171,28 +162,22 @@ class Level:
|
|||
if int(col) != -1:
|
||||
x = col_index * TILESIZE
|
||||
y = row_index * TILESIZE
|
||||
# # Regenerate grass
|
||||
# if style == 'grass':
|
||||
# random_grass_image = choice(
|
||||
# self.graphics['grass'])
|
||||
#
|
||||
# Terrain((x, y), [
|
||||
# self.visible_sprites,
|
||||
# self.obstacle_sprites,
|
||||
# self.attackable_sprites
|
||||
# ],
|
||||
# 'grass',
|
||||
# random_grass_image)
|
||||
# Regenerate grass
|
||||
if style == 'grass':
|
||||
random_grass_image = choice(
|
||||
self.graphics['grass'])
|
||||
|
||||
Terrain((x, y), [
|
||||
self.visible_sprites,
|
||||
self.obstacle_sprites,
|
||||
self.attackable_sprites
|
||||
],
|
||||
'grass',
|
||||
random_grass_image)
|
||||
|
||||
if style == 'entities':
|
||||
|
||||
if col == '500':
|
||||
continue
|
||||
|
||||
if col == '400':
|
||||
continue
|
||||
|
||||
else:
|
||||
if col in ['390', '391', '392', '393']:
|
||||
if col == '390':
|
||||
monster_name = 'bamboo'
|
||||
elif col == '391':
|
||||
|
@ -287,12 +272,10 @@ class Level:
|
|||
def toggle_pause(self):
|
||||
self.paused = not self.paused
|
||||
|
||||
def run(self, who='observer', fps='v0.9'):
|
||||
def run(self):
|
||||
# Draw the game
|
||||
self.visible_sprites.custom_draw(self.observer)
|
||||
self.ui.display(self.observer)
|
||||
|
||||
debug(f"{fps}")
|
||||
self.visible_sprites.custom_draw()
|
||||
self.ui.display()
|
||||
|
||||
if not self.paused:
|
||||
# Update the game
|
||||
|
@ -310,7 +293,7 @@ class Level:
|
|||
|
||||
for player in self.player_sprites:
|
||||
if player.is_dead():
|
||||
print(f"\nPlayer {player.player_id} is dead")
|
||||
print(f"\nPlayer {player.player_id} is dead\n")
|
||||
player.stats.exp = -10
|
||||
player.update()
|
||||
self.dead_players[player.player_id] = player.is_dead()
|
||||
|
|
|
@ -182,8 +182,7 @@ if __name__ == "__main__":
|
|||
|
||||
for player in game.level.player_sprites:
|
||||
|
||||
episode_reward[player.player_id][step] = np.mean(
|
||||
player.reward)
|
||||
episode_reward[player.player_id][step] = player.reward
|
||||
|
||||
if (step % horizon == 0 and step != 0) or player.is_dead():
|
||||
|
||||
|
|