Quellcode für gamegridp.actor

# -*- coding: utf-8 -*-
"""
Created on Mon Apr 16 21:50:48 2018

@author: asieb
"""

import logging
import math
import cProfile
import pygame


[Doku]class Actor(pygame.sprite.Sprite): """ Ein Actor ist eine Spielfigur oder ein Objekt in der Welt, z.B. ein Auto, eine Wand, ein Untergrund. Attributes ---------- grid: Grid Das Spielfeld in dem der Actor sich befindet. color: (r,g,b) Die Farbe des Actors (falls dieser über k ein Hintergrundbild verfügt. title: str Der Name des Actors size: (x,y): Die größe des Actors in Pixeln (x und y) direction: int Die Richtung als int-Wert zwischen 0° und 360° 0° bezeichnet dabei einen Blick nach rechts und der Winkel verläuft gegen den Uhrzeigersinn. is_blocking: bool Legt fest, ob der Akteur das Feld für andere Akteure blockiert. Wenn die Variable wahr ist, ist es nicht möglich sich über das Feld des Akteurs zu bewegen. image_rect: Rect Das Rechteck (Rectangle), welches das Objekt umschließt. is_rotatable: bool Wahr, wenn sich das Bild mit der Richtung mitdrehen soll. class_name Der Typ des Akteurs - entspricht dem Klassennamen. actor_id Jeder Akteur hat eine eindeutige ID. Methoden -------- """ # Konstruktor def __init__(self, grid, location: tuple = (0, 0), color: tuple = (0, 0, 255), title: str = "Actor", img_path: str = None, size: tuple = (40, 40), img_action: str = None): pygame.sprite.Sprite.__init__(self) # define instance variables self.title = title self._actor_id = 0 self._logging = logging.getLogger('Actor:') # Define instance variables self._original_images = [] # All images stores for actor self._image = None self._image_index = 0 self._is_rotatable = False self._is_flipped = False self.__grid__ = grid self._location = location self._direction = 0 self.color = color self.size = size self.animation_speed = self.grid.speed/2 self._animated = False self._is_blocking = False self._collision_partners = pygame.sprite.Group() # Set Actor image self._logging.debug("actor.__init__() : Target-Location:" + str(self.location)) self._has_image = False # Add image to actor if img_path is not None: self.add_image(img_path, img_action, size) else: self.delete_images() self._logging.debug( "actor.__init__() : Actor: " + str(title) + "'s setup wurde ausgeführt" + str(self._is_rotatable)) # Add actor to grid grid.add_actor(self, location) # set the bounding-box style (cell for cell-based games, image for pixel-based games if self.grid.cell_size == 1: self._bounding_box_type = "image" else: self._bounding_box_type = "cell" self.__bounding_box_size__ = None self.setup() self._logging.debug("actor.__init__() : Actor " + str(title) + " wurde initialisiert") # Properties @property def is_blocking(self): """bool: Legt fest, ob der Akteur das Feld "blockt", d.h. für andere Akteure unpassierbar macht. """ return self._is_blocking @is_blocking.setter def is_blocking(self, value: bool): self._is_blocking = value @property def direction(self) -> int: """int: Legt die Richtung fest, in die der Akteur "schaut" 0° bezeichnet dabei nach Osten, andere Winkel werden gegen den Uhrzeigersinn angegeben. Die Direction kann alternativ auch als String ("left", "right", "top", "bottom" festgelegt werden. """ return self._direction @direction.setter def direction(self, value: int): if value == "right": value = 0 if value == "left": value = 180 if value == "up": value = 90 if value == "down": value = 270 self._logging.debug( "actor.rotation() : rotated by " + str(value) + " degrees. Is rotatable?: " + str(self._is_rotatable)) self.__rotate__(value) self._direction = value # if value < 0: # self.direction = 360 + value # if value > 360: self._direction = value % 360 @property def image_rect(self): """ :return: The surrounding Rectangle used for redrawing and image manipulation """ try: left, top = self.__get_image_coordinates_in_pixels__() width = self._image.get_width() height = self._image.get_height() except AttributeError: left, top, width, height = 0, 0, 0, 0 return pygame.Rect(left, top, width, height) @property def image(self): """ Gets the actual image of the actor. """ return self._image @image.setter def image(self, value: str): """ sets the actual image :param value: the path to the image """ self._image = value @property def is_rotatable(self): """ : return true if actor-image is rotatable, else false """ return self._is_rotatable @is_rotatable.setter def is_rotatable(self, value: bool): """ sets the actual image :param value: the path to the image """ self._is_rotatable = value @property def grid(self): return self.__grid__ @property def location(self) -> tuple: """ returns the location of object """ return self._location @location.setter def location(self, value: tuple): """ Sets the location :type value: tuple with x and y-coordinate """ self._logging.debug("actor.location: Location set") self.__grid__.repaint_area(pygame.Rect(self.image_rect)) self._location = value self.__grid__.repaint_area(pygame.Rect(self.image_rect)) self.__grid__.__update__(no_logic=True) @property def has_image(self): """ Checks if actor has an image :return: true if actor has an image, else false """ return self._has_image @has_image.setter def has_image(self, value): self._has_image = value @property def class_name(self) -> str: return self.__class__.__name__ @property def actor_id(self) -> int: return self._actor_id @actor_id.setter def actor_id(self, value:int): self._actor_id = value @property def rect(self,): """ Gibt die umgebene Bounding-Box um den Akteur zurück. :return: Die umgebende Bounding-Box. """ if self._bounding_box_type == "image": rect = self.__image_rect__() return rect else: return self.__cell_rect__() # Methoden
[Doku] def act(self): """ Überschreibe diese Methode in deinen eigenen Actor-Klassen """ pass
[Doku] def set_image(self, img_path: str, img_action: str = None, size=None): """ Fügt ein einzelnes Bild zu einem Actor hinzu. :param img_path: Der Pfad des Bildes relativ zum eigenen Dateipfad. :param img_action: Die Aktion die durchgeführt werden soll: *scale*, *crop*, *do_nothing* :param size: scale/crop : Die Größe des veränderten Bildes as 2-Tupel """ if self.has_image: self.delete_images() self.add_image(img_path, img_action, size)
[Doku] def add_image(self, img_path: str, img_action: str = None, size=None): """ Ergänzt ein einzelnes Bild zu einem Actor. Auf diese Weise können mehrere Bilder hinzugefügt werden. Die Animation kann dann mit *animate()* gestartet werdeb :param img_path: Der Pfad des Bildes relativ zum eigenen Dateipfad. :param img_action: Die Aktion die durchgeführt werden soll: *scale*, *crop*, *do_nothing* :param size: scale/crop : Die Größe des veränderten Bildes as 2-Tupel """ self._logging.info("add_image(): Start add image") self.__grid__.repaint_area(pygame.Rect(self.image_rect)) if img_action is None and self.grid.cell_size == 1: img_action = "do_nothing" if img_action is None and self.grid.cell_size > 1: img_action = "scale" self._logging.info( "img_action:" + str(img_action)) if not self.has_image: self._original_images = [] self._logging.info("add_image(): list was cleared:" + str(self._original_images.__len__())) self._logging.info("add_image(): Has image:" + str(self.has_image)) self._original_images.append(pygame.image.load(img_path).convert_alpha()) self._logging.info("actor.add_image() : Number of Actor images:" + str(self._original_images.__len__())) self.__image_transform__(-1, img_action, size) self.image = self._original_images[0] # overwrite image self.__grid__.repaint_area(pygame.Rect(self.image_rect)) self.has_image = True
[Doku] def delete_images(self): """ Löscht alle Bilder eines Akteurs. Dies kann z.B. sinnvoll sein, wenn eine neue Animation festgelegt werden soll und dafür die alte Animation zuvor gelöscht werden muss. """ self._original_images = [] self._image = pygame.Surface(self.size) self._image.fill(self.color) self._original_images.append(self._image) self.has_image = False
[Doku] def animate(self): """ Startet eine Animation. """ if not self._animated: self._animated = True
[Doku] def add_collision_partner(self, partner): """ .. deprecated:: 0.4.0 `add_collision_partner` wird in GameGrid 0.6 ersetzt werden. """ self._collision_partners.add(partner)
[Doku] def stop(self): """ Stopt die Animation eines Akteurs. """ self._animated = False
def _next_sprite(self): """ Läd das nächste Sprite in einer Animation. """ if self._animated: if self.grid.frame % self.animation_speed == 0: # every n-th frame (n: animation speed) do: self.grid.repaint_area(pygame.Rect(self.image_rect)) if self._image_index < self._original_images.__len__() - 1: self._image_index = self._image_index + 1 else: self._image_index = 0 self.image = self._original_images[self._image_index] self.draw() self.grid.repaint_area(pygame.Rect(self.image_rect)) self._logging.info("actor.image_next() : Image Index:" + str(self._image_index) + "/" + str( self._original_images.__len__() - 1)) def __rotate__(self, direction: int): """ rotates the actor by _direction_ degrees :param direction: """ if self.is_rotatable: self.__grid__.repaint_area(pygame.Rect(self.image_rect)) # rotate the original image to new direction self._logging.debug("actor.__rotate: rotate Image" + str(dir(self._original_images)) + ", Image: " + str( self._image) + "Index:" + str(self._image_index)) self.image = pygame.transform.rotate(self._original_images[self._image_index], direction) self.__grid__.repaint_area(pygame.Rect(self.image_rect))
[Doku] def is_in_grid(self, target: tuple = None) -> bool: """ Überprüft ob ein Akteur (bzw. eine gegebene Zellen-Koordinate im Grid ist. :param target Überprüft eine beliebige Zellen-Koordinate, ob diese in Grid liegt (Falls kein Ziel angegeben ist, wird die Zellen-Koordinate des Akteurs selbst verwendet) """ if target == None: target = self.location if self.grid.is_location_in_grid(target): return True return False
[Doku] def is_at_border(self) -> str: """ Überprüft, ob der Akteur an der Grenze zum Rand ist. :return: Die zugehörige Grenze als String ("left", "right", "top" oder "bottom") """ if self.is_at_left_border(): return "left" elif self.is_at_right_border(): return "right" elif self.is_at_bottom_border(): return "bottom" elif self.is_at_top_border(): return "top" else: return False
[Doku] def is_at_left_border(self) -> bool: """ Überprüft, ob der Akteur an der Grenze zum linken Rand ist. :return: True oder False """ if self.grid.is_at_left_border(self.rect): return True else: return False
[Doku] def is_at_bottom_border(self) -> bool: """ Überprüft, ob der Akteur an der Grenze zum unteren Rand ist. :return: True oder False """ if self.grid.is_at_bottom_border(self.rect): return True else: return False
[Doku] def is_at_right_border(self) -> bool: """ Überprüft, ob der Akteur an der Grenze zum rechten Rand ist. :return: True oder False """ if self.grid.is_at_right_border(self.rect): return True else: return False
[Doku] def is_at_top_border(self) -> bool: """ Überprüft, ob der Akteur an der Grenze zum oberen Rand ist. :return: True oder False """ if self.grid.is_at_top_border(self.rect): return True else: return False
[Doku] def bounding_box_is_in_grid(self, target: tuple = None) -> bool: """ Überprüft, ob die Bounding-Box eines Akteurs (komplett) im Grid ist. :return: True oder False """ if target == None: box = self.rect else: box = self.rect(target) if self.grid.is_rectangle_in_grid(box): return True else: return False
def get_bounding_box_collision(self, actor, class_name : str = None): self.grid.get_bounding_box_collision(actor, class_name) def get_all_bounding_box_collisions(self, actor, class_name : str = None): self.grid.get_all_bounding_box_collisions(actor, class_name)
[Doku] def flip_x(self): """ Spiegelt das Bild des Akteurs über die y-Achse. Der Akteur selbst wird dabei um 180° gedreht. """ if not self._is_flipped: self._is_flipped = True else: self._is_flipped = False self.__flip_x__() self.turn_left(180)
def __flip_x__(self): """ Flipped das Element in x-Richtung """ try: if not self._is_flipped: self.__grid__.repaint_area(pygame.Rect(self.image_rect)) self._logging.debug( "actor.flip_x() : Flipping " + self.title + " image number " + str(self._image_index)) self.image = pygame.transform.flip(self._original_images[self._image_index], False, False) self.__grid__.repaint_area(pygame.Rect(self.image_rect)) else: self.__grid__.repaint_area(pygame.Rect(self.image_rect)) self.image = pygame.transform.flip(self._original_images[self._image_index], True, False) self.__grid__.repaint_area(pygame.Rect(self.image_rect)) except IndexError: self._logging.warning("actor.flip_x : Index Error in __flip_x__() in: Image Index is out of bounds")
[Doku] def set_rotatable(self): """ DEPRECATED / VERALTET Achtung: Verwende stattdessen das Attribut: is_rotatable """ self._is_rotatable = True
def set_text(self, text, size): myfont = pygame.font.SysFont("monospace", size) label = myfont.render(text, 1, (0, 0, 0)) self.image.blit(label, (0, 0)) self._original_images[0] = self._image self.__grid__.repaint_area(pygame.Rect(self.image_rect))
[Doku] def get_all_actors_at_location(self, class_name, location=None) -> list: """ Gibt *alle* Akteure einer bestimmten Klasse an der selben Position wie der aktuelle Akteur zurück (Alternativ kann auch eine beliebige Position abgefragt werden). :param class_name: Der Klassenname nachdem gesucht werden soll als String (z.B. alle Akteure vom Typ "Wall"). :param location: Optional kann eine andere Zellen-Koordinate als Tupel (x,y) angegeben werden. :return: Eine Liste aller Akteure vom angegebenen Typ """ if location == None: location = self.location actors = self.grid.get_all_actors_at_location(location, class_name) if self in actors: actors.remove(self) return actors
[Doku] def get_actor_at_location(self, class_name, location=None) -> list: """ Gibt *einen* Akteur an der Position zurück. :param class_name: Der Klassenname nachdem gesucht werden soll als String (z.B. alle Akteure vom Typ "Wall"). :param location: Optional kann eine andere Zellen-Koordinate als Tupel (x,y) angegeben werden. :return: Der erste Akteur vom angegegebenen Typ. """ if location == None: location = self.location actors_at_location = self.get_all_actors_at_location(class_name, location) if actors_at_location: return actors_at_location[0] else: return None
[Doku] def get_actor_in_front(self, class_name, distance=1) -> list: """ Gibt einen Akteur in x-Feldern Entfernung vor dem aktuellen Akteur zurück. (Alternativ kann auch eine beliebige Position abgefragt werden). :param class_name: Der Klassenname nachdem gesucht werden soll als String (z.B. alle Akteure vom Typ "Wall"). :param distance: Anzahl an Feldern, die nach vorne geschaut werden soll. :return: Eine Liste aller Akteure vom angegebenen Typ """ location = self.look_forward(distance) actors_at_location = self.get_all_actors_at_location(class_name, location) if actors_at_location: return actors_at_location[0]
def __image_transform__(self, index: int, img_action: str, size: str = None): """ Should be called before main-loop :param size: img_acton : "scale" -> data : location """ img_action = str.lower(img_action) cell_size = self.grid.cell_size if img_action == "scale": if size is None: size = (cell_size, cell_size) self._original_images[index] = pygame.transform.scale(self._original_images[index], (size[0], size[1])) elif img_action == "center": cropped_surface = pygame.Surface((cell_size, cell_size), pygame.SRCALPHA, 32) width = self._original_images[self._image_index].get_width() height = self._original_images[self._image_index].get_height() x_pos = (self.grid.cell_size - width) / 2 y_pos = (self.grid.cell_size - height) / 2 cropped_surface.blit(self._original_images[self._image_index], (x_pos, y_pos), (0, 0, cell_size, cell_size)) self._original_images[self._image_index] = cropped_surface elif img_action == "do_nothing": self._original_images[self._image_index] = self._original_images[self._image_index] def __image_rect__(self, location=None): """ the image rect when drawn to another location """ if location == None: location = self.location try: width = self._image.get_width() height = self._image.get_height() left, top = self.__get_image_coordinates_in_pixels__(location) except AttributeError: left, top, width, height = 0, 0, 0, 0 return pygame.Rect(left, top, width, height) def __cell_rect__(self, location: tuple = None): if location == None: location = self.location return self.grid.cell_rect(location)
[Doku] def set_bounding_box_size(self, value): """ Legt die Größe der umgebenen Bounding-Box fest. :param value: Eine Größe (width, height) als Tupel. """ self.__bounding_box_size__ = value
def __get_image_coordinates_in_pixels__(self, location: tuple = None): """ Gibt die Bildkoordinaten der oberen linken Recke des Akteur-Bildes zurück. :return: Tupel (x,y) mit Pixelkoordinaten der linken oberen Ecke """ if location == None: column = self.location[0] row = self.location[1] else: column = location[0] row = location[1] cell_margin = self.__grid__.cell_margin cell_size = self.__grid__.cell_size if self._image.get_width() > cell_size: overlapping_x = (self._image.get_width() - cell_size) / 2 else: overlapping_x = 0 if self._image.get_height() > cell_size: overlapping_y = (self._image.get_height() - cell_size) / 2 else: overlapping_y = 0 cell_left = cell_margin + (cell_margin + cell_size) * column - overlapping_x cell_top = cell_margin + (cell_margin + cell_size) * row - overlapping_y return cell_left, cell_top
[Doku] def get_neighbour_cells(self) -> list: """ Gibt alle 8 umgebenen Zellen zurück. :return: Alle Nachbarzellen als Liste. """ locations = [] y_pos = self.location[0] x_pos = self.location[1] locations.append([x_pos + 1, y_pos]) locations.append([x_pos + 1, y_pos + 1]) locations.append([x_pos, y_pos + 1]) locations.append([x_pos - 1, y_pos + 1]) locations.append([x_pos - 1, y_pos]) locations.append([x_pos - 1, y_pos - 1]) locations.append([x_pos, y_pos - 1]) locations.append([x_pos + 1, y_pos - 1]) return locations
[Doku] def listen(self, key, data): """ Diese Methode sollte in deiner Kind-Klasse überschrieben werden. """ pass
[Doku] def get_location(self) -> tuple: """ Gibt die aktuelle Position des Akteurs zurück :return: the location as tuple """ return self.location
[Doku] def set_x(self, x): """ Setzt die x-Koordinate der Akteurs. :param x: Die x-Koordinate die gesetzt werden soll. """ self.location = (x, self.location[1])
[Doku] def set_y(self, y): """ Setzt die y-Koordinate der Akteurs. :param y: Die y-Koordinate die gesetzt werden soll. """ self.location = (self.location[0], y)
[Doku] def get_x(self): """ Gibt die x-Koordinate des Akteuers zurück. :param x: Gibt die x-Koordinate des Akteurs zurück. """ return self.location[0]
[Doku] def get_y(self): """ Gibt die y-Koordinate des Akteuers zurück. :param y: Gibt die y-Koordinate des Akteurs zurück """ return self.location[1]
[Doku] def setup(self): """ Sollte in deiner Kind-Klasse überschrieben werden. """ pass
[Doku] def turn_left(self, degrees: int = 90): """ Dreht den Akteur um degrees Grad nach links. :param degrees: Die Gradzahl um die der Akteur gedreht wird. :return: Die neue Richtung in Grad. """ direction = self.direction + degrees self.direction = direction self._logging.debug("Richtung:" + str(self.direction)) return self.direction
[Doku] def turn_right(self, degrees: int = 90): """ Dreht den Akteur um degrees Grad nach links. :param degrees: Die Gradzahl um die der Akteur gedreht wird. :return: Die neue Richtung in Grad. """ direction = self.direction - degrees self.direction = direction self._logging.debug("Richtung:" + str(self.direction)) return self.direction
[Doku] def move(self, distance: int = 1, move: bool = True): """ Bewegt den Akteur **distance** Schritte vorwärts. Wenn der Zug nicht valide ist, wird er nicht durchgeführt. :param distance: Die Anzahl an Schritten die der Akteur vorgehen soll :param move: Wenn der Parameter False ist, wird nur überprüft, ob der Zug legal ist. :return: Ist der Zug ein valider Zug? True/False """ target = self.look_forward(distance) self._logging.debug( "actor" + str(self) + ".move(): ...try to move from" + str(self.location) + " to target" + str( target) + " direction:" + str(self.direction)) return self.move_to(target, move)
[Doku] def move_to(self, target: tuple, move: bool = True): """ Bewegt den Akteur an die angegebene Position. Wenn der Zug nicht valide ist wird er nicht durchgeführt. :param target: Die Ziel Zellenkoordinaten :param move: Wenn der Parameter False ist, wird nur überprüft, ob der Zug legal ist. :return: Ist der Zug ein valider Zug? True/False """ if self.is_valid_target(target): if move is True: self.location = target return True else: return False
[Doku] def move_back(self, distance: int = 1, move: bool = True): """ Bewegt den Akteur **distance** Schritte rückwärts. Wenn der Zug nicht valide ist, wird er nicht durchgeführt. :param distance: Die Anzahl an Schritten die der Akteur vorgehen soll :param move: Wenn der Parameter False ist, wird nur überprüft, ob der Zug legal ist. :return: Ist der Zug ein valider Zug? True/False """ target = self.look_back(distance) return self.move_to(target, move)
[Doku] def move_right(self, distance=1, move: bool = True): """ Bewegt den Akteur **distance** Schritte nach rechts. Wenn der Zug nicht valide ist, wird er nicht durchgeführt. :param distance: Die Anzahl an Schritten die der Akteur vorgehen soll :param move: Wenn der Parameter False ist, wird nur überprüft, ob der Zug legal ist. :return: Ist der Zug ein valider Zug? True/False """ self.direction = 0 return self.move(distance, move)
[Doku] def move_left(self, distance=1, move: bool = True): """ Bewegt den Akteur **distance** Schritte nach links. Wenn der Zug nicht valide ist, wird er nicht durchgeführt. :param distance: Die Anzahl an Schritten die der Akteur vorgehen soll :param move: Wenn der Parameter False ist, wird nur überprüft, ob der Zug legal ist. :return: Ist der Zug ein valider Zug? True/False """ self.direction = 180 self.move(distance, move)
[Doku] def move_down(self, distance=1, move: bool = True): """ Bewegt den Akteur **distance** Schritte nach unten. Wenn der Zug nicht valide ist, wird er nicht durchgeführt. :param distance: Die Anzahl an Schritten die der Akteur vorgehen soll :param move: Wenn der Parameter False ist, wird nur überprüft, ob der Zug legal ist. :return: Ist der Zug ein valider Zug? True/False """ self.direction = 270 return self.move(distance, move)
[Doku] def move_up(self, distance=1, move: bool = True): """ Bewegt den Akteur **distance** Schritte nach oben. Wenn der Zug nicht valide ist, wird er nicht durchgeführt. :param distance: Die Anzahl an Schritten die der Akteur vorgehen soll :param move: Wenn der Parameter False ist, wird nur überprüft, ob der Zug legal ist. :return: Ist der Zug ein valider Zug? True/False """ self.direction = 90 return self.move(distance, move)
[Doku] def look_forward(self, distance: int = 1) -> tuple: """ Schaut *distance* Felder nach vorne und gibt die zugehörige Koordinate zurück. :param distance : Anzahl an Felder die voraus geschaut wird. :return location : Zellenkoordinate als Tuple (x,y) """ self._logging.debug("actor.look_forward() : Location:" + str(self.location) + "Direction" + str(self.direction)) loc_x = round(self.location[0] + math.cos(math.radians(self.direction)) * distance) loc_y = round(self.location[1] - math.sin(math.radians(self.direction)) * distance) return loc_x, loc_y
[Doku] def look_back(self, distance: int = 1) -> tuple: """ Schaut *distance* Felder nach hinten und gibt die zugehörige Koordinate zurück. :param distance : Anzahl an Felder die voraus geschaut wird. :return location : Zellenkoordinate als Tuple (x,y) """ self._logging.debug("actor.look_forward() : Location:" + str(self.location) + "Direction" + str(self.direction)) loc_x = round(self.location[0] - math.cos(math.radians(self.direction)) * distance) loc_y = round(self.location[1] + math.sin(math.radians(self.direction)) * distance) return loc_x, loc_y
[Doku] def look_up(self, distance: int = 1) -> tuple: """ Schaut *distance* Felder nach oben und gibt die zugehörige Koordinate zurück. :param distance : Anzahl an Felder die voraus geschaut wird. :return location : Zellenkoordinate als Tuple (x,y) """ self._logging.debug("actor.look_forward() : Location:" + str(self.location) + "Direction" + str(self.direction)) loc_x = self.location[0] loc_y = self.location[1] - distance return loc_x, loc_y
[Doku] def look_down(self, distance: int = 1) -> tuple: """ Schaut *distance* Felder nach unten und gibt die zugehörige Koordinate zurück. :param distance : Anzahl an Felder die voraus geschaut wird. :return location : Zellenkoordinate als Tuple (x,y) """ self._logging.debug("actor.look_forward() : Location:" + str(self.location) + "Direction" + str(self.direction)) loc_x = self.location[0] loc_y = self.location[1] + distance return loc_x, loc_y
[Doku] def look_left(self, distance: int = 1) -> tuple: """ Schaut *distance* Felder nach links und gibt die zugehörige Koordinate zurück. :param distance : Anzahl an Felder die voraus geschaut wird. :return location : Zellenkoordinate als Tuple (x,y) """ self._logging.debug("actor.look_forward() : Location:" + str(self.location) + "Direction" + str(self.direction)) loc_x = self.location[0] - distance loc_y = self.location[1] return loc_x, loc_y
[Doku] def look_right(self, distance: int = 1) -> tuple: """ Schaut *distance* Felder nach rechts und gibt die zugehörige Koordinate zurück. :param distance : Anzahl an Felder die voraus geschaut wird. :return location : Zellenkoordinate als Tuple (x,y) """ self._logging.debug("actor.look_forward() : Location:" + str(self.location) + "Direction" + str(self.direction)) loc_x = self.location[0] + distance loc_y = self.location[1] return loc_x, loc_y
[Doku] def is_valid_move(self, move_func=None, distance=1): """ Überprüft, ob ein Zug legal ist. :param move_func: Eine move-Funktion, z.B. move, move_back, move_left,... :param distance: Die Anzahl an Schritten, die der move-Funktion als Parameter übergeben werden sollen. :return: True falls Zug legal ist, ansonsten False. """ if move_func == None: move_func = self.move return move_func(distance, False)
[Doku] def is_valid_target(self, target: tuple = None): """ Gibt zurück, ob die angegebene Position einen legalen Zug erlaubt. :param target: Das zu überprüfende Ziel als (x,y)-Tupel Wenn kein Ziel angegeben wird, schaut der Akteur ein Feld nach vorne. :return True, falls Zug legal ist, ansonsten False """ valid = False if target is None: target = self.look_forward() if self.is_in_grid(target): self._logging.debug("actor.is_valid_target() : target:" + str(target) + ",true") valid = True else: self._logging.debug("actor.is_valid_target() : target:" + str(target) + ",false") valid = False # check if target is not blocked actors_at_position = self.__grid__.get_all_actors_at_location(target) for actor in actors_at_position: if actor.is_blocking: valid = False return valid
[Doku] def draw(self): """ Zeichnet den Akteur auf das Spielfeld. """ if self.has_image: cell_left, cell_top = self.__get_image_coordinates_in_pixels__() self.__flip_x__() self.__rotate__(self.direction) if self.grid._show_bounding_boxes: pygame.draw.rect(self._image, (255, 0, 0), (0, 0, self.rect.width, self.rect.height), 2) if self.grid._show_direction_marker: # self._logging.debug("actor.draw() - Draw line from"+str(self._image.get_rect().center)+" to "+str(self._image.get_rect().topleft)) x = round( self.rect.width / 2 + math.cos(math.radians(self.direction)) * self.rect.width) y = round(self.rect.height / 2 - math.sin( math.radians(self.direction)) * self.rect.height) pygame.draw.line(self.image, (255, 0, 0), (self.rect.width / 2, self.rect.height / 2), (x, y), 2) self.grid.grid_surface.blit(self._image, (cell_left, cell_top))
[Doku] def remove(self): """ Entfernt den Akteur vom Grid. """ self._remove_from_grid() del (self)
def _remove_from_grid(self): """ removes the actor from grid """ self.grid._actors.remove(self) self.__grid__ = None