当前位置: 首页 > 知识库问答 >
问题:

当fps高于15时,PyGame蛇的速度太高[重复]

郦良才
2023-03-14

我有一个艰难的时间,在这个蛇游戏中计算速度的物理,我用pyplay。问题是,一旦我将fps设置为高于15,蛇的速度也会增加。我知道这与毫秒等有关,我发现这是有效的,高fps和慢速度。然而,在那一点上,我不能让X和Y正确,这样我就可以吃苹果了。在这一点上,我几乎迷失了方向。这是我的整个蛇游戏。我不介意分享它,因为我想一完成就开源。

import pygame
import random
from pygame.locals import (
    K_UP,
    K_DOWN,
    K_LEFT,
    K_RIGHT,
    K_ESCAPE,
    KEYDOWN,
    K_n,
    K_o,
    K_w,
    K_a,
    K_s,
    K_d,
    K_RETURN,
    QUIT,
)

pygame.init()
pygame.display.set_caption("Le jeu snake !")


class Game:
    def __init__(self):
        self.white = (255, 255, 255)
        self.black = (0, 0, 0)
        self.red = (255, 0, 0)
        self.blue = (0, 0, 255)
        self.green = (0, 255, 0)

        self.background = pygame.image.load("snake_bg.png")

        self.SCREEN_WIDTH = 600
        self.SCREEN_HEIGHT = 400

        self.screen = pygame.display.set_mode([self.SCREEN_WIDTH, self. SCREEN_HEIGHT])

        self.running = True
        self.paused = False
        self.agreed = False

        self.snake_block = 25
        self.apple_block = 25

        self.snake_x = 0
        self.snake_y = 0
        self.apple_x = 0
        self.apple_y = 0

        self.center = (self.SCREEN_WIDTH // 2, self.SCREEN_HEIGHT // 2)

        self.width_grid = 0
        self.height_grid = 0

        self.snake_x_change = 0
        self.snake_y_change = 0

        self.snake_list = list()
        self.snake_head = list()
        self.snake_length = 1

        self.score = 0

        self.clock = pygame.time.Clock()

        self.velocity = 25

    def draw_grid(self):
        self.width_grid = [x * 25 for x in range(0, self.SCREEN_WIDTH)]
        self.height_grid = [y * 25 for y in range(0, self.SCREEN_WIDTH)]

        """for grid_x in self.width_grid:
            pygame.draw.line(self.screen, self.white, [0, grid_x], [self.SCREEN_WIDTH, grid_x], 2)
            if grid_x >= 600:
                break
        for grid_y in self.height_grid:
            pygame.draw.line(self.screen, self.white, [grid_y, 0], [grid_y, self.SCREEN_WIDTH], 2)
            if grid_y >= 600:
                break"""

    def set_position(self, thing):
        if thing == "snake":
            self.snake_x = self.SCREEN_WIDTH / 2
            self.snake_y = self.SCREEN_HEIGHT / 2
        if thing == "apple":
            self.apple_x = random.choice(self.width_grid[0:24])
            self.apple_y = random.choice(self.height_grid[0:16])

    def draw(self, obj):
        if obj == "snake":
            for XnY in self.snake_list:
                pygame.draw.rect(self.screen, self.green, (XnY[0], XnY[1], self.snake_block, self.snake_block), 2)
        elif obj == "apple":
            pygame.draw.rect(self.screen, self.red, (self.apple_x, self.apple_y, self.apple_block, self.apple_block))

    def set_keys_direction(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
            if event.type == KEYDOWN:
                if event.key == K_DOWN:
                    self.snake_y_change = self.velocity
                    self.snake_x_change = 0
                if event.key == K_RIGHT:
                    self.snake_x_change = self.velocity
                    self.snake_y_change = 0
                if event.key == K_UP:
                    self.snake_y_change = -self.velocity
                    self.snake_x_change = 0
                if event.key == K_LEFT:
                    self.snake_x_change = -self.velocity
                    self.snake_y_change = 0
                if event.key == K_s:
                    self.snake_y_change = self.velocity
                    self.snake_x_change = 0
                if event.key == K_w:
                    self.snake_y_change = -self.velocity
                    self.snake_x_change = 0
                if event.key == K_d:
                    self.snake_x_change = self.velocity
                    self.snake_y_change = 0
                if event.key == K_a:
                    print("Q works")
                    self.snake_x_change = -self.velocity
                    self.snake_y_change = 0
                if not self.agreed:
                    if event.key == K_ESCAPE:
                        pygame.quit()
                    if event.key == K_RETURN:
                        self.agreed = True
                if self.agreed:
                    if event.key == K_n:
                        pygame.quit()
                    if event.key == K_o:
                        self.paused = False
                        self.score = 0
                if event.key == K_ESCAPE:
                    self.snake_length += 1

        self.elapsed = self.clock.tick(30)

    def build_snake(self):
        snake_head = list()
        snake_head.append(self.snake_x)
        snake_head.append(self.snake_y)
        self.snake_list.append(snake_head)

        if len(self.snake_list) > self.snake_length:
            del self.snake_list[0]

        for snake in self.snake_list[:-1]:
            if snake == snake_head:
                self.snake_reset()

        self.draw("snake")

    def check_apple_eaten(self):
        if self.snake_x == self.apple_x and self.snake_y == self.apple_y:
            self.set_position("apple")
            self.snake_length += 1
            self.score += 1

    def snake_borders_check(self):
        if self.snake_x < 0 or self.snake_x > self.SCREEN_WIDTH - 25:
            self.snake_reset()
        if self.snake_y < 0 or self.snake_y > self.SCREEN_HEIGHT - 25:
            self.snake_reset()

    def snake_reset(self):
        self.paused = True
        self.set_position("snake")
        self.set_position("apple")
        del self.snake_list[1:]
        self.snake_length = 1

    def snake_bit_check(self):
        pass

        """if len(self.snake_list) >= 6:
            for snake in self.snake_list[2:]:
                if self.snake_list[0][0] == snake[0] and self.snake_list[0][1] == snake[1]:
                    print("SnakeList[0][0]: {0} || SnakeList[0][1]: {0}".format(self.snake_list[0][0],
                                                                                self.snake_list[0][1]))
                    print("snake: {0}".format(snake))

                    self.snake_reset()"""

    def show_text(self, message, position, font_name="fonts/arial_narrow_7.ttf", font_size=32):
        font = pygame.font.Font(font_name, font_size)
        text = font.render(message, True, self.white, self.black)
        text_rect = text.get_rect(center=position)

        self.screen.blit(text, text_rect)

    def game_over(self):
        self.screen.blit(self.background, (0, 0))
        self.show_text("Ton score: {0}".format(self.score), (100, 20))
        self.show_text("Tu as perdu ! Veux-tu recommencer ?",
                      (self.SCREEN_WIDTH // 2, self.SCREEN_HEIGHT // 2 - 100))
        self.show_text("Appuie sur O (oui) ou sur N (non)",
                      (self.SCREEN_WIDTH // 2, self.SCREEN_HEIGHT // 2))
        self.show_text("Sinon, Echap pour quitter",
                      (self.SCREEN_WIDTH // 2, self.SCREEN_HEIGHT // 2 + 100))

    def check_agreement(self):
        self.show_text("Ceci est une réplique du jeu snake faite",
                      (self.SCREEN_WIDTH // 2, self.SCREEN_HEIGHT // 2 - 100))
        self.show_text("par Kevin pour un simple projet personnel.",
                      (self.SCREEN_WIDTH // 2 + 1, self.SCREEN_HEIGHT // 2 - 70))
        self.show_text("Si vous voulez jouer au jeu, appuyez sur la",
                      (self.SCREEN_WIDTH // 2 + 5, self.SCREEN_HEIGHT // 2 - 20))
        self.show_text("touche Entrée, sinon Echap pour quitter !",
                      (self.SCREEN_WIDTH // 2 - 11, self.SCREEN_HEIGHT // 2 + 10))
        self.show_text("- Utilise les touches flèches pour changer de direction",
                      (self.SCREEN_WIDTH // 2 - 10, self.SCREEN_HEIGHT // 2 + 55), font_size=24)
        self.show_text("- Ne te mord pas toi-même",
                      (self.SCREEN_WIDTH // 2 - 144, self.SCREEN_HEIGHT // 2 + 75), font_size=24)
        self.show_text("- Ne rentre pas dans les bords",
                      (self.SCREEN_WIDTH // 2 - 128, self.SCREEN_HEIGHT // 2 + 95), font_size=24)

    def game(self):
        self.draw_grid()
        self.set_position("snake")
        self.set_position("apple")

        while self.running:
            self.screen.blit(self.background, (0, 0))
            self.set_keys_direction()

            if self.agreed:
                self.draw_grid()

                self.draw("apple")

                self.build_snake()

                self.check_apple_eaten()

                self.snake_bit_check()

                self.snake_borders_check()
            else:
                self.check_agreement()

            if not self.paused:
                self.snake_x += self.snake_x_change
                self.snake_y += self.snake_y_change
            else:
                self.game_over()

            self.clock.tick(30)

            pygame.display.flip()


game = Game()

game.game()

pygame.quit()

共有1个答案

王凯旋
2023-03-14

self.clock.tick()的返回值是自上次调用以来的时间。使用返回值来控制速度。定义蛇每秒移动的距离(例如self.velocity=400表示每秒400像素)。获取帧之间的时间(delta_t),并按经过的时间(delta_t/1000)缩放蛇的运动:

class Game:
    def __init__(self):
        # [...]

        # distance per second 
        self.velocity = 400

    # [...]

    def game(self):

        # [...]

        while self.running:
            delta_t = self.clock.tick(30)

            # [...]

            if not self.paused:
                step = delta_t / 1000 # / 1000 because unit of velocity is seconds
                self.snake_x += self.snake_x_change * step
                self.snake_y += self.snake_y_change * step
            else:
                self.game_over()

            pygame.display.flip()

通过这种设置,很容易控制蛇的速度。例如,当蛇长大时,速度可以提高(例如,self.velocity=50)。

当然,在绘制蛇和进行碰撞测试时,必须将蛇的位置(self.snake\u xself.snake\u y)四舍五入为网格大小的倍数(25的倍数)。使用round执行此操作:

x, y = round(self.snake_x / 25) * 25, round(self.snake_y / 25) * 25

确保存储在snake\u列表中的位置是25的倍数。如果蛇头已到达一个新字段,只需在列表中添加一个新的蛇头:

if len(self.snake_list) <= 0 or snake_head != self.snake_list[-1]:
   self.snake_list.append(snake_head)

将其应用于方法build_snakeDrawcheck_apple_eaten

class Game:
    # [...]

    def build_snake(self):
        snake_head = list()
        x, y = round(self.snake_x / 25) * 25, round(self.snake_y / 25) * 25
        snake_head.append(x)
        snake_head.append(y)
        if len(self.snake_list) <= 0 or snake_head != self.snake_list[-1]:
            self.snake_list.append(snake_head)

        if len(self.snake_list) > self.snake_length:
            del self.snake_list[0]

        for snake in self.snake_list[:-1]:
            if snake == snake_head:
                self.snake_reset()

        self.draw("snake")

    def check_apple_eaten(self):
        x, y = round(self.snake_x / 25) * 25, round(self.snake_y / 25) * 25
        if x == self.apple_x and y == self.apple_y:
            self.set_position("apple")
            self.snake_length += 1
            self.score += 1

    def snake_borders_check(self):
        x, y = round(self.snake_x / 25) * 25, round(self.snake_y / 25) * 25
        if x < 0 or x > self.SCREEN_WIDTH - 25:
            self.snake_reset()
        if y < 0 or y > self.SCREEN_HEIGHT - 25:
            self.snake_reset()

 类似资料:
  • 我目前正在为一个学校项目使用pygame制作一个经典的2D平台的早期阶段,我正在实验跳跃机械师,这时我遇到了这个相当奇怪的问题。即使我考虑了更新之间的时间增量,但是当帧之间的时间增加时,跳变长度和跳变高度都会变短。 这里我让3个Player对象跳过屏幕,以700像素/秒的恒定速度向右移动,初始速度为700像素/秒。人工增加的最小延迟时间分别为0.001s、0.017s和0.1s。 这就是在Play

  • 我正在使用默认的快速滚动,我遵循了本指南来支持它。

  • 我正在尝试显示3个选项时,图标设置点击。我想覆盖它,它实际上工作(好好的)。 我的问题是第二个布局高度是手动设置的,我想改变它的高度与正常框(它的一个布局回收器视图项)相同。 有没有人可以帮助我如何设置第二个项目的高度与前一个项目的高度相同?我在OnBindViewWholder中尝试过,但没有成功 在照片下,我将添加来自适配器的xml文件和代码 适配器:

  • 我在玩Pygame,做一些简单的游戏只是为了学习它。然而,我很难按照我想要的方式实现fps。 据我所知,fps通常设置为: 然后在整个程序中,我确保每个循环/帧的写入时间为1/60秒,因此我可以,例如,使对象以我想要的速度移动。将滴答声增加到120 fps将使游戏运行过快,而降低滴答声将使游戏运行过慢。 然而,这不是我所熟悉的fps在其他游戏中的工作方式。在大多数游戏中,fps可以随您的需要而变化

  • 问题内容: 是否可以使用加速度计检测高度?例如,如果我手持手机,然后举起手臂来检测身高? 谢谢 问题答案: 假设您的意思是要检测手机从其凝视点起的高度,是的。android加速度计可测量力,有关如何使用它的更多信息,请参见此处 。请记住,加速度计并不是一个完美的设备,因此您的结果将是手机实际移动了多少的近似值。

  • 我试图设置一个渐变覆盖整个页面 这是我的代码: (我知道我写的最大高度:1%;,请继续阅读) 正如我所说,身高:100% 不起作用,所以我尝试使用各种输入,我看到的是,当我使用像素作为最大高度时,渐变的高度会发生变化,但无论我选择什么输入作为百分比的最大高度,渐变的高度都会保持不变,例如,在我的代码中,我使用了最大高度:1% 和渐变仍然超出了网页的高度。 我检查了开发工具,并应用了max heig