Added functionnal save system and broken load system
This commit is contained in:
parent
eca6b9af1f
commit
f67eae3803
Binary file not shown.
Binary file not shown.
|
@ -5,6 +5,9 @@ from ..interfaces import FightingEntity, Map
|
|||
|
||||
|
||||
class Monster(FightingEntity):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def act(self, m: Map) -> None:
|
||||
"""
|
||||
By default, a monster will move randomly where it is possible
|
||||
|
@ -35,24 +38,32 @@ class Monster(FightingEntity):
|
|||
|
||||
|
||||
class Beaver(Monster):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
name = "beaver"
|
||||
maxhealth = 30
|
||||
strength = 2
|
||||
|
||||
|
||||
class Hedgehog(Monster):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
name = "hedgehog"
|
||||
maxhealth = 10
|
||||
strength = 3
|
||||
|
||||
|
||||
class Rabbit(Monster):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
name = "rabbit"
|
||||
maxhealth = 15
|
||||
strength = 1
|
||||
|
||||
|
||||
class TeddyBear(Monster):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
name = "teddy_bear"
|
||||
maxhealth = 50
|
||||
strength = 0
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from random import randint
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Optional,Generator
|
||||
import json
|
||||
import os
|
||||
|
||||
from .entities.player import Player
|
||||
from .enums import GameMode, KeyValues, DisplayActions
|
||||
|
@ -37,11 +39,6 @@ class Game:
|
|||
self.player.move(self.map.start_y, self.map.start_x)
|
||||
self.map.spawn_random_entities(randint(3, 10))
|
||||
|
||||
@staticmethod
|
||||
def load_game(filename: str) -> None:
|
||||
# TODO loading map from a file
|
||||
raise NotImplementedError()
|
||||
|
||||
def run(self, screen: Any) -> None:
|
||||
"""
|
||||
Main infinite loop.
|
||||
|
@ -65,7 +62,7 @@ class Game:
|
|||
if self.state == GameMode.PLAY:
|
||||
self.handle_key_pressed_play(key)
|
||||
elif self.state == GameMode.MAINMENU:
|
||||
self.main_menu.handle_key_pressed(key, self)
|
||||
self.handle_key_pressed_main_menu(key)
|
||||
elif self.state == GameMode.SETTINGS:
|
||||
self.settings_menu.handle_key_pressed(key, raw_key, self)
|
||||
self.display_actions(DisplayActions.REFRESH)
|
||||
|
@ -88,3 +85,50 @@ class Game:
|
|||
self.map.tick()
|
||||
elif key == KeyValues.SPACE:
|
||||
self.state = GameMode.MAINMENU
|
||||
|
||||
def handle_key_pressed_main_menu(self, key: KeyValues) -> None:
|
||||
"""
|
||||
In the main menu, we can navigate through options.
|
||||
"""
|
||||
if key == KeyValues.DOWN:
|
||||
self.main_menu.go_down()
|
||||
if key == KeyValues.UP:
|
||||
self.main_menu.go_up()
|
||||
if key == KeyValues.ENTER:
|
||||
option = self.main_menu.validate()
|
||||
if option == menus.MainMenuValues.START:
|
||||
self.state = GameMode.PLAY
|
||||
elif option == menus.MainMenuValues.SAVE:
|
||||
self.save_game()
|
||||
elif option == menus.MainMenuValues.LOAD:
|
||||
self.load_game()
|
||||
elif option == menus.MainMenuValues.SETTINGS:
|
||||
self.state = GameMode.SETTINGS
|
||||
elif option == menus.MainMenuValues.EXIT:
|
||||
sys.exit(0)
|
||||
|
||||
def game_to_str(self) -> str:
|
||||
d = dict()
|
||||
d["Map"] = game.map
|
||||
d["Player"] = game.player
|
||||
|
||||
def save_state(self) -> dict():
|
||||
return self.map.save_state()
|
||||
|
||||
def load_state(self, d: dict) -> None:
|
||||
self.map.load_state(d)
|
||||
|
||||
def load_game(self) -> None:
|
||||
"""
|
||||
Loads the game from a file
|
||||
"""
|
||||
if os.path.isfile("save.json"):
|
||||
with open("save.json", "r") as f:
|
||||
self.load_state(json.loads(f.read()))
|
||||
|
||||
def save_game(self) -> None:
|
||||
"""
|
||||
Save the game to a file
|
||||
"""
|
||||
with open("save.json", "w") as f:
|
||||
f.write(json.dumps(self.save_state()))
|
||||
|
|
|
@ -78,6 +78,17 @@ class Map:
|
|||
|
||||
return Map(width, height, tiles, start_y, start_x)
|
||||
|
||||
@staticmethod
|
||||
def load_dungeon_from_string(content: str) -> "Map":
|
||||
"""
|
||||
Transforms a string into the list of corresponding tiles
|
||||
"""
|
||||
lines = content.split("\n")
|
||||
lines = [line for line in lines[1:] if line]
|
||||
tiles = [[Tile.from_ascii_char(c)
|
||||
for x, c in enumerate(line)] for y, line in enumerate(lines)]
|
||||
return tiles
|
||||
|
||||
def draw_string(self, pack: TexturePack) -> str:
|
||||
"""
|
||||
Draw the current map as a string object that can be rendered
|
||||
|
@ -108,14 +119,39 @@ class Map:
|
|||
for entity in self.entities:
|
||||
entity.act(self)
|
||||
|
||||
def save_state(self) -> dict:
|
||||
d = dict()
|
||||
d["width"] = self.width
|
||||
d["height"] = self.height
|
||||
d["start_y"] = self.start_y
|
||||
d["start_x"] = self.start_x
|
||||
d["currentx"] = self.currentx
|
||||
d["currenty"] = self.currenty
|
||||
for enti in self.entities:
|
||||
d.update(enti.save_state())
|
||||
d["map"] = self.draw_string(TexturePack.ASCII_PACK)
|
||||
return d
|
||||
|
||||
def load_state(self, d: dict) -> None:
|
||||
self.width = d["width"]
|
||||
self.height = d["height"]
|
||||
self.start_y = d["start_y"]
|
||||
self.start_x = d["start_x"]
|
||||
self.currentx = d["currentx"]
|
||||
self.currenty = d["currenty"]
|
||||
self.map = self.load_dungeon_from_string(d["map"])
|
||||
#add entities
|
||||
|
||||
class Tile(Enum):
|
||||
EMPTY = auto()
|
||||
WALL = auto()
|
||||
FLOOR = auto()
|
||||
|
||||
@classmethod
|
||||
def from_ascii_char(cls, ch: str) -> "Tile":
|
||||
@staticmethod
|
||||
def from_ascii_char(ch: str) -> "Tile":
|
||||
"""
|
||||
Maps an ascii character to its equivalent in the texture pack
|
||||
"""
|
||||
for tile in Tile:
|
||||
if tile.char(TexturePack.ASCII_PACK) == ch:
|
||||
return tile
|
||||
|
@ -206,6 +242,22 @@ class Entity:
|
|||
Rabbit, TeddyBear
|
||||
return [Beaver, Bomb, Heart, Hedgehog, Rabbit, TeddyBear]
|
||||
|
||||
def save_state(self) -> dict:
|
||||
"""
|
||||
Saves the coordinates of the entity
|
||||
"""
|
||||
d = dict()
|
||||
d["x"] = self.x
|
||||
d["y"] = self.y
|
||||
return d
|
||||
|
||||
def recover_state(self, d : dict) -> None:
|
||||
"""
|
||||
Loads the coordinates of the entity from a dictionnary
|
||||
"""
|
||||
self.x = d["x"]
|
||||
self.y = d["y"]
|
||||
|
||||
|
||||
class FightingEntity(Entity):
|
||||
maxhealth: int
|
||||
|
@ -222,6 +274,15 @@ class FightingEntity(Entity):
|
|||
super().__init__()
|
||||
self.health = self.maxhealth
|
||||
self.dead = False
|
||||
self.health = 0
|
||||
self.strength = 0
|
||||
self.dead = False
|
||||
self.intelligence = 0
|
||||
self.charisma = 0
|
||||
self.dexterity = 0
|
||||
self.constitution = 0
|
||||
self.level = 1
|
||||
|
||||
|
||||
def hit(self, opponent: "FightingEntity") -> None:
|
||||
opponent.take_damage(self, self.strength)
|
||||
|
@ -234,3 +295,17 @@ class FightingEntity(Entity):
|
|||
def die(self) -> None:
|
||||
self.dead = True
|
||||
self.map.remove_entity(self)
|
||||
|
||||
def keys(self) -> list:
|
||||
return ["maxhealth", "health", "level", "dead", "strength", "intelligence", "charisma", "dexterity", "constitution"]
|
||||
|
||||
def save_state(self) -> dict:
|
||||
d = super().save_state()
|
||||
for name in self.keys():
|
||||
d[name] = self.__getattribute__(name)
|
||||
return d
|
||||
|
||||
def recover_state(self, d : dict) -> None:
|
||||
super().recover_state(d)
|
||||
for name in d.keys():
|
||||
self.__setattribute__(name, d[name])
|
||||
|
|
|
@ -25,6 +25,8 @@ class Menu:
|
|||
|
||||
class MainMenuValues(Enum):
|
||||
START = 'Jouer'
|
||||
SAVE = 'Sauvegarder'
|
||||
LOAD = 'Charger'
|
||||
SETTINGS = 'Paramètres'
|
||||
EXIT = 'Quitter'
|
||||
|
||||
|
@ -35,23 +37,6 @@ class MainMenuValues(Enum):
|
|||
class MainMenu(Menu):
|
||||
values = [e for e in MainMenuValues]
|
||||
|
||||
def handle_key_pressed(self, key: KeyValues, game: Any) -> None:
|
||||
"""
|
||||
In the main menu, we can navigate through options.
|
||||
"""
|
||||
if key == KeyValues.DOWN:
|
||||
self.go_down()
|
||||
if key == KeyValues.UP:
|
||||
self.go_up()
|
||||
if key == KeyValues.ENTER:
|
||||
option = self.validate()
|
||||
if option == MainMenuValues.START:
|
||||
game.state = GameMode.PLAY
|
||||
elif option == MainMenuValues.SETTINGS:
|
||||
game.state = GameMode.SETTINGS
|
||||
elif option == MainMenuValues.EXIT:
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
class SettingsMenu(Menu):
|
||||
waiting_for_key: bool = False
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
1 1
|
||||
##############################################################################################################
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
#............................................................................................................#
|
||||
##############################################################################################################
|
|
@ -0,0 +1 @@
|
|||
{"width": 80, "height": 40, "start_y": 1, "start_x": 17, "currentx": 29, "currenty": 25, "x": 74, "y": 22, "maxhealth": 50, "health": 0, "level": 1, "dead": false, "strength": 0, "intelligence": 0, "charisma": 0, "dexterity": 0, "constitution": 0, "map": " ########### ######### \n #.........# #.......# \n #.........# ############.......# \n #.........###############..........#.......############## \n #.........#........................#....................# \n #.........#.............#..........#.......#............# \n ########.########.............#..................#............# \n #.........# #.............####.#######.......#............# \n #.........# #.............##.........###################### \n #.........# #####.##########.........# ########### \n #.........# #......# #.........# #.........# \n ########.##########......# #.........# #.........# \n #...........##......# #.........# #.........# \n #...........##......# #.........# #.........# \n #...........##......# #.........# ################.###### \n #...........##......# #.........# #.................############\n #...........##......# ########.########.......#.........#..........#\n #...........##......# #...............#.......#.........#..........#\n #...........######### #...............#.......#.........#..........#\n #...........# #...............#.......#....................#\n #####.####### #.......................#.........#..........#\n #.........# #...............###################..........#\n #.........############ #...............# #..........#\n #.........#..........# #...............# ############\n #....................#####.###########.############# \n ########.#########...................# #.............# \n #........# #..........#........# #.............######### \n #........# ######.##########........# #.............#.......# \n #........# #..........# #........# #.....................# \n #........# #..........# #........# #.............#.......# \n #........# #..........# #........# #.............#.......# \n #........# #..........# #........# #.............#.......# \n #........# #..........#########.##### #.............#.......# \n #........# #..........#.........# ##########.############.####### \n #........# #..........#.........# #..............# #..........# \n ########## #..........#.........# #..............# #..........# \n ############.........# #..............# #..........# \n #.........# #..............# #..........# \n ########### #..............# #..........# \n ################ ############ "}
|
Loading…
Reference in New Issue