For some reason the movement of my sprite is only diagonally up and left when pressing A, diagonally down and right when pressing D, and W/S just don't work despite the correct vectors being given to move in any direction. Here's where the inputs are handled:
class Operator:
PLAYER = 'player'
COMPUTER = 'computer'
def __init__(self, type, AI=None):
self.type = type
self.AI = AI
def handle(self, entity):
keys = pygame.key.get_pressed()
direction = Vector(0, 0)
if self.type == Operator.PLAYER:
if keys[pygame.K_w]:
direction += Vector(0, -1)
if keys[pygame.K_s]:
direction += Vector(0, 1)
if keys[pygame.K_a]:
direction += Vector(-1, 0)
if keys[pygame.K_d]:
direction += Vector(1, 0)
if direction:
entity.move(direction)
return bool(direction)
And here is the relevant sprite code:
class Sprite(pygame.sprite.Sprite):
@property
def x(self):
return self._x_coordinate
@x.setter
def x(self, value):
self._x_coordinate = self.rect.centerx = wrap(value,
WIDTH,
-self.width)
@property
def y(self):
return self._y_coordinate
@x.setter
def y(self, value):
self._y_coordinate = self.rect.centery = wrap(value,
HEIGHT,
-self.height)
@property
def position(self):
return Vector(self.x, self.y)
@position.setter
def position(self, value: Vector):
self.x, self.y = value
@property
def width(self):
return self.rect.width
@property
def height(self):
return self.rect.height
def set_surface(self, surface):
self.image = surface
class Entity(Sprite):
@property
def colliding(self):
return pygame.sprite.spritecollide(self,
sprites(self),
False)
@property
def velocity(self):
return self.internal_velocity + self.external_velocity
@property
def angle(self):
return self.velocity.as_polar()[1]
def __init__(self, size, position, operator=None, image=None, color='#FF4C4C'):
super().__init__()
if image:
image = pygame.image.load(image)
self.image = pygame.Surface(image.get_size() if image else size)
self.rect = self.image.get_rect()
self.position = position
self.operator = operator
self.internal_velocity = Vector(0, 0)
self.external_velocity = Vector(0, 0)
if not image:
self.image.fill(color)
else:
self.image.blit(image, ORIGIN)
def draw(self, surface):
if camera.on_screen(self):
surface.blit(self.image,
(self.x - self.width / 2, self.y - self.height / 2))
if debugging:
offset = Vector()
offset.from_polar((20, self.angle))
pygame.draw.line(surface,
'#54CE0E',
self.position,
self.position + offset,
1)
def update(self):
if self.operator and not self.operator.handle(self):
self.internal_velocity *= FRICTION
self.external_velocity *= FRICTION
self.position += self.velocity
if self.internal_velocity.x and 0.2 > self.internal_velocity.x > -0.2:
self.internal_velocity.x = floor(self.internal_velocity.x)
if self.internal_velocity.y and 0.2 > self.internal_velocity.y > -0.2:
self.internal_velocity.y = floor(self.internal_velocity.y)
def move(self, vector: Vector):
self.internal_velocity += vector
if self.internal_velocity.length() > MOVE_SPEED:
self.internal_velocity.scale_to_length(MOVE_SPEED)
def set_operator(self, operator):
self.operator = operator
def wrap(number, maximum, minimum=0):
return (number - minimum) % (maximum - minimum + 1) + minimum
def floor(number):
if number > 0:
return math.floor(number)
elif not number:
return 0
else:
return math.floor(abs(number)) * -1
I can provide the whole program, but it's a little over 350 lines so let me know if it's needed.
Something weird seems to be going on in your Entiry.update function.
Firstly self.operator is not a boolean. Second,
self.operator.handlereturns true if both x and y values are non zero. This means friction is only applied when entity is not moving, which does not make any sense. But taking the whole if statement into account friction is always being applied because self.operator will always have a value. But all of this would only change scale not the direction.The real problem seems to be the typo, again in update function. I have no idea what is happening here but I am pretty sure this is the problem because if these evaluate to true, your self.internal_velocity vector changes direction. If your vector has has friction applied to it and thus has a value between -1 and 1, it will get floored right down to 0. Assuming your FRICTION constant is less than 1. Which is why I am assuming it does not work.
and