如何检查可以放置在pygame中任何地方的物体的碰撞情况。

问题描述 投票:2回答:1

在我的游戏中,玩家可以通过按空格键在屏幕的任何地方投掷炸弹。3秒后,炸弹的图像会被爆炸图像取代。我想让我的玩家与爆炸图像相撞时减少5个健康值。我尝试了几种方法,但是由于一些循环错误(我不明白),玩家在爆炸时不断失去健康。我想只减少5个健康值,即如果他的健康值是100,而他在爆炸时,应该只减少到95,而不是一直减少。我在下面附上我的完整代码。谢谢你的帮助。

import pygame
import random
import math

pygame.font.init()

width = 900
height = 600

screen = pygame.display.set_mode([width, height])

walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'),
             pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'),
             pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')]

walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'),
            pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'),
            pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')]

char = pygame.image.load('standing.png')
bomb_pic = pygame.transform.scale(pygame.image.load('bomb.png'), (20, 20))
bomb_explosion = pygame.transform.scale(pygame.image.load('explosion1.png'), (40, 40))

pics = [bomb_pic, bomb_explosion]
shop = pygame.transform.scale(pygame.image.load("shop.png"), (60, 60))
boss = pygame.image.load("enemyboss.png")

player = [walkLeft, walkRight, char]

enemy_Left = [pygame.image.load('L1E.png'), pygame.image.load('L2E.png'), pygame.image.load('L3E.png'),
              pygame.image.load('L4E.png'), pygame.image.load('L5E.png'), pygame.image.load('L6E.png'),
              pygame.image.load('L7E.png'), pygame.image.load('L8E.png'), pygame.image.load('L9E.png')]

boss = pygame.image.load('pixel_monster.png')

position = [60, 60]
x = 50  # same as position
y = 50  # same as position
width = 40
height = 60
vel = 5
isJump = False
jumpCount = 10
left = False
right = False
down = False
up = False
walkCount = 0
run_once = False

enemy_vel = 2
enemy_list = []

clock = pygame.time.Clock()
FPS = 60

font = pygame.font.Font('freesansbold.ttf', 32)
items_font = pygame.font.Font('freesansbold.ttf', 16)
font_small = pygame.font.Font('freesansbold.ttf', 18)

bombs = []
explosions = []

bag = {'bomb': 0}
# print(bag["bomb"])
health = 100
got_hit = []


class Button():
    def __init__(self, color, x, y, width, height, text=''):
        self.color = color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text = text

    def draw(self, win, outline=None):

        # Call this method to draw the button on the screen
        if outline:
            pygame.draw.rect(win, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)

        pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height), 0)

        if self.text != '':
            font = pygame.font.SysFont('comicsans', 20)
            text = font.render(self.text, 1, (0, 0, 0))
            win.blit(text, (
                self.x + (self.width / 2 - text.get_width() / 2), self.y + (self.height / 2 - text.get_height() / 2)))


def shop_run():
    shop_bomb = Button((0, 200, 0), 820, 150, 60, 20, text="Bomb_b")
    bright_green = (0, 255, 0)
    green = (0, 200, 0)
    shop_bomb.draw(screen)


def redrawGameWindow():
    global walkCount
    global font
    global font_small
    global bag
    global items_font
    global enemy_list
    global pics
    global position
    global health
    global run_once
    global explosions
    global got_hit

    current_time = pygame.time.get_ticks()

    dx = []
    dy = []
    dist = []
    screen.fill([166, 166, 166])

    pygame.draw.rect(screen, (220, 0, 0), (700, 500, 100, 100))
    for five_enemies in range(5):
        random_enemy_location_y = random.randrange(50, 500)
        random_enemy_location_x = random.randrange(700, 840)
        enemy_list.append([random_enemy_location_x, random_enemy_location_y])

    for enemies in range(5):
        screen.blit(enemy_Left[enemies], enemy_list[enemies])
        dx.append(position[0] - enemy_list[enemies][0])
        dy.append(position[1] - enemy_list[enemies][1])
        dist.append(math.hypot(dx[enemies], dy[enemies]))
        dx[enemies], dy[enemies] = dx[enemies] / dist[enemies], dy[enemies] / dist[enemies]

        enemy_list[enemies][0] += dx[enemies] * 2
        enemy_list[enemies][1] += dy[enemies] * 2

    # for i in range(len(enemy_list)):
    #     for j in range(i + 1, len(enemy_list)):
    #         if enemy_list[i][0] - enemy_list[j][0] < 60:
    #             enemy_list[i][0] += 10

    #         elif enemy_list[i][1] - enemy_list[j][1]< 60:
    #            enemy_list[i][1] += 10

    pygame.draw.rect(screen, (70, 0, 220), (0, 170, 100, 300))  # main base
    pygame.draw.rect(screen, (220, 0, 0), (50, 200, 5, 250))
    pygame.draw.rect(screen, (0, 220, 0), (50, 200, 5, 250))
    screen.blit(font.render("B", True, (0, 0, 0)), (10, 200 + 40))
    screen.blit(font.render("A", True, (0, 0, 0)), (10, 235 + 40))
    screen.blit(font.render("S", True, (0, 0, 0)), (10, 270 + 40))
    screen.blit(font.render("E", True, (0, 0, 0)), (10, 305 + 40))

    pygame.draw.rect(screen, (220, 0, 0), (position[0] - 3, position[1], 50, 5))
    pygame.draw.rect(screen, (0, 220, 0), (position[0] - 3, position[1], 50, 5))

    pygame.draw.rect(screen, (0, 0, 0), (800, 0, 100, 600))
    if x + char.get_width() < 60 and y + char.get_height() < 60:
        shop_run()

    screen.blit(shop, (0, 0))
    screen.blit(font_small.render("Shop", True, (0, 0, 0)), (5, 5))

    screen.blit(font.render("Menu", True, (255, 255, 255)), (805, 10))
    screen.blit(items_font.render("Bombs: " + str(bag["bomb"]), True, (255, 255, 255)), (805, 550))
    # screen.blit(bomb_explosion, (450, 300))
    # screen.blit(boss, (450, 300))

    if walkCount + 1 >= 27:
        walkCount = 0

    if left:
        screen.blit(player[0][walkCount // 3], (x, y))
        walkCount += 1

    elif right:
        screen.blit(player[1][walkCount // 3], (x, y))
        walkCount += 1

    elif down:
        screen.blit(player[2], (x, y))
        walkcount = 0

    elif up:
        screen.blit(player[2], (x, y))
        walkcount = 0

    else:
        screen.blit(player[2], (x, y))
        walkCount = 0

    for i in reversed(range(len(bombs))):
        pos, end_time = bombs[i]
        if current_time > end_time:
            bombs.pop(i)
        else:
            screen.blit(pics[0], pos)

    for j in reversed(range(len(explosions))):
        pos = explosions[j][0]
        end_time_2 = explosions[j][1]
        if current_time > end_time_2:
            explosions.pop(j)


        elif current_time > (end_time_2 - 2000):
            screen.blit(pics[1], pos)

        else:
            continue

    pygame.display.update()


def main():
    run = True
    pygame.display.set_caption("bomb-mania")

    global x
    global y
    global width
    global height
    global vel

    global isJump
    global jumpCount

    global left
    global right
    global down
    global up

    global walkCount

    global bomb_pic

    global font
    global bombs
    global explosions
    global position
    global got_hit

    global pos2list

    while run:

        current_time = pygame.time.get_ticks()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

            if x + char.get_width() < 60 and y + char.get_height() < 60:
                buy = pygame.key.get_pressed()
                if buy[pygame.K_b]:
                    bag["bomb"] += 1
                    # print(bag["bomb"])

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE and bag["bomb"] >= 1:
                    current_time_2 = pygame.time.get_ticks()
                    pos = x + char.get_width() / 2, y + char.get_height() - 20
                    pos2 = ((x + char.get_width() / 2) - 10), (y + char.get_height() - 30)
                    end_time = current_time + 3000  # 3000 milliseconds = 3 seconds
                    end_time_2 = current_time_2 + 5000
                    explosions.append((pos2, end_time_2))
                    # print(explosions[-1][0][0])
                    got_hit.append(False)
                    bombs.append((pos, end_time))
                    bag["bomb"] -= 1

        redrawGameWindow()

        keys = pygame.key.get_pressed()

        if keys[pygame.K_LEFT] and x > vel - 15:
            x -= vel
            position[0] -= vel
            left = True
            right = False
            down = False
            up = False
            # print(position)

        elif keys[pygame.K_RIGHT] and x < 800 - vel - width:
            x += vel
            position[0] += vel
            left = False
            right = True
            down = False
            up = False
            # print(position)

        elif keys[pygame.K_DOWN] and y < 600 - height:
            y += vel
            position[1] += vel
            left = False
            right = False
            down = True
            up = False
            # print(position)

        elif keys[pygame.K_UP] and y > vel - 15:
            y -= vel
            position[1] -= vel
            left = False
            right = False
            down = False
            up = True
            # print(position)

        else:
            left = False
            right = False
            down = False
            up = False
            walkCount = 0

        clock.tick(FPS)
        pygame.display.flip()


main()
python python-3.x pygame
1个回答
1
投票

首先,当炸弹被创建时,不要添加爆炸。

if event.type == pygame.KEYDOWN:
    if event.key == pygame.K_SPACE and bag["bomb"] >= 1:
        current_time_2 = pygame.time.get_ticks()
        pos = x + char.get_width() / 2, y + char.get_height() - 20
        pos2 = ((x + char.get_width() / 2) - 10), (y + char.get_height() - 30)
        end_time = current_time + 3000  # 3000 milliseconds = 3 seconds

        # end_time_2 = current_time_2 + 2000      <--- DELETE
        # explosions.append((pos2, end_time_2))   <--- DELETE

        got_hit.append(False)
        bombs.append((pos, end_time))
        bag["bomb"] -= 1

当炸弹的阈值超过时,就会产生爆炸 在元组中添加一个额外的布尔属性,以指示plyer是否被炸弹伤害 ((pos2, end_time_2, False)):

for i in reversed(range(len(bombs))):
    pos, end_time = bombs[i]
    if current_time > end_time:
        end_time_2 = end_time + 5000
        pos2 = (pos[0] - 10, pos[1] - 30
        explosions.append((pos2, end_time_2, False))
        bombs.pop(i)
    else:
        screen.blit(pics[0], pos)

创建一个 pygame.Rect 炸弹和玩家,并评估弹头是否与炸弹相撞。改变 伤害 如果层叠器与爆炸相撞,则元组中的指示器。该 pygame.Rect 对象可以通过 pygame.Surface.get_rect. 位置可以通过一个关键字参数来设置(如 player_rect = player[0][0].get_rect(topleft = (x, y))):

for j in reversed(range(len(explosions))):
    pos, end_time_2, hurt = explosions[j]
    if current_time > end_time_2:
        explosions.pop(j)
    else:
        screen.blit(pics[1], pos)

        if not hurt:
            explosion_rect = pics[1].get_rect(topleft = pos)
            player_rect = player[0][0].get_rect(topleft = (x, y))
            if player_rect.colliderect(explosion_rect):
                explosions[j] = (pos, end_time_2, True)
                health -= 5

© www.soinside.com 2019 - 2024. All rights reserved.