I'm trying to make a small game using pygame (Just for fun) but I can't get my collision between objects right. So I decided to draw the collisions and noticed the collision is not around my character. Here's what I mean: The rectangles are the collisions
Here's my code:
import pygame
pygame.init()
winWidth = 400
winHeigth = 400
win = pygame.display.set_mode((winWidth, winHeigth))
pygame.display.set_caption("Pokemon copy")
Items = []
walkUp = [pygame.image.load('Up1.png'), pygame.image.load('Up2.png'), pygame.image.load('Up3.png'), pygame.image.load('Up4.png'), pygame.image.load('Up5.png'), pygame.image.load('idleUp.png'), pygame.image.load('Up6.png'), pygame.image.load('Up5.png'), pygame.image.load('Up6.png')]
walkDown = [pygame.image.load('D1.png'), pygame.image.load('D2.png'), pygame.image.load('D3.png'), pygame.image.load('D4.png'), pygame.image.load('D5.png'), pygame.image.load('idle.png'), pygame.image.load('D3.png'), pygame.image.load('D4.png'), pygame.image.load('D2.png')]
walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'), pygame.image.load('R4.png'), pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'), pygame.image.load('R4.png'), pygame.image.load('idleRight.png')]
walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'), pygame.image.load('L4.png'), pygame.image.load('L3.png'), pygame.image.load('L2.png'), pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('idleLeft.png')]
bg = pygame.image.load('Test.png')
idle = [pygame.image.load('idle.png'), pygame.image.load("idleUp.png"), pygame.image.load("idleLeft.png"), pygame.image.load("idleRight.png")]
myfont = pygame.font.SysFont("monospace", 15)
clock = pygame.time.Clock()
class trainer():
def __init__(self, x, y):
self.x = x
self.y = y
self.width = 32
self.heigth = 32
self.enemy = pygame.image.load('idleE.png')
self.rect = self.enemy.get_rect()
def draw(self, win):
win.blit(self.enemy, (self.x, self.y))
class player():
def __init__(self, x, y, width, heigth):
self.x = x
self.y = y
self.width = width
self.heigth = heigth
self.vel = 5
self.left = False
self.right = False
self.up = False
self.down = False
self.walkCount = 0
self.stamina = 100
self.Event = pygame.USEREVENT+1
self.previous = "right"
self.player = pygame.image.load("idle.png")
self.rect = self.player.get_rect(center=(self.x, self.y))
self.pos = self.x, self.y
def draw(self, win):
if self.walkCount + 1 >= 27:
self.walkCount = 0
if self.up:
self.rect.center = self.x, self.y
win.blit(walkUp[self.walkCount//3], (self.x, self.y))
self.walkCount += 1
elif self.down:
self.rect.center = self.x, self.y
win.blit(walkDown[self.walkCount//3], (self.x, self.y))
self.walkCount += 1
elif self.right:
self.rect.center = self.x, self.y
win.blit(walkRight[self.walkCount//3], (self.x, self.y))
self.walkCount += 1
elif self.left:
self.rect.center = self.x, self.y
win.blit(walkLeft[self.walkCount//3], (self.x, self.y))
self.walkCount += 1
else:
if self.previous == "up":
win.blit(idle[1], (self.x, self.y))
elif self.previous == "down":
win.blit(idle[0], (self.x, self.y))
elif self.previous == "left":
win.blit(idle[2], (self.x, self.y))
elif self.previous == "right":
win.blit(idle[3], (self.x, self.y))
def Collision(self, Potion):
if self.rect.colliderect(Potion.rect):
return True
else:
return False
def getPos(self):
return self.x, self.y
class usableItems():
def __init__(self, x, y):
self.usable = True
self.x = x
self.y = y
class potion(usableItems):
def __init__(self, usable, x, y):
super().__init__(x, y)
self.heal = 20
self.potion = pygame.image.load("Potion.png")
self.rect = self.potion.get_rect(center=(self.x, self.y))
def draw(self, win):
self.rect.center = self.x, self.y
win.blit(self.potion, (self.x, self.y))
def write(text, x, y, color):
text = myfont.render(text, 4, pygame.Color(color))
text_rect = text.get_rect(center=(winWidth//2, y))
return text, text_rect
def inventory():
Inventory = True
while Inventory:
clock.tick(27)
for event in pygame.event.get():
if event.type == pygame.QUIT:
Inventory = False
keys = pygame.key.get_pressed()
if keys[pygame.K_ESCAPE]:
Inventory = False
redrawInventoryWindow(Items)
def redrawInventoryWindow(items):
win.fill((0, 0, 0))
if len(items) == 0:
message = "You currently have no items!"
text, text_rect = write(message, 10, 70, (255, 255, 255))
win.blit(text, text_rect)
else:
distance = 10
for item in items:
text2, text_rect2 = write(item, 0, distance, (255, 255, 255))
distance += 25
win.blit(text2, text_rect2)
pygame.display.update()
def redrawGameWindow(character, trainer1, Potion):
win.fill((255, 255, 255))
text = "Stamina: " + str(int(character.stamina)) + "/100"
label = myfont.render(text, 1, (0, 0, 0))
win.blit(label, (0, winHeigth - 50))
character.draw(win)
pygame.draw.rect(win, (0, 255, 0), character, 3, 1)
trainer1.draw(win)
Potion.draw(win)
pygame.draw.rect(win, (200, 55, 0), Potion, 3, 2)
pygame.display.update()
def game():
character = player(50, 50, 32, 32)
trainer1 = trainer(300, 360)
Potion = potion(True, 150, 150)
run = True
while run:
clock.tick(27)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_i]:
inventory()
elif keys[pygame.K_LCTRL] and character.stamina > 0:
vel = 7.5
pygame.time.set_timer(character.Event, 1000)
character.stamina -= 1
elif not keys[pygame.K_LCTRL] and character.stamina < 100:
vel = 5
pygame.time.set_timer(character.Event, 1000)
character.stamina += 0.5
else:
vel = 5
if keys[pygame.K_LEFT] and character.x > 0:
character.previous = "left"
character.x -= vel
character.left = True
character.right = False
character.up = False
character.down = False
elif keys[pygame.K_RIGHT] and character.x < winWidth - character.width:
character.previous = "right"
character.x += vel
character.right = True
character.left = False
character.up = False
character.down = False
elif keys[pygame.K_UP] and character.y > 0:
character.previous = "up"
character.y -= vel
character.up = True
character.down = False
character.left = False
character.right = False
elif keys[pygame.K_DOWN] and character.y < winHeigth - character.heigth:
character.previous = "down"
character.y += vel
character.down = True
character.up = False
character.left = False
character.right = False
else:
character.right = False
character.left = False
character.up = False
character.down = False
character.walkCount = 0
if character.Collision(Potion):
if keys[pygame.K_DOWN]:
character.y -= vel
elif keys[pygame.K_UP]:
character.y += vel
elif keys[pygame.K_LEFT]:
character.x += vel
elif keys[pygame.K_RIGHT]:
character.x -= vel
vel = 0
redrawGameWindow(character, trainer1, Potion)
pygame.quit()
game()
Note that I'm pretty new to programming so I'm aware there's a lot to improve in my code.
Your rectangles are correct, but the Sprites are drawn at the wrong position. The position of the Sprites is defined by the rect
attribute. The attributes x
and y
define the center of the Sprite. However, the argument dest for the method blit
specifies the upper left corner where the source pygame.Surface
. is drawn. See blit
:
Draws a source Surface onto this Surface. The draw can be positioned with the dest argument. The dest argument can either be a pair of coordinates representing the position of the upper left corner of the blit or a Rect, where the upper left corner of the rectangle will be used as the position for the blit.
You you have to change all the draw
methods:
class trainer():
# [...]
def draw(self, win):
self.rect.center = self.x, self.y
win.blit(self.enemy, self.rect)
class player():
# [...]
def draw(self, win):
self.rect.center = self.x, self.y
if self.walkCount + 1 >= 27:
self.walkCount = 0
if self.up:
win.blit(walkUp[self.walkCount//3], self.rect)
self.walkCount += 1
elif self.down:
win.blit(walkDown[self.walkCount//3], self.rect)
self.walkCount += 1
# continue for all "win.blit()"
class potion(usableItems):
# [...]
def draw(self, win):
self.rect.center = self.x, self.y
win.blit(self.potion, self.rect)