BTP main module - game.py¶
Contents
About¶
This is main game executable file which contains main logics of the game and manipulates other modules and classes (basically, screens module).
At first, we set game.CAPTION and game.SIZE constants, which is responsible for main window title and size respectively.
CAPTION = 'Big Typernatural Project'
SIZE = (1000, 700) #: Should be at least the size of images in Images folder
Note
Size of the window must be smaller or at least the same as any image used as background, otherwise the image won’t cover all screen and there will be black areas.
Then we create new pygame window using those constants.
if __name__ == '__main__':
pg.display.set_caption(CAPTION)
screen = pg.display.set_mode(SIZE)
Game().loop(screen)
pg.quit()
Last two lines are basically creation of main game class game.Game and a proper pygame quit. The game.Game class is looping through whole lots of game logics while True, so it’s okay that we’re quiting our game right after game.Game creation.
Note
The __name__ == '__main__' thing is basically checking whether we’re running our game standalone way (form console, as executable, etc.) or we’re importing it. Even though I’m not intended to import it and you’re should not too, it’s proper way to protect your project from undesired execution.
Imports¶
screens | For wrapping screens around (see Interfaces wrapper - screens.py) |
os | Determine whether file exists or not |
pickle | For saving/loading Pers() object (savegame) |
random | For executing battle only if the chance is right |
pygame | As a core of the whole game it is imported in each module |
Classes¶
Game¶
This is the main logics class which rules the game while true through screens module.
We have only one method here and nothing else - game.Game.loop(). So, basically, we don’t need a class - we can easily make it a function or even write all the code within __name__ == '__main__' condition, but I like OOP concepts and I like extensibility of classes and object. So for now it will stand a class, but when the stable 1.0 version is out - we’ll see.
Todo
Make something about attr -> param linking support
Our game.Game.loop() method have only one attribute - game.Game.loop.surface which is the screen area for drawing all the stuff.
At first, we set some variables:
pers = Pers()
started = False # Prevent multiple game loads + game quit to menu trigger
- game.Game.loop.pers - our game.Pers object to work with. All the data about your character is stored within it. Your hitpoints, your current location and etc.
- game.Game.loop.started - boolean which tells us whether game is already loaded or is it should yet be loaded/created.
Then goes main cycle which loops while True.
while True:
# Create menu
while pers.name == '':
login = screens.Menu().main(surface)
# Create loginscreen
if login:
pers.name = screens.Login().main(surface)
# Load game of save new game, then started=True
if not started:
if os.path.isfile('Saves/' + pers.name):
pers.load()
else:
pers.save()
screens.Introduction().main(surface, pers.name)
started = True
(pers.place, mobs) = screens.World().main(surface, pers.place)
if random.randrange(0, 100) < mobs['Chance']:
pers = screens.Battle().main(surface, mobs, pers, Mob())
# Save each loop
pers.save()
Here we create menu using class screens.Menu and it’s method screens.Menu.main(). When ‘New game / load game’ option is selected, menu returns something (not important what) into the local login variable which, if not empty, will load screens.Login.main() method from screens.Login.
Well, the login screen will return a name when it is entered to login screen and Enter is pressed. The name will be stored in game.Pers.name variable and then whole cycle will stop working. Because game.Pers.name won’t be empty anymore.
The next step is to save game and start intro or to load game if user entered the name which already exists in Saves folder. Here we’re using os module to check whether savegame exists or not.
If it exists, we use game.Pers.load() method which loads whole object data by means of pickle. If it isn’t, firstly we’re saving whole object data to the file and then we’re executing screens.World.main() method form screens.World class, which is intended to tell user some pre-history of game world and give hime base knowledge of what he’ll be waiting within the game.
After that, the variable game.Game.loop.started sets to True and this part of code never repeats too.
Next step is finally the world loading. Class screens.World is showing world until any action was performed. When an action was performed, screens.World returns next place to game.Pers.place and mobs record for new place to local variable mobs.
There’s our random module comes in handy: we’re using it to calculate chances that we’re in trouble and monsters are attacking.
Then we’re saving a game (after successful battle) and all begins again
Note
There will be lots more logics added to calculate, it’s early development stage of the game. In the future, you’ll be able to ‘cleanse’ locations so that mobs you’ve killed won’t attack you again or even will respawn after some time. Now, however, if you’ll kill any monsters (hah, battle is not yet ready) and you’ll try to load the game - they can attack you again.
Mob¶
There’s not much done yet about this class. It’s here just for an example of what will be done soon.
- class game.Mob(maxhp)[source]¶
Creates new monster who is to fight you
- maxhp = 20¶
Standard mob hitpoints
Source code:
maxhp = 20 #: Standard mob hitpoints
hp = maxhp
def __init__(self, maxhp):
self.maxhp = maxhp
Pers¶
Handles all Player data.
- class game.Pers[source]¶
-
- name = ''¶
Player name stored internally for easy self save/load
- place = 'OldManHouse'¶
Standard first place of a game (changeable through the game)
Source code:
name = '' #: Player name stored internally for easy self save/load
place = 'OldManHouse' #: Standard first place of a game (changeable through the game)
maxhp = 20
hp = maxhp
def save(self):
"""Saves self Pers() object to file"""
with open('Saves/' + self.name, 'wb') as f:
pickle.dump(self, f)
print('Game saved as ' + self.name)
def load(self):
"""Load self Pers() object from file"""
with open('Saves/' + self.name, 'rb') as f:
self = pickle.load(f)
print('Game loaded as ' + self.name)