Hi, I'm making a simple oop game in python using pygame.
Currently, my game object classes have methods like move, draw and check collision. I would like to create a new class with the intention of handling these interactions in a way that my game object classes don't have to know about other game objects anymore
Here are the abstract classes for the game objects
import pygame
from abc import ABC, abstractmethod
import copy
class ABCObject(ABC):
def __init__(self, initial_x: int, initial_y: int, size: int, color: tuple):
self._size = size
self._rect = pygame.Rect(
initial_x, initial_y, self._size, self._size)
self._color = color
@property
def size(self):
return self._size
@property
def rect(self):
return self._rect
@property
def color(self):
return self._color
@size.setter
def size(self, new_size: int):
if isinstance(new_size, int):
self._size = new_size
@color.setter
def color(self, new_color: tuple):
if isinstance(new_color, tuple):
if len(new_color) == 3 and isinstance(new_color[1], int) and isinstance(new_color[0], int) and isinstance(new_color[2], int):
self._color = new_color
def draw(self, win, offset):
fake_rect = copy.deepcopy(self._rect)
fake_rect.topleft -= offset
pygame.draw.rect(win, self._color, fake_rect)
from abc_object import ABCObject
class Kinetic_object(ABCObject, ABC):
def __init__(self, initial_x: int, initial_y: int, size: int, color: tuple, speed: int):
super().__init__(initial_x, initial_y, size, color)
self._speed = speed
self._velX = 0
self._velY = 0
@property
def speed(self):
return self._speed
@property
def velX(self):
return self._velX
@property
def velY(self):
return self._velY
@velX.setter
def velX(self, new_velX):
if isinstance(new_velX, (int, float)):
self._velX = new_velX
@velY.setter
def velY(self, new_velY):
if isinstance(new_velY, (int, float)):
self._velY = new_velY
@speed.setter
def speed(self, new_speed):
if isinstance(new_speed, int):
self._speed = new_speed
@abstractmethod
def move(self):
pass
And here is my player class:
import math
import copy
from abc_command import Command
from abc_kinetic_object import Kinetic_object
class Player(Kinetic_object, Command):
def __init__(self, initial_x: int, initial_y: int, size: int, speed: int, obstacles: list):
Kinetic_object.__init__(
self, initial_x, initial_y, size, (250, 160, 60), speed)
Command.__init__(
self, {'up': False, 'down': False, 'right': False, 'left': False})
# usar depois para mudar sprite
self._facing_direction = 'down'
self._obstacles = obstacles
# usar para normalizar os vetores de velocidade, caso contrario, anda mais rápido nas diagonais
def normalize(self):
if self._velX != 0 and self._velY != 0:
self._velX *= 1/math.sqrt(2)
self._velY *= 1/math.sqrt(2)
# Colisoes, funciona se nao colidir com objetos em movimento
def move(self):
self.normalize()
self._rect.x += self._velX
self.check_collisions('horizontal')
self._rect.y += self._velY
self.check_collisions('vertical')
def check_collisions(self, direction):
if direction == 'horizontal':
for obstacle in self._obstacles:
if obstacle.rect.colliderect(self._rect):
if self._velX > 0: # direita
self._rect.right = obstacle.rect.left
elif self._velX < 0: # esquerda
self._rect.left = obstacle.rect.right
if direction == 'vertical':
for obstacle in self._obstacles:
if obstacle.rect.colliderect(self._rect):
if self._velY > 0: # baixo
self._rect.bottom = obstacle.rect.top
elif self._velY < 0: # cima
self._rect.top = obstacle.rect.bottom
def change_facing_direction(self):
# so apertando para direita
if self._commands['right'] and not (self._commands['down'] or self._commands['up'] or self._commands['left']):
self._facing_direction = 'right'
# so apertando para esquerda
elif self._commands['left'] and not (self._commands['down'] or self._commands['up'] or self._commands['right']):
self._facing_direction = 'left'
# so apertando para cima
elif self._commands['up'] and not (self._commands['down'] or self._commands['right'] or self._commands['left']):
self._facing_direction = 'up'
# so apertando para baixo
elif self._commands['down'] and not (self._commands['up'] or self._commands['left'] or self._commands['right']):
self._facing_direction = 'down'
def execute_commands(self):
self.change_facing_direction()
self._velX = 0
self._velY = 0
if self._commands['left'] and not self._commands['right']:
self._velX = -self._speed
if self._commands['right'] and not self._commands['left']:
self._velX = self._speed
if self._commands['up'] and not self._commands['down']:
self._velY = -self._speed
if self._commands['down'] and not self._commands['up']:
self._velY = self._speed
I would like to know which design pattern would be appropriate in order to remove methods like "move" from game objects and implement them in other controller classes, I have different objects that all move in a different way.
Aucun commentaire:
Enregistrer un commentaire