0
\$\begingroup\$

I'm really new to PyGame and trying to program a game, and I can't figure out how to make a hitbox that when this image hits the edge, the game stops it from going past the edges

import pygame
from pygame.math import Vector2

pygame.init
dis_width=1000
dis_height=1000
dis=pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption("Snowperson game")
white=(255,255,255)
cyan=(153,255,255)
red=(255,0,0)


dis.fill(cyan)

class Snow:
    def __init__(self,newX, newY):
        self.x = newX
        self.y = newY
        self.image = pygame.image.load("Snowperson1.png")
        self.vel = Vector2(0,0)
        self.pos = Vector2(pos)
        self.rect = self.image.get_rect(center=pos)


    def x(self):
        self.x

    def y(self):
        self.y

    def draw(self, window):
        window.blit(self.image,(self.x,self.y))

    def snowRight(self):
        self.x +=10

    def snowLeft(self):
        self.x -=10

    def snowUp(self):
        self.y -= 10

    def snowDown(self):
        self.y += 10

pygame.key.set_repeat(100,100)


snowman = Snow(50,50)


while True:
    dis.fill(cyan)
    snowman.draw(dis)
    pygame.draw.rect(dis, red, (0,0, 1000, 1000), 2)
    pygame.display.update()
    snowman.snowLeft == True

    for event in pygame.event.get():

        if event.type==pygame.QUIT or (event.type==pygame.KEYUP and event.key==pygame.K_ESCAPE):
            pygame.quit()

        elif event.type == pygame.KEYDOWN:

            if event.key == pygame.K_UP:
                snowman.snowUp()
            elif event.key == pygame.K_DOWN:
                snowman.snowDown()
            elif event.key == pygame.K_RIGHT:
                snowman.snowRight()
            elif event.key == pygame.K_LEFT and snowman.snowLeft == True:
                snowman.snowLeft()

    if snowman.rect()== 0:
        while True:
            snowman.snowLeft == False
```
\$\endgroup\$
4
  • \$\begingroup\$ how looks your image? Normally you can use Rect() to have rectangle hitbox and use functions colliderect(), collidepoint() to detect collision. You can even keep few Rect() to check every region separatelly. And finally PyGame can use mask (black&white image) to detect collisions - but this can make more CPU power. \$\endgroup\$
    – furas
    Feb 28, 2022 at 19:14
  • \$\begingroup\$ you don't need def x(self): self.x and def y(self): self.y - first it would need return to get value, second class can't have at the same time variable with name x and method with name x. Method will replace variable. \$\endgroup\$
    – furas
    Feb 28, 2022 at 19:18
  • \$\begingroup\$ see in pygame.Rect.colliderect (to detect collision with other Rect) and pygame.Rect.collidepoint (to detect collision with mouse position) in pygame.Rect(). You can also get Rect() for window and use pygame.Rect.contain to check if object is fully inside window \$\endgroup\$
    – furas
    Feb 28, 2022 at 19:24
  • \$\begingroup\$ there is no need to use prefix snow in functions/variables in class Show. It will be simpler to keep objects on list and run the same functions for all objects - ie. .move_left() (for obj in [snowman, zombie]: obj.move_left()) \$\endgroup\$
    – furas
    Feb 28, 2022 at 19:35

1 Answer 1

1
\$\begingroup\$

The simplest is to use self.rect in Snow and compare with window rect which you can get dis.get_rect()

dis_rect = dis.get_rect()

if snowman.rect.left < dis_rect.left:
   snowman.rect.left = dis_rect.left:

if snowman.rect.right > dis_rect.right:
   snowman.rect.right = dis_rect.right:

if snowman.rect.top < dis_rect.top:
   snowman.rect.top = dis_rect.top:

if snowman.rect.bottom < dis_rect.bottom:
   snowman.rect.bottom = dis_rect.bottom:

but this also need to keep position in self.rect instead of self.x, self.y

    def move_right(self):
        self.move(10, 0)
        
    def move_left(self):
        self.move(-10, 0)

    def move_up(self):
        self.move(0, -10)

    def move_down(self):
        self.move(0, 10)

    def move(self, dx, dy):
        self.rect.x += dx
        self.rect.y += dy

BTW: there is no need to use prefix snow in functions and variables in Snow. Later it can be simpler when all objects have the same names of functions - ie. .move_left() - because you can put all of objects on list and use for-loop to run the same function for all of objects. PyGame has even pygame.sprite.Group() for this.


Rect has also method to detect

  • collision with point

    snowman.rect.colliderect(mouse_pos)
    

    which you can use to detect mouse on object or click on button

  • collision with other rect

    snowman.rect.colliderect(zombie.rect)
    

    but it gives only True/False but it doesn't give information if it was collision on left, right, top or bottom - so common method is to check it in two steps. First move left/right and check collision - and if there was collision then: if speed_x > 0 (so you move right) then collision on right, if speed_y < 0 (so you move left) then collision on left. Second move top/bottom and check collision again - and if there was collision then: if speed_y > 0 (so you move down) then collision on bottom, if speed_y < 0 (so you move up) then collision on top.


EDIT:

Full working code

import pygame
#from pygame.math import Vector2

# --- constants ---  # PEP8: `UPPER_CASE_NAME` for constants

DIS_WIDTH  = 1000       # PEP8: spaces around `=`
DIS_HEIGHT = 1000

WHITE = (255, 255, 255)
CYAN  = (153, 255, 255)

RED   = (255,   0,   0)
GREEN = (  0, 255,   0)
BLUE  = (  0,   0, 255)

# --- classes ---  # PEP8: `CamelCaseName` for classes
                   # PEP8: `lower_case_name` for functions
                   
class Snow:
    def __init__(self, x, y, color):
        #self.image = pygame.image.load("Snowperson1.png")
        
        self.image = pygame.Surface((25, 75))
        self.image.fill(color)
        
        self.rect = self.image.get_rect(centerx=x, centery=y)
        
        self.vel_x = 0
        self.vel_y = 0

    def draw(self, window):
        window.blit(self.image, self.rect)

    def move_right(self):
        self.vel_x = 10
        
    def move_left(self):
        self.vel_x = -10

    def move_up(self):
        self.vel_y = -10

    def move_down(self):
        self.vel_y = 10

    def update(self, zombie):
        
        #print(self.vel_x, self.vel_y)
        
        # --- X ---
        
        self.rect.x += self.vel_x
        
        # window border - left,right
        
        if self.rect.left < dis_rect.left:
            self.rect.left = dis_rect.left

        if self.rect.right > dis_rect.right:
            self.rect.right = dis_rect.right
            
        # collisions with zombie - left,right
        
        if self.rect.colliderect(zombie.rect):
            if self.vel_x > 0:
                self.rect.right = zombie.rect.left
            elif self.vel_x < 0:
                self.rect.left = zombie.rect.right
    
        # --- Y ---

        self.rect.y += self.vel_y

        # window border - top,bottom

        if self.rect.top < dis_rect.top:
            self.rect.top = dis_rect.top

        if self.rect.bottom > dis_rect.bottom:
            self.rect.bottom = dis_rect.bottom

        # collisions with zombie - top,bottom
        
        if self.rect.colliderect(zombie.rect):
            if self.vel_y > 0:
                self.rect.bottom = zombie.rect.top
            elif self.vel_y < 0:
                self.rect.top = zombie.rect.bottom
            
# --- main ---

pygame.init()

dis = pygame.display.set_mode((DIS_WIDTH, DIS_HEIGHT))
dis_rect = dis.get_rect()

pygame.display.set_caption("Snowperson game")

pygame.key.set_repeat(100, 100)  # PEP8: space after comma

# - objects -

snowman = Snow(50, 50, BLUE)     # PEP8: space after `,`
zombie = Snow(150, 150, GREEN)  # PEP8: space after `,`

# - mainloop -

while True:
    
    # - draw -
    
    dis.fill(CYAN)

    snowman.draw(dis)
    zombie.draw(dis)
    
    pygame.draw.rect(dis, RED, (0, 0, 1000, 1000), 2)
    pygame.display.flip()
    
    # - move -
    
    snowman.vel_x = 0
    snowman.vel_y = 0
    
    for event in pygame.event.get():

        if event.type==pygame.QUIT:
            pygame.quit()

        elif event.type == pygame.KEYDOWN:
            if  event.key==pygame.K_ESCAPE:
                pygame.quit()
                
            elif event.key == pygame.K_UP:
                snowman.move_up()
            elif event.key == pygame.K_DOWN:
                snowman.move_down()
            elif event.key == pygame.K_RIGHT:
                snowman.move_right()
            elif event.key == pygame.K_LEFT:
                snowman.move_left()

    # - update - move and check collision -
    
    snowman.update(zombie)
```
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .