I am working on a simple game. I created a pygame sprite and moved it by adding its rect position with a direction (from wasd input). However, it seems to be moving left and up (where all the directions are negative) quicker than right and down (where all the directions are positive)
Here is the code:
import pygame
from settings import *
from support import import_folder
class Player(pygame.sprite.Sprite):
def __init__(self, pos, groups,obstacle_sprites,create_attack,destroy_attack,create_magic):
#for sprites
super().__init__(groups)
self.image = pygame.image.load(f'{abs_path}/graphics/test/player.png').convert_alpha()
self.rect = self.image.get_rect(topleft = pos)
self.hitbox = self.rect.inflate(0,-26)
# graphics setup
self.import_player_assets()
self.status = 'down'
self.frame_index = 0
self.animation_speed = 0.15
#movement
self.direction = pygame.math.Vector2()
self.attacking = False
self.attack_cooldown = 400
self.attack_time = None
self.obstacle_sprites = obstacle_sprites
#weapon
self.create_attack = create_attack
self.destory_attack = destroy_attack
#gets the correct data from weapon dictionary in settings.py also turns keys into list
self.weapon_index = 0
self.weapon = list(weapon_data.keys())[self.weapon_index]
self.can_switch_weapon = True
self.weapon_switch_time = None
self.switch_duration_cooldown = 200
# Magic
self.create_magic = create_magic
self.magic_index = 0
self.magic = list(magic_data.keys())[self.magic_index]
self.can_switch_magic = True
self.magic_switch_time = None
#Stats
self.stats = {'health': 100, 'energy':60, 'attack': 10, 'magic': 4, 'speed': 5}
self.health = self.stats['health']
self.energy = self.stats['energy']
self.exp = 0
self.speed = self.stats['speed']
#For the player animations
def import_player_assets(self):
character_path = f'{abs_path}/graphics/player2/'
self.animations = {'up': [], 'down': [], 'left': [], 'right': [],
'right_idle': [], 'left_idle': [], 'up_idle': [], 'down_idle': [],
'right_attack': [], 'left_attack': [], 'up_attack': [], 'down_attack': []}
for animation in self.animations.keys():
full_path = character_path + animation
self.animations[animation] = import_folder(full_path)
def input(self):
keys = pygame.key.get_pressed()
#Movement Input
#The extra if statement is to make the speed the same even when its going in diagonals, some are set to .8
#because pygame is wierd
if not self.attacking:
if (keys[pygame.K_w] and keys[pygame.K_s]):
self.direction.y = 0
elif keys[pygame.K_w]:
if (keys[pygame.K_a] or keys[pygame.K_d]):
self.direction.y = -.7
else:
self.direction.y = -1
self.status = 'up'
elif keys[pygame.K_s]:
if (keys[pygame.K_a] or keys[pygame.K_d]):
self.direction.y = .7
else:
self.direction.y = 1
self.status = 'down'
else:
self.direction.y = 0
if (keys[pygame.K_d] and keys[pygame.K_a]):
self.direction.x = 0
elif keys[pygame.K_d]:
if (keys[pygame.K_w] or keys[pygame.K_s]):
self.direction.x = .7
else:
self.direction.x = 1
self.status = 'right'
elif keys[pygame.K_a]:
if (keys[pygame.K_w] or keys[pygame.K_s]):
self.direction.x = -.7
else:
self.direction.x = -1
self.status = 'left'
else:
self.direction.x = 0
#Attack Input
#if keys[pygame.K_LSHIFT] and not self.attacking
if keys[pygame.K_SPACE]:
self.attacking = True
self.attack_time = pygame.time.get_ticks()
self.create_attack()
#Spell Input
if keys[pygame.K_LSHIFT]:
self.attacking = True
self.attack_time = pygame.time.get_ticks()
style = list(magic_data.keys())[self.magic_index]
strength = list(magic_data.values())[self.magic_index]['strength'] + self.stats['magic']
cost = list(magic_data.values())[self.magic_index]['cost']
self.create_magic(style, strength, cost)
#Switch weapons Input
if keys[pygame.K_q] and self.can_switch_weapon:
self.can_switch_weapon = False
self.weapon_switch_time = pygame.time.get_ticks()
if self.weapon_index < len(list(weapon_data.keys())) - 1:
self.weapon_index += 1
else:
self.weapon_index = 0
self.weapon = list(weapon_data.keys())[self.weapon_index]
#Switch spells Input
if keys[pygame.K_e] and self.can_switch_magic:
self.can_switch_magic = False
self.magic_switch_time = pygame.time.get_ticks()
if self.magic_index < len(list(magic_data.keys())) - 1:
self.magic_index += 1
else:
self.magic_index = 0
self.magic = list(magic_data.keys())[self.magic_index]
def get_status(self):
#Idle Status:
if self.direction.x == 0 and self.direction.y == 0:
if not 'idle' in self.status and not 'attack' in self.status:
self.status = self.status + '_idle'
if self.attacking:
self.direction.x = 0
self.direction.y = 0
if not 'attack' in self.status:
if 'idle' in self.status:
self.status = self.status.replace('_idle','_attack')
else:
self.status = self.status + '_attack'
else:
if 'attack' in self.status:
self.status = self.status.replace('_attack','')
def move(self, speed):
#Moving the player feat. collision detection
self.hitbox.x += self.direction.x * speed
self.collision('horizontal')
self.hitbox.y += self.direction.y * speed
self.collision('vertical')
self.rect.center = self.hitbox.center
#Pygame cannot tell if something collides but only if it overlaps
#So i check for horizontal/vertical movement because it cant tell where it overlaps
def collision(self, direction):
if direction == 'horizontal':
for sprite in self.obstacle_sprites:
#Checking the hitbox of sprite with hitbox of obstacle
if sprite.hitbox.colliderect(self.hitbox):
if self.direction.x > 0: #checks if player is moving right
#moves the right side of player to left side of obstacle
self.hitbox.right = sprite.hitbox.left
if self.direction.x < 0:
#vice versa
self.hitbox.left = sprite.hitbox.right
if direction == 'vertical':
for sprite in self.obstacle_sprites:
#Checking the hitbox of sprite with hitbox of obstacle
if sprite.hitbox.colliderect(self.hitbox):
if self.direction.y > 0: #checks if player is moving down
#moves the bottom side of player to top side of obstacle
self.hitbox.bottom = sprite.hitbox.top
if self.direction.y < 0: #move up
#vice versa
self.hitbox.top = sprite.hitbox.bottom
#Cooldown function so people cant spam attacks
def cooldowns(self):
current_time = pygame.time.get_ticks()
if self.attacking:
if current_time - self.attack_time >= self.attack_cooldown:
self.attacking = False
self.destory_attack()
if not self.can_switch_weapon:
if current_time - self.weapon_switch_time >= self.switch_duration_cooldown:
self.can_switch_weapon = True
if not self.can_switch_magic:
if current_time - self.magic_switch_time >= self.switch_duration_cooldown:
self.can_switch_magic = True
#Loop the images to make moving sprites
def animate(self):
#Goes into the image dictionary and puts player status as key, the animation = the item
animation = self.animations[self.status]
#loop over frame index
self.frame_index += self.animation_speed
if self.frame_index >= len(animation):
self.frame_index = 0
#Set the image
self.image = animation[int(self.frame_index)]
self.rect = self.image.get_rect(center = self.hitbox.center)
def update(self):
self.input()
self.cooldowns()
self.get_status()
self.animate()
self.move(self.speed)