1

I am trying to make a basic game where the goblin moves from left hits the side then goes back again. I am trying to check if the player sprite is overlapping with the goblin sprite when the player attacks, then do some damage to the goblin. Although my player is always on contact with the enemy even when he isn't close to coming in contact. Why is this happening?

import pygame

pygame.init()
walkleft = [pygame.image.load("W_L.png"), pygame.image.load("W_L2.png")]
walkright = [pygame.image.load("W_R.png"), pygame.image.load("W_R2.png")]
walkup = [pygame.image.load("W_D.png"), pygame.image.load("W_D2.png")]
walkdown = [pygame.image.load("W_U.png"), pygame.image.load("W_U2.png")]
Link = pygame.image.load("Standing.png")
pygame.init()
win = pygame.display.set_mode((500, 480))
tan = ((230,220,170))
pygame.display.update()

clock = pygame.time.Clock()

attack = pygame.mixer.Sound('attack.wav')

class Player(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height, location):
        pygame.sprite.Sprite.__init__(self)
        super().__init__()
        self.image = pygame.image.load("standing.png")
        self.rect = self.image.get_rect()
        self.width = width
        self.height = height
        self.left = False
        self.right = False
        self.up = False
        self.down = False
        self.standing = True
        self.x = x
        self.y = y
        self.walkcount = 0
        self.vel = 5
        self.attack = pygame.mixer.Sound("attack.wav")
    
    def Hit(self):
        if ( player.rect.colliderect( goblin.rect ) ):
            self.attack.play()
            goblin.hit()

    def draw(self, win):
        if self.walkcount + 1 >= 6:
            self.walkcount = 0
        if not(self.standing):
            if self.left:
                win.blit(walkleft[self.walkcount//3], (self.x, self.y))
                self.walkcount += 1
            elif self.right:
                win.blit(walkright[self.walkcount//3], (self.x, self.y))
                self.walkcount += 1
                
            elif self.up:
                win.blit(walkup[self.walkcount//3], (self.x, self.y))
                self.walkcount += 1
                
            elif self.down:
                win.blit(walkdown[self.walkcount//3], (self.x, self.y))
                self.walkcount += 1
            
            else:
                win.blit(Link, (self.x, self.y))
        else:
            win.blit(Link, (self.x, self.y))
                    
        

class Goblin(pygame.sprite.Sprite):
    E_walkright = [pygame.image.load('E_R.png'), pygame.image.load('E_R2.png')]
    E_walkleft = [pygame.image.load('E_L.png'), pygame.image.load('E_L2.png')]

    def __init__(self, x, y, width, height, end, location):
        pygame.sprite.Sprite.__init__(self)
        super().__init__()
        self.image = pygame.image.load("E_Standing.png")
        self.rect = self.image.get_rect()
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.end = end
        self.path = [self.x, self.end]
        self.walkCount = 0
        self.vel = 3
        self.health = 10
        self.visible = True

    def draw(self,win):
        self.move()
        if self.visible:
            if self.walkCount + 1 >= 6:
                self.walkCount = 0

            if self.vel > 0:
                win.blit(self.E_walkright[self.walkCount //3], (self.x, self.y))
                self.walkCount += 1
            else:
                win.blit(self.E_walkleft[self.walkCount //3], (self.x, self.y))
                self.walkCount += 1


    def move(self):
        if self.vel > 0:
            if self.x + self.vel < self.path[1]:
                self.x += self.vel
            else:
                self.vel = self.vel * -1
                self.walkCount = 0
        else:
            if self.x - self.vel > self.path[0]:
                self.x += self.vel
            else:
                self.vel = self.vel * -1
                self.walkCount = 0

    def hit(self):
        if self.health > 0:
            self.health -= 1
        else:
            self.visible = False
        print('hit')



player = Player(0,0,24,24, 0)
goblin = Goblin(100, 100, 24,24,480, 0)

player_group = pygame.sprite.Group()
player_group.add(player)

goblin_group = pygame.sprite.Group()
goblin_group.add(goblin)

goblin_group.draw(win)
player_group.draw(win)

run = True
while run:
    win.fill((tan))
    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_LEFT] and player.x > player.vel:
        player.x -= player.vel
        player.left = True
        player.right = False
        player.standing = False
        player.down = False
        player.up = False
        
    elif keys[pygame.K_RIGHT] and player.x < 500 - player.width - player.vel:
        player.x += player.vel
        player.right = True
        player.left = False
        player.standing = False
        player.down = False
        player.up = False
        
    elif keys[pygame.K_DOWN] and player.y < 480 - player.height - player.vel:
        player.y += player.vel
        player.right = False
        player.left = False
        player.up = True
        player.standing = False
        player.down = False
    
    elif keys[pygame.K_UP] and player.y > player.vel:
        player.y -= player.vel
        player.right = False
        player.left = False
        player.up = False
        player.down = True
        player.standing = False
    
    elif keys[pygame.K_SPACE]:
        player.Hit()
    
    else:
        player.standing = True
        player.walkCount = 0
        
    
    
    
    goblin.draw(win)
    player.draw(win)
    pygame.display.update()
    goblin.update()
hata
  • 11,633
  • 6
  • 46
  • 69
b9e
  • 13
  • 2

1 Answers1

0

The problem is that your are comparing the Player.rect with Goblin.rect. These are correct at the time of object creation, but when the Player (or Goblin) moves the rect is not updated to match. So you're still comparing the positions from the start state.

It would be better & simpler to use the given x,y to initially position the sprite's .rect, and from then on maintain the position with the .rect. It can also (easily) be used for both collision detection and drawing to the screen.

It's not a big change:

class Goblin(pygame.sprite.Sprite):
    E_walkright = [pygame.image.load('E_R.png'), pygame.image.load('E_R2.png')]
    E_walkleft = [pygame.image.load('E_L.png'), pygame.image.load('E_L2.png')]

    def __init__(self, x, y, width, height, end, location):
        pygame.sprite.Sprite.__init__(self)
        super().__init__()
        self.image = pygame.image.load("E_Standing.png")
        self.rect = self.image.get_rect( topleft=(x,y) )   # set initial position
        self.path = [ x, end ]
        self.walkCount = 0
        self.vel = 3
        self.health = 10
        self.visible = True

    def draw(self,win):
        self.move()
        if self.visible:
            if self.walkCount + 1 >= 6:
                self.walkCount = 0

            if self.vel > 0:
                win.blit(self.E_walkright[self.walkCount //3], self.rect )
                self.walkCount += 1
            else:
                win.blit(self.E_walkleft[self.walkCount //3],  self.rect )
                self.walkCount += 1


    def move(self):
        if self.vel > 0:
            if self.rect.x + self.vel < self.path[1]:
                self.rect.x += self.vel
            else:
                self.vel = self.vel * -1
                self.walkCount = 0
        else:
            if self.rect.x - self.vel > self.path[0]:
                self.rect.x += self.vel
            else:
                self.vel = self.vel * -1
                self.walkCount = 0

    def hit(self):
        if self.health > 0:
            self.health -= 1
        else:
            self.visible = False
        print('hit')

Obviously similar changes are needed for Player too.

So when any movement is made, it is simply applied to the .rect.x and .rect.y rather than to a discrete x & y.

hata
  • 11,633
  • 6
  • 46
  • 69
Kingsley
  • 14,398
  • 5
  • 31
  • 53