Skip to content

Commit

Permalink
Feat: Keep record of saved coins through a session and restore them w…
Browse files Browse the repository at this point in the history
…ith the session itself
  • Loading branch information
DiddiLeija committed Aug 16, 2024
1 parent 126edc4 commit 06af943
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 25 deletions.
19 changes: 16 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import pyxel

from src import stages_list
from src.tools import init_class, write_savedata, draw_stats
from src.tools import init_class, savedata_fix, get_savedata, draw_stats, POSSIBLE_LEVELS
from src.scenes import BaseScene
from src.menu import Menu


class Main:
Expand All @@ -19,17 +21,28 @@ class Main:
def __init__(self):
pyxel.load("resource.pyxres")
self.situation = init_class(stages_list["menu"], 0)
self.situation.restore_coins(get_savedata()["saved_coins"])
pyxel.run(self.update, self.draw)

def update(self):
self.situation.update()
# If the situation "ends", jump into the next one
# Also, keep memory of your player choice :)
if self.situation.finished:
coin_reset = 0
tmp = self.situation.player_choice
if self.situation.nextlevel not in ("menu", "death"):
write_savedata({"level": self.situation.nextlevel})
savedata_fix("level", self.situation.nextlevel)
if type(self.situation).__name__.lower() in POSSIBLE_LEVELS and self.situation.check_anyone_alive:
print("true")
savedata_fix("saved_coins", self.situation.get_coin_count())
if not isinstance(self.situation, BaseScene):
coin_reset = get_savedata()["saved_coins"]
if isinstance(self.situation, Menu):
if self.situation.stage == "start":
coin_reset = 0
self.situation = init_class(stages_list[self.situation.nextlevel], tmp)
self.situation.restore_coins(coin_reset)
del tmp # we have to remove 'tmp' ASAP

def draw(self):
Expand All @@ -45,5 +58,5 @@ def draw(self):

if __name__ == "__main__":
pyxel.init(128, 144, title="Diddi and Eli", capture_sec=120)
pyxel.fullscreen(True) # why not? :P
# pyxel.fullscreen(True) # why not? :P
Main()
8 changes: 4 additions & 4 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ def format(session: nox.Session):
"Format the codebase."
session.install("-r", "requirements.txt")
session.install("-r", "test-requirements.txt")
session.run("ruff", "check", *files, "--fix") # TODO: ignore certain rules?
session.run("ruff", "format", *files) # a reinforcement to 'ruff check --fix'
session.run("ruff", "check", *files, "--fix")
session.run("ruff", "format", *files) # an important reinforcement to 'ruff check --fix'


@nox.session
def lint(session: nox.Session):
"Lint the codebase."
session.install("-r", "requirements.txt")
session.install("-r", "test-requirements.txt")
session.run("ruff", "check", *files) # TODO: ignore certain rules?
session.run("ruff", "check", *files)


@nox.session(name="reset-savedata")
def reset_savedata(session: nox.Session):
"Clean up 'savedata.json', which should not have any contents, use it carefully."
new_data = '{"level": "intro"}'
new_data = '{"level": "intro", "saved_coins": 0}'
session.run(
"python",
"-c",
Expand Down
2 changes: 1 addition & 1 deletion savedata.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"level": "intro"}
{"level": "intro", "saved_coins": 0}
5 changes: 5 additions & 0 deletions src/characters.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,11 @@ def get_coin_count(self):
"just return the coin count for further usage."
return TOTAL_COINS

def restore_coins(self, amount=0):
"restore a deleted coin count or fully reset it."
global TOTAL_COINS
TOTAL_COINS = amount

def get_scroll_x(self):
"return scroll_x for external purposes."
# TODO: get rid of this workaround
Expand Down
3 changes: 2 additions & 1 deletion src/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Menu(BaseLevel):
2: "[3] Multiplayer",
}
music_vol = 5
reset_coin_counter = True
# reset_coin_counter = True
gen_clouds = False
saved_available = False

Expand Down Expand Up @@ -50,6 +50,7 @@ def update(self):
# Just get into the next window
self.finished = True
self.nextlevel = "intro"
self.restore_coins(0)
elif self.stage == "startsaved":
# Move to the saved window
self.finished = True
Expand Down
54 changes: 38 additions & 16 deletions src/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@
)


def check_savedata(data):
"Internal function to avoid warped/incorrect save data."
if data["level"] not in POSSIBLE_LEVELS:
data["level"] = "intro"
return data
class InternalOperationCrash(Exception):
"""
custom exception for internal errors with internal stuff
that could only crash under testing circumstances.
"""


def report_crash(opname, original):
raise InternalOperationCrash(
f"Error: Internal operation '{opname}' showed unexpected behavior. "
f"If you are not testing this operation, please report this error. ('{original}')"
)


def draw_text(text, x, y, *, maincol=7, subcol=1):
Expand All @@ -37,6 +44,13 @@ def init_class(obj, popt):
return obj(popt)


def check_savedata(data):
"Internal function to avoid warped/incorrect save data."
if data["level"] not in POSSIBLE_LEVELS:
data["level"] = "intro"
return data


def get_savedata():
"Read and return the save data."
with io.open("savedata.json", "r") as js:
Expand All @@ -45,24 +59,32 @@ def get_savedata():


def write_savedata(data):
"Write the save data from scratch."
"""
Lower-level tool to write the save data from scratch.
'savedata_fix' and 'savedata_fixes' should be used at
upper levels (e.g. 'main.py').
"""
with io.open("savedata.json", "w") as js:
new_data = check_savedata(data)
js.write(json.dumps(new_data, sort_keys=True))


class InternalOperationCrash(Exception):
"""
custom exception for internal errors with internal stuff
that could only crash under testing circumstances.
"""
def savedata_fix(key, value):
"Modify a single save data key."
data = get_savedata()
data[key] = value
data = check_savedata(data)
write_savedata(data)


def report_crash(opname, original):
raise InternalOperationCrash(
f"Error: Internal operation '{opname}' showed unexpected behavior. "
f"If you are not testing this operation, please report this error. ('{original}')"
)
def savedata_fixes(fixes: dict) -> None:
"run 'savedata_fix' for each key on a given dict."
for k, v in fixes.items():
try:
savedata_fix(k, v)
except Exception:
# TODO: warn/report about this crash
pass


def gradient(height, skips):
Expand Down

0 comments on commit 06af943

Please sign in to comment.