Game

class pygamelib.engine.Game(name='Game', player=None, boards={}, menu={}, current_level=None, enable_partial_display=False, partial_display_viewport=None, mode=90000003, user_update=None, input_lag=0.01, enable_physic=False)

Bases: object

A class that serve as a game engine.

This object is the central system that allow the management of a game. It holds boards (see pygamelib.engine.Board), associate it to level, takes care of level changing, etc.

Note

The game object has an object_library member that is always an empty array except just after loading a board. In this case, if the board have a “library” field, it is going to be used to populate object_library. This library is accessible through the Game object mainly so people have access to it across different Boards during level design in the editor. That architecture decision is debatable.

Note

The constructor of Game takes care of initializing the terminal to properly render the colors on Windows.

Important

The Game object automatically assumes ownership over the Player.

__init__(name='Game', player=None, boards={}, menu={}, current_level=None, enable_partial_display=False, partial_display_viewport=None, mode=90000003, user_update=None, input_lag=0.01, enable_physic=False)
Parameters:
  • name (str) – The Game name.
  • boards (dict) – A dictionnary of boards with the level number as key and a board reference as value.
  • menu (dict) – A dictionnary of menus with a category (str) as key and another dictionnary (key: a shortcut, value: a description) as value.
  • current_level (int) – The current level.
  • enable_partial_display (bool) – A boolean to tell the Game object to enable or not partial display of boards. Default: False.
  • partial_display_viewport (list) – A 2 int elements array that gives the radius of the partial display in number of row and column. Please see display_around().
  • mode (int) – The mode parameter configures the way the run() method is going to behave. The default value is constants.MODE_TBT. TBT is short for “Turn By Turn”. In that mode, the Game object wait for an user input before looping. Exactly like when you wait for user input with get_key(). The other possible value is constants.MODE_RT. RT stands for “Real Time”. In that mode, the Game object waits for a minimal amount of time (0.01 i.e 100 FPS, configurable through the input_lag parameter) in order to get the input from the user and call the update function right away. This parameter is only useful if you use Game.run().
  • user_update (function) – A reference to the main program update function. The update function is called for each new frame. It is called with 3 parameters: the game object, the user input (can be None) and the elapsed time since last frame.
  • input_lag (float|int) – The amount of time the run() function is going to wait for a user input before returning None and calling the update function. Default is 0.01.

Methods

__init__([name, player, boards, menu, …])
param name:The Game name.
actuate_npcs(level_number[, elapsed_time]) Actuate all NPCs on a given level
actuate_projectiles(level_number[, elapsed_time]) Actuate all Projectiles on a given level
add_board(level_number, board) Add a board for the level number.
add_menu_entry(category, shortcut, message) Add a new entry to the menu.
add_npc(level_number, npc[, row, column, …]) Add a NPC to the game.
add_projectile(level_number, projectile[, …]) Add a Projectile to the game.
animate_items(level_number[, elapsed_time]) That method goes through all the BoardItems of a given map and call Animation.next_frame().
change_level(level_number) Change the current level, load the board and place the player to the right place.
clear_session_logs() Delete all the log lines from the logs.
clear_screen() Clear the whole screen (i.e: remove everything written in terminal)
config(section) Get the content of a previously loaded configuration section.
create_config(section) Initialize a new config section.
current_board() This method return the board object corresponding to the current_level.
delete_all_levels() Delete all boards and their associated levels from the game object.
delete_level(lvl_number) Delete a level and its associated Board from the game object.
delete_menu_category([category]) Delete an entire category from the menu.
display_board() Display the current board.
display_menu(category[, orientation, paginate]) Display the menu.
display_player_stats([life_model, void_model]) Display the player name and health.
get_board(level_number) This method returns the board associated with a level number.
get_key() Reads the next key-stroke returning it as a string.
get_menu_entry(category, shortcut) Get an entry of the menu.
insert_board(level_number, board) Insert a board for the level number.
instance(*args, **kwargs) Returns the instance of the Game object
load_board(filename[, lvl_number]) Load a saved board
load_config(filename, section) Load a configuration file from the disk.
session_log(line) Add a line to the session logs.
session_logs() Return the complete session logs since instantiation.
move_player(direction[, step]) Easy wrapper for Board.move().
neighbors([radius, obj]) Get a list of neighbors (non void item) around an object.
pause() Set the game engine state to PAUSE.
remove_npc(level_number, npc) This methods remove the NPC from the level in parameter.
run()

New in version 1.2.0.

save_board(lvl_number, filename) Save a board to a JSON file
save_config(section, filename, append) Save a configuration section.
start() Set the game engine state to RUNNING.
stop() Set the game engine state to STOPPED.
update_menu_entry(category, shortcut, message) Update an entry of the menu.
actuate_npcs(level_number, elapsed_time=0.0)

Actuate all NPCs on a given level

This method actuate all NPCs on a board associated with a level. At the moment it means moving the NPCs but as the Actuators become more capable this method will evolve to allow more choice (like attack use objects, etc.)

Parameters:
  • level_number (int) – The number of the level to actuate NPCs in.
  • elapsed_time (float) – The amount of time that passed since last call. This parameter is not mandatory.

Example:

mygame.actuate_npcs(1)

Note

This method only move NPCs when their actuator state is RUNNING. If it is PAUSED or STOPPED, the NPC is not moved.

Note

Since version 1.2.0 it’s possible for a Movable item to have different vertical and horizontal movement steps, so actuate_npc respect that by integrating the steps with a unit direction vector. It should be completely transparent and you should not expect any change. Just more movement freedom. If you do experience issues, please report a bug.

Note

Since version 1.2.0 and the appearance of the realtime mode, we have to account for movement speed. This method does it.

actuate_projectiles(level_number, elapsed_time=0.0)

Actuate all Projectiles on a given level

This method actuate all Projectiles on a board associated with a level. This method differs from actuate_npcs() as some logic is involved with projectiles that NPC do not have. This method decrease the available range by projectile.step each time it’s called. It also detects potential collisions. If the available range falls to 0 or a collision is detected the projectile hit_callback is called.

Parameters:
  • level_number (int) – The number of the level to actuate Projectiles in.
  • elapsed_time (float) – The amount of time that passed since last call. This parameter is not mandatory.

Example:

mygame.actuate_projectiles(1)

Note

This method only move Projectiles when their actuator state is RUNNING. If it is PAUSED or STOPPED, the Projectile is not moved.

Important

Please have a look at the pygamelib.board_items.Projectile.hit() method for more information on the projectile hit mechanic.

add_board(level_number: int, board: pygamelib.engine.Board) → None

Add a board for the level number.

This method associate a Board (pygamelib.engine.Board) to a level number.

Example:

game.add_board(1,myboard)
Parameters:
  • level_number (int) – the level number to associate the board to.
  • board (pygamelib.engine.Board) – a Board object corresponding to the level number.
Raises:

PglInvalidTypeException – If either of these parameters are not of the correct type.

add_menu_entry(category, shortcut, message, data=None)

Add a new entry to the menu.

Deprecated since version 1.3.0: This function will be removed in version 1.4.0

Add another shortcut and message to the specified category.

Categories help organize the different sections of a menu or dialogues.

Parameters:
  • category (str) – The category to which the entry should be added.
  • shortcut (str) – A shortcut (usually one key) to display.
  • message (various) – a message that explains what the shortcut does.
  • data – a data that you can get from the menu object.

The shortcut and data is optional.

Example:

game.add_menu_entry('main_menu','d','Go right',constants.RIGHT)
game.add_menu_entry('main_menu',None,'-----------------')
game.add_menu_entry('main_menu','v','Change game speed')
add_npc(level_number, npc, row=None, column=None, layer=None, auto_layer=True)

Add a NPC to the game. It will be placed on the board corresponding to the level_number. If row and column are not None, the NPC is placed at these coordinates. Else, it’s randomly placed in an empty cell.

Example:

game.add_npc(1,my_evil_npc,5,2)
Parameters:
  • level_number (int) – the level number of the board.
  • npc (pygamelib.board_items.NPC) – the NPC to place.
  • row (int) – the row coordinate to place the NPC at.
  • column (int) – the column coordinate to place the NPC at.

If either of these parameters are not of the correct type, a PglInvalidTypeException exception is raised.

Important

If the NPC does not have an actuator, this method is going to affect a pygamelib.actuators.RandomActuator() to npc.actuator. And if npc.step == None, this method sets it to 1

add_projectile(level_number, projectile, row=None, column=None)

Add a Projectile to the game. It will be placed on the board corresponding to level_number. Neither row nor column can be None.

Example:

game.add_projectile(1, fireball, 5, 2)
Parameters:
  • level_number (int) – the level number of the board.
  • projectile (Projectile) – the Projectile to place.
  • row (int) – the row coordinate to place the Projectile at.
  • column (int) – the column coordinate to place the Projectile at.

If either of these parameters are not of the correct type, a PglInvalidTypeException exception is raised.

Important

If the Projectile does not have an actuator, this method is going to affect pygamelib.actuators.RandomActuator(moveset=[RIGHT]) to projectile.actuator. And if projectile.step == None, this method sets it to 1.

animate_items(level_number, elapsed_time=0.0)

That method goes through all the BoardItems of a given map and call Animation.next_frame().

Parameters:
  • level_number (int) – The number of the level to animate items in.
  • elapsed_time (float) – The amount of time that passed since last call. This parameter is not mandatory.
Raise:

PglInvalidLevelException PglInvalidTypeException

Example:

mygame.animate_items(1)
change_level(level_number: int) → None

Change the current level, load the board and place the player to the right place.

Example:

game.change_level(1)
Parameters:level_number (int) – the level number to change to.
Raises:base.PglInvalidTypeException – If parameter is not an int.
clear_screen()

Clear the whole screen (i.e: remove everything written in terminal)

Deprecated since version 1.2.0: Starting 1.2.0 we are using the pygamelib.engine.Screen object to manage the screen. That function is a simple forward and is kept for backward compatibility only. You should use Game.screen.clear()

clear_session_logs() → None

Delete all the log lines from the logs.

Example:

game = Game.instance()
game.clear_logs()

Note

The session log system is nothing more than a list to do your “debug prints”. If you want a real logging system, please use Python logging module.

config(section: str = 'main') → dict

Get the content of a previously loaded configuration section.

Parameters:section (str) – The name of the section.

Example:

if mygame.config('main')['pgl-version-required'] < 10200:
    print('The pygamelib version 1.2.0 or greater is required.')
    exit()
create_config(section: str) → None

Initialize a new config section.

The new section is a dictionary.

Parameters:section (str) – The name of the new section.

Example:

if mygame.config('high_scores') is None:
    mygame.create_config('high_scores')
mygame.config('high_scores')['first_place'] = mygame.player.name
current_board() → pygamelib.engine.Board

This method return the board object corresponding to the current_level.

Example:

game.current_board().display()

If current_level is set to a value with no corresponding board a PglException exception is raised with an invalid_level error.

delete_all_levels()

Delete all boards and their associated levels from the game object.

You might want to think twice before using that function…

Example:

game.delete_all_levels()
delete_level(lvl_number: int = None)

Delete a level and its associated Board from the game object.

Both the level and the board can’t be used after that (unless they are reloaded or replaced of course).

Parameters:

lvl_number (int) – The number of the level to remove.

Raises:

Example:

my_game.delete_level(1)
delete_menu_category(category=None)

Delete an entire category from the menu.

Deprecated since version 1.3.0: This function will be removed in version 1.4.0

That function removes the entire list of messages that are attached to the category.

Parameters:category (str) – The category to delete.
Raises:PglInvalidTypeException – If the category is not a string

Important

If the entry have no shortcut it’s advised not to try to update unless you have only one NoneType as a shortcut.

Example:

game.add_menu_entry('main_menu','d','Go right')
game.update_menu_entry('main_menu','d','Go LEFT',constants.LEFT)
display_board()

Display the current board.

The behavior of that function is dependant on how you configured this object. If you set enable_partial_display to True AND partial_display_viewport is set to a correct value, it will call Game.current_board().display_around() with the correct parameters. The partial display will be centered on the player (Game.player). Otherwise it will just call Game.current_board().display().

If the player is not set or is set to constants.NO_PLAYER partial display won’t activate automatically.

Example:

mygame.enable_partial_display = True
# Number of rows, number of column (on each side, total viewport
# will be 20x20 in that case).
mygame.partial_display_viewport = [10, 10]
# This will call Game.current_board().display_around()
mygame.display()
mygame.enable_partial_display = False
# This will call Game.current_board().display()
mygame.display()
display_menu(category, orientation=30000010, paginate=10)

Display the menu.

Deprecated since version 1.3.0: This function will be removed in version 1.4.0

This method display the whole menu for a given category.

Parameters:
  • category (str) – The category to display. Mandatory parameter.
  • orientation (pygamelib.constants) – The shortcut of the entry you want to get.
  • paginate (int) – pagination parameter (how many items to display before changing line or page).

Example:

game.display_menu('main_menu')
game.display_menu('main_menu', constants.ORIENTATION_HORIZONTAL, 5)
display_player_stats(life_model='\x1b[41m \x1b[0m', void_model='\x1b[40m \x1b[0m')

Display the player name and health.

Deprecated since version This: method is completely deprecated and not even compatible with the Screen Buffer system. It will be removed in 1.4.0.

This method print the Player name, a health bar (20 blocks of life_model). When life is missing the complement (20-life missing) is printed using void_model. It also display the inventory value as “Score”.

Parameters:
  • life_model (str) – The character(s) that should be used to represent the remaining life.
  • void_model (str) – The character(s) that should be used to represent the lost life.

Note

This method might change in the future. Particularly it could take a template of what to display.

get_board(level_number: int) → pygamelib.engine.Board

This method returns the board associated with a level number. :param level_number: The number of the level. :type level_number: int

Raises:PglInvalidTypeException – if the level_number is not an int.

Example:

level1_board = mygame.get_board(1)
static get_key()

Reads the next key-stroke returning it as a string.

Example:

key = Utils.get_key()
if key == Utils.key.UP:
    print("Up")
elif key == "q"
    exit()

Note

See readkey documentation in readchar package.

get_menu_entry(category, shortcut)

Get an entry of the menu.

Deprecated since version 1.3.0: This function will be removed in version 1.4.0

This method return a dictionnary with 3 entries :
  • shortcut
  • message
  • data
Parameters:
  • category (str) – The category in which the entry is located.
  • shortcut (str) – The shortcut of the entry you want to get.
Returns:

The menu entry or None if none was found

Return type:

dict

Example:

ent = game.get_menu_entry('main_menu','d')
game.move_player(int(ent['data']),1)
insert_board(level_number: int, board: pygamelib.engine.Board) → None

Insert a board for the level number.

This method does basically the same thing than add_board() except that if the level number is already associated it re-affect the numbers down.

Example:

game.insert_board(1,myboard_1)
# level number 1 is associated with myboard_1
game.insert_board(2,myboard_2)
# level number 1 is associated with myboard_1
# level number 2 is associated with myboard_2
game.insert_board(2,myboard_3)
# level number 1 is associated with myboard_1
# level number 2 is now associated with myboard_3
# level number 3 is associated with myboard_2
Parameters:
  • level_number (int) – the level number to associate the board to.
  • board (pygamelib.engine.Board) – a Board object corresponding to the level number.
Raises:

PglInvalidTypeException – If either of these parameters are not of the correct type.

classmethod instance(*args, **kwargs)

Returns the instance of the Game object

Creates a Game object on first call an then returns the same instance on further calls

Returns:Instance of Game object
load_board(filename, lvl_number=0)

Load a saved board

Load a Board saved on the disk as a JSON file. This method creates a new Board object, populate it with all the elements (except a Player) and then return it.

If the filename argument is not an existing file, the open function is going to raise an exception.

This method, load the board from the JSON file, populate it with all BoardItem included, check for sanity, init the board with BoardItemVoid and then associate the freshly created board to a lvl_number. It then create the NPCs and add them to the board.

Parameters:
  • filename (str) – The file to load
  • lvl_number (int) – The level number to associate the board to. Default is 0.
Returns:

a newly created board (see pygamelib.engine.Board)

Example:

mynewboard = game.load_board( 'awesome_level.json', 1 )
game.change_level( 1 )
load_config(filename: str, section: str = 'main') → dict

Load a configuration file from the disk. The configuration file must respect the INI syntax. The goal of these methods is to simplify configuration files management.

Parameters:
  • filename (str) – The filename to load. does not check for existence.
  • section (str) – The section to put the read config file into. This allow for multiple files for multiple purpose. Section is a human readable unique identifier.
Raises:
  • FileNotFoundError – If filename is not found on the disk.
  • json.decoder.JSONDecodeError – If filename could not be decoded as JSON.
Returns:

The parsed data.

Return type:

dict

Warning

breaking changes: before v1.1.0 that method use to load file using the configparser module. This have been dumped in favor of json files. Since that methods was apparently not used, there is no backward compatibility.

Example:

mygame.load_config('game_controls.json','game_control')
move_player(direction, step=1)

Easy wrapper for Board.move().

Example:

mygame.move_player(constants.RIGHT,1)
neighbors(radius=1, obj=None)

Get a list of neighbors (non void item) around an object.

This method returns a list of objects that are all around an object between the position of an object and all the cells at radius.

Parameters:
  • radius (int) – The radius in which non void item should be included
  • object (pygamelib.board_items.BoardItem) – The central object. The neighbors are calculated for that object. If None, the player is the object.
Returns:

A list of BoardItem. No BoardItemVoid is included.

Raises:

PglInvalidTypeException – If radius is not an int.

Example:

for item in game.neighbors(2):
    print(f'{item.name} is around player at coordinates '
        '({item.pos[0]},{item.pos[1]})')
pause()

Set the game engine state to PAUSE.

Example:

mygame.pause()
remove_npc(level_number, npc)

This methods remove the NPC from the level in parameter.

Parameters:
  • level (int) – The number of the level from where the NPC is to be removed.
  • npc (NPC) – The NPC object to remove.

Example:

mygame.remove_npc(1, dead_npc)
run()

New in version 1.2.0.

The run() method act as the main game loop and does a number of things for you:

  1. It grabs the user input. If the Game object is configured with MODE_TBT (the default), nothing happen until the user hit a key. If the mode is set to MODE_RT, it will wait for input_lag secondes for a user input before going to step 3.
  2. It calculate the elapsed time between 2 frames.
  3. Accumulates the elapsed time in the player dtmove variable (if there is a player object configured)
  4. It sets the cursor position to 0,0 (meaning that your user_update function will draw on top of the previously drawn window). The Board.display() and Board.display_around() method clean the end of their line.
  5. It calls the user_update function with 3 parameters: the game object, the key hit by the user (it can be None) and the elapsed time between to calls.
  6. Clears the end of the screen.
  7. Actuates NPCs.
  8. Actuates projectiles.
  9. Animates items.
  10. Actuates particles (WIP).
Raises:PglInvalidTypeException, PglInvalidTypeException

Example:

mygame.run()
save_board(lvl_number, filename)

Save a board to a JSON file

This method saves a Board and everything in it but the BoardItemVoid.

Not check are done on the filename, if anything happen you get the exceptions from open().

Parameters:
  • lvl_number (int) – The level number to get the board from.
  • filename (str) – The path to the file to save the data to.
Raises:

Example:

game.save_board( 1, 'hac-maps/level1.json')

If Game.object_library is not an empty array, it will be saved also.

Warning

In version 1.3.0 the Board class changed a lot and a layer system has been added. Therefor, boards saved from version 1.3.0+ are not compatible with previous version. Previous boards can be loaded (Game.load_board() is backward compatible), but when saved they will be converted to the new format.

save_config(section: str = None, filename: str = None, append: bool = False) → None

Save a configuration section.

Parameters:
  • section (str) – The name of the section to save on disk.
  • filename (str) – The file to write in. If not provided it will write in the file that was used to load the given section. If section was not loaded from a file, save will raise an exception.
  • append (bool) – Do we need to append to the file or replace the content (True = append, False = replace)

Example:

mygame.save_config('game_controls', 'data/game_controls.json')
session_log(line: str) → None

Add a line to the session logs.

Session logs needs to be activated first.

Parameters:line (str) – The line to add to the logs.

Example:

game = Game.instance()
game.SESSION_LOGS = True
game.session_log('Game engine initialized')

Note

The session log system is nothing more than a list to do your “debug prints”. If you want a real logging system, please use Python logging module.

session_logs() → list

Return the complete session logs since instantiation.

Example:

game = Game.instance()
game.SESSION_LOG = True
for line in game.logs():
    print(line)

Note

The session log system is nothing more than a list to do your “debug prints”. If you want a real logging system, please use Python logging module.

start()

Set the game engine state to RUNNING.

The game has to be RUNNING for actuate_npcs() and move_player() to do anything.

Example:

mygame.start()
stop()

Set the game engine state to STOPPED.

Example:

mygame.stop()
update_menu_entry(category, shortcut, message, data=None)

Update an entry of the menu.

Deprecated since version 1.3.0: This function will be removed in version 1.4.0

Update the message associated to a category and a shortcut.

Parameters:
  • category (str) – The category in which the entry is located.
  • shortcut (str) – The shortcut of the entry you want to update.
  • message (various) – a message that explains what the shortcut does.
  • data – a data that you can get from the menu object.

Important

If the entry have no shortcut it’s advised not to try to update unless you have only one NoneType as a shortcut.

Example:

game.add_menu_entry('main_menu','d','Go right')
game.update_menu_entry('main_menu','d','Go LEFT',constants.LEFT)