FerrenReve
FerrenReve

Reputation: 3

Collision between a rect and a circle

The problem is next, I have falling circles and I need them to be deleted if they will overlap with the player. I have tried to create a bunch of methods to get coordinates of the circles and the rectangle however when i try checking if they overlap i get an error.

TypeError: unorderable types: method() > method()

Here is the code:

# Colour
# Created by Niktia Kotter

#!/usr/bin/env python
import pygame, sys, random, time
from pygame.locals import*

# set up pygame
pygame.init()
FPS=60
fpsclock = pygame.time.Clock()

# colours   R    G    B
WHITE   = (255, 255, 255)
BLACK   = (0  , 0  , 0  )
RED     = (237, 28 , 36 )

# set up screen
SCREEN_W = 800
SCREEN_H = 480
SCREEN =  pygame.display.set_mode((SCREEN_W,SCREEN_H),0,32)            
snapMultX = SCREEN_W / 5
snapMultY = SCREEN_H / 5
basicFont = pygame.font.SysFont(None, 32)

# set up functions
def isPointInsideRect(Cx, Cy, rectX, rectY, rectW, rectH ):
    if ((Cx > rectX) and \
    (Cx < rectY) and \
    (Cy > rectW) and \
    (Cy < rectH)):
        return True
    else:
        return False

"""
def doRectsOverlap(rect1, rect2):
    for a,b in [(rect1, rect2), (rect2, rect1)]:
        # check if a's corners are inside b
        if ((isPointInsideRect(a.left, a.top, b)) or
            (isPointInsideRect(a.left, a.bottom, b)) or
            (isPointInsideRect(a.right, a.top, b)) or
            (isPointInsideRect(a.right, a.bottom, b))):
            return True

    return False
"""

# set up calsses
class Actor:

    def __init__ (self):


        self._x = snapMultX*2
        self._y = SCREEN_H - snapMultX/5 -(snapMultX/2)
        self._w = snapMultX
        self._h = snapMultX/2
        self._colour = WHITE
        self._Rect = pygame.Rect(self._x, self._y, self._w, self._h)

    def moveRight(self):
        self._x += snapMultX

    def moveLeft(self):
        self._x -= snapMultX

    def draw(self):
        pygame.draw.rect(SCREEN, self._colour, (self._x, self._y, self._w, self._h))
        return 
    def rectX(self):
        return self._x
    def rectY(self):
        return self._y
    def rectW(self):
        return self._w
    def rectH(self):
        return self._h

class Enemy:

    def __init__ (self, location):

        self._x = snapMultX*location+snapMultX/2
        self._y = 0
        self._r = snapMultX/10
        self._colour = WHITE

    def move(self, dy):

        self._y += dy

    def draw(self):
        pygame.draw.circle(SCREEN, self._colour, (int(self._x),int(self._y)), int(self._r), 0)
        return

    def GetCircleX(self):
        return self._x

    def GetCircleY(self):
        return self._y

class Capture(object):

    def __init__(self):

        self.caption = pygame.display.set_caption('Space Invaders')
        self.screen = SCREEN
        self.startGame = True
        self.gameOver = False
        self.enemyCount = 0
        self.timer = 50
        self.score = 0

    def main(self):

        clock = pygame.time.Clock()
        enemy =[]
        player = Actor()

        while True:
            if self.startGame:

                SCREEN.fill(BLACK)

                pygame.draw.polygon(SCREEN,WHITE, [(snapMultX*1-snapMultX/5*2,0), (snapMultX*0+snapMultX/5*2,0), (snapMultX*0+snapMultX/2,snapMultY/4)])
                pygame.draw.polygon(SCREEN,WHITE, [(snapMultX*2-snapMultX/5*2,0), (snapMultX*1+snapMultX/5*2,0), (snapMultX*1+snapMultX/2,snapMultY/4)])
                pygame.draw.polygon(SCREEN,WHITE, [(snapMultX*3-snapMultX/5*2,0), (snapMultX*2+snapMultX/5*2,0), (snapMultX*2+snapMultX/2,snapMultY/4)])
                pygame.draw.polygon(SCREEN,WHITE, [(snapMultX*4-snapMultX/5*2,0), (snapMultX*3+snapMultX/5*2,0), (snapMultX*3+snapMultX/2,snapMultY/4)])
                pygame.draw.polygon(SCREEN,WHITE, [(snapMultX*5-snapMultX/5*2,0), (snapMultX*4+snapMultX/5*2,0), (snapMultX*4+snapMultX/2,snapMultY/4)])                

                player.draw()

# enemy move/spawn timer
                self.timer -= 1

# enemy spawner
                if self.timer <= 0:

                    num = random.randint(0, 5)

                    if num == 0:
                        print (0)
                        enemy.append(Enemy(0))
                    if num == 1:
                        print (1)
                        enemy.append(Enemy(1))
                    if num == 2:
                        print (2)
                        enemy.append(Enemy(2))
                    if num == 3:
                        print (3)
                        enemy.append(Enemy(3))
                    if num == 4:
                        print (4)
                        enemy.append(Enemy(4))

# player mover
                for event in pygame.event.get():

                    if player._x != snapMultX*4 and (event.type == KEYDOWN) and (event.key == K_d):
                        player.moveRight()

                    if player._x != 0 and(event.type == KEYDOWN) and (event.key == K_a):
                        player.moveLeft()   

                    if event.type == QUIT:
                        pygame.quit()
                        sys.exit()
# enemy logic
                if self.timer <= 0:
                    for e in enemy:
                        e.move(snapMultY)

                        if isPointInsideRect(e.GetCircleX, e.GetCircleY, player.rectX, player.rectY, player.rectW, player.rectH):
                            self.score += 1
                            enemy.remove(e)

                        if e._y > snapMultY*5:      
                            enemy.remove(e)
# reste timer
                    self.timer = 50                    

                for e in enemy:
                    e.draw()

# score
                self.myScore = "Score = " + str(self.score)
                text = basicFont.render(self.myScore, True, RED, WHITE)
                textRect = text.get_rect()
                textRect.centerx = SCREEN.get_rect().centerx
                textRect.centery = SCREEN.get_rect().centery
                SCREEN.blit(text, textRect)

                pygame.display.update()
                fpsclock.tick(FPS) 

if __name__ == '__main__':
    game = Capture()
    game.main()       

Upvotes: 0

Views: 227

Answers (1)

RD3
RD3

Reputation: 1089

The cause of your error is actually a typo and the joys of Python Duck Typing. The key to debugging is understanding what the error means.

Your error "TypeError: unorderable types: method() > method()". What does this mean? Obviously you have a type error, but what does that really mean. It means that Python is trying to complete an operation that has certain requirements. In this case in has do to with unorderable types - we are trying to do a comparison on two things that don't have an orderable property so that they can't be compared in that way. The next portion says "method() > method()". That means we are attempting to compare that one method is greater than another. That probably isn't what is intended.

So now we have to look at those comparisons in our ifs. Lets look at isPointInsideRect.

def isPointInsideRect(Cx, Cy, rectX, rectY, rectW, rectH ):
    if ((Cx > rectX) and (Cx < rectY) and (Cy > rectW) and (Cy < rectH)):
        return True
    else:
        return False

Here we are doing a whole bunch of comparisons on six values. Lets look at where this method gets called? This function gets called in one uncommented-out line (Line 175).

if isPointInsideRect(e.GetCircleX, e.GetCircleY, player.rectX, player.rectY, player.rectW, player.rectH):

Do you see the issue here? Each of those values that you are passing into the function aren't values, they are method definitions. Hence, everytime isPointInsideRect is doing those comparisons, they are comparing one method to another. And that isn't a valid comparison.

Trying changing line 175 to:

if isPointInsideRect(e.GetCircleX(), e.GetCircleY(), player.rectX(), player.rectY(), player.rectW(), player.rectH()):    

Upvotes: 1

Related Questions