【问题标题】:OOP game in pygame, keyboard events and controlingpygame中的OOP游戏,键盘事件和控制
【发布时间】:2017-10-08 23:13:49
【问题描述】:

我一直在制作一款游戏,有点像“打砖块” 我有的是一个球和一个桨。

这是我尝试使用 OOP 制作的第一款游戏,所以我非常感谢你们所有的 cmets。我创建了一个 Objectmanager 类来管理游戏中的所有对象,现在我不知道将键盘控制和玩家拨片移动放在哪里。

  1. 为 Objectmanager 编写了 keyevent 方法并将 event.key 传递给它,然后操纵桨 - 效果不佳。
  2. 相同的方法,但传递 pygame.key.getpressed() 并检查 Objectmanager 中的按钮

这两种方式都会使桨以一种糟糕的方式移动,或者在我希望它停止时不停止。

我认为 1. 更好,但我无法做到完美,所以我向您请教一些建议。 我会在一个循环中轻松完成它,但我真的很想学习 OOP,我不知道我是否应该将它放在 Objectmanager 或主循环中。 我也在考虑将 Paddle 放入主循环,而不是放入 Objectmanager。你怎么看?谢谢你们。

import random, pygame, sys, math, itertools
from pygame.locals import *
#            R    G    B
BLACK    = (  0,   0,   0)
GRAY     = (100, 100, 100)
NAVYBLUE = ( 60,  60, 100)
WHITE    = (255, 255, 255)
RED      = (255,   0,   0)
GREEN    = (  0, 255,   0)
BLUE     = (  0,   0, 255)
YELLOW   = (255, 255,   0)
ORANGE   = (255, 128,   0)
PURPLE   = (255,   0, 255)
CYAN     = (  0, 255, 255)
BALLSIZE = 15
BALLSPEED = 5
FPS = 60
PADDLEWIDTH = 80
PADDLEHEIGHT = 20

class Ball:
    def __init__(self):
        self.middle = [250,250]
        self.angle = math.radians(random.randint(1, 360))
        self.speed = BALLSPEED
    def update(self):
        xspeed = self.speed * math.sin(self.angle)
        yspeed = self.speed * math.cos(self.angle)
        deltax = round(xspeed)
        deltay = round(yspeed)
        self.middle[0] += deltax
        if self.middle[0] <= 0 or self.middle[0] >= 500:
            self.middle[0] -= 2*deltax
            self.angle = 2*math.pi - self.angle
        self.middle[1] += deltay
        if self.middle[1] <= 0 or self.middle[1] >= 500:
            self.middle[1] -= 2*deltay
            self.angle = math.pi - self.angle
    def draw(self,surface):
        pygame.draw.circle(surface,WHITE,self.middle,BALLSIZE)

class Paddle:
    def __init__(self):
        self.middle = [250,480]
        self.deltax = 0
    def update(self):
        self.middle[0] += self.deltax
    def rect(self):
        return pygame.Rect(self.middle[0]-(PADDLEWIDTH/2),self.middle[1]-(PADDLEHEIGHT/2),PADDLEWIDTH,PADDLEHEIGHT)
    def moveleft(self):
        self.deltax -= 10
    def moveright(self):
        self.deltax += 10
    def stop(self):
        self.deltax = 0
    def draw(self,surface):
        pygame.draw.rect(surface,WHITE,self.rect())
        pygame.draw.rect(surface, GRAY, self.rect(),4)

class ObjectManager:
    def __init__(self):
        self.balls = [Ball(),]
        self.paddle = Paddle()
    def add(self,object):
        if type(object) == Ball:
            self.balls.append(object)

    def update(self):
        for object in itertools.chain(self.balls,(self.paddle,)):
            object.update()
    def keyevent(self,keys):
        if keys[K_RIGHT]:
            self.paddle.moveright()
        elif keys[K_LEFT]:
            self.paddle.moveleft()
        else:
            self.paddle.stop()
    def draw(self,surface):
        for object in itertools.chain(self.balls,(self.paddle,)):
            object.draw(surface)

class Game:
    def __init__(self):
        pygame.init()
        self.FPS = FPS
        self.fpsClock = pygame.time.Clock()
        DISPLAYSURF = pygame.display.set_mode((500,500),0,32)
        pygame.display.set_caption('arkanoid')
        manager = ObjectManager()

        while True:
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                elif event.type == KEYDOWN:
                    if event.key == K_ESCAPE:
                        pygame.quit()
                        sys.exit()

            manager.keyevent(pygame.key.get_pressed())
            manager.update()

            DISPLAYSURF.fill(BLACK)
            manager.draw(DISPLAYSURF)
            pygame.display.update()
            self.fpsClock.tick(self.FPS)
game = Game()

【问题讨论】:

    标签: python oop pygame


    【解决方案1】:

    您的ObjectManager 应该只负责您的自定义GameObject,它可以是定义move(), update() 等的抽象类或接口。 (你的球和桨可以继承/实现)。

    所以从我的角度来看,我认为您应该在主循环中处理事件。 (创建一个 EventManager 也是一种选择。)你应该问自己这个类负责什么?并让它们尽可能简单以区分关注点。

    我还将颜色放入字典列表中,例如:

    ['black':{'R':0,'G':0,'B':0}]
    

    这样您就可以在运行时更轻松地更改颜色,例如选择随机颜色。

    【讨论】:

      【解决方案2】:

      对象管理器:

      def keydown(self,key):
          if key == K_RIGHT:
              self.paddle.moveright()
          elif key == K_LEFT:
              self.paddle.moveleft()
      def keyup(self):
          self.paddle.stop()
      

      主循环:

          for event in pygame.event.get():
              if event.type == QUIT:
                  pygame.quit()
                  sys.exit()
              elif event.type == KEYDOWN:
                  if event.key == K_ESCAPE:
                      pygame.quit()
                      sys.exit()
                  else:
                      manager.keydown(event.key)
              else:
                  manager.keyup()
      

      你觉得呢?这很好用,当我发布我的问题时,我才开始这样做......

      【讨论】:

        猜你喜欢
        • 2015-08-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-03
        • 1970-01-01
        • 2017-01-30
        • 1970-01-01
        • 2015-01-10
        • 1970-01-01
        相关资源
        最近更新 更多