【问题标题】:Flip boolean in Pygame (Main Menu)Pygame中的翻转布尔值(主菜单)
【发布时间】:2020-06-03 14:54:27
【问题描述】:

我目前正在 Pygame 中开发一个小型 2d 游戏。里面是一个继承自 Character 类的 Player 类。 Player 类有一个处理键盘输入的移动函数:

import pygame
import os
import sys
import time


pygame.init()

#window size
screen_width = 540
screen_height = 405

win = pygame.display.set_mode((screen_width, screen_height))



#Village Background

#Village Background Overlay

#Background Music

#time for FPS management
clock = pygame.time.Clock()

class Character(object):
def __init__(self, x, y, character_width, character_height):
    self.x = x #character x position
    self.y = y #character y position
    self.character_width = character_width
    self.character_height = character_height
    self.velocity = 5 #character speed
    self.walk_count = 0
    self.hitbox = (self.x + 20, self.y, 28, 28)

这是我的播放器类:

class Player_Red(Character):
def __init__(self, x, y, character_width, character_height):
    super().__init__(x, y, character_width, character_height)
    self.red_char_right = False
    self.red_char_left = False
    self.red_char_down = False
    self.red_char_up = False
    self.latest_dir = "DOWN"
    self.pause = False

def draw(self, win):
    if not self.red_char_right and not self.red_char_left and not self.red_char_down and not self.red_char_up: #first display of character
        win.blit(red_char_walk_down[0], (self.x,self.y))
    if self.walk_count + 1 >= 27: #go to first image if no image to display left
        self.walk_count = 0
    if self.red_char_right: #display images red_char_right
        win.blit(red_char_walk_right[self.walk_count//3], (self.x,self.y))
        self.walk_count += 1
    elif self.red_char_left: #display images red_char_left
        win.blit(red_char_walk_left[self.walk_count//3], (self.x,self.y))
        self.walk_count += 1
    elif self.red_char_down: #display images red_char_down
        win.blit(red_char_walk_down[self.walk_count//3], (self.x,self.y))
        self.walk_count += 1
    elif self.red_char_up: #display images red_char_up
        win.blit(red_char_walk_up[self.walk_count//3], (self.x,self.y))
        self.walk_count += 1
    else: #display latest char image if no input
        if self.latest_dir == "right":
            win.blit(red_char_walk_right[0], (self.x,self.y))
        if self.latest_dir == "left":
            win.blit(red_char_walk_left[0], (self.x,self.y))
        if self.latest_dir == "down":
            win.blit(red_char_walk_down[0], (self.x,self.y))
        if self.latest_dir == "up":
            win.blit(red_char_walk_up[0], (self.x,self.y))
    self.hitbox = (self.x + 5, self.y + 1, 21, 30)

def movement(self, win):
    keys = pygame.key.get_pressed() #keyboard input
    t = time.localtime()
    current_time = time.strftime("%H:%M:%S", t)

    for event in pygame.event.get():
        print(current_time)
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_ESCAPE:
                self.pause = not self.pause

    if self.pause:
        return
    if keys[pygame.K_a] and self.x > 5:
        self.latest_dir = "left"
        if '{}: {}'.format(self.x, self.y) not in village_left_border: #handling a key
            self.x -= self.velocity
            self.red_char_right = False
            self.red_char_left = True
            self.red_char_down = False
            self.red_char_up = False

    elif keys[pygame.K_d] and self.x < screen_width-self.character_width:
        self.latest_dir = "right"
        if '{}: {}'.format(self.x, self.y) not in village_right_border: #handling d key
            self.x += self.velocity
            self.red_char_right = True
            self.red_char_left = False
            self.red_char_down = False
            self.red_char_up = False

    elif keys[pygame.K_w] and self.y > 5:
        self.latest_dir = "up"
        if '{}: {}'.format(self.x, self.y) not in village_upper_border: #handling w key
            self.y -= self.velocity
            self.red_char_right = False
            self.red_char_left = False
            self.red_char_down = False
            self.red_char_up = True

    elif keys[pygame.K_s] and self.y < screen_height-self.character_height:
        self.latest_dir = "down"
        if '{}: {}'.format(self.x, self.y) not in village_lower_border: #handling s key
            self.y += self.velocity
            self.red_char_right = False
            self.red_char_left = False
            self.red_char_down = True
            self.red_char_up = False

    else: #no key pressed
        self.red_char_right = False
        self.red_char_left = False
        self.red_char_down = False
        self.red_char_up = False
        self.walk_count = 0

为了澄清,它是口袋妖怪系列中的红色精灵。这是我的其余代码:

def redraw_game_window():
    #display background

    #display place

    #character
    Player.draw(win)

    #display background overlay
    win.blit(background_village_overlay, (0,0))

    pygame.display.update()


#checking if player is before a door
check_buildings()


Player = Player_Red(250, 150, 32, 32)


#borders of the map

#Sounds
def sound_handling()





#Mainloop
run = True
while run:
    clock.tick(27) #FPS rate

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False


    #Player    
    Player.movement(win)

    #Sounds
    sound_handling()

    #Entering buildings
    check_buildings()

    #Update Window
    redraw_game_window()



#Mainloop End 
pygame.quit()

以上是我的大部分代码。我为我跳过的东西留下了 cmets,也让代码保持清晰。游戏以每秒 27 帧的速度运行。我在角色类的移动方法中包含了一个打印语句,以查看它查找事件的频率(因为我想构建一个需要处理 KEYUP - K_ESCAPE 事件的主菜单)。我希望代码检查每一帧中的 KEYUP - K_ESCAPE 事件,但是当我运行代码时,我得到以下信息:

17:29:20; 17:29:41; 17:30:37; 17:30:39; 17:30:50; 17:30:50;

我不明白为什么代码没有在 pygame.event.get() 循环中输入 for 事件,每滴答声意味着每秒 27 次。它有时只是不进入它 20 秒,有时每秒两次。我已经看过如果我将 print 语句放在 for 循环之外会发生什么,并且移动方法每秒调用 27 次,所以它只是 for 循环不能正常运行。如果对我的代码有任何问题,请提出。

【问题讨论】:

  • 您在主循环中执行 pygame.event.get() 两次,并在此之上分别处理 pygame.key.get_pressed() 。一旦你检查了 Quit,一旦你检查了 Escape,剩下的就是其他输入。我怀疑这不是预期的方法。但是,我认为问题在于,如果给定帧中没有发生任何事件,则 for 循环不会运行,因此不会触发打印。因为它仍然会定期检查,但有时它没有什么可报告的。下次您进行测试时,请按住键盘按钮或其他东西。
  • 是的,你是对的。我在与 pygame.K_ESCAPE 事件相同的循环中检查 pygame.QUIT 不起作用!非常感谢先生!

标签: python oop pygame


【解决方案1】:

一个建议是使用pygame.event.get() 而不是pygame.key.get_pressed()

这样您就可以判断事件是KEYDOWN 还是KEYUP。您可以在 KEYUP 上切换布尔值,因为这是一个不会多次触发的单一事件。

for event in pygame.event.get():
    if event.type == pygame.KEYUP:
        if event.key == pygame.K_ESCAPE:
            self.pause = not self.pause

编辑:从if event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE:调整代码。

【讨论】:

  • 对,理论上可行(首先感谢)。但是,在我使用代码后,我得到了以下错误: if event.key == pygame.K_ESCAPE: AttributeError: 'Event' object has no attribute 'key' PS C:\Users\Pc>
  • 我现在没有安装 pygame,所以无法验证,但我已经多次看到这种语法:例如programcreek.com/python/example/6891/pygame.KEYUP。也许你的循环声明中有拼写错误?
  • @DavidA。 event 对象将没有属性 key,除非它是关键事件。所以你必须首先检查pygame.KEYUPpygame.KEYDOWN。我猜你可能有一些缩进错误并在检查类型之前检查键
  • @Ted Klein Bergman 我怀疑这一点,并将我的答案编辑为嵌套的 if。我在编辑原因中记录了它,但在我的答案中没有。我最初的答案是使用event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE。然而,我很惊讶它得到了评估。在 Python 中,如果 and 的第一个子句的计算结果为 False,它不会计算第二个子句,这难道不是真的吗?
  • 您的第一次编辑也是正确的。我将我的回应直接交给了大卫。我相信他们在尝试应用您的答案时出错了,很可能是缩进错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-30
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-16
  • 2018-02-19
相关资源
最近更新 更多