pygame在碰撞后删除图像并计分

时间:2019-01-23 20:53:14

标签: python image pygame collision-detection collision

我有一个游戏,其中有两个由A&D键控制的海豚。您必须躲避船,并捡起每条鱼。碰撞后如何删除图像?对于鱼,我想要它,因此如果您不打鱼(它经过海豚),则游戏将进入OVERSTATE。如果您确实碰到一条鱼,请删除图像,将1加到分数上,然后继续游戏。任何帮助表示赞赏!

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

# import modules
import pygame
import random
import os

# positions the game tab to the top left portion of the monitor
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d, %d" % (0, 20)

# initializes pygame
pygame.init()

# set the caption
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)

# states
MENUSTATE = 0
INFOSTATE = 1
GAMESTATE = 2
OVERSTATE = 3

# variables for dolphin movement
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():  # used for drawing the background of the game
    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):  # draws the menu screen
    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
            boatY = -100
            boatY2 = -450
            fishY = -800
            fishY2 = -1150
        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):  # draws the info screen
    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, 505), textFont, BLACK)
    string = "D - Switch Right Lane"
    blit_text(screen, string, (130, 530), textFont, BLACK)
    string = "ESC - Close Game"
    blit_text(screen, string, (130, 555), 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

def drawOver(button, mouseX, mouseY):
    st = OVERSTATE
    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, (48, 80), titleFont, BLACK)
    textRect = pygame.Rect(0, (H // 4) + 30, W, H // 3)
    pygame.draw.rect(screen, STRIPE, textRect)
    string = "GAME OVER"
    blit_text(screen, string, (70, 230), menuFont, BLACK)
    pygame.display.update()
    return st

# images
boat = pygame.image.load("boat.png").convert_alpha()
mainsheet = pygame.image.load("mainsheetSmall.png").convert()
fish1 = pygame.image.load("fishBlue.png").convert_alpha()
fish2 = pygame.image.load("fishOrange.png").convert_alpha()

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  # speed for all downward falling objects

# 1st pair of boats
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
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

在这里可以找到船和鱼的碰撞

def drawGame(button):
    st = GAMESTATE
    dolphin1Rect = pygame.Rect((x1, y), (width, height))  # hitbox of left dolphin
    pygame.draw.rect(screen, GREEN, (x1, y, width, height))
    dolphin2Rect = pygame.Rect((x2, y), (width, height))  # hitbox of right dolphin
    pygame.draw.rect(screen, GREEN, (x2, y, width, height))

    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)
    drawScene()

    # dolphins
    screen.blit(cellList[cellPosition], (x1 + 4, y - 1))
    screen.blit(cellList[cellPosition], (x2 + 4, y - 1))

    # boats
    screen.blit(boat, (boatX, boatY))
    screen.blit(boat, (boatX2, boatY))
    screen.blit(boat, (boatX3, boatY2))
    screen.blit(boat, (boatX4, boatY2))

    # fish
    screen.blit(fish, (fishX, fishY))
    screen.blit(fish, (fishX2, fishY))
    screen.blit(fish, (fishX3, fishY2))
    screen.blit(fish, (fishX4, fishY2))

    # collision testing

    boatList = [boat1Rect, boat2Rect, boat3Rect, boat4Rect]
    if pygame.Rect.collidelist(dolphin1Rect, boatList) > -1:
        st = MENUSTATE
    if pygame.Rect.collidelist(dolphin2Rect, boatList) > -1:
        st = MENUSTATE
    button = 0
    pygame.display.update()
    return st


# main loop
running = True
state = OVERSTATE  # sets the default state as MENUSTATE
button = mx = my = 0  # initializes mouse
while running:
    clock.tick(60)  # makes the game tick 60 frames per second
    button = 0
    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 state == GAMESTATE:
        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:  # if the current pos is less tan cellList, add one
            cellPosition += 1
        else:
            cellPosition = 0  # else, reset the cell pos to 0, the default

        boatY += speed
        if boatY > H + 625:
            boatX = random.choice([lane1, lane2, lane3, lane4])  # choose a random lane
            if boatX == lane1:
                boatX2 = random.choice([lane3, lane4])  # choose a lane on the other side
            elif boatX == lane2:
                boatX2 = random.choice([lane3, lane4])  # choose a lane on the other side
            else:
                boatX2 = random.choice([lane1, lane2])  # choose a lane on the other side
            boatY = -100

        boatY2 += speed
        if boatY2 > H + 100:
            boatX3 = random.choice([lane1, lane2, lane3, lane4])  # choose a random lane
            if boatX3 == lane1:
                boatX4 = random.choice([lane3, lane4])  # choose a lane on the other side
            elif boatX3 == lane2:
                boatX4 = random.choice([lane3, lane4])  # choose a lane on the other side
            else:
                boatX4 = random.choice([lane1, lane2])  # choose a lane on the other side
            boatY2 = -625

        fishY += speed
        if fishY > H + 275:
            fishX = random.choice([lane1, lane2, lane3, lane4])  # choose a random lane
            if fishX == lane1:
                fishX2 = random.choice([lane3, lane4])  # choose a lane on the other side
            elif fishX == lane2:
                fishX2 = random.choice([lane3, lane4])  # choose a lane on the other side
            else:
                fishX2 = random.choice([lane1, lane2])  # choose a lane on the other side
            fishY = -450

        fishY2 += speed
        if fishY2 > H + 450:
            fishX3 = random.choice([lane1, lane2, lane3, lane4])  # choose a random lane
            if fishX3 == lane1:
                fishX4 = random.choice([lane3, lane4])  # choose a lane on the other side
            elif fishX3 == lane2:
                fishX4 = random.choice([lane3, lane4])  # choose a lane on the other side
            else:
                fishX4 = random.choice([lane1, lane2])  # choose a lane on the other side
            fishY2 = -275
            if speed < 11:
                speed *= 1.1

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

1 个答案:

答案 0 :(得分:1)

因此,对于您的特定问题,您需要一种方法来检查是否击中了每个元素(鱼)。由于您没有使用面向对象的编程,因此您只需为每个变量创建一个变量,并在命中它们时将其设置为true。

然后在将它们拖到屏幕上之前,您可以检查其值是否为真。

因此在主循环之前,您需要具备以下条件:

fish_1_hit = False
fish_2_hit = False
fish_3_hit = False
fish_4_hit = False

然后在您要添加的主循环中

if dolphin1Rect.colliderect(fish1Rect):
    fish_1_hit = True
if dolphin1Rect.colliderect(fish2Rect):
    fish_2_hit = True
if dolphin1Rect.colliderect(fish3Rect):
    fish_3_hit = True
if dolphin1Rect.colliderect(fish4Rect):
    fish_4_hit = True

if dolphin2Rect.colliderect(fish1Rect):
    fish_1_hit = True
if dolphin2Rect.colliderect(fish2Rect):
    fish_2_hit = True
if dolphin2Rect.colliderect(fish3Rect):
    fish_3_hit = True
if dolphin2Rect.colliderect(fish4Rect):
    fish_4_hit = True

最终更改绘制功能,以便在绘制鱼之前检查鱼是否被击中:

# fish
if not fish_1_hit:
    screen.blit(fish, (fishX, fishY))
if not fish_2_hit:
    screen.blit(fish, (fishX2, fishY))
if not fish_3_hit:
    screen.blit(fish, (fishX3, fishY2))
if not fish_4_hit:
    screen.blit(fish, (fishX4, fishY2))

我建议您考虑使用列表来保存任何未来项目的相关实体(例如鱼)和面向对象的程序设计(OOP),因为要用多个实体进行任何事情都将是非常具有挑战性的用您正在使用的方法。