首页 > 解决方案 > pygame,如何让我的游戏中的分数在循环内只添加一次?

问题描述

我几乎完成了我的飞扬小鸟克隆的核心机制,除了我不确定如何添加一次分数,问题在于它在循环中,所以当玩家与物体/隐形墙碰撞时,它实际上会碰撞多次并在分数上增加一个以上,所以我的问题是我如何让它只碰撞一次并在分数上增加一次。

import sys
import pygame
import random

pygame.init()
pygame.display.set_caption("Slivering snake")
window = pygame.display.set_mode((1024, 768))
clock = pygame.time.Clock()
black = 0, 0, 0
red = 255, 0, 0
score = 0
font = pygame.font.SysFont("segoe ui", 34, True)


class Player:
    def __init__(self, x, y, w, h, ):
        self.x, self.y, self.width, self.height = x, y, w, h
        self.colour = 0, 0, 255
        self.force = 12.5
        self.timer = 0

    def movement(self):
        self.keys = pygame.key.get_pressed()
        if self.keys[pygame.K_w] or self.keys[pygame.K_UP]:
            self.force -= 0.2
            self.y -= self.force

    def gravity(self):
        self.y += 4

        self.timer += 1
        if self.timer >= 32:
            self.timer = 0
            self.force = 12.5

    def draw(self):
        pygame.draw.rect(window, self.colour, (self.x, self.y, self.width, self.height))


player = Player(60, 200, 50, 50)


class Pipes:
    def __init__(self, x, y, w, h, s):
        self.x, self.y = x, y
        self.width, self.height = w, h
        self.speed = s
        self.colour = 0, 255, 0
        self.x1, self.y1 = 1450, 0

    def movement(self):
        self.x -= self.speed
        if self.x < -95:
            self.x = 1030
            location = random.randint(-300, 300)
            self.y = location

        self.x1 -= self.speed
        if self.x1 < -95:
            self.x1 = 1030
            location = random.randint(-300, 300)
            self.y1 = location

    def draw(self):
        pygame.draw.rect(window, self.colour, (self.x, self.y - 300, self.width, self.height))
        pygame.draw.rect(window, self.colour, (self.x, self.y + 490, self.width, self.height))
        pygame.draw.rect(window, self.colour, (self.x1, self.y1 - 300, self.width, self.height))
        pygame.draw.rect(window, self.colour, (self.x1, self.y1 + 490, self.width, self.height))


pipes = Pipes(900, 0, 70, 600, 3.5)

running = True
while running:
    window.fill(black)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    pipe_list = [
        pygame.Rect(pipes.x, pipes.y - 300, pipes.width, pipes.height),
        pygame.Rect(pipes.x, pipes.y + 490, pipes.width, pipes.height),
        pygame.Rect(pipes.x1, pipes.y1 - 300, pipes.width, pipes.height),
        pygame.Rect(pipes.x1, pipes.y1 + 490, pipes.width, pipes.height)
    ]
    score_rect = [
        pygame.Rect(pipes.x, 0, 1, 1024),
        pygame.Rect(pipes.x1, 0, 1, 1024)
    ]

    player.gravity()
    player.movement()
    pipes.movement()
    player_rect = pygame.Rect(player.x, player.y, player.width, player.height)
    for collision in pipe_list:
        if player_rect.colliderect(collision):
            running = False
    for points in score_rect:
        if player_rect.colliderect(points):
            score = score + 1

    text = font.render("Score " + str(score), True, red)
    print(score)
    pipes.draw()
    player.draw()
    window.blit(text, (30, 20))
    clock.tick(60)
    pygame.display.flip()

标签: pythonpygame

解决方案


一个Pipes对象不应包含 2 个或更多管道,它仅包含 1 个管道,并且如果管道已通过则具有状态 ( self.passed)

class Pipes:
    def __init__(self, x, y, w, h, s):
        self.x, self.y = x, y
        self.width, self.height = w, h
        self.speed = s
        self.colour = 0, 255, 0
        self.passed = False

在开始重新创建管道时,必须重置状态通道:

class Pipes:
    # [...]

    def movement(self):
        self.x -= self.speed
        if self.x < -95:
            self.x = 1030
            location = random.randint(-300, 300)
            self.y = location
            self.passed = False

该类有一个方法score,它评估对象是否被传递,并在传递管道时返回 true:

class Pipes:
    # [...] 

    def score(self, player_rect):
        if not self.passed  and player_rect.colliderect(pygame.Rect(self.x, 0, 1, 1024)):
            self.passed = True
            return True
        return False

此外,还有一种方法可以评估玩家是否与管道发生碰撞:

```py
class Pipes:
    # [...] 

    def collide(self, player_rect):
        rect1 = pygame.Rect(self.x, self.y - 300, self.width, self.height)
        rect2 = pygame.Rect(self.x, self.y + 490, self.width, self.height)
        return player_rect.colliderect(rect1) or player_rect.colliderect(rect2)

创建 2 个管道的列表

pipe_list = [
    Pipes(900, 0, 70, 600, 3.5), 
    Pipes(1450, 0, 70, 600, 3.5)]

移动、绘制、点碰撞测试并循环评估分数:

while running:
    # [...]

    for pipe in pipe_list:
        pipe.movement()
    player_rect = pygame.Rect(player.x, player.y, player.width, player.height)
    for pipe in pipe_list:
        if pipe.collide(player_rect):
            running = False
    for pipe in pipe_list:
        if  pipe.score(player_rect):
            score += 1

    # [...]    

    for pipe in pipe_list:
        pipe.draw()

请参阅示例:

import sys
import pygame
import random

pygame.init()
pygame.display.set_caption("Slivering snake")
window = pygame.display.set_mode((1024, 768))
clock = pygame.time.Clock()
black = 0, 0, 0
red = 255, 0, 0
score = 0
font = pygame.font.SysFont("segoe ui", 34, True)


class Player:
    def __init__(self, x, y, w, h, ):
        self.x, self.y, self.width, self.height = x, y, w, h
        self.colour = 0, 0, 255
        self.force = 12.5
        self.timer = 0

    def movement(self):
        self.keys = pygame.key.get_pressed()
        if self.keys[pygame.K_w] or self.keys[pygame.K_UP]:
            self.force -= 0.2
            self.y -= self.force

    def gravity(self):
        self.y += 4

        self.timer += 1
        if self.timer >= 32:
            self.timer = 0
            self.force = 12.5

    def draw(self):
        pygame.draw.rect(window, self.colour, (self.x, self.y, self.width, self.height))


player = Player(60, 200, 50, 50)


class Pipes:
    def __init__(self, x, y, w, h, s):
        self.x, self.y = x, y
        self.width, self.height = w, h
        self.speed = s
        self.colour = 0, 255, 0
        self.passed = False

    def movement(self):
        self.x -= self.speed
        if self.x < -95:
            self.x = 1030
            location = random.randint(-300, 300)
            self.y = location
            self.passed = False

    def score(self, player_rect):
        if not self.passed  and player_rect.colliderect(pygame.Rect(self.x, 0, 1, 1024)):
            self.passed = True
            return True
        return False

    def collide(self, player_rect):
        rect1 = pygame.Rect(self.x, self.y - 300, self.width, self.height)
        rect2 = pygame.Rect(self.x, self.y + 490, self.width, self.height)
        return player_rect.colliderect(rect1) or player_rect.colliderect(rect2)

    def draw(self):
        pygame.draw.rect(window, self.colour, (self.x, self.y - 300, self.width, self.height))
        pygame.draw.rect(window, self.colour, (self.x, self.y + 490, self.width, self.height))


pipe_list = [
    Pipes(900, 0, 70, 600, 3.5), 
    Pipes(1450, 0, 70, 600, 3.5)]

running = True
while running:
    window.fill(black)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()

    player.gravity()
    player.movement()

    for pipe in pipe_list:
        pipe.movement()
    player_rect = pygame.Rect(player.x, player.y, player.width, player.height)
    for pipe in pipe_list:
        if pipe.collide(player_rect):
            running = False
    for pipe in pipe_list:
        if  pipe.score(player_rect):
            score += 1

    text = font.render("Score " + str(score), True, red)
    print(score)
    for pipe in pipe_list:
        pipe.draw()

    player.draw()
    window.blit(text, (30, 20))
    clock.tick(60)
    pygame.display.flip()

推荐阅读