带有 pygame 的简单游戏,清理代码 + 游戏过屏

问题描述

这是我在这里写的第一篇文章。通过几个教程和从这里得到的一些建议,我创建了简单的游戏。 有人可以看看代码吗?有没有更好的方法来构建这些功能? 我知道它看起来很乱,但至少它可以工作;) 因为这是我的第一场比赛,我真的很喜欢它。这是我的代码 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(0,-15),Vector2(5,-10)]
        wind_arrow = [Vector2(0,20),Vector2(20,30),Vector2(30,15),0),10)]
        current_arrow = [Vector2(0,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,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)):
            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)),40))
        write('Current direction: ' + str(round(self.current_angle)) + "deg . Current force: " + str(
            round(self.current_force,60))

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

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


经过一些修改后,我的 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,((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:",100))
        else:
            pass

    def draw(self):

        # base shape
        vessel = [Vector2(5,60))

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

解决方法

您可以这样调用 writegameover()

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

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

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

请注意,writegameover() 方法的缩进应与您的 draw() 方法相同

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

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

,

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

  if self.offset < 0:

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

writegameover 函数:

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

时间延迟和退出有效,对于文本显示,我收到错误:ValueError: invalid color argument。 如果我在参数中指定颜色:

self.writegameover(self,0)

我得到: 类型错误:writegameover() 需要 3 到 4 个位置参数,但给出了 5 个

我尝试编写类似的工作正常的函数。出于某种原因,writegameover 有一些颜色问题。