【问题标题】:Simple game with pygame , cleanup code + game over screen带有pygame的简单游戏,清理代码+屏幕游戏
【发布时间】:2021-05-04 08:58:16
【问题描述】:

这是我在这里写的第一篇文章。通过从这里获得的几个教程和一些建议,我创建了简单的游戏。 有人可以看看代码吗?有没有更好的方法来构建这些功能? 我知道它看起来很乱,但至少它的工作;) 因为这是我的第一场比赛,我真的很喜欢它。这是我的代码 game.py 文件中的代码:

import sys

import pygame

from rocket import Rocket


class Game(object):
    def __init__(self):
        # configuration
        self.tps_max = 100.0
        # initialization
        pygame.init()
        self.screen = pygame.display.set_mode((1280, 720))
        self.screen_rect = self.screen.get_rect()
        self.tps_clock = pygame.time.Clock()
        self.tps_delta = 0.0
        self.player = Rocket(self)
        game = True
        while game is True:
            # Handle events
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit(0)
                elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                    sys.exit(0)

            # ticking
            self.tps_delta += self.tps_clock.tick() / 1000.0
            while self.tps_delta > 1 / self.tps_max:
                self.tick()
                self.tps_delta -= 1 / self.tps_max

            # drawing
            self.screen.fill((164, 222, 245))
            self.draw()
            pygame.display.flip()

    def tick(self):
        # check input
        self.player.tick()

    def draw(self):
        self.player.draw()



if __name__ == "__main__":
    Game()

Rocket.py 文件中的代码:

import pygame
import random
import math
import sys

from pygame.math import Vector2

pygame.font.init()
font = pygame.font.Font(None, 30)


class Rocket(object):

    def __init__(self, game):

        self.game_over = False
        self.game = game
        size = self.game.screen.get_size()

        self.speed = 3.0
        self.wind_force = 0.2
        self.wind_angle = random.randint(0, 359)
        self.current_force = 0.1
        self.current_angle = random.randint(0, 359)
        self.random_change = 0
        self.pos = Vector2(size[0] / 2, size[1] / 2)

        self.vel = Vector2(0, 0)
        self.acc = Vector2(0, 0)
        # heading vector

        self.heading = self.vel.angle_to(Vector2(0, 1))
        self.angle_speed = 0

    def addforce(self, force):
        self.acc += force

    def tick(self):
        # Input
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_w]:
            self.addforce(Vector2(0, -self.speed * 0.6).rotate(self.heading))
        if pressed[pygame.K_s]:
            self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading))
            # self.addforce(Vector2(0, self.speed))
        if pressed[pygame.K_d]:
            self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading - 90))
        if pressed[pygame.K_a]:
            self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading + 90))
        if pressed[pygame.K_q]:
            self.angle_speed -= 1
        if pressed[pygame.K_e]:
            self.angle_speed += 1
        # Physics

        self.wind_angle = (self.wind_angle + random.randint(-2, 2)) % 360
        self.wind_force += ((random.randint(-1, 2)) / 1000)

        self.current_angle = (self.current_angle + 0.1 * random.randint(-1, 1)) % 360
        self.current_force += ((random.randint(-1, 2)) / 1000)

        self.vel *= 0.5
        self.vel += Vector2(0, self.wind_force).rotate(self.wind_angle)
        self.vel += Vector2(0, self.current_force).rotate(self.current_angle)
        self.vel += self.acc
        self.pos += self.vel
        self.acc *= 0.5
        self.angle_speed *= 0.5

        self.heading = (self.heading + self.angle_speed) % 360
        # offset
        # check distance from centre to vessel pos
        self.offset = math.hypot(((self.vel[0] - self.pos[0]) + 640), ((self.vel[1] - self.pos[1]) + 360))
        # offset as 1
        self.offset /= 750
        # offset as accuracy in %
        self.offset = int((1 - self.offset) * 100)
        # gamer over to do
        if self.offset < 0:
            sys.exit(0)
        else:
            pass

    def draw(self):

        # base shape
        vessel = [Vector2(5, 10), Vector2(-5, 10), Vector2(-5, -10), Vector2(0, -15), Vector2(5, -10)]
        wind_arrow = [Vector2(0, 10), Vector2(0, 20), Vector2(20, 20), Vector2(20, 30), Vector2(30, 15), Vector2(20, 0),
                      Vector2(20, 10)]
        current_arrow = [Vector2(0, 10), Vector2(0, 20), Vector2(20, 20), Vector2(20, 30), Vector2(30, 15),
                         Vector2(20, 0),
                         Vector2(20, 10)]

        # rotating points

        vessel = [p.rotate(self.heading) for p in vessel]
        wind_arrow = [p.rotate(self.wind_angle + 90) for p in wind_arrow]
        current_arrow = [p.rotate(self.current_angle + 90) for p in current_arrow]

        # centered position & scale
        vessel = [self.pos + p * 6 for p in vessel]
        wind_arrow = [self.pos + p for p in wind_arrow]
        current_arrow = [self.pos + p for p in current_arrow]
        # draw shape
        pygame.draw.polygon(self.game.screen, (255, 177, 10), vessel)
        pygame.draw.polygon(self.game.screen, (233, 66, 245), wind_arrow)
        pygame.draw.polygon(self.game.screen, (22, 57, 217), current_arrow)

        def write(text, location, color=(0, 0, 0)):
            self.game.screen.blit(font.render(text, True, color), location)

        write(" Accuracy:" + str(self.offset), (20, 10))
        write('Wind direction: ' + str(round(self.wind_angle)) + "deg . Wind force: " + str(
            round((self.wind_force * 10), 2)), (20, 40))
        write('Current direction: ' + str(round(self.current_angle)) + "deg . Current force: " + str(
            round(self.current_force, 2)),
              (20, 60))

        # def writegameover(text, location, color=(0, 0, 0)):
        #     self.game.screen.blit(font.render(text, True, color), location)
        #     if self.game_over:
        #         writegameover(" GAME OVER", (200, 100))

我很高兴我所拥有的,这比我预期的要容易。更少我了解所有代码。我可以做一些小的修改,但我知道我的游戏远非完美。 除了清理和优化之外,我无法处理的问题是游戏结束屏幕。 我不知道game_over方法()放在哪里。现在我刚刚设置在满足 game_over 条件时退出游戏,但我想显示一些带有问题“再次玩?”的游戏结束屏幕有一些分数。我知道最好的解决方案是实现状态 Running、reset、game_over 等,但这对我来说太复杂了。 你能帮我解决这个问题吗?同样,请理解这是我的第一个 python 应用程序,所以你们的任何建议将不胜感激。


经过一些修改,我的 Rocket.py 文件仍然没有显示 Game over subtitle:

import pygame
import random
import math
import sys

from pygame.math import Vector2

pygame.font.init()
font = pygame.font.Font(None, 30)

class Rocket(object):

    def __init__(self, game):

        self.game_over = False
        self.game = game
        size = self.game.screen.get_size()

        self.speed = 3.0
        self.wind_force = 0.2
        self.wind_angle = random.randint(0, 359)
        self.current_force = 0.1
        self.current_angle = random.randint(0, 359)
        self.random_change = 0
        self.pos = Vector2(size[0] / 2, size[1] / 2)

        self.vel = Vector2(0, 0)
        self.acc = Vector2(0, 0)
        # heading vector

        self.heading = self.vel.angle_to(Vector2(0, 1))
        self.angle_speed = 0

    def addforce(self, force):
        self.acc += force

    def tick(self):
        # Input
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_w]:
            self.addforce(Vector2(0, -self.speed * 0.6).rotate(self.heading))
        if pressed[pygame.K_s]:
            self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading))
            # self.addforce(Vector2(0, self.speed))
        if pressed[pygame.K_d]:
            self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading - 90))
        if pressed[pygame.K_a]:
            self.addforce(Vector2(0, self.speed * 0.3).rotate(self.heading + 90))
        if pressed[pygame.K_q]:
            self.angle_speed -= 1
        if pressed[pygame.K_e]:
            self.angle_speed += 1
        # Physics

        self.wind_angle = (self.wind_angle + random.randint(-2, 2)) % 360
        self.wind_force += ((random.randint(-1, 2)) / 1000)

        self.current_angle = (self.current_angle + 0.1 * random.randint(-1, 1)) % 360
        self.current_force += ((random.randint(-1, 2)) / 1000)

        self.vel *= 0.5
        self.vel += Vector2(0, self.wind_force).rotate(self.wind_angle)
        self.vel += Vector2(0, self.current_force).rotate(self.current_angle)
        self.vel += self.acc
        self.pos += self.vel
        self.acc *= 0.5
        self.angle_speed *= 0.5

        self.heading = (self.heading + self.angle_speed) % 360
        # offset
        # check distance from centre to vessel pos
        self.offset = math.hypot(((self.vel[0] - self.pos[0]) + 640), ((self.vel[1] - self.pos[1]) + 360))
        # offset as 1
        self.offset /= 750
        # offset as accuracy in %
        self.offset = int((1 - self.offset) * 100)
        # gamer over to do
        if self.offset < 0:
         #    sys.exit(0)

            self.writegameover(" GAME OVER:", (200, 100))
        else:
            pass

    def draw(self):

        # base shape
        vessel = [Vector2(5, 10), Vector2(-5, 10), Vector2(-5, -10), Vector2(0, -15), Vector2(5, -10)]
        wind_arrow = [Vector2(0, 10), Vector2(0, 20), Vector2(20, 20), Vector2(20, 30), Vector2(30, 15), Vector2(20, 0),
                      Vector2(20, 10)]
        current_arrow = [Vector2(0, 10), Vector2(0, 20), Vector2(20, 20), Vector2(20, 30), Vector2(30, 15),
                         Vector2(20, 0),
                         Vector2(20, 10)]

        # rotating points

        vessel = [p.rotate(self.heading) for p in vessel]
        wind_arrow = [p.rotate(self.wind_angle + 90) for p in wind_arrow]
        current_arrow = [p.rotate(self.current_angle + 90) for p in current_arrow]

        # centered position & scale
        vessel = [self.pos + p * 6 for p in vessel]
        wind_arrow = [self.pos + p for p in wind_arrow]
        current_arrow = [self.pos + p for p in current_arrow]
        # draw shape
        pygame.draw.polygon(self.game.screen, (255, 177, 10), vessel)
        pygame.draw.polygon(self.game.screen, (233, 66, 245), wind_arrow)
        pygame.draw.polygon(self.game.screen, (22, 57, 217), current_arrow)

        def write(text, location, color=(0, 0, 0)):
            self.game.screen.blit(font.render(text, True, color), location)

        write(" Accuracy:" + str(self.offset), (20, 10))
        write('Wind direction: ' + str(round(self.wind_angle)) + "deg . Wind force: " + str(
            round((self.wind_force * 10), 2)), (20, 40))
        write('Current direction: ' + str(round(self.current_angle)) + "deg . Current force: " + str(
            round(self.current_force, 2)),
              (20, 60))

    def writegameover(self, text, location, color=(0, 0, 0)):
        self.game.screen.blit(font.render(text, True, color), location)

【问题讨论】:

  • 嗨 Dan3el,欢迎!我很高兴你在这里得到了一些答案,但对于未来,我想我会推荐一种不同的方式在这里发帖,以最大限度地提高你得到好的答案的机会。尝试直接在标题或第一句话中解决问题。背景很好,但如果人们必须阅读大量背景,他们可能不会。我建议在一开始就说“有没有更好的方法来构建这些功能”。无论如何,我希望这对您将来有所帮助。祝你好运

标签: python pygame code-cleanup


【解决方案1】:

您可以像这样拨打writegameover()

if self.offset < 0:
    # sys.exit(0)
    self.writegameover('GAME OVER', (200, 100), (0, 0, 0))

然后在write()方法之后低头

def writegameover(self, text, location, color=(0, 0, 0)):
    # self.game.screen.blit(font.render(text, True, color), location)
    print('over')

注意writegameover()方法的缩进应该和你的draw()方法一样

现在您将看到,当您越界时,您的程序将连续打印出来

我也很想知道游戏的目标是什么。我应该跟随蓝色箭头还是粉红色箭头

【讨论】:

  • 感谢您的回答。我会试试你的建议。游戏的重点是尽可能长时间地靠近屏幕中心。由于某些原因,写函数不起作用,所以你现在看不到风、电流和精度
【解决方案2】:

游戏仍然没有在屏幕上显示 GAME OVER。 游戏结束条件:

  if self.offset < 0:

            self.writegameover(self, "GAME OVER", (200, 100))
            pygame.time.delay(1000)
            sys.exit(0)

writegameover 函数:

 def writegameover(self, text, location, color=(0, 0, 0)):
        self.game.screen.blit(font.render(text, True, color), location)

时间延迟和退出工作,对于文本显示我得到错误:ValueError:无效颜色参数。 如果我在参数中指定颜色:

self.writegameover(self, "GAME OVER", (200, 100), (0,0,0)

我得到: TypeError: writegameover() 接受 3 到 4 个位置参数,但给出了 5 个

我尝试做类似的事情来编写运行良好的函数。出于某种原因,writegameover 的颜色有些问题。

【讨论】:

  • 当调用这样的函数时:self.function(argument1, argument2) 你不需要指定 self 作为参数
猜你喜欢
  • 2013-12-24
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-21
  • 1970-01-01
相关资源
最近更新 更多