简体   繁体   中英

Colliding rectangles without classes in python

So I'm making this cool avoiding game and I've got everything done except for the collision. Since I'm a noob to the pygame module, I didn't do any classes, and I don't know how I would check if the player hitbox collides with the enemy hitbox. Also, I know a few people have asked this before, but the answers they gave are either unclear to me or are for sprites, not rectangles. Here's my code: https://hastebin.com/exaximafiy.py

#avoid game
#import
import pygame
from time import sleep
import os
import math
import random
import pygame.mixer
from pygame.locals import * 

#intiate pygame
pygame.mixer.init()
pygame.init()

os.system("cls")

#set screen size
screen = pygame.display.set_mode((1024,768))

#set title
pygame.display.set_caption("Avoid") 


def menu():
    pygame.time.delay(100)
    #set title
    pygame.display.set_caption("Avoid - Menu Screen") 
    running = True
    while running:
        #close program if user clicked big X
        if pygame.mixer.get_busy() != None:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running=False
                    pygame.quit()
                    break

        #set bg
        screen.fill((255,255,255))
        menubg=pygame.image.load("menuScreen.png")
        screen.blit(menubg,(0,0))
        pygame.display.flip()

        #detect button press (enter to play, h for instructions, q for options, esc to quit)
        keys = pygame.key.get_pressed()

        if keys[pygame.K_RETURN]:
            game()
        if keys[pygame.K_h]:
            instructions()
        if keys[pygame.K_ESCAPE]:
            pygame.quit()
        if keys[pygame.K_q]:
            options()

    pygame.quit()
def instructions():
    running=False
    #set title
    pygame.display.set_caption("Avoid - Instructions") 
    running=True
    while running:
        #close program if user clicked big X
        if pygame.mixer.get_busy() != None:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running=False
                    pygame.quit()
                    break

        #set bg
        screen.fill((255,255,255))
        helpbg=pygame.image.load("instructions.png")
        screen.blit(helpbg,(0,0))
        pygame.display.flip()

        #if esc pressed, go to menu
        keys = pygame.key.get_pressed()

        if keys[pygame.K_ESCAPE]:
            pygame.time.delay(100)
            menu()



def gameOver():
    running=False
    #set title
    pygame.display.set_caption("Avoid - Game Over") 
    running=True
    while running:
        #close program if user clicked big X
        if pygame.mixer.get_busy() != None:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running=False
                    pygame.quit()
                    break

        #set bg
        screen.fill((255,255,255))
        menubg=pygame.image.load("gameOver.png")
        screen.blit(menubg,(0,0)) 
        pygame.display.flip()

        #detect input
        keys = pygame.key.get_pressed()

        if keys[pygame.K_RETURN]:
            game()
        if keys[pygame.K_ESCAPE]:
            pygame.quit()  


def game():
    running=False
    #play music
    song = pygame.mixer.Sound("song.wav")
    song.play(-1)

    #set title
    pygame.display.set_caption("Avoid - Game Screen") 

    #set vars
    #enemy x and y pos
    randx = random.randint(17,1007)
    randy = random.randint(17,751)
    #time vars (time2 = enemyspawn, time = stopwatch, time3 = playersize time, time4 = playersize)
    time2 = 0.5
    time=0
    time3 = 10
    time4 = 1
    #player x,y
    x = 1024*0.5
    y = 768*0.5
    #enemy width,height
    width = 50
    height = 50
    #colors
    red=(255,0,0)
    #speed
    vel=10  
    #set player size
    playerSize = 15

    running = True
    while running:
        #pygame.time.delay(10)
        #close program if user clicked big X
        if pygame.mixer.get_busy() != None:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running=False
                    pygame.quit()
                    break

        #set stopwatch
        time=time+0.040


        #movement
        keys = pygame.key.get_pressed()
        #arrow
        if keys[pygame.K_DOWN] and y < 751:
            y += vel
        if keys[pygame.K_UP] and y > 17:
            y -= vel
        if keys[pygame.K_RIGHT] and x < 1007:
            x += vel
        if keys[pygame.K_LEFT] and x > 17:
            x -= vel
        #wasd
        if keys[pygame.K_s] and y < 751:
            y += vel
        if keys[pygame.K_w] and y > 17:
            y -= vel
        if keys[pygame.K_d] and x < 1007:
            x += vel
        if keys[pygame.K_a] and x > 17:
            x -= vel
        #if esc quit, y - collide
        if keys[pygame.K_ESCAPE]:
            pygame.quit()
        if keys[pygame.K_y]:
            collision()



        #shows what coords you on
        print(x,y)


        #set bg
        screen.fill((255,255,255))
        gamebg=pygame.image.load("gamebg.png")
        screen.blit(gamebg,(0,0))
        pygame.display.flip()

        #time thing in middle
        time1 = float('%.2f' % round(time,1))
        myfont = pygame.font.SysFont('Arial', 35)
        textsurface = myfont.render(("time: " +str(time1)), 1, (0,0,0))
        screen.blit(textsurface,(455,384))

        #load enemys

        if time2 < time1:
            time2 = (time2+0.5)
            randx = random.randint(17,1007)
            randy = random.randint(17,751)

        #rainbow
        enemy=pygame.image.load("red.png")
        screen.blit(enemy,(randx,randy))
        pygame.display.flip()

        pygame.time.wait(1)
        enemy=pygame.image.load("orange.png")
        screen.blit(enemy,(randx,randy))
        pygame.display.flip()

        pygame.time.wait(1)
        enemy=pygame.image.load("yellow.png")
        screen.blit(enemy,(randx,randy))
        pygame.display.flip()

        pygame.time.wait(1)
        enemy=pygame.image.load("green.png")
        screen.blit(enemy,(randx,randy))
        pygame.display.flip()

        pygame.time.wait(1)
        enemy=pygame.image.load("blue.png")
        screen.blit(enemy,(randx,randy))
        pygame.display.flip()

        pygame.time.wait(1)
        enemy=pygame.image.load("indigo.png")
        screen.blit(enemy,(randx,randy))
        pygame.display.flip()

        pygame.time.wait(1)
        enemy=pygame.image.load("violet.png")
        screen.blit(enemy,(randx,randy))
        pygame.display.flip()

        #change size
        if time3 < time1:
            time3 = (time3+10.0)
            playerSize = (playerSize + 15)
            time4 = (time4 + 0.9)


        #draw hitboxes
        #player
        playerHitbox=((x-(17.5*time4)),(y-(18*time4)),(35*time4),(35*time4))
        #enemy
        enemyHitbox=(randx,randy,50,50)
        #draw
        pygame.draw.rect(screen,red,playerHitbox,2)
        pygame.draw.rect(screen,red,enemyHitbox,2)

        #draw player (red circle)
        player = pygame.draw.circle(screen, red, [int(x),int(y)], playerSize)
        #update screen
        pygame.display.update()

        def collision():
            song.stop()
            pygame.time.delay(1000)
            gameOver()



        # def checkCollision(playerHitbox, enemyHitbox):
        #     col = playerHitbox.colliderect(enemyHitbox)
        #     if col == True:
        #         collision()

        # checkCollision(playerHitbox,enemyHitbox)

        if Rect.colliderect(enemyHitbox):
            collision()

menu()

Any leads would be helpful and you can ask me to clarify in the comments below.

Every Rect object in Pygame has a method colliderect which can test if that Rect object collides (overlaps) with any other Rect object. More info

To check if a rectangle at point ( x1 , y1 ) with a width w1 and height h1 collides with a rectangle at point ( x2 , y2 ) with a width w2 and height h2 , you can implement this like so:

pygame.Rect(x1,y1,w1,h1).colliderect(pygame.Rect(x2,y2,w2,h2))

In your specific example for example, you could implement what you are trying to do with:

def checkCollision(playerHitbox, enemyHitbox):
    return pygame.Rect(*playerHitbox).colliderect(pygame.Rect(*enemyHitbox))

NB: the * I used here unpacks the tuple into arguments. Ie: the first element is sent as the first argument, the second is sent as the second argument, etc. More info .

You were on the right track in your code, remember that this method operates on Rect objects and not on tuples of the information itself. You therefore need to instantiate the necessary Rect objects as shown above ^

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM