|
@@ -21,103 +21,81 @@
|
|
|
import builtins
|
|
import builtins
|
|
|
import os
|
|
import os
|
|
|
import time
|
|
import time
|
|
|
-from typing import Tuple, Type
|
|
|
|
|
|
|
+from collections import OrderedDict
|
|
|
|
|
+from typing import Any, Tuple, Type
|
|
|
|
|
|
|
|
import pygame
|
|
import pygame
|
|
|
|
|
|
|
|
import jogai
|
|
import jogai
|
|
|
import jogai._globals as _globals
|
|
import jogai._globals as _globals
|
|
|
-import jogai.settings as settings
|
|
|
|
|
-from jogai import character, group, logger, scene, utils, widgets
|
|
|
|
|
|
|
+from jogai import character, groups, logger, scene, texts, utils, widgets
|
|
|
|
|
+from jogai.settings import settings
|
|
|
from jogai.translations import gettext as _
|
|
from jogai.translations import gettext as _
|
|
|
from jogai.utils import _get_events, _get_keys
|
|
from jogai.utils import _get_events, _get_keys
|
|
|
|
|
|
|
|
|
|
+_PREDEFINED_ATTRIBUTES_ALLOWED = (
|
|
|
|
|
+ _('caption'),
|
|
|
|
|
+ _('characters'),
|
|
|
|
|
+ _('gravity'),
|
|
|
|
|
+ _('marks'),
|
|
|
|
|
+ _('scene'),
|
|
|
|
|
+ _('texts'),
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
# --------------- #
|
|
# --------------- #
|
|
|
# GLOBALS #
|
|
# GLOBALS #
|
|
|
# --------------- #
|
|
# --------------- #
|
|
|
|
|
|
|
|
running = True
|
|
running = True
|
|
|
-_predefined_attributes_allowed = [
|
|
|
|
|
- _('caption'),
|
|
|
|
|
- _('gravity'),
|
|
|
|
|
-]
|
|
|
|
|
|
|
|
|
|
# ------------------ #
|
|
# ------------------ #
|
|
|
# FUNCTIONS #
|
|
# FUNCTIONS #
|
|
|
# ------------------ #
|
|
# ------------------ #
|
|
|
|
|
|
|
|
|
|
|
|
|
-def _load_scene(data: dict) -> 'scene.Scene':
|
|
|
|
|
- """
|
|
|
|
|
- Load scene from data schema.
|
|
|
|
|
-
|
|
|
|
|
- Parameters:
|
|
|
|
|
- data: input schema
|
|
|
|
|
-
|
|
|
|
|
- Returns:
|
|
|
|
|
- An object containing the scene
|
|
|
|
|
-
|
|
|
|
|
- """
|
|
|
|
|
- if _('scene') in data:
|
|
|
|
|
- return scene.Scene(data[_('scene')])
|
|
|
|
|
- return scene.Scene()
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-def _load_attributes(data: dict):
|
|
|
|
|
- """
|
|
|
|
|
- Load attributes from data schema.
|
|
|
|
|
|
|
+def _calculate_initial_collisions():
|
|
|
|
|
+ for loaded_character in _globals.vg_characters:
|
|
|
|
|
+ loaded_character.current_collisions = (
|
|
|
|
|
+ loaded_character.calculate_collisions(
|
|
|
|
|
+ (loaded_character.x, loaded_character.y)
|
|
|
|
|
+ )
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
- Parameters:
|
|
|
|
|
- data: input schema
|
|
|
|
|
- """
|
|
|
|
|
|
|
|
|
|
- if not isinstance(data, dict):
|
|
|
|
|
- raise TypeError(
|
|
|
|
|
- _('The attributes in the input schema must be a dict.')
|
|
|
|
|
|
|
+def _calculate_initial_touch():
|
|
|
|
|
+ for loaded_character in _globals.vg_characters:
|
|
|
|
|
+ loaded_character.current_touch = loaded_character.calculate_touch(
|
|
|
|
|
+ (loaded_character.x, loaded_character.y)
|
|
|
)
|
|
)
|
|
|
- for attribute in data:
|
|
|
|
|
- # utils._convert_function_arguments_to_string()
|
|
|
|
|
- if attribute in _predefined_attributes_allowed:
|
|
|
|
|
- eval(f'set_{attribute}(data["{attribute}"])')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-def _load_characters(data: dict) -> list:
|
|
|
|
|
|
|
+def _load_data(data: dict):
|
|
|
"""
|
|
"""
|
|
|
- Load characters from data schema.
|
|
|
|
|
|
|
+ Loads data from the schema.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
data: input schema
|
|
data: input schema
|
|
|
-
|
|
|
|
|
- Returns:
|
|
|
|
|
- A list containing all loaded characters
|
|
|
|
|
"""
|
|
"""
|
|
|
- data_characters = {}
|
|
|
|
|
- if not _('characters') in data:
|
|
|
|
|
- return []
|
|
|
|
|
- data_characters = data[_('characters')]
|
|
|
|
|
|
|
+ if not isinstance(data, dict):
|
|
|
|
|
+ raise TypeError(_('the attributes in the input schema must be a dict'))
|
|
|
|
|
|
|
|
- characters = []
|
|
|
|
|
- for character_name, character_data in data_characters.items():
|
|
|
|
|
- if 'filename' in character_data:
|
|
|
|
|
- character_filename = character_data['filename']
|
|
|
|
|
|
|
+ for name, value in data.items():
|
|
|
|
|
+ # utils._convert_function_arguments_to_string()
|
|
|
|
|
+ if name in _PREDEFINED_ATTRIBUTES_ALLOWED:
|
|
|
|
|
+ if isinstance(value, str):
|
|
|
|
|
+ value = f'"{value}"'
|
|
|
|
|
+ eval(_('set_{}({})').format(name, value))
|
|
|
else:
|
|
else:
|
|
|
- character_filename = f'{character_name}.png'
|
|
|
|
|
- loaded_character = character.Character(
|
|
|
|
|
- character_filename,
|
|
|
|
|
- character_name,
|
|
|
|
|
- )
|
|
|
|
|
- loaded_character._load_data(character_data)
|
|
|
|
|
- characters.append(loaded_character)
|
|
|
|
|
- return characters
|
|
|
|
|
|
|
+ add_attribute(name, value)
|
|
|
|
|
|
|
|
|
|
|
|
|
def simulate_key_press(key: int | str, down: bool = True):
|
|
def simulate_key_press(key: int | str, down: bool = True):
|
|
|
"""
|
|
"""
|
|
|
- Post a key press simulation to pygame event module.
|
|
|
|
|
|
|
+ Posts a key press simulation to pygame event module.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
- key: Key to simulate
|
|
|
|
|
- down: Keystroke direction. True for KEYDOWN, False for KEYUP
|
|
|
|
|
|
|
+ key: key to simulate
|
|
|
|
|
+ down: keystroke direction. True for KEYDOWN, False for KEYUP
|
|
|
|
|
|
|
|
Examples:
|
|
Examples:
|
|
|
>>> simulate_key_press('a') # doctest: +SKIP
|
|
>>> simulate_key_press('a') # doctest: +SKIP
|
|
@@ -136,10 +114,10 @@ def simulate_key_press(key: int | str, down: bool = True):
|
|
|
|
|
|
|
|
def key_pressed(key: int | str) -> bool:
|
|
def key_pressed(key: int | str) -> bool:
|
|
|
"""
|
|
"""
|
|
|
- Check if a key has been pressed.
|
|
|
|
|
|
|
+ Checks if a key has been pressed.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
- key: The key to be checked
|
|
|
|
|
|
|
+ key: the key to be checked
|
|
|
|
|
|
|
|
Returns:
|
|
Returns:
|
|
|
True if the key is pressed, False otherwise.
|
|
True if the key is pressed, False otherwise.
|
|
@@ -152,42 +130,55 @@ def key_pressed(key: int | str) -> bool:
|
|
|
return _get_keys()[key]
|
|
return _get_keys()[key]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+def add_attribute(name: str, value: Any):
|
|
|
|
|
+ """
|
|
|
|
|
+ Adds a new attribute to the videogame.
|
|
|
|
|
+
|
|
|
|
|
+ Parameters:
|
|
|
|
|
+ name: a name for this attribute
|
|
|
|
|
+ value: a value for this attribute
|
|
|
|
|
+
|
|
|
|
|
+ Examples:
|
|
|
|
|
+ >>> add_attribute('test': 'foo') # doctest: +SKIP
|
|
|
|
|
+ """
|
|
|
|
|
+ _globals.vg_attributes.update({name: value})
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def add_character(new_character: 'character.Character'):
|
|
def add_character(new_character: 'character.Character'):
|
|
|
"""
|
|
"""
|
|
|
- Add a new character to the videogame.
|
|
|
|
|
|
|
+ Adds a new character to the videogame.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
new_character: the character to add
|
|
new_character: the character to add
|
|
|
|
|
|
|
|
Examples:
|
|
Examples:
|
|
|
- >>> prepare()
|
|
|
|
|
>>> p = character.Character('protagonist.png')
|
|
>>> p = character.Character('protagonist.png')
|
|
|
- >>> add_character(p)
|
|
|
|
|
|
|
+ >>> add_character(p) # doctest: +SKIP
|
|
|
"""
|
|
"""
|
|
|
if not isinstance(new_character, character.Character):
|
|
if not isinstance(new_character, character.Character):
|
|
|
- raise TypeError(_('Only Character instances can be added.'))
|
|
|
|
|
|
|
+ raise TypeError(_('only Character instances can be added'))
|
|
|
_globals.vg_characters.append(new_character)
|
|
_globals.vg_characters.append(new_character)
|
|
|
|
|
|
|
|
|
|
|
|
|
-def add_chronometer(new_chronometer: 'widgets.Chronometer'):
|
|
|
|
|
|
|
+def add_chronometer(new_chronometer: 'texts.Chronometer'):
|
|
|
"""
|
|
"""
|
|
|
- Add a new chronometer to the videogame.
|
|
|
|
|
|
|
+ Adds a new chronometer to the videogame.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
new_chronometer: the chronometer to be added
|
|
new_chronometer: the chronometer to be added
|
|
|
|
|
|
|
|
Examples:
|
|
Examples:
|
|
|
- >>> chrono = widgets.Chronometer(30)
|
|
|
|
|
|
|
+ >>> chrono = texts.Chronometer(30)
|
|
|
>>> add_chronometer(chrono) # doctest: +SKIP
|
|
>>> add_chronometer(chrono) # doctest: +SKIP
|
|
|
"""
|
|
"""
|
|
|
- if not isinstance(new_chronometer, widgets.Chronometer):
|
|
|
|
|
- raise TypeError(_('Only Chronometer instances can be added.'))
|
|
|
|
|
|
|
+ if not isinstance(new_chronometer, texts.Chronometer):
|
|
|
|
|
+ raise TypeError(_('only Chronometer instances can be added'))
|
|
|
_globals.vg_chronometers.append(new_chronometer)
|
|
_globals.vg_chronometers.append(new_chronometer)
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_group(new_group: 'group.SquareGroup'):
|
|
def add_group(new_group: 'group.SquareGroup'):
|
|
|
"""
|
|
"""
|
|
|
- Add a new group to the videogame.
|
|
|
|
|
|
|
+ Adds a new group to the videogame.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
new_group: the character to be added
|
|
new_group: the character to be added
|
|
@@ -197,14 +188,17 @@ def add_group(new_group: 'group.SquareGroup'):
|
|
|
>>> rectangle = group.RectangleGroup(p, 4, 2)
|
|
>>> rectangle = group.RectangleGroup(p, 4, 2)
|
|
|
>>> add_group(rectangle) # doctest: +SKIP
|
|
>>> add_group(rectangle) # doctest: +SKIP
|
|
|
"""
|
|
"""
|
|
|
- if not isinstance(new_group, group.Group):
|
|
|
|
|
- raise TypeError(_('Only Group instances can be added.'))
|
|
|
|
|
|
|
+ if not isinstance(new_group, groups.Group):
|
|
|
|
|
+ raise TypeError(_('only Group instances can be added'))
|
|
|
_globals.vg_groups.append(new_group)
|
|
_globals.vg_groups.append(new_group)
|
|
|
|
|
+ for vg_character in new_group.sprites():
|
|
|
|
|
+ if vg_character in _globals.vg_characters:
|
|
|
|
|
+ _globals.vg_characters.remove(vg_character)
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_levelbar(new_levelbar: 'widgets.LevelBar'):
|
|
def add_levelbar(new_levelbar: 'widgets.LevelBar'):
|
|
|
"""
|
|
"""
|
|
|
- Add a new level bar to the videogame.
|
|
|
|
|
|
|
+ Adds a new level bar to the videogame.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
new_levelbar: the level bar to be added
|
|
new_levelbar: the level bar to be added
|
|
@@ -214,45 +208,45 @@ def add_levelbar(new_levelbar: 'widgets.LevelBar'):
|
|
|
>>> add_levelbar(lb) # doctest: +SKIP
|
|
>>> add_levelbar(lb) # doctest: +SKIP
|
|
|
"""
|
|
"""
|
|
|
if not isinstance(new_levelbar, widgets.LevelBar):
|
|
if not isinstance(new_levelbar, widgets.LevelBar):
|
|
|
- raise TypeError(_('Only LevelBar instances can be added.'))
|
|
|
|
|
|
|
+ raise TypeError(_('only LevelBar instances can be added'))
|
|
|
_globals.vg_levelbars.append(new_levelbar)
|
|
_globals.vg_levelbars.append(new_levelbar)
|
|
|
|
|
|
|
|
|
|
|
|
|
-def add_scoreboard(new_text: 'widgets.Text'):
|
|
|
|
|
|
|
+def add_scoreboard(new_scoreboard: 'texts.Scoreboard'):
|
|
|
"""
|
|
"""
|
|
|
- Add a new scoreboard to the videogame.
|
|
|
|
|
|
|
+ Adds a new scoreboard to the videogame.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
new_scoreboard: the scoreboard to be added
|
|
new_scoreboard: the scoreboard to be added
|
|
|
|
|
|
|
|
Examples:
|
|
Examples:
|
|
|
- >>> sc = widgets.Scoreboard('Test')
|
|
|
|
|
|
|
+ >>> sc = texts.Scoreboard('Test')
|
|
|
>>> add_scoreboard(sc) # doctest: +SKIP
|
|
>>> add_scoreboard(sc) # doctest: +SKIP
|
|
|
"""
|
|
"""
|
|
|
- if not isinstance(new_scoreboard, widgets.Scoreboard):
|
|
|
|
|
- raise TypeError(_('Only Scoreboard instances can be added.'))
|
|
|
|
|
- _globals.vg_scobreboards.append(new_scoreboard)
|
|
|
|
|
|
|
+ if not isinstance(new_scoreboard, texts.Scoreboard):
|
|
|
|
|
+ raise TypeError(_('only Scoreboard instances can be added'))
|
|
|
|
|
+ _globals.vg_scoreboards.append(new_scoreboard)
|
|
|
|
|
|
|
|
|
|
|
|
|
-def add_text(new_text: 'widgets.Text'):
|
|
|
|
|
|
|
+def add_text(new_text: 'texts.Text'):
|
|
|
"""
|
|
"""
|
|
|
- Add a new text to the videogame.
|
|
|
|
|
|
|
+ Adds a new text to the videogame.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
new_text: the text to be added
|
|
new_text: the text to be added
|
|
|
|
|
|
|
|
Examples:
|
|
Examples:
|
|
|
- >>> text = widgets.Text('Test')
|
|
|
|
|
|
|
+ >>> text = texts.Text('Test')
|
|
|
>>> add_text(text) # doctest: +SKIP
|
|
>>> add_text(text) # doctest: +SKIP
|
|
|
"""
|
|
"""
|
|
|
- if not isinstance(new_text, widgets.Text):
|
|
|
|
|
- raise TypeError(_('Only Text instances can be added.'))
|
|
|
|
|
|
|
+ if not isinstance(new_text, texts.Text):
|
|
|
|
|
+ raise TypeError(_('only Text instances can be added'))
|
|
|
_globals.vg_texts.append(new_text)
|
|
_globals.vg_texts.append(new_text)
|
|
|
|
|
|
|
|
|
|
|
|
|
def init():
|
|
def init():
|
|
|
"""
|
|
"""
|
|
|
- Start the pygame engine if it is not started.
|
|
|
|
|
|
|
+ Starts the pygame engine if it is not started.
|
|
|
|
|
|
|
|
Examples:
|
|
Examples:
|
|
|
>>> init()
|
|
>>> init()
|
|
@@ -263,11 +257,12 @@ def init():
|
|
|
_globals._window = pygame.display.set_mode(
|
|
_globals._window = pygame.display.set_mode(
|
|
|
(settings.WINDOW_WIDTH, settings.WINDOW_HEIGHT)
|
|
(settings.WINDOW_WIDTH, settings.WINDOW_HEIGHT)
|
|
|
)
|
|
)
|
|
|
|
|
+ pygame.key.set_repeat(settings.KEY_DELAY, settings.KEY_INTERVAL)
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_running() -> bool:
|
|
def is_running() -> bool:
|
|
|
"""
|
|
"""
|
|
|
- Check if the game is running. Useful in the main loop.
|
|
|
|
|
|
|
+ Checks if the game is running. Useful in the main loop.
|
|
|
|
|
|
|
|
Returns:
|
|
Returns:
|
|
|
True if the game is running. False otherwise.
|
|
True if the game is running. False otherwise.
|
|
@@ -280,7 +275,7 @@ def is_running() -> bool:
|
|
|
|
|
|
|
|
def listen_events():
|
|
def listen_events():
|
|
|
"""
|
|
"""
|
|
|
- Listen for events coming from the keyboard and window clicks.
|
|
|
|
|
|
|
+ Listens for events coming from the keyboard and window clicks.
|
|
|
|
|
|
|
|
Examples:
|
|
Examples:
|
|
|
>>> simulate_key_press('ESCAPE')
|
|
>>> simulate_key_press('ESCAPE')
|
|
@@ -299,7 +294,7 @@ def listen_events():
|
|
|
|
|
|
|
|
def get_color(x: int, y: int) -> Tuple[int, int, int]:
|
|
def get_color(x: int, y: int) -> Tuple[int, int, int]:
|
|
|
"""
|
|
"""
|
|
|
- Get the RGB components for a point in the game window.
|
|
|
|
|
|
|
+ Gets the RGB components for a point in the game window.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
x: Position on the abscissa axis
|
|
x: Position on the abscissa axis
|
|
@@ -311,65 +306,117 @@ def get_color(x: int, y: int) -> Tuple[int, int, int]:
|
|
|
Examples:
|
|
Examples:
|
|
|
>>> color = get_color(100, 200)
|
|
>>> color = get_color(100, 200)
|
|
|
"""
|
|
"""
|
|
|
- if not isinstance(x, int) or not isinstance(y, int):
|
|
|
|
|
|
|
+ if not type(x) == int or not type(y) == int:
|
|
|
raise TypeError(
|
|
raise TypeError(
|
|
|
- _('The coordinates of the point must be a non-negative integers.')
|
|
|
|
|
|
|
+ _('the coordinates of the point must be a non-negative integers')
|
|
|
)
|
|
)
|
|
|
if not (0 <= x <= settings.WINDOW_WIDTH) or not (
|
|
if not (0 <= x <= settings.WINDOW_WIDTH) or not (
|
|
|
0 <= y <= settings.WINDOW_HEIGHT
|
|
0 <= y <= settings.WINDOW_HEIGHT
|
|
|
):
|
|
):
|
|
|
raise ValueError(
|
|
raise ValueError(
|
|
|
- _('The coordinates of the point must be a non-negative integers.')
|
|
|
|
|
|
|
+ _('the coordinates of the point must be a non-negative integers')
|
|
|
)
|
|
)
|
|
|
- return tuple(_globals._window.get_at((x, y))[:-1])
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if _globals._window:
|
|
|
|
|
+ return tuple(_globals._window.get_at((x, y))[:-1])
|
|
|
|
|
+ return None
|
|
|
|
|
|
|
|
|
|
|
|
|
def paint(
|
|
def paint(
|
|
|
sprite: Type['scene.Scene']
|
|
sprite: Type['scene.Scene']
|
|
|
| Type['character.Character']
|
|
| Type['character.Character']
|
|
|
- | Type['widgets.Text'],
|
|
|
|
|
|
|
+ | Type['texts.Text'],
|
|
|
):
|
|
):
|
|
|
"""
|
|
"""
|
|
|
- Paint multiple sprite types on the main window.
|
|
|
|
|
|
|
+ Paints multiple sprite types on the main window.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
- sprite: The element to be painted.
|
|
|
|
|
|
|
+ sprite: the element to be painted
|
|
|
|
|
+ """
|
|
|
|
|
+ # TODO: check sprite type and show error if no image or no rect
|
|
|
|
|
+ if sprite.image and sprite.rect:
|
|
|
|
|
+ _globals._window.blit(sprite.image, sprite.rect)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def paint_character(sprite: Type['character.Character']):
|
|
|
|
|
+ """
|
|
|
|
|
+ Paints a character on the main window.
|
|
|
|
|
+
|
|
|
|
|
+ Parameters:
|
|
|
|
|
+ sprite: the element to be painted
|
|
|
|
|
+ """
|
|
|
|
|
+ if sprite.visible:
|
|
|
|
|
+ paint(sprite)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def paint_group(group: Type['groups.Group']):
|
|
|
|
|
+ """
|
|
|
|
|
+ Paints a group of sprites on the main window.
|
|
|
|
|
+
|
|
|
|
|
+ Parameters:
|
|
|
|
|
+ group: the group of sprites to be painted.
|
|
|
|
|
+ """
|
|
|
|
|
+ for sprite_item in group.characters:
|
|
|
|
|
+ sprite_item._update_rect_position()
|
|
|
|
|
+ paint(sprite_item)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def paint_scene(sprite: Type['scene.Scene']):
|
|
|
|
|
+ """
|
|
|
|
|
+ Paints a scene on the main window.
|
|
|
|
|
+
|
|
|
|
|
+ Parameters:
|
|
|
|
|
+ sprite: the element to be painted
|
|
|
"""
|
|
"""
|
|
|
# TODO: check sprite type
|
|
# TODO: check sprite type
|
|
|
if hasattr(sprite, 'background'):
|
|
if hasattr(sprite, 'background'):
|
|
|
_globals._window.fill(sprite.background)
|
|
_globals._window.fill(sprite.background)
|
|
|
- if hasattr(sprite, 'image') and hasattr(sprite, 'rect'):
|
|
|
|
|
- _globals._window.blit(sprite.image, sprite.rect)
|
|
|
|
|
|
|
+
|
|
|
|
|
+ paint(sprite)
|
|
|
|
|
|
|
|
|
|
|
|
|
-def paint_group(group: Type['group.SquareGroup']):
|
|
|
|
|
|
|
+def paint_text(lines: Type['texts.Text'] | list):
|
|
|
"""
|
|
"""
|
|
|
- Paint a group of sprites on the main window.
|
|
|
|
|
|
|
+ Paints a text on the main window.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
- group: The group of sprites to be painted.
|
|
|
|
|
|
|
+ text: the element to be painted
|
|
|
"""
|
|
"""
|
|
|
- group.draw(_globals._window)
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if isinstance(lines, jogai.texts.Text):
|
|
|
|
|
+ lines = [lines]
|
|
|
|
|
+
|
|
|
|
|
+ for line in lines:
|
|
|
|
|
+ if line.visible:
|
|
|
|
|
+ paint(line)
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_caption(caption: str):
|
|
def set_caption(caption: str):
|
|
|
"""
|
|
"""
|
|
|
- Set the caption for the videogame.
|
|
|
|
|
|
|
+ Sets the caption for the videogame.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
- caption: Caption to be setted
|
|
|
|
|
|
|
+ caption: caption to be setted
|
|
|
|
|
|
|
|
Examples:
|
|
Examples:
|
|
|
>>> set_caption('My videogame')
|
|
>>> set_caption('My videogame')
|
|
|
"""
|
|
"""
|
|
|
if not isinstance(caption, str):
|
|
if not isinstance(caption, str):
|
|
|
- raise TypeError(_('The caption for the videogame must be a string.'))
|
|
|
|
|
|
|
+ raise TypeError(_('the caption for the videogame must be a string'))
|
|
|
|
|
+ _globals.vg_title = caption
|
|
|
pygame.display.set_caption(caption)
|
|
pygame.display.set_caption(caption)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+def set_characters(data_characters: dict):
|
|
|
|
|
+ (
|
|
|
|
|
+ _globals.vg_characters,
|
|
|
|
|
+ _globals.vg_groups,
|
|
|
|
|
+ ) = character._load_characters_and_groups(data_characters)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def set_gravity(gravity: int):
|
|
def set_gravity(gravity: int):
|
|
|
"""
|
|
"""
|
|
|
- Set the gravity in the videogame.
|
|
|
|
|
|
|
+ Sets the gravity in the videogame.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
gravity: Gravity force to be setted.
|
|
gravity: Gravity force to be setted.
|
|
@@ -377,21 +424,21 @@ def set_gravity(gravity: int):
|
|
|
Examples:
|
|
Examples:
|
|
|
>>> set_gravity(5)
|
|
>>> set_gravity(5)
|
|
|
"""
|
|
"""
|
|
|
- if not isinstance(gravity, int):
|
|
|
|
|
- raise TypeError(_('The gravity must be an integer.'))
|
|
|
|
|
|
|
+ if not type(gravity) == int:
|
|
|
|
|
+ raise TypeError(_('the gravity must be an integer'))
|
|
|
_globals._gravity = gravity
|
|
_globals._gravity = gravity
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_marks(
|
|
def set_marks(
|
|
|
- x_gap: int = 0,
|
|
|
|
|
- y_gap: int = 0,
|
|
|
|
|
- x_color: tuple = (255, 180, 30),
|
|
|
|
|
- y_color: tuple = (0, 0, 255),
|
|
|
|
|
- width: int = 1,
|
|
|
|
|
|
|
+ x_gap: int = settings.MARKS_DEFAULT_X_GAP,
|
|
|
|
|
+ y_gap: int = settings.MARKS_DEFAULT_Y_GAP,
|
|
|
|
|
+ x_color: tuple = settings.MARKS_DEFAULT_X_COLOR,
|
|
|
|
|
+ y_color: tuple = settings.MARKS_DEFAULT_Y_COLOR,
|
|
|
|
|
+ width: int = settings.MARKS_DEFAULT_WIDTH,
|
|
|
debug: bool = False,
|
|
debug: bool = False,
|
|
|
):
|
|
):
|
|
|
"""
|
|
"""
|
|
|
- Set distance mark lines and position information along both axis.
|
|
|
|
|
|
|
+ Sets distance mark lines and position information along both axis.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
x_gap: The gap distance on abscissa axis.
|
|
x_gap: The gap distance on abscissa axis.
|
|
@@ -404,78 +451,149 @@ def set_marks(
|
|
|
_globals.marks = utils.Marks(x_gap, y_gap, x_color, y_color, width, debug)
|
|
_globals.marks = utils.Marks(x_gap, y_gap, x_color, y_color, width, debug)
|
|
|
|
|
|
|
|
|
|
|
|
|
-def prepare(data_filename: str = ''):
|
|
|
|
|
|
|
+def set_scene(data_scene):
|
|
|
|
|
+ _globals.vg_scene = scene._load_scene(data_scene)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def set_texts(data_texts):
|
|
|
|
|
+ _globals.vg_texts = texts._load_texts(data_texts)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def prepare(environment_name: str):
|
|
|
"""
|
|
"""
|
|
|
- Prepare the game environment before entering the main loop.
|
|
|
|
|
|
|
+ Decorator function to prepare the game environments before entering the main loop.
|
|
|
|
|
|
|
|
Examples:
|
|
Examples:
|
|
|
>>> init()
|
|
>>> init()
|
|
|
>>> prepare()
|
|
>>> prepare()
|
|
|
"""
|
|
"""
|
|
|
- if not _globals._window:
|
|
|
|
|
- init()
|
|
|
|
|
- pygame.key.set_repeat(settings.KEY_DELAY, settings.KEY_INTERVAL)
|
|
|
|
|
- if data_filename:
|
|
|
|
|
- vg_data = utils._load_yaml_from_filename(data_filename)
|
|
|
|
|
- else:
|
|
|
|
|
- vg_data = _globals._default_data
|
|
|
|
|
|
|
|
|
|
- _globals.vg_scene = _load_scene(vg_data)
|
|
|
|
|
- _globals.vg_characters = _load_characters(vg_data)
|
|
|
|
|
- _globals.vg_attributes = _load_attributes(vg_data)
|
|
|
|
|
|
|
+ def decorator(environment):
|
|
|
|
|
+ _globals.environments.update({environment_name: environment})
|
|
|
|
|
+
|
|
|
|
|
+ return decorator
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def load_environment(
|
|
|
|
|
+ new_environment: str,
|
|
|
|
|
+ items_to_transfer: list | dict = [],
|
|
|
|
|
+ to_export: bool = False,
|
|
|
|
|
+):
|
|
|
|
|
+ if isinstance(items_to_transfer, dict):
|
|
|
|
|
+ items_to_transfer = [
|
|
|
|
|
+ items_to_transfer,
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ if not to_export:
|
|
|
|
|
+ if not new_environment in _globals.environments.keys():
|
|
|
|
|
+ raise KeyError(_('the environment name does not exist'))
|
|
|
|
|
+ if not _globals._window:
|
|
|
|
|
+ init()
|
|
|
|
|
+
|
|
|
|
|
+ _globals.vg_chronometers = []
|
|
|
|
|
+ _globals.vg_levelbars = []
|
|
|
|
|
+ _globals.vg_scoreboards = []
|
|
|
|
|
+
|
|
|
|
|
+ vg_data = utils._load_yaml_from_filename(f'{new_environment}.yaml')
|
|
|
|
|
+
|
|
|
|
|
+ _load_data(vg_data)
|
|
|
|
|
+
|
|
|
|
|
+ character_names = [c.name for c in _globals.vg_characters]
|
|
|
|
|
+ for item in items_to_transfer:
|
|
|
|
|
+ match item:
|
|
|
|
|
+ case character.Character():
|
|
|
|
|
+ if item.name in character_names:
|
|
|
|
|
+ character_names.pop(character_names.index(item.name))
|
|
|
|
|
+ add_character(item)
|
|
|
|
|
+ case groups.Group():
|
|
|
|
|
+ add_group(item)
|
|
|
|
|
+ case texts.Chronometer():
|
|
|
|
|
+ add_chronometer(item)
|
|
|
|
|
+ case texts.Scoreboard():
|
|
|
|
|
+ add_scoreboard(item)
|
|
|
|
|
+ case texts.Text():
|
|
|
|
|
+ add_text(item)
|
|
|
|
|
+ case widgets.LevelBar():
|
|
|
|
|
+ add_levelbar(item)
|
|
|
|
|
+ case dict():
|
|
|
|
|
+ for name, value in item.items():
|
|
|
|
|
+ add_attribute(name, value)
|
|
|
|
|
|
|
|
if _globals.vg_characters:
|
|
if _globals.vg_characters:
|
|
|
|
|
+ _calculate_initial_collisions()
|
|
|
_globals.character_focus = _globals.vg_characters[0]
|
|
_globals.character_focus = _globals.vg_characters[0]
|
|
|
|
|
|
|
|
- # TODO: Check and filter variable names added to builtins
|
|
|
|
|
- setattr(builtins, 'vgscene', _globals.vg_scene)
|
|
|
|
|
|
|
+ builtins.__dict__.update({_('current_scene'): _globals.vg_scene})
|
|
|
|
|
+
|
|
|
|
|
+ for vg_text in _globals.vg_texts:
|
|
|
|
|
+ # Check if character names exist in the predefined builtins
|
|
|
|
|
+ # if not vg_character.name in _globals.predefined_builtins:
|
|
|
|
|
+ # if not vg_text.name in builtins.__dict__.keys():
|
|
|
|
|
+ builtins.__dict__[vg_text.name] = vg_text
|
|
|
|
|
+
|
|
|
for vg_character in _globals.vg_characters:
|
|
for vg_character in _globals.vg_characters:
|
|
|
- setattr(builtins, vg_character.name, vg_character)
|
|
|
|
|
|
|
+ # Check if character names exist in the predefined builtins
|
|
|
|
|
+ # if not vg_character.name in _globals.predefined_builtins:
|
|
|
|
|
+ # if not vg_character.name in builtins.__dict__.keys():
|
|
|
|
|
+ builtins.__dict__[vg_character.name] = vg_character
|
|
|
|
|
+
|
|
|
|
|
+ for vg_group in _globals.vg_groups:
|
|
|
|
|
+ # Check if group names exist in the predefined builtins
|
|
|
|
|
+ # if not vg_group.name in _globals.predefined_builtins:
|
|
|
|
|
+ # if not vg_group.name in builtins.__dict__.keys():
|
|
|
|
|
+ builtins.__dict__[vg_group.name] = vg_group
|
|
|
|
|
+
|
|
|
|
|
+ for name, value in _globals.vg_attributes.items():
|
|
|
|
|
+ builtins.__dict__[name] = value
|
|
|
|
|
+
|
|
|
|
|
+ _globals.current_environment = new_environment
|
|
|
|
|
|
|
|
|
|
|
|
|
def stop():
|
|
def stop():
|
|
|
"""
|
|
"""
|
|
|
- Finish the infinite videogame loop.
|
|
|
|
|
|
|
+ Finishes the infinite videogame loop.
|
|
|
"""
|
|
"""
|
|
|
global running
|
|
global running
|
|
|
running = False
|
|
running = False
|
|
|
|
|
|
|
|
|
|
|
|
|
-def update():
|
|
|
|
|
|
|
+def update(to_quit: bool = False):
|
|
|
"""
|
|
"""
|
|
|
- Refresh the display surface and listen events.
|
|
|
|
|
|
|
+ Updates the display surface and listen events.
|
|
|
"""
|
|
"""
|
|
|
if _globals.vg_scene:
|
|
if _globals.vg_scene:
|
|
|
if _globals.vg_characters:
|
|
if _globals.vg_characters:
|
|
|
- _globals.vg_scene.set_position(_globals.character_focus.x)
|
|
|
|
|
- paint(_globals.vg_scene)
|
|
|
|
|
|
|
+ _globals.vg_scene._set_abscissa_position(
|
|
|
|
|
+ _globals.character_focus.x
|
|
|
|
|
+ )
|
|
|
|
|
+ paint_scene(_globals.vg_scene)
|
|
|
if _globals.vg_characters:
|
|
if _globals.vg_characters:
|
|
|
for pos, vg_character in enumerate(_globals.vg_characters):
|
|
for pos, vg_character in enumerate(_globals.vg_characters):
|
|
|
tracking = (
|
|
tracking = (
|
|
|
True if vg_character == _globals.character_focus else False
|
|
True if vg_character == _globals.character_focus else False
|
|
|
)
|
|
)
|
|
|
vg_character._update_rect_position(tracking=tracking)
|
|
vg_character._update_rect_position(tracking=tracking)
|
|
|
- paint(vg_character)
|
|
|
|
|
|
|
+ paint_character(vg_character)
|
|
|
vg_character.update()
|
|
vg_character.update()
|
|
|
if _globals.vg_groups:
|
|
if _globals.vg_groups:
|
|
|
- for group_item in _globals.vg_groups:
|
|
|
|
|
- for sprite_item in group_item.sprites():
|
|
|
|
|
- sprite_item._update_rect_position()
|
|
|
|
|
- paint(sprite_item)
|
|
|
|
|
- sprite_item.update()
|
|
|
|
|
|
|
+ for vg_group in _globals.vg_groups:
|
|
|
|
|
+ paint_group(vg_group)
|
|
|
|
|
+ vg_group.update()
|
|
|
if _globals.vg_levelbars:
|
|
if _globals.vg_levelbars:
|
|
|
for levelbar_item in _globals.vg_levelbars:
|
|
for levelbar_item in _globals.vg_levelbars:
|
|
|
levelbar_item.draw()
|
|
levelbar_item.draw()
|
|
|
if _globals.vg_scoreboards:
|
|
if _globals.vg_scoreboards:
|
|
|
for scoreboard_item in _globals.vg_scoreboards:
|
|
for scoreboard_item in _globals.vg_scoreboards:
|
|
|
- paint(scoreboard_item)
|
|
|
|
|
|
|
+ scoreboard_item.draw()
|
|
|
if _globals.vg_chronometers:
|
|
if _globals.vg_chronometers:
|
|
|
for chronometers_item in _globals.vg_chronometers:
|
|
for chronometers_item in _globals.vg_chronometers:
|
|
|
- paint(chronometers_item)
|
|
|
|
|
|
|
+ chronometers_item.draw()
|
|
|
chronometers_item.update()
|
|
chronometers_item.update()
|
|
|
if _globals.vg_texts:
|
|
if _globals.vg_texts:
|
|
|
for texts_item in _globals.vg_texts:
|
|
for texts_item in _globals.vg_texts:
|
|
|
- paint(texts_item)
|
|
|
|
|
|
|
+ if texts_item.visible:
|
|
|
|
|
+ texts_item._update_rect_position()
|
|
|
|
|
+ texts_item.draw()
|
|
|
if _globals.visible_inventory:
|
|
if _globals.visible_inventory:
|
|
|
_globals.visible_inventory.draw()
|
|
_globals.visible_inventory.draw()
|
|
|
if _globals.marks:
|
|
if _globals.marks:
|
|
@@ -483,11 +601,13 @@ def update():
|
|
|
pygame.display.flip()
|
|
pygame.display.flip()
|
|
|
_globals._clock.tick(settings.FPS)
|
|
_globals._clock.tick(settings.FPS)
|
|
|
listen_events()
|
|
listen_events()
|
|
|
|
|
+ if not to_quit:
|
|
|
|
|
+ _globals.environments[_globals.current_environment]()
|
|
|
|
|
|
|
|
|
|
|
|
|
-def quit(wait: int = 0):
|
|
|
|
|
|
|
+def quit(wait: int = settings.DEFAULT_TIME_TO_QUIT):
|
|
|
"""
|
|
"""
|
|
|
- Exit the game.
|
|
|
|
|
|
|
+ Exits the game.
|
|
|
|
|
|
|
|
Parameters:
|
|
Parameters:
|
|
|
wait: Seconds to wait before exiting
|
|
wait: Seconds to wait before exiting
|
|
@@ -495,7 +615,8 @@ def quit(wait: int = 0):
|
|
|
Examples:
|
|
Examples:
|
|
|
>>> quit(1)
|
|
>>> quit(1)
|
|
|
"""
|
|
"""
|
|
|
- if isinstance(wait, int) and wait > 0:
|
|
|
|
|
|
|
+ update(to_quit=True)
|
|
|
|
|
+ if type(wait) == int and wait > 0:
|
|
|
time.sleep(wait)
|
|
time.sleep(wait)
|
|
|
pygame.quit()
|
|
pygame.quit()
|
|
|
stop()
|
|
stop()
|