首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在游戏中为无止境的跑步者游戏建立障碍系统

在游戏中为无止境的跑步者游戏建立障碍系统
EN

Stack Overflow用户
提问于 2021-10-15 21:07:41
回答 1查看 533关注 0票数 0

我正在尝试在Pythonpygame中复制谷歌铬恐龙游戏。我对pygame没有太多的经验。我设法创造了所有的恐龙精灵动画(行走,跳跃和弯曲),现在我试图增加障碍。所以我想做的是,当用户的分数超过35分时,障碍就会开始随机产生。问题是,当比分超过35分时,障碍就会出现在对方身上,一些障碍会不断出现和消失,只是看起来很糟糕和非常滞后。怎样才能使障碍更加顺利?守则的有关部分:

代码语言:javascript
运行
复制
import pygame
import random
import os
from threading import Thread
pygame.init()

w, h = pygame.display.get_surface().get_size()
imgX = w
def generate_obstacles():
    global imgX
    obstacles_tuple = (obstacle1, obstacle2, obstacle3, obstacle4, obstacle5)
    chosen_obstacle = random.choice(obstacles_tuple)
    try:
        if WINDOW.get_width() >= imgX > 0:
            WINDOW.blit(chosen_obstacle, (imgX, 323))
        else:
            imgX = w
    except pygame.error:
        quit()

    pygame.display.update()


def draw():
    WINDOW.fill("#FFFFFF")
    pygame.display.update()


r1, r2 = 5000, 7000
def timer(score):
    global r1, r2
    timer_running = True
    while timer_running:
        rand_time = random.randint(r1, r2)
        pygame.time.delay(rand_time)
        generate_obstacles()

        if r1 >= 500 and r2 >= 500:
            if score % 100 == 0:
                r1 -= 20
                r2 -= 20
        keys = pygame.key.get_pressed()
        if event.type == pygame.QUIT or keys[pygame.K_ESCAPE]:
            break



game_intro(True)
run = True
my_sprite = Dino()
speed = 5
while run:
    pygame.time.delay(100)
    bgX -= speed
    bgX2 -= speed
    imgX -= speed
    if bgX < floor.get_width() * -1:
        bgX = floor.get_width()
    if bgX2 < floor.get_width() * -1:
        bgX2 = floor.get_width()
    for event in pygame.event.get():
        keys = pygame.key.get_pressed()
        if event.type == pygame.QUIT or keys[pygame.K_ESCAPE]:
            with open("highscore.txt", "w") as f:
                f.write(str(my_sprite.high_score))
            run = False
            pygame.quit()
            quit()

        if event.type == pygame.USEREVENT+1:
            my_sprite.fall()

        if (keys[pygame.K_UP] or keys[pygame.K_SPACE]) and not my_sprite.is_jumping:
            my_sprite.jump()

        if keys[pygame.K_DOWN]:
            my_sprite.bend()

    draw()
    my_sprite.walk()

    if my_sprite.score >= 35:
        Thread(target=lambda: timer(my_sprite.score)).start()

我还制作了一个视频,这样您就可以更好地理解问题所在。

完整代码:

代码语言:javascript
运行
复制
import pygame
import random
import os
from threading import Thread
pygame.init()

WINDOW = pygame.display.set_mode((500, 500))
pygame.display.set_caption("Dinosaur Game")
walk1_image = pygame.image.load("images/walk1.png")
walk1 = pygame.transform.scale(walk1_image, (64, 64))
bend1_image = pygame.image.load("images/bend1.png")
bend1 = pygame.transform.scale(bend1_image, (64, 64))
bend2_image = pygame.image.load("images/bend2.png")
bend2 = pygame.transform.scale(bend2_image, (64, 64))
walk2_image = pygame.image.load("images/walk2.png")
walk2 = pygame.transform.scale(walk2_image, (64, 64))
die_image = pygame.image.load("images/die.png")
die = pygame.transform.scale(die_image, (64, 64))
jump_image = pygame.image.load("images/jump.png")
jump = pygame.transform.scale(jump_image, (64, 64))

images_list = [walk1, walk2, die, jump, bend1]
floor_image = pygame.image.load("obstacles/floor-0.png").convert()
floor = pygame.transform.scale(floor_image, (500, 100))
bgX = 0
bgX2 = floor.get_width()
in_main = False

obstacle1_image = pygame.image.load("obstacles/obstacle1.png")
obstacle1 = pygame.transform.scale(obstacle1_image, (78, 78))
obstacle2_image = pygame.image.load("obstacles/obstacle2.png")
obstacle2 = pygame.transform.scale(obstacle2_image, (156, 78))
obstacle3_image = pygame.image.load("obstacles/obstacle3.png")
obstacle3 = pygame.transform.scale(obstacle3_image, (64, 64))
obstacle4_image = pygame.image.load("obstacles/obstacle4.png")
obstacle4 = pygame.transform.scale(obstacle4_image, (128, 64))
obstacle5_image = pygame.image.load("obstacles/obstacle5.png")
obstacle5 = pygame.transform.scale(obstacle5_image, (192, 64))

def game_intro(intro):
    while intro:
        WINDOW.fill("#FFFFFF")
        my_font = pygame.font.SysFont("comicsans", 40)
        label = my_font.render("Press space to play", True, (105, 105, 105))
        WINDOW.blit(jump, (125, 200))
        WINDOW.blit(label, (125, 300))
        my_font = pygame.font.SysFont("comicsans", 20)
        label2 = my_font.render("Made by: Roni", True, (0, 0, 0))
        WINDOW.blit(label2, (10, 480))
        pygame.display.update()
        for event2 in pygame.event.get():
            keys2 = pygame.key.get_pressed()
            if event2.type == pygame.QUIT or keys2[pygame.K_ESCAPE]:
                intro = False
                pygame.quit()
                quit()

            if keys2[pygame.K_SPACE]:
                if not os.path.isfile("highscore.txt"):
                    f = open("highscore.txt", "w")
                    f.write("0")
                    f.close()
                intro = False
                return


class Dino(pygame.sprite.Sprite):
    def __init__(self):
        super(Dino, self).__init__()
        self.images = [walk1, walk2]
        self.index = 0
        self.image = self.images[self.index]
        self.x = 200
        self.y = 323
        self.is_falling = False
        self.is_jumping = False
        self.is_bend = False
        self.is_down = False
        self.score = 0
        self.high_score = 0

    def walk(self):
        self.update_score()
        WINDOW.blit(floor, (bgX, 300))
        WINDOW.blit(floor, (bgX2, 300))
        self.score += 1

        if self.is_jumping:
            WINDOW.blit(jump, (self.x, self.y))
        elif self.is_bend:
            bend_images = [bend1, bend2]
            keys3 = pygame.key.get_pressed()
            self.index += 1
            if self.index >= len(self.images):
                self.index = 0
            bend = bend_images[self.index]
            if keys3[pygame.K_DOWN]:
                WINDOW.blit(bend, (self.x, self.y))
            else:
                self.is_bend = False
                self.walk()
        else:
            self.index += 1
            if self.index >= len(self.images):
                self.index = 0
            self.image = self.images[self.index]
            WINDOW.blit(self.image, (self.x, self.y))

        pygame.display.update()

    def jump(self):
        self.is_jumping = True
        for i in range(3):
            self.y -= 20
            self.walk()
            pygame.time.delay(10)
            WINDOW.fill("#FFFFFF")

        self.is_falling = True
        pygame.time.set_timer(pygame.USEREVENT+1, 1000)

    def fall(self):
        if self.is_falling:
            while self.y != 323:
                self.y += 20
                self.walk()
                WINDOW.fill("#FFFFFF")
                self.is_falling = False
                self.is_jumping = False
                pygame.display.update()

    def bend(self):
        self.is_bend = True
        self.walk()

    def update_score(self):
        my_font = pygame.font.SysFont("comicsans", 40)
        zeros = 5 - len(str(self.score))
        str_score = "0" * zeros + str(self.score)
        label = my_font.render(str_score, True, (0, 0, 0))
        WINDOW.blit(label, (410, 0))

        with open("highscore.txt", "r") as f:
            self.high_score = int(f.read())

        if self.high_score <= self.score:
            self.high_score = self.score

        zeros2 = 5 - len(str(self.high_score))
        str_score2 = "0" * zeros2 + str(self.high_score)
        label2 = my_font.render("HI: " + str_score2, True, (0, 0, 0))
        WINDOW.blit(label2, (250, 0))
        pygame.display.update()


w, h = pygame.display.get_surface().get_size()
imgX = w
def generate_obstacles():
    global imgX
    obstacles_tuple = (obstacle1, obstacle2, obstacle3, obstacle4, obstacle5)
    chosen_obstacle = random.choice(obstacles_tuple)
    try:
        if WINDOW.get_width() >= imgX > 0:
            WINDOW.blit(chosen_obstacle, (imgX, 323))
        else:
            imgX = w
    except pygame.error:
        quit()

    pygame.display.update()


def draw():
    WINDOW.fill("#FFFFFF")
    pygame.display.update()


r1, r2 = 5000, 7000
def timer(score):
    global r1, r2
    timer_running = True
    while timer_running:
        rand_time = random.randint(r1, r2)
        pygame.time.delay(rand_time)
        generate_obstacles()

        if r1 >= 500 and r2 >= 500:
            if score % 100 == 0:
                r1 -= 20
                r2 -= 20
        keys = pygame.key.get_pressed()
        if event.type == pygame.QUIT or keys[pygame.K_ESCAPE]:
            break



game_intro(True)
run = True
my_sprite = Dino()
speed = 5
while run:
    pygame.time.delay(100)
    bgX -= speed
    bgX2 -= speed
    imgX -= speed
    if bgX < floor.get_width() * -1:
        bgX = floor.get_width()
    if bgX2 < floor.get_width() * -1:
        bgX2 = floor.get_width()
    for event in pygame.event.get():
        keys = pygame.key.get_pressed()
        if event.type == pygame.QUIT or keys[pygame.K_ESCAPE]:
            with open("highscore.txt", "w") as f:
                f.write(str(my_sprite.high_score))
            run = False
            pygame.quit()
            quit()

        if event.type == pygame.USEREVENT+1:
            my_sprite.fall()

        if (keys[pygame.K_UP] or keys[pygame.K_SPACE]) and not my_sprite.is_jumping:
            my_sprite.jump()

        if keys[pygame.K_DOWN]:
            my_sprite.bend()

    draw()
    my_sprite.walk()

    if my_sprite.score >= 35:
        Thread(target=lambda: timer(my_sprite.score)).start()

多亏了qouify,这个问题才得以解决。你可以看看他的答案,看看是什么解决了这个问题。完全更新的代码:

代码语言:javascript
运行
复制
import pygame
import random
import os
from threading import Thread
pygame.init()

WINDOW = pygame.display.set_mode((500, 500))
pygame.display.set_caption("Dinosaur Game")
walk1_image = pygame.image.load("Dino/walk1.png")
walk1 = pygame.transform.scale(walk1_image, (64, 64))
bend1_image = pygame.image.load("Dino/bend1.png")
bend1 = pygame.transform.scale(bend1_image, (64, 64))
bend2_image = pygame.image.load("Dino/bend2.png")
bend2 = pygame.transform.scale(bend2_image, (64, 64))
walk2_image = pygame.image.load("Dino/walk2.png")
walk2 = pygame.transform.scale(walk2_image, (64, 64))
die_image = pygame.image.load("Dino/die.png")
die = pygame.transform.scale(die_image, (64, 64))
jump_image = pygame.image.load("Dino/jump.png")
jump = pygame.transform.scale(jump_image, (64, 64))

images_list = [walk1, walk2, die, jump, bend1]
floor_image = pygame.image.load("Others/floor-0.png").convert()
floor = pygame.transform.scale(floor_image, (500, 100))
bgX = 0
bgX2 = floor.get_width()
in_main = False

obstacle1_image = pygame.image.load("Obstacles/obstacle1.png")
obstacle1 = pygame.transform.scale(obstacle1_image, (78, 78))
obstacle2_image = pygame.image.load("Obstacles/obstacle2.png")
obstacle2 = pygame.transform.scale(obstacle2_image, (156, 78))
obstacle3_image = pygame.image.load("Obstacles/obstacle3.png")
obstacle3 = pygame.transform.scale(obstacle3_image, (64, 64))
obstacle4_image = pygame.image.load("Obstacles/obstacle4.png")
obstacle4 = pygame.transform.scale(obstacle4_image, (128, 64))
obstacle5_image = pygame.image.load("Obstacles/obstacle5.png")
obstacle5 = pygame.transform.scale(obstacle5_image, (192, 64))

def game_intro(intro):
    while intro:
        WINDOW.fill("#FFFFFF")
        my_font = pygame.font.SysFont("comicsans", 40)
        label = my_font.render("Press space to play", True, (105, 105, 105))
        WINDOW.blit(jump, (125, 200))
        WINDOW.blit(label, (125, 300))
        my_font = pygame.font.SysFont("comicsans", 20)
        label2 = my_font.render("Made by: Roni Meirom", True, (0, 0, 0))
        WINDOW.blit(label2, (10, 480))
        pygame.display.update()
        for event2 in pygame.event.get():
            keys2 = pygame.key.get_pressed()
            if event2.type == pygame.QUIT or keys2[pygame.K_ESCAPE]:
                intro = False
                pygame.quit()
                quit()

            if keys2[pygame.K_SPACE]:
                if not os.path.isfile("highscore.txt"):
                    f = open("highscore.txt", "w")
                    f.write("0")
                    f.close()
                intro = False
                return


class Dino(pygame.sprite.Sprite):
    def __init__(self):
        super(Dino, self).__init__()
        self.images = [walk1, walk2]
        self.index = 0
        self.image = self.images[self.index]
        self.x = 200
        self.y = 323
        self.is_falling = False
        self.is_jumping = False
        self.is_bend = False
        self.is_down = False
        self.score = 0
        self.high_score = 0

    def walk(self):
        self.update_score()
        WINDOW.blit(floor, (bgX, 300))
        WINDOW.blit(floor, (bgX2, 300))
        self.score += 1

        if self.is_jumping:
            WINDOW.blit(jump, (self.x, self.y))
        elif self.is_bend:
            bend_images = [bend1, bend2]
            keys3 = pygame.key.get_pressed()
            self.index += 1
            if self.index >= len(self.images):
                self.index = 0
            bend = bend_images[self.index]
            if keys3[pygame.K_DOWN]:
                WINDOW.blit(bend, (self.x, self.y))
            else:
                self.is_bend = False
                self.walk()
        else:
            self.index += 1
            if self.index >= len(self.images):
                self.index = 0
            self.image = self.images[self.index]
            WINDOW.blit(self.image, (self.x, self.y))


    def jump(self):
        self.is_jumping = True
        for i in range(3):
            self.y -= 20
            self.walk()
            pygame.time.delay(10)
            WINDOW.fill("#FFFFFF")

        self.is_falling = True
        pygame.time.set_timer(pygame.USEREVENT+1, 1000)

    def fall(self):
        if self.is_falling:
            self.y += 20
            if self.y != 323:
                self.y = 323
                self.is_falling = False
                self.is_jumping = False

    def bend(self):
        self.is_bend = True
        self.walk()

    def update_score(self):
        my_font = pygame.font.SysFont("comicsans", 40)
        zeros = 5 - len(str(self.score))
        str_score = "0" * zeros + str(self.score)
        label = my_font.render(str_score, True, (0, 0, 0))
        WINDOW.blit(label, (410, 0))

        with open("highscore.txt", "r") as f:
            self.high_score = int(f.read())

        if self.high_score <= self.score:
            self.high_score = self.score

        zeros2 = 5 - len(str(self.high_score))
        str_score2 = "0" * zeros2 + str(self.high_score)
        label2 = my_font.render("HI: " + str_score2, True, (0, 0, 0))
        WINDOW.blit(label2, (250, 0))


w, h = pygame.display.get_surface().get_size()
imgX = w
def generate_obstacles():
    global imgX
    obstacles_tuple = (obstacle1, obstacle2, obstacle3, obstacle4, obstacle5)
    chosen_obstacle = random.choice(obstacles_tuple)
    try:
        if WINDOW.get_width() >= imgX > 0:
            WINDOW.blit(chosen_obstacle, (imgX, 323))
        else:
            imgX = w
    except pygame.error:
        quit()


r1, r2 = 5000, 7000
def timer(score):
    global r1, r2
    timer_running = True
    while timer_running:
        rand_time = random.randint(r1, r2)
        pygame.time.delay(rand_time)
        generate_obstacles()

        if r1 >= 500 and r2 >= 500:
            if score % 100 == 0:
                r1 -= 20
                r2 -= 20
        keys = pygame.key.get_pressed()
        if event.type == pygame.QUIT or keys[pygame.K_ESCAPE]:
            break



game_intro(True)
run = True
my_sprite = Dino()
speed = 5
while run:
    bgX -= speed
    bgX2 -= speed
    imgX -= speed
    if bgX < floor.get_width() * -1:
        bgX = floor.get_width()
    if bgX2 < floor.get_width() * -1:
        bgX2 = floor.get_width()
    for event in pygame.event.get():
        keys = pygame.key.get_pressed()
        if event.type == pygame.QUIT or keys[pygame.K_ESCAPE]:
            with open("highscore.txt", "w") as f:
                f.write(str(my_sprite.high_score))
            run = False
            pygame.quit()
            quit()

        if event.type == pygame.USEREVENT+1:
            my_sprite.fall()

        if (keys[pygame.K_UP] or keys[pygame.K_SPACE]) and not my_sprite.is_jumping:
            my_sprite.jump()

        if keys[pygame.K_DOWN]:
            my_sprite.bend()

    WINDOW.fill("#FFFFFF")
    my_sprite.walk()

    if my_sprite.score >= 35:
        Thread(target=lambda: timer(my_sprite.score)).start()

    pygame.time.delay(100)
    pygame.display.update()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-16 12:15:32

它怀疑代码的一个问题是可以通过以下方法并发调用pygame.display.update()

  • 主程序通过draw函数实现;
  • 通过线程,当分数大于35时,通过draw_obstacles函数启动。

这也许可以解释为什么一些障碍会很快出现和消失。也许,只要删除函数pygame.display.update()中的draw_obstacles,就可以解决这个问题。

另一个可能解释滞后的问题与启动线程的条件有关。在我看来,一旦得分超过35分,您将在主循环的每次迭代中启动另一个线程,这意味着有很多线程。因此,除非您的代码中有某种条件可以防止这一点,否则您应该添加一个条件。

看到完整的代码后,编辑了,我注意到了一些问题。

首先,正如前面提到的,您应该在主循环中只执行一次pygame.display.update()。对于WINDOW.fill,您的代码中有几个位置。这就是物体迅速出现和消失的原因。

您的程序(和每个游戏程序)应该有以下结构。

代码语言:javascript
运行
复制
while run:
    process_events_and_change_objects_status()
    WINDOW.fill("#FFFFFF")
    redraw_everything()
    pygame.display.update()
    wait()

而且在其他地方不应该有对WINDOW.fillpygame.display.update()的任何其他调用。

第二,查看fall方法:

代码语言:javascript
运行
复制
def fall(self):
    if self.is_falling:
        while self.y != 323:
            self.y += 20
            self.walk()
            WINDOW.fill("#FFFFFF")
            self.is_falling = False
            self.is_jumping = False
            pygame.display.update()

在这里,您尝试同时做两件事:更新对象状态和用self.walk重绘所有东西。这是不好的,因为,例如,如果当前屏幕上存在障碍,则不会绘制它们,因为self.walk不关心障碍。此外,这意味着恐龙下落时不能处理事件。因此,您必须将其更改为只更新对象状态。

代码语言:javascript
运行
复制
def fall(self):
    if self.is_falling:
        self.y += 20
        if self.y != 323:
            self.is_falling = False
            self.is_jumping = False

然后在主循环中由self.walk管理重绘。bendjump也是如此。

因此,我认为您需要修改程序结构,以便在代码中清楚地将绘图部分与处理部分(处理事件和更新恐龙状态)分开。否则,如果将两者混合在一起,您将面临当前所面临的问题,您的代码将无法维护和发展。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69590609

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档