user8419680
user8419680

Reputation:

Why does the collision detection not function correctly?

import random, pygame, sys, json, time, os
import colours as c
import xml.etree.ElementTree as ET

pygame.init()

with open('CONFIG.json') as config_file:
    CONFIG = json.load(config_file)

gameDisplay = pygame.display.set_mode((CONFIG['screen_resolution']))
pygame.display.set_caption('BEE RPG TYCOON')

pygame.display.update()


#Collisions


gameExit = False


x = 300
y = 300
x_change = 0
y_change = 0

clock = pygame.time.Clock()

class Spritesheet:
    #Loads an atlas image
    def __init__(self, imgFile, dataFile):
        self.spritesheet = pygame.image.load(imgFile).convert()
        if dataFile:
            tree = ET.parse(dataFile)
            self.map = {}
            for node in tree.iter():
                if node.attrib.get('name'):
                    name = node.attrib.get('name')
                    self.map[name]={}
                    self.map[name]['x'] = int(node.attrib.get('x'))
                    self.map[name]['y'] = int(node.attrib.get('y'))
                    self.map[name]['width'] = int(node.attrib.get('width'))
                    self.map[name]['height'] = int(node.attrib.get('height'))
    def getImageRect(self, x, y, w, h):
        return self.spritesheet.subsurface(pygame.Rect(x,y,w,h))


    def getImageName(self, name):
        rect = pygame.Rect(self.map[name]['x'], self.map[name]['y'],
            self.map[name]['width'], self.map[name]['height'])

        return self.spritesheet.subsurface(rect)

#Spritesg
sheet = Spritesheet("walkRight.png", "charSprite.xml")


class player():
    def __init__(self, x, y, sprite, width, height):
        self.x=x
        self.y=y
        self.sprite = sprite
        self.sprite.set_colorkey(c.green)
        self.width = width
        self.height = height
        self.rect = self.sprite.get_rect()


player = player(300, 300, sheet.getImageName("walkRightIdle.png"), 20, 22)

class enemy():

    def __init__(self,x,y,bx,by,sprite,movement,trackRad, lock, movRange,mv,width,height):
        #Basic Properties
        self.x=x
        self.y=y
        self.bx=bx
        self.by=by
        self.sprite = sprite
        self.width = width
        self.height = height
        self.rect = self.sprite.get_rect()
        #Artificial Intelligence
        self.movement = movement #How far it moves per frame.
        self.trackRad = trackRad #The radius in which the enemy can move
        self.lock = lock #Locks the enemy into a pattern
        self.movRange = movRange #When lock = 1 this determines how far it can go from it's base position, when lock = 2 this determines how far it goes in a square
        self.mv = mv #The Random generator that decides which direction it moves.
        #Lock Mechanics
        #0 - The enemy goes anywhere randomly (Looks janky)
        #1 - The enemy goes anywhere randomly, but if it leaves it's movRange it goes back (also looks janky)
        #2 - The enemy patrols in a square
        #3 - The enemy chases the player
        #4 - The enemy patrols and chases the player

basicEnemy = enemy(310,310,310,310, sheet.getImageName("walkRightIdleE.png"),5,10,1,50,random.randint(0,3), 20,22)
basicEnemy1 = enemy(250,250,250,250, sheet.getImageName("walkRightIdleE.png"),5,10,0,0,random.randint(0,3), 20 ,22)
basicEnemy2 = enemy(100,100,100,100, sheet.getImageName("walkRightIdleE.png"),5,10,2,2,random.randint(0,3),20,22)


class hive():

    def __init__(self, x, y, sprite):

        self.x = x
        self.y = y
        self.sprite = sprite

mv = random.randint(0,3)
def enemyAi(enemy, player):
    enemy.mv = random.randint(0,50)
    #Collisions
    if enemy.rect.colliderect(player.rect):
        print("stopped")
    elif enemy.lock == 0:
        if enemy.mv == 0:
            enemy.x = enemy.x + enemy.movement
        elif enemy.mv == 1:
            enemy.y = enemy.y + enemy.movement
        elif enemy.mv == 2:
            enemy.x = enemy.x - enemy.movement
        elif enemy.mv == 3:
            enemy.y = enemy.y - enemy.movement
        else:
            print("Nothing")
    elif enemy.lock == 1:
        if enemy.mv == 0:
            if enemy.x > enemy.bx + enemy.movRange:
                    enemy.x = enemy.x - enemy.movement
            else:
                enemy.x = enemy.x + enemy.movement
        elif enemy.mv == 1:
            if enemy.y > enemy.by + enemy.movRange:
                    enemy.y = enemy.y - enemy.movement
            else:
                enemy.y = enemy.y + enemy.movement
        elif enemy.mv == 2:
            if enemy.x < enemy.bx - enemy.movement:
                enemy.x = enemy.x - enemy.movement
            else:
                enemy.x = enemy.x - enemy.movement
        elif enemy.mv == 3:
            if enemy.y < enemy.by - enemy.movRange:
                enemy.y = enemy.y + enemy.movement
            else:
                enemy.y = enemy.y - enemy.movement
    elif enemy.lock == 2:
        enemy.x = enemy.x + enemy.movement
        enemy.y = enemy.y + enemy.movement
        enemy.x = enemy.x - enemy.movement
        enemy.y = enemy.y - enemy.movement











hive1 = hive(250, 300, "hive.png")

spriteAnim = 0
player.sprite = sheet.getImageName("walkRightIdle.png")
while not gameExit: # Game loop
    enemyAi(basicEnemy, player)
    enemyAi(basicEnemy1,player)
    enemyAi(basicEnemy2,player)
    for event in pygame.event.get(): #Event handling
        if event.type == pygame.QUIT: #Game closes when cross is X ye
            gameExit = True # Ends the loop
        #Movement
        #print(event)

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                if spriteAnim == 0:
                    player.sprite = sheet.getImageName("walkLeft1.png")
                else:
                    player.sprite = sheet.getImageName("walkLeft2.png")
                    spriteAnim = 0
                x_change += -5

            if event.key == pygame.K_RIGHT:
                player.sprite = sheet.getImageName("walkRight1.png")
                x_change += 5
                player.sprite = sheet.getImageName("walkRight2.png")
            if event.key == pygame.K_UP:
                player.sprite = sheet.getImageName("walkUp1.png")
                y_change += -5
                player.sprite = sheet.getImageName("walkUp2.png")
            if event.key == pygame.K_DOWN:
                player.sprite = sheet.getImageName("walkDown1.png")
                y_change += 5
                player.sprite = sheet.getImageName("walkDown2.png")
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                x_change = 0
                player.sprite = sheet.getImageName("walkLeftIdle.png")
            if event.key == pygame.K_RIGHT:
                x_change = 0
                player.sprite = sheet.getImageName("walkRightIdle.png")
            if event.key == pygame.K_UP:
                y_change = 0
                player.sprite = sheet.getImageName("walkUpIdle.png")
            if event.key == pygame.K_DOWN:
                player.sprite = sheet.getImageName("walkDownIdle.png")
                y_change = 0




    hiveSprite = pygame.image.load(hive1.sprite)

    player.x += x_change
    player.y += y_change

    zone = pygame.image.load("Untitled.png")

    gameDisplay.fill(c.white)
    gameDisplay.blit(zone, (310, 310))
    gameDisplay.blit(player.sprite, (player.x, player.y))
    gameDisplay.blit(basicEnemy.sprite,(basicEnemy.x, basicEnemy.y))
    gameDisplay.blit(basicEnemy1.sprite,(basicEnemy1.x, basicEnemy1.y))
    gameDisplay.blit(basicEnemy2.sprite,(basicEnemy2.x, basicEnemy2.y))
    pygame.display.update()


    clock.tick(int(CONFIG['framesPerSecond']))

#Code Goes Here

pygame.quit()
quit()

I recently added the code:

if enemy.rect.colliderect(player.rect):

to my program and it causes all of the enemy sprites to freeze when the game loads rather than when they touch the player sprite, I have no clue why this is doing this and any way to stop this and make it work properly (only stop when being touched by another sprite) would be greatly appreciated, I can provide xml and json files if nessicary but I doubt they will be.

Upvotes: 1

Views: 60

Answers (1)

skrx
skrx

Reputation: 20438

If something goes wrong with the collision detection, print the rects of all involved objects. If you do that, you'll quickly see that the rects are all at the same position (0, 0), therefore they're colliding immediately after the game starts.

You have to set the positions of the rects in your classes:

self.rect.topleft = (self.x, self.y)
# Or
self.rect.x = self.x
self.rect.y = self.y
# Or
self.rect = self.sprite.get_rect(topleft=(self.x, self.y))

You can also use self.rect.center or other attributes of the rect.


Also, don't forget to move the rects of your objects as well in your main loop, otherwise they'll just stay at the same starting position. In your case you can just set the topleft to enemy.x and .y (or just remove the x and y attributes and update the rect.x and rect.y directly):

enemy.rect.topleft = (enemy.x, enemy.y)

Upvotes: 1

Related Questions