我正在尝试在Pythonpygame中复制谷歌铬恐龙游戏。我对pygame没有太多的经验。我设法创造了所有的恐龙精灵动画(行走,跳跃和弯曲),现在我试图增加障碍。所以我想做的是,当用户的分数超过35分时,障碍就会开始随机产生。问题是,当比分超过35分时,障碍就会出现在对方身上,一些障碍会不断出现和消失,只是看起来很糟糕和非常滞后。怎样才能使障碍更加顺利?守则的有关部分:
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()我还制作了一个视频,这样您就可以更好地理解问题所在。
完整代码:
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,这个问题才得以解决。你可以看看他的答案,看看是什么解决了这个问题。完全更新的代码:
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()发布于 2021-10-16 12:15:32
它怀疑代码的一个问题是可以通过以下方法并发调用pygame.display.update():
draw函数实现;draw_obstacles函数启动。这也许可以解释为什么一些障碍会很快出现和消失。也许,只要删除函数pygame.display.update()中的draw_obstacles,就可以解决这个问题。
另一个可能解释滞后的问题与启动线程的条件有关。在我看来,一旦得分超过35分,您将在主循环的每次迭代中启动另一个线程,这意味着有很多线程。因此,除非您的代码中有某种条件可以防止这一点,否则您应该添加一个条件。
看到完整的代码后,编辑了,我注意到了一些问题。
首先,正如前面提到的,您应该在主循环中只执行一次pygame.display.update()。对于WINDOW.fill,您的代码中有几个位置。这就是物体迅速出现和消失的原因。
您的程序(和每个游戏程序)应该有以下结构。
while run:
process_events_and_change_objects_status()
WINDOW.fill("#FFFFFF")
redraw_everything()
pygame.display.update()
wait()而且在其他地方不应该有对WINDOW.fill或pygame.display.update()的任何其他调用。
第二,查看fall方法:
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不关心障碍。此外,这意味着恐龙下落时不能处理事件。因此,您必须将其更改为只更新对象状态。
def fall(self):
if self.is_falling:
self.y += 20
if self.y != 323:
self.is_falling = False
self.is_jumping = False然后在主循环中由self.walk管理重绘。bend和jump也是如此。
因此,我认为您需要修改程序结构,以便在代码中清楚地将绘图部分与处理部分(处理事件和更新恐龙状态)分开。否则,如果将两者混合在一起,您将面临当前所面临的问题,您的代码将无法维护和发展。
https://stackoverflow.com/questions/69590609
复制相似问题