1
\$\begingroup\$

I am a beginner in Python and Pygame and I have a problem with my game in pygame. I have Maze class and Player class but I can't do proper collisions. I reached the moment where I have no idea why my code isn't working.

Here is my code:

class Maze(pygame.sprite.Sprite):
def __init__(self):
    self.W = 25
    self.H = 14
    self.maze = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
                 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1,
                 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1,
                 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1,
                 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1,
                 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
                 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1,
                 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1,
                 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1,
                 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1,
                 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1,
                 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1,
                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ]
def draw(self,screen):
    block_surf = pygame.image.load(os.path.join(img_folder, "new.png")).convert()
    bx = 0
    by = 0
    for i in range(0,self.W*self.H):
        if self.maze[ bx + (by*self.W) ] == 1:
            screen.blit(block_surf,( bx * 40 , by * 40))
        bx = bx + 1
        if bx > self.W-1:
            bx = 0 
            by = by + 1

def collisions(self):
    bx = 0 
    by = 0 
    for i in range(0, self.W * self.H):
        if self.maze[ bx + (by * self.W) ] == 1:

            rect = pygame.Rect(bx * 40, by * 40, 40, 40)

            if rect.colliderect(Player.get_rect):
                pass  # Collision!
                return False

            bx = bx + 1
            if bx > self.W-1:
                bx = 0 
                by = by + 1
class Player(pygame.sprite.Sprite):
    def __init__(self): #sprite for a player
        pygame.sprite.Sprite.__init__(self) #for sprite working
        self.image = pygame.image.load(os.path.join(img_folder, "player.png")).convert() #look of the sprite
        self.image.set_colorkey(white) #to delete black things around rect img
        self.rect = self.image.get_rect() #kind of border around it
        self.rect.centerx = width/2 + 40
        self.rect.bottom = height- 120
        self.speedx = 0
        self.speedy = 0
    def update(self): #moving player
        maze = Maze()
        collisions = maze.collisions
        self.speedx = 0
        self.speedy = 0
        keystate = pygame.key.get_pressed()
        if keystate[pygame.K_LEFT]:
            if collisions == False:
                self.speedx = 0
            else:
                self.speedx = -1
        elif keystate[pygame.K_RIGHT]:
            if self.rect.x > 920:
                self.speedx = 0
            # elif self.rect.y <= 636 and self.rect.y > 580: 
                # self.speedy = 0
            elif self.rect.x == 40 and self.rect.y < 482 and self.rect.y > 401:
                self.speedy = 0
            elif self.rect.x == 40 and self.rect.y < 399 and self.rect.y > 282:
                self.speedy = 0
            elif self.rect.x == 40 and self.rect.y < 279 and self.rect.y > 160:
                self.speedy = 0 
            elif self.rect.x == 40 and self.rect.y < 157 and self.rect.y > 41:
                self.speedy = 0
            else:
                self.speedx = 1
        elif keystate[pygame.K_UP]:
            if self.rect.y < 41:
                self.speedy = 0
            elif self.rect.y == 159 and self.rect.x > 46 and self.rect.x < 160:
                self.speedy = 0
            elif self.rect.y == 281 and self.rect.x > 45 and self.rect.x < 154:
                self.speedy = 0 
            else:
                self.speedy = -1
        elif keystate[pygame.K_DOWN]:
            if self.rect.y > 480:
                self.speedy = 0
            elif self.rect.x > 405 and self.rect.x < 634 and self.rect.y > 440:
                self.speedy = 0
            elif self.rect.y == 280 and self.rect.x > 46 and self.rect.x < 155:
                self.speedy = 0
            else:
                self.speedy = 1
        self.rect.x += self.speedx
        self.rect.y += self.speedy
    def get_rect(self):
        return pygame.Rect(self.rect.x, self.rect.y, 40, 40)

https://pastebin.com/70fkATnB

Can someone explain to me why it isn't working and help to improve it?

I tried many ideas - even writing from hand positions x and y to create collisions. But it's really bad practice to do so I turned to pygame option sprite.colliderect(sprite2)

https://pastebin.com/70fkATnB

I want to receive information why my code isn't working properly and tips for improving it.

\$\endgroup\$
  • \$\begingroup\$ In what specific way is this code "not working" or the collisions not "proper"? What behaviour do you observe when running or stepping through this code, and how does it differ from the behaviour you want? \$\endgroup\$ – DMGregory Apr 23 at 11:20
  • \$\begingroup\$ Well, just collisions don't work - the player still can go though maze walls. Also from my testing (I tried to print something in function get_rect and collisions) it seems that these functions are not called? I'm not sure anymore. \$\endgroup\$ – Rosalie Black Apr 23 at 11:22
0
\$\begingroup\$

I think the main problem stems from this

collisions = maze.collisions  

and this

if collisions == False:  

You are setting the value of collisions to be a function, when you are apparently trying to call that function and use the result.

I would recommend to learn some debugging techniques so you can check your programs control flow as well as the state of its variables.

\$\endgroup\$
  • \$\begingroup\$ Yes, I also think so. When I change maze.collisions to maze.collisions() then I get an error - Argument must be rect style object. I'm not sure why as I thought I did it correctly with rectangles. \$\endgroup\$ – Rosalie Black Apr 24 at 6:33
0
\$\begingroup\$

I think you are confused between functions/methods themselves, and calling a function/method.

Take the example

def square_num(num):
    return num * num


print(square_num)
print(square_num(5))

This has output

<function square_num at 0x00950858>
25

That is. when we use square_num without any arguments, python returns a reference to the function, but it doesn't evaluate it. When you give it the arguments (or, for a function without arguments, write () after it) then it actually runs the function. As another example:

def say_hello():
    print("Hello world!")

say_hello
say_hello()

will only print "hello world!" once, only the last line actually runs the function.

Do you understand why the line

if rect.colliderect(Player.get_rect)

can't work now? It is because you are trying to collide a rect with a function, which is meaningless.

The second mistake in that line is calling get_rect on the class Player, rather than an instance of that class. Conceptually this is a rather similar distinction as between a function and an execution of that function. There are many many guides online that explain the difference between a class and a class instance (the latter is also called an object).

To cut a long story short, you need to change your functions to

def collisions(self, player_instance):
    ....
    if rect.colliderect(player_instance.get_rect()):
        print("We've had a collision!")
    ...


def update(self): #moving player
    maze = Maze()
    collisions = maze.collisions(self)

Note, I'd also define the maze in the init method of Player rather than recreating it on every update

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.