Pygame碰撞检测无法正常工作 [英] Pygame collision detection not working how I want it to

查看:78
本文介绍了Pygame碰撞检测无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

冲突无法按我希望的方式工作。我想要这样,以便每当您击中一条船时,您都将返回到MENUSTATE,并且每当您击中一条鱼时,图像都会消失并且游戏将继续运行。根据我的尝试,只要两个物体仍在碰撞,游戏就会在船撞后回到MENUSTATE,但完成后会回到GAMESTATE。我如何拥有它,使其在与船相撞后永久停留在MENUSTATE中?当与人相撞并且游戏仍在运行时,我将如何删除鱼图像?

Collisions are not working the way I want them to. I want it so that whenever you hit a boat, you are sent back to MENUSTATE, and whenever you hit a fish, the image disappears and the game keeps running. From what I've tried, the game will go back to MENUSTATE after a boat collision for as long as the two objects are still colliding, but will go back to GAMESTATE when it's done. How can I have it so it permanently stays in the MENUSTATE after a collision with the boat, and how would I go about removing the fish image when you collide with one, and have the game still run?

图片和SFX: https://mega.nz/fm/zHohiSJD

import pygame
    import random
    import os

    os.environ['SDL_VIDEO_WINDOW_POS'] = "%d, %d" % (0, 20)  # positions the game tab to the top left portion of the monitor
    pygame.init()  # initializes pygame
    pygame.display.set_caption("Biomagnification ")
    SIZE = W, H = 400, 700  # determining the screen size of the game
    screen = pygame.display.set_mode(SIZE)  # creating a display surface
    clock = pygame.time.Clock()  # creating a clock

    # RGB colours
    RED = (255, 0, 0)
    GREEN = (0, 255, 0)
    BLUE = (0, 0, 255)
    BACKGROUND = (94, 194, 222)
    STRIPE = (60, 160, 190)
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    GREY = (80, 80, 80)


    MENUSTATE = 0
    INFOSTATE = 1
    GAMESTATE = 2
    # variables
    x1 = 30  # desired X position for the left dolphin/hitbox
    x2 = 330  # desired X position for the right dolphin/hitbox
    lane1 = 30
    lane2 = 130
    lane3 = 230
    lane4 = 330
    y = 530  # desired y value of the hitbox
    width, height = (40, 64)  # width and height of the hitbox

    toggle1 = 0  # toggle for left dolphin
    toggle2 = 0  # toggle for right dolphin

    target_x1 = 30
    target_x2 = 330
    vel_x = 10  # speed at which the dolphins move

    # fonts
    menuFont = pygame.font.SysFont('impact', 60)
    titleFont = pygame.font.SysFont('Impact', 40)
    textFont = pygame.font.SysFont('Calibri', 16)
    text2Font = pygame.font.SysFont('Calibri', 20)

    # method to blit text, taken from my university assignment 2
    def blit_text(surface, string, pos, font, color=pygame.Color('black')):
        words = [word.split(' ') for word in string.splitlines()]  # 2D array where each row is a list of words.
        space = font.size(' ')[0]  # The width of a space.
        max_width, max_height = surface.get_size()
        x, y = pos
        for line in words:
            for word in line:
                word_surface = font.render(word, 0, color)
                word_width, word_height = word_surface.get_size()
                if x + word_width >= max_width:
                    x = pos[0]  # Reset the x.
                    y += word_height  # Start on new row.
                surface.blit(word_surface, (x, y))
                x += word_width + space
            x = pos[0]  # Reset the x.
            y += word_height  # Start on new row.


    def drawScene():
        screen.fill(BACKGROUND)  # fills the background with the colour ((94, 194, 222)
        pygame.draw.polygon(screen, STRIPE, ((200, 700), (300, 700), (400, 600), (400, 500)))  # draws the different coloured stripes
        pygame.draw.polygon(screen, STRIPE, ((0, 700), (100, 700), (400, 400), (400, 300)))
        pygame.draw.polygon(screen, STRIPE, ((0, 500), (0, 600), (400, 200), (400, 100)))
        pygame.draw.polygon(screen, STRIPE, ((0, 300), (0, 400), (400, 0), (300, 0)))
        pygame.draw.polygon(screen, STRIPE, ((0, 100), (0, 200), (200, 0), (100, 0)))
        pygame.draw.line(screen, WHITE, (100, 0), (100, 700), 2)  # draws the white separating lines in the background
        pygame.draw.line(screen, WHITE, (200, 0), (200, 700), 6)
        pygame.draw.line(screen, WHITE, (300, 0), (300, 700), 2)

    def drawMenu(button, mouseX, mouseY):
        st = MENUSTATE
        screen.fill(BACKGROUND)
        pygame.draw.polygon(screen, STRIPE, ((300, 700), (400, 700), (400, 600)))  # draws the different coloured stripes
        pygame.draw.polygon(screen, STRIPE, ((0, 100), (0, 0), (100, 0)))
        string = "biomagnification"
        blit_text(screen, string, (52, 80), titleFont, BLACK)
        playRect = pygame.Rect(W // 3, (H // 4) + 30, W // 3, H // 10)
        pygame.draw.rect(screen, STRIPE, playRect)
        string = "play"
        blit_text(screen, string, (146, 200), menuFont, BLACK)
        infoRect = pygame.Rect(W // 3, (H // 2.5) + 30, W // 3, H // 10)
        pygame.draw.rect(screen, STRIPE, infoRect)
        string = "info"
        blit_text(screen, string, (152, 307), menuFont, BLACK)
        quitRect = pygame.Rect(W // 3, (H // 1.81) + 30, W // 3, H // 10)
        pygame.draw.rect(screen, STRIPE, quitRect)
        string = "quit"
        blit_text(screen, string, (148, 410), menuFont, BLACK)
        if button == 1:
            if playRect.collidepoint(mouseX, mouseY) == True:
                st = GAMESTATE
            elif infoRect.collidepoint(mouseX, mouseY) == True:
                st = INFOSTATE
            elif quitRect.collidepoint(mouseX, mouseY) == True:
                pygame.quit()
        pygame.display.update()
        return st

    def drawInfo(button, mouseX, mouseY):
        st = INFOSTATE
        screen.fill(BACKGROUND)
        pygame.draw.polygon(screen, STRIPE, ((300, 700), (400, 700), (400, 600)))  # draws the different coloured stripes
        pygame.draw.polygon(screen, STRIPE, ((0, 100), (0, 0), (100, 0)))
        string = "biomagnification:"
        blit_text(screen, string, (50, 80), titleFont, BLACK)
        textRect = pygame.Rect(0, (H // 4) + 30, W, H // 3)
        pygame.draw.rect(screen, STRIPE, textRect)
        string = "the process by which a compound increases its concentration in the tissues of organisms as it travels up the food chain."
        blit_text(screen, string, (20, 135), textFont, BLACK)
        string = "Magnesium, an element commonly found in E-Waste increases its concentration in tissue as it travels up the food chain."
        blit_text(screen, string, (20, 230), textFont, BLACK)
        string = "Score is measured in PPM (parts per million) of Mg."
        blit_text(screen, string, (20, 300), textFont, BLACK)
        string = "• Eat fish to increase your PPM of Mg!"
        blit_text(screen, string, (20, 340), text2Font, BLACK)
        string = "• Dodge fishing boats!"
        blit_text(screen, string, (20, 380), text2Font, BLACK)
        text2Rect = pygame.Rect(0, (H // 1.65) + 30, W, H // 5)
        pygame.draw.rect(screen, STRIPE, text2Rect)
        string = "Controls"
        blit_text(screen, string, (165, 465), text2Font, BLACK)
        string = "A - Switch Left Lane"
        blit_text(screen, string, (130, 495), textFont, BLACK)
        string = "D - Switch Right Lane"
        blit_text(screen, string, (130, 520), textFont, BLACK)
        string = "ESC - Main Menu"
        blit_text(screen, string, (130, 545), textFont, BLACK)
        backRect = pygame.Rect(W // 3, 612, W // 3, H // 10)
        pygame.draw.rect(screen, STRIPE, backRect)
        string = "back"
        blit_text(screen, string, (139, 610), menuFont, BLACK)
        if button == 1:
            if backRect.collidepoint(mouseX, mouseY) == True:
                st = MENUSTATE
        pygame.display.update()
        return st

    # dolphin spritesheet
    mainsheet = pygame.image.load("mainsheetSmall.png").convert()  # load in the spritesheet
    sheetSize = mainsheet.get_size()  # gets the size of the spritesheet
    horiz_cells = 36  # number of horizontal frames/cells in the spritesheet
    vert_cells = 1  # number of vertical frames/cells in the spritesheet
    cell_width = int(sheetSize[0] / horiz_cells)  # determining the width of each cell
    cell_height = int(sheetSize[1] / vert_cells)  # determing the height of each cell

    cellList = []  # creates a list for all the cells
    for vert in range(0, sheetSize[1], cell_height):
        for horz in range(0, sheetSize[0], cell_width):
            surface = pygame.Surface((cell_width, cell_height))
            surface.blit(mainsheet, (0, 0),
                         (horz, vert, cell_width, cell_height))
            colorkey = surface.get_at((0, 0))  # gets the colour at O, 0 (white)
            surface.set_colorkey(colorkey)  # removes all the white from the spritesheet, making the background transparent
            cellList.append(surface)  # appends to the list of cells (cellList)

    cellPosition = 0  # determines which frame is playing. Starts at 0


    speed = 4
    # 1st pair of boats
    boat = pygame.image.load("boat.png").convert_alpha()
    boatX = random.choice([lane1, lane2, lane3, lane4])
    if boatX == lane1:
        boatX2 = random.choice([lane3, lane4])
    elif boatX == lane2:
        boatX2 = random.choice([lane3, lane4])
    else:
        boatX2 = random.choice([lane1, lane2])
    boatY = -100

    # 2nd pair of boats
    boatX3 = random.choice([lane1, lane2, lane3, lane4])
    if boatX3 == lane1:
        boatX4 = random.choice([lane3, lane4])
    elif boatX3 == lane2:
        boatX4 = random.choice([lane3, lane4])
    else:
        boatX4 = random.choice([lane1, lane2])
    boatY2 = -450

    # 1st pair of fish
    fish1 = pygame.image.load("fishBlue.png").convert_alpha()
    fish2 = pygame.image.load("fishOrange.png").convert_alpha()
    fish = random.choice([fish1, fish2])
    fishX = random.choice([lane1, lane2, lane3, lane4])
    if fishX == lane1:
        fishX2 = random.choice([lane3, lane4])
    elif fishX == lane2:
        fishX2 = random.choice([lane3, lane4])
    else:
        fishX2 = random.choice([lane1, lane2])
    fishY = -800

    # 2nd pair of fish
    fishX3 = random.choice([lane1, lane2, lane3, lane4])
    if fishX3 == lane1:
        fishX4 = random.choice([lane3, lane4])
    elif fishX3 == lane2:
        fishX4 = random.choice([lane3, lane4])
    else:
        fishX4 = random.choice([lane1, lane2])
    fishY2 = -1150


    # main loop
    running = True
    state = MENUSTATE
    button = mx = my = 0
    while running:
        clock.tick(60)  # makes the game tick 60 frames per second

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.MOUSEBUTTONDOWN:
                mx, my = pygame.mouse.get_pos()
                button = pygame.mouse.get_pressed()[0]

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:  # detects if the user presses the ESC key
                    pygame.quit()
                elif event.key == pygame.K_a:  # detects if the user presses the A key
                    pygame.mixer.music.load('percussiveHit.mp3')
                    pygame.mixer.music.play()
                    toggle1 += 1  # adds 1 to toggle1
                    if toggle1 % 2 == 1:  # if toggle1 mod 2 equals 1
                        target_x1 += 100  # add 100 to the target position
                    else:
                        target_x1 -= 100  # if toggle1 mod 2 does not equal 1, subtract 100 from the target position making it the original of 30
                elif event.key == pygame.K_d:  # detects if the user presses the D key
                    pygame.mixer.music.load('percussiveHit.mp3')
                    pygame.mixer.music.play()
                    toggle2 += 1  # adds 1 to toggle2
                    if toggle2 % 2 == 1:  # if toggle2 mod 2 equals 1
                        target_x2 -= 100  # subtract 100 the to target position
                    else:
                        target_x2 += 100  # if toggle2 mod 2 does not equal 1, add 100 to the target position making it the original of 330
        if x1 < target_x1:
            x1 = min(x1 + vel_x, target_x1)
        else:
            x1 = max(x1 - vel_x, target_x1)

        if x2 < target_x2:
            x2 = min(x2 + vel_x, target_x2)
        else:
            x2 = max(x2 - vel_x, target_x2)

        if cellPosition < len(cellList) - 1:
            cellPosition += 1
        else:
            cellPosition = 0

        boatY += speed
        if boatY > H + 625:
            boatX = random.choice([lane1, lane2, lane3, lane4])
            if boatX == lane1:
                boatX2 = random.choice([lane3, lane4])
            elif boatX == lane2:
                boatX2 = random.choice([lane3, lane4])
            else:
                boatX2 = random.choice([lane1, lane2])
            boatY = -100

        boatY2 += speed
        if boatY2 > H + 100:
            boatX3 = random.choice([lane1, lane2, lane3, lane4])
            if boatX3 == lane1:
                boatX4 = random.choice([lane3, lane4])
            elif boatX3 == lane2:
                boatX4 = random.choice([lane3, lane4])
            else:
                boatX4 = random.choice([lane1, lane2])
            boatY2 = -625

        fishY += speed
        if fishY > H + 275:
            fishX = random.choice([lane1, lane2, lane3, lane4])
            if fishX == lane1:
                fishX2 = random.choice([lane3, lane4])
            elif fishX == lane2:
                fishX2 = random.choice([lane3, lane4])
            else:
                fishX2 = random.choice([lane1, lane2])
            fishY = -450

        fishY2 += speed
        if fishY2 > H + 450:
            fishX3 = random.choice([lane1, lane2, lane3, lane4])
            if fishX3 == lane1:
                fishX4 = random.choice([lane3, lane4])
            elif fishX3 == lane2:
                fishX4 = random.choice([lane3, lane4])
            else:
                fishX4 = random.choice([lane1, lane2])
            fishY2 = -275
            if speed < 11:
                speed *= 1.1
        def drawGame():
            st = GAMESTATE
            dolphin1Rect = pygame.Rect((x1, y), (width, height))
            pygame.draw.rect(screen, GREEN, (x1, y, width, height))# hitbox of left dolphin
            dolphin2Rect = pygame.Rect((x2, y), (width, height))
            pygame.draw.rect(screen, GREEN, (x2, y, width, height))  # hitbox of right dolphin
            drawScene()  # draws the scene (background, lane-lines, etc)
            # players
            screen.blit(cellList[cellPosition], (x1 + 4, y - 1))  # the left dolphin
            screen.blit(cellList[cellPosition], (x2 + 4, y - 1))  # the right dolphin

            boat1Rect = pygame.Rect((boatX + 3, boatY + 14), (34, 81))
            pygame.draw.rect(screen, GREEN, boat1Rect)
            boat2Rect = pygame.Rect((boatX2 + 3, boatY + 14, 34, 81))
            pygame.draw.rect(screen, GREEN, boat2Rect)
            boat3Rect = pygame.Rect((boatX3 + 3, boatY2 + 14, 34, 81))
            pygame.draw.rect(screen, GREEN, boat3Rect)
            boat4Rect = pygame.Rect((boatX4 + 3, boatY2 + 14, 34, 81))
            pygame.draw.rect(screen, GREEN, boat4Rect)

            fish1Rect = pygame.Rect((fishX, fishY), (40, 40))
            pygame.draw.rect(screen, GREEN, fish1Rect)
            fish2Rect = pygame.Rect((fishX2, fishY, 40, 40))
            pygame.draw.rect(screen, GREEN, fish2Rect)
            fish3Rect = pygame.Rect((fishX3, fishY2, 40, 40))
            pygame.draw.rect(screen, GREEN, fish3Rect)
            fish4Rect = pygame.Rect((fishX4, fishY2, 40, 40))
            pygame.draw.rect(screen, GREEN, fish4Rect)

            screen.blit(boat, (boatX, boatY))
            screen.blit(boat, (boatX2, boatY))
            screen.blit(boat, (boatX3, boatY2))
            screen.blit(boat, (boatX4, boatY2))
            screen.blit(fish, (fishX, fishY))
            screen.blit(fish, (fishX2, fishY))
            screen.blit(fish, (fishX3, fishY2))
            screen.blit(fish, (fishX4, fishY2))
            boatList = [boat1Rect, boat2Rect, boat3Rect, boat4Rect]
            collideToggle = 0
            if pygame.Rect.collidelist(dolphin1Rect, boatList) > -1:
                st = MENUSTATE
            if pygame.Rect.collidelist(dolphin2Rect, boatList) > -1:
                st = MENUSTATE
            if dolphin1Rect.colliderect(fish1Rect) == False and fishY > y:
                st = MENUSTATE
            elif dolphin2Rect.colliderect(fish1Rect) == False and fishY > y:
                st = MENUSTATE
            elif dolphin1Rect.colliderect(fish2Rect) == False and fishY > y:
                st = MENUSTATE
            elif dolphin2Rect.colliderect(fish2Rect) == False and fishY > y:
                st = MENUSTATE
            elif dolphin1Rect.colliderect(fish3Rect) == False and fishY2 > y:
                st = MENUSTATE
            elif dolphin2Rect.colliderect(fish3Rect) == False and fishY2 > y:
                st = MENUSTATE
            elif dolphin1Rect.colliderect(fish4Rect) == False and fishY2 > y:
                st = MENUSTATE
            elif dolphin2Rect.colliderect(fish4Rect) == False and fishY2 > y:
                st = MENUSTATE
            return st
            pygame.display.update()


        if state == MENUSTATE:
            state = drawMenu(button, mx, my)
        elif state == GAMESTATE:
            state = drawGame()
            pygame.display.update()
        elif state == INFOSTATE:
            drawInfo(button, mx, my)
        else:
            running = False*


推荐答案

嘿,您似乎省略了检查对象是否碰撞的代码,如果您需要帮助调试自己的碰撞检测功能,这将非常有用。我的建议是检查Pygame精灵及其功能。我对Pygame感到很生疏,但我确实记得他们有碰撞检测功能非常适合我的目的(太空入侵者克隆和平台游戏)。查看 https://www.pygame.org/docs/ref/sprite.html

Hey seems like you omitted your code that checks whether or not the objects are collided, and that would be useful if you need help debugging your own collision detection. My recommendation would be to check out the Pygame sprites and their functions.I am rusty on my Pygame, but I do remember they have collision detection that worked well for my purposes (space invaders clone and platformer-style game). Check out https://www.pygame.org/docs/ref/sprite.html.

这篇关于Pygame碰撞检测无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆