This year I actually managed to finish a game for Nanoreno! It’s called ‘reset/you’ and you can find the game page here. I thought it’d be cool to go through some of my favourite parts of working on this game in this blog post.
First: impromptu RPG battle system! I had a try at coding a very simple battle system in python/renpy. First I set up character classes with some basic skills. I’d been learning about classes in python recently in my job so this was a fun way to practice that.
init python: class BattleCharacter: # set up a generic battle character class with various stats def __init__(self, max_hp, strength, defence): self.max_hp = max_hp self.current_hp = self.max_hp self.strength = strength self.defence = defence def attack(self): # plus/minus up to 25% of total str stat variance = int(round((self.strength * 0.05))) rng = renpy.random.randint(-variance, variance) return int(round(self.strength + rng)) def damage_taken(self, damage): # calculate damage taken taking defence into account # don't drop below zero reduction = damage / self.defence damage = int(round(damage - reduction)) if self.current_hp - damage < 0: return self.current_hp else: return damage def defend(self): # increment defence on using defend self.defence += 5 def heal(self): # return the amount healed not going above max hp amount = int(round(self.attack() * 1.25)) if amount + self.current_hp > self.max_hp: return self.max_hp - self.current_hp else: return amount # extra skills def gravity(target): # reduces hp by 60% of current hp return int(round(target.current_hp * .6))
Then used in the script:
# set up characters $ xephyr = BattleCharacter(max_hp=3000, strength=487, defence=16) $ boss = BattleCharacter(max_hp=5000, strength=783, defence=23) # screen to show the HP counter in the top left show screen battle with dissolve jump battle label battle: menu: "Attack": $ damage_taken = boss.damage_taken(xephyr.attack()) $ boss.current_hp -= damage_taken with vpunch with flashwhite N "[damage_taken] damage!" "Repair": $ damage_repaired = xephyr.heal() $ xephyr.current_hp += damage_repaired with flashwhite N "Xephyr repairs [damage_repaired] HP." if boss.current_hp <= 0: jump victory else: # make time occasionally use a powerful spell $ gravity_chance = renpy.random.randint(0, 5) if gravity_chance == 1: N "Time uses Gravity." $ damage_taken = xephyr.damage_taken(gravity(xephyr)) $ xephyr.current_hp -= damage_taken else: N "Time attacks." $ damage_taken = xephyr.damage_taken(boss.attack()) $ xephyr.current_hp -= damage_taken with vpunch with flashwhite N "Xephyr takes [damage_taken] damage!" if xephyr.current_hp <= 0: jump cirrus_helps jump battle
This part of the script basically acts as a while loop - as long as the boss’ HP is above zero you will keep looping back to the
battle label where you will be shown the menu again. To add a bit of narrative going through the fight I added a counter to the loop:
label battle: $ counter += 1 menu: "Attack": if counter == 2: Xephyr "I have to stop you!" if counter == 4: Xephyr "It's never useless!" if counter == 6: Xephyr "No!" $ damage_taken = boss.damage_taken(xephyr.attack()) $ boss.current_hp -= damage_taken with vpunch with flashwhite N "[damage_taken] damage!" "Repair": if counter == 2: Xephyr "I have to stop you!" if counter == 4: Xephyr "It's never useless!" if counter == 6: Xephyr "No!" $ damage_repaired = xephyr.heal() $ xephyr.current_hp += damage_repaired with flashwhite N "Xephyr repairs [damage_repaired] HP."
The counter gets incremented each time you go through the loop so as the battle progresses you get new bits of dialogue from Xephyr (and the boss).
There are many issues with this system that I would iron out if I were using it for a bigger game but for a gimmicky little boss fight at the end of this game it serves its purpose pretty well.
On a non-coding note: it was nice to take a break from working on Metamorphoser, which is mostly written in first person, to write something totally in third person and with a very different kind of tone. Despite being a horror game, Metamorphoser’s writing is often very silly and doesn’t take itself seriously - to match its protagonist’s personality. For this game I wanted something a bit more serious, a little cold and detached as a contrast. Working on this game was also a good exercise in concentrating first and foremost on getting something finished no matter how short it is. The game ended up only being about 4k words but I think I managed to wrap up a nice little story in that amount.
On another writing note: I got to write online communication! Which was very fun. It was cool to try and think how different people type when they’re online and in what setting. The conversations Xephyr has with her online contact start on an anonymous message board and then move into an instant messaging app. It was interesting trying to figure out both characters’ typing styles according to the kind of setting they’re in.
The anonymous message board:
The instant messaging app:
Now that I’ve actually succeeded in finishing a game for Nanoreno I want to see if I can do it every year! It’s just really nice to have another complete game out there, no matter how barebones it is.