Pygame 有时无法检测到 KEYUP 或 KEYDOWN
Pygame sometimes fails to detect KEYUP or KEYDOWN
我正在学习 pygame 这个木乃伊游戏,但玩家的动作没有按要求做出反应。有时,它会起作用,有时,即使释放了键,它也会继续移动。为什么 pygame 在我松开或按下箭头键时始终检测不到?谢谢你的帮助。
箭头键的使用方式在“游戏”中描述,“更新”方法的结尾。
主要 :
"""
Created on Mon Jun 14 09:54:56 2021
@author: Graven
"""
import pygame as pg
import math
from game import Game
pg.init() # charger les composants de pygame
clock = pg.time.Clock()
# Générer la fenêtre du jeu
screenSize = (1080, 720)
pg.display.set_caption('Comet fall game') #(title, icontitle) Définir le titre de la fenêtre
screen = pg.display.set_mode(screenSize) # (size, flag...) taille de la fenêtre
# Importer l'arrière plan
background = pg.image.load('assets/bg.jpg')
# Importer la bannière
banner = pg.image.load('assets/banner.png')
banner = pg.transform.scale(banner, (500, 500))
banner_rect = banner.get_rect()
banner_rect.x = math.ceil(screen.get_width() / 4)
# importerle bouton pour lancer la partie
play_button = pg.image.load('assets/button.png')
play_button = pg.transform.scale(play_button, (400, 150))
play_button_rect = play_button.get_rect()
play_button_rect.x = math.ceil(screen.get_width() / 3.33)
play_button_rect.y = math.ceil(screen.get_height() / 2)
# Charger le jeu
game = Game()
running = True # jeu en cours d'execution
# Boucle tant que running est vrai
while running :
# pg.time.delay(10)
# Appliquer l'arrière plan du jeu
screen.blit(background, (-1000, -200)) # injecter l'image sur l'écran
# Vérifier si notre jeu a commencé ou non
if game.is_playing:
# Déclencher les instructions de la partie
game.update(screen, screenSize)
# Vérifier si le jeu n'a pas encore commencé
else :
# Ajouter l'écran de bienvenue
screen.blit(play_button, play_button_rect)
screen.blit(banner,banner_rect)
# mettre à jour l'écran
pg.display.flip()
# clock.tick(1000)
# si le joueur ferme cette fenetre ou click sur start
for event in pg.event.get(): # reprendre tous les évenements possibles
# vérifier que l'evenement est fermeture de fenetre
if event.type == pg.QUIT :
running = False
pg.quit()
elif event.type == pg.MOUSEBUTTONDOWN:
# Vérification pour savoir si le curseur est en collision avec le boutton
if play_button_rect.collidepoint(event.pos):
# mettre le jeu en mode "lancé"
game.start()
游戏:
"""
Created on Mon Jun 14 10:40:05 2021
@author: Graven
"""
import pygame as pg
from player import Player
from monster import Monster
clock = pg.time.Clock()
# Créer une seconde classe qui représente le jeu
class Game :
def __init__(self):
# Définir si le jeu a commencé ou non
self.is_playing = False
# Générer notre joueur
self.all_players = pg.sprite.Group() # Uniquement pour la fonction collision qui vérifie un sprite avec un groupe
self.player = Player(self)
self.all_players.add(self.player)
# Enregistrer toutes les touches actionnées
self.pressed = {}
# Groupe de monstre
self.all_monsters = pg.sprite.Group()
self.k=0
def start(self):
# lors d'une nouvelle partie, respawn des monstres
self.is_playing = True
# self.spawn_monster()
# self.spawn_monster()
def game_over(self):
# Remettre le jeu à neuf, retirer les monstres, remettre 100 pv et jeu en attente
self.all_monsters = pg.sprite.Group()
self.player.health = self.player.max_health
self.is_playing = False
def update(self, screen, screenSize):
# Appliquer l'image du joueur
screen.blit(self.player.image, self.player.rect)
# Visualiser la barre de vie du joueur
self.player.update_health_bar(screen, self.player.chargeState)
# Récupérer les projectiles du joueur
for projectile in self.player.all_projectile:
projectile.move()
# Récupérer les monstres du jeu
for monster in self.all_monsters:
monster.forward()
monster.update_health_bar(screen)
# Appliquer l'ensemble des images de mon groupe de projectiles
self.player.all_projectile.draw(screen)
# Appliquer l'ensemble des images de mon groupe de monstre
self.all_monsters.draw(screen)
# Charge du projectile
if self.player.charge_projectile:
self.player.chargeState += 1
else:
self.player.chargeState = 0
# Vérifier si le joueur souhaite se déplacer
if self.pressed.get(pg.K_RIGHT) and self.player.rect.x < screenSize[0] - self.player.rect.width:
self.player.move_right()
elif self.pressed.get(pg.K_LEFT) and self.player.rect.x > 0:
self.player.move_left()
# si le joueur réalise un évenement
for event in pg.event.get(): # reprendre tous les évenements possibles
# vérifier que l'evenement est fermeture de fenetre
if event.type == pg.QUIT :
pg.quit()
# Détecter si un joueur lache une touche du clavier
elif event.type == pg.KEYDOWN:
self.pressed[event.key] = True
# Détecter si espace est enclenché pour lancer le projectile
if event.key == pg.K_SPACE:
self.player.charge_projectile = True
elif event.type == pg.KEYUP and self.player.charge_projectile :
self.player.launch_projectile()
self.player.charge_projectile = False
self.pressed[event.key] = False
elif event.type == pg.KEYUP :
self.pressed[event.key] = False
# self.k += 1
# print(self.k, self.pressed)
def check_collision(self, sprite, group):
return pg.sprite.spritecollide(sprite, group, False, pg.sprite.collide_mask)
def spawn_monster(self):
monster = Monster(self)
self.all_monsters.add(monster)
玩家:
"""
Created on Mon Jun 14 10:39:16 2021
@author: Graven
"""
import pygame as pg
from projectile import Projectile
# Créer une première classe qui représente le joueur
class Player(pg.sprite.Sprite) :
def __init__(self, game):
super().__init__()
self.game = game
self.health = 100
self.max_health = 100
self.chargeState = 0
self.attack = 0.5
self.max_charge = 100
self.velocity = 3
self.image = pg.image.load('assets/player.png')
self.rect = self.image.get_rect()
self.rect.x = 450
self.rect.y = 500
self.all_projectile = pg.sprite.Group()
self.charge_projectile = False
def damage(self, amout):
self.health -= amout
if self.health <= 0 :
self.game.game_over()
def move_right(self):
# si le joueur n'est pas en collision avec un monstre
if not self.game.check_collision(self, self.game.all_monsters):
self.rect.x += self.velocity
def move_left(self):
self.rect.x -= self.velocity
def launch_projectile(self):
# Créer une nouvelle instance de la classe projectile
self.all_projectile.add(Projectile(self))
def update_health_bar(self, surface, max_charge):
# Définir une couleur pour la jauge de vie(vert) et son arrière plan (gris)
if max_charge < self.max_charge :
bar_color = (111, 210, 46)
else:
bar_color = (255, 128, 0)
back_bar_color = (60, 63,60)
# Définir la position de la jauge de vie et sa largeur/épaisseur
bar_position = [self.rect.x +50, self.rect.y + 20, self.health, 7] # Définir la position de l'arrière plan dela jauge
back_bar_position = [self.rect.x + 50, self.rect.y + 20, self.max_health, 7]
# Dessiner la barre de vie
pg.draw.rect(surface, back_bar_color, back_bar_position)
pg.draw.rect(surface, bar_color, bar_position)
怪物
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 14 18:48:46 2021
@author: Graven
"""
import pygame as pg
import random
# Création d'une classe qui gère la notion de monstre
class Monster(pg.sprite.Sprite):
def __init__(self, game):
self.game = game
super().__init__()
self.max_health = 60 + random.randint(0,60)
self.health = self.max_health
self.attack = 0.3
self.image = pg.image.load('assets/mummy.png')
self.rect = self.image.get_rect()
self.rect.x = 1080 + random.randint(0, 300)
self.rect.y = 540
self.velocity = random.randint(1,3)
def damage(self, amount):
self.health -= amount
if self.health <= 0 :
# Réapparaitre comme un nouveau monstre
self.rect.x = 1080 + random.randint(0, 300)
self.max_health = 60 + random.randint(0,60)
self.health = self.max_health
self.velocity = random.randint(1,3)
def update_health_bar(self, surface):
# Définir une couleur pour la jauge de vie(vert) et son arrière plan (gris)
bar_color, back_bar_color = (111, 210, 46), (60, 63,60)
# Définir la position de la jauge de vie et sa largeur/épaisseur
bar_position = [self.rect.x + 10, self.rect.y - 20, self.health, 5]
# Définir la position de l'arrière plan dela jauge
back_bar_position = [self.rect.x + 10, self.rect.y - 20, self.max_health, 5]
# Dessiner la barre de vie
pg.draw.rect(surface, back_bar_color, back_bar_position)
pg.draw.rect(surface, bar_color, bar_position)
def forward(self):
# si le monster n'est pas en collision avec le joueur
if not self.game.check_collision(self, self.game.all_players):
self.rect.x -= self.velocity
else:
# Si le monstre est en collision avec le joueur, inflige des degats
self.game.player.damage(self.attack)
投射物:
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 14 11:41:52 2021
@author: Graven
"""
import pygame as pg
# définir la classe qui gère le projectile de notre joueur
class Projectile(pg.sprite.Sprite):
#définir le constructeur
def __init__(self, player):
super().__init__()
self.velocity = 5
self.player = player
self.image = pg.image.load('assets/projectile.png')
self.rect = self.image.get_rect()
self.damage = int(self.player.attack * min(self.player.chargeState, self.player.max_charge)**1.1)
self.image = pg.transform.scale(self.image, (self.damage, self.damage))
self.rect.x = player.rect.x + 95
self.rect.y = player.rect.y + 115 - self.damage/2
self.origin_image = self.image
self.angle = 0
def rotate(self):
# Tourner le projectile
self.angle += 2
self.image = pg.transform.rotozoom(self.origin_image, self.angle, 1)
self.rect = self.image.get_rect(center = self.rect.center)
def remove(self):
self.player.all_projectile.remove(self)
def move(self):
self.rect.x += self.velocity
# self.rotate()
# centre_proj = self.rect.center
# print('centre_proj',centre_proj)
# Vérifier su le projectile entre en collision avec un monstre
for monstre_rencontre in self.player.game.check_collision(self, self.player.game.all_monsters):
# Attribuer les dégats
monstre_rencontre.damage(self.damage)
#supprimer le projectile
self.remove()
# Vérifier si le projectie n'est plus présent sur l'écran
if self.rect.x > 1080:
# Supprimer le projectile
self.remove()
pygame.event.get()
获取所有消息并将它们从队列中删除。请参阅文档:
This will get all the messages and remove them from the queue. [...]
如果在多个事件循环中调用pygame.event.get()
,则只有一个循环接收事件,而不是所有循环都接收所有事件。因此,有些事件似乎被遗漏了。
每帧获取一次事件并在多个循环中使用它们或将事件列表传递给处理它们的函数和方法:
class Game:
# [...]
def update(self, screen, screenSize, eventList):
# [...]
for event in eventList:
# [...]
while running :
eventList = pg.event.get()
# [...]
if game.is_playing:
# Déclencher les instructions de la partie
game.update(screen, screenSize, eventList)
# [...]
for event in eventList:
# [...]
我正在学习 pygame 这个木乃伊游戏,但玩家的动作没有按要求做出反应。有时,它会起作用,有时,即使释放了键,它也会继续移动。为什么 pygame 在我松开或按下箭头键时始终检测不到?谢谢你的帮助。 箭头键的使用方式在“游戏”中描述,“更新”方法的结尾。
主要 :
"""
Created on Mon Jun 14 09:54:56 2021
@author: Graven
"""
import pygame as pg
import math
from game import Game
pg.init() # charger les composants de pygame
clock = pg.time.Clock()
# Générer la fenêtre du jeu
screenSize = (1080, 720)
pg.display.set_caption('Comet fall game') #(title, icontitle) Définir le titre de la fenêtre
screen = pg.display.set_mode(screenSize) # (size, flag...) taille de la fenêtre
# Importer l'arrière plan
background = pg.image.load('assets/bg.jpg')
# Importer la bannière
banner = pg.image.load('assets/banner.png')
banner = pg.transform.scale(banner, (500, 500))
banner_rect = banner.get_rect()
banner_rect.x = math.ceil(screen.get_width() / 4)
# importerle bouton pour lancer la partie
play_button = pg.image.load('assets/button.png')
play_button = pg.transform.scale(play_button, (400, 150))
play_button_rect = play_button.get_rect()
play_button_rect.x = math.ceil(screen.get_width() / 3.33)
play_button_rect.y = math.ceil(screen.get_height() / 2)
# Charger le jeu
game = Game()
running = True # jeu en cours d'execution
# Boucle tant que running est vrai
while running :
# pg.time.delay(10)
# Appliquer l'arrière plan du jeu
screen.blit(background, (-1000, -200)) # injecter l'image sur l'écran
# Vérifier si notre jeu a commencé ou non
if game.is_playing:
# Déclencher les instructions de la partie
game.update(screen, screenSize)
# Vérifier si le jeu n'a pas encore commencé
else :
# Ajouter l'écran de bienvenue
screen.blit(play_button, play_button_rect)
screen.blit(banner,banner_rect)
# mettre à jour l'écran
pg.display.flip()
# clock.tick(1000)
# si le joueur ferme cette fenetre ou click sur start
for event in pg.event.get(): # reprendre tous les évenements possibles
# vérifier que l'evenement est fermeture de fenetre
if event.type == pg.QUIT :
running = False
pg.quit()
elif event.type == pg.MOUSEBUTTONDOWN:
# Vérification pour savoir si le curseur est en collision avec le boutton
if play_button_rect.collidepoint(event.pos):
# mettre le jeu en mode "lancé"
game.start()
游戏:
"""
Created on Mon Jun 14 10:40:05 2021
@author: Graven
"""
import pygame as pg
from player import Player
from monster import Monster
clock = pg.time.Clock()
# Créer une seconde classe qui représente le jeu
class Game :
def __init__(self):
# Définir si le jeu a commencé ou non
self.is_playing = False
# Générer notre joueur
self.all_players = pg.sprite.Group() # Uniquement pour la fonction collision qui vérifie un sprite avec un groupe
self.player = Player(self)
self.all_players.add(self.player)
# Enregistrer toutes les touches actionnées
self.pressed = {}
# Groupe de monstre
self.all_monsters = pg.sprite.Group()
self.k=0
def start(self):
# lors d'une nouvelle partie, respawn des monstres
self.is_playing = True
# self.spawn_monster()
# self.spawn_monster()
def game_over(self):
# Remettre le jeu à neuf, retirer les monstres, remettre 100 pv et jeu en attente
self.all_monsters = pg.sprite.Group()
self.player.health = self.player.max_health
self.is_playing = False
def update(self, screen, screenSize):
# Appliquer l'image du joueur
screen.blit(self.player.image, self.player.rect)
# Visualiser la barre de vie du joueur
self.player.update_health_bar(screen, self.player.chargeState)
# Récupérer les projectiles du joueur
for projectile in self.player.all_projectile:
projectile.move()
# Récupérer les monstres du jeu
for monster in self.all_monsters:
monster.forward()
monster.update_health_bar(screen)
# Appliquer l'ensemble des images de mon groupe de projectiles
self.player.all_projectile.draw(screen)
# Appliquer l'ensemble des images de mon groupe de monstre
self.all_monsters.draw(screen)
# Charge du projectile
if self.player.charge_projectile:
self.player.chargeState += 1
else:
self.player.chargeState = 0
# Vérifier si le joueur souhaite se déplacer
if self.pressed.get(pg.K_RIGHT) and self.player.rect.x < screenSize[0] - self.player.rect.width:
self.player.move_right()
elif self.pressed.get(pg.K_LEFT) and self.player.rect.x > 0:
self.player.move_left()
# si le joueur réalise un évenement
for event in pg.event.get(): # reprendre tous les évenements possibles
# vérifier que l'evenement est fermeture de fenetre
if event.type == pg.QUIT :
pg.quit()
# Détecter si un joueur lache une touche du clavier
elif event.type == pg.KEYDOWN:
self.pressed[event.key] = True
# Détecter si espace est enclenché pour lancer le projectile
if event.key == pg.K_SPACE:
self.player.charge_projectile = True
elif event.type == pg.KEYUP and self.player.charge_projectile :
self.player.launch_projectile()
self.player.charge_projectile = False
self.pressed[event.key] = False
elif event.type == pg.KEYUP :
self.pressed[event.key] = False
# self.k += 1
# print(self.k, self.pressed)
def check_collision(self, sprite, group):
return pg.sprite.spritecollide(sprite, group, False, pg.sprite.collide_mask)
def spawn_monster(self):
monster = Monster(self)
self.all_monsters.add(monster)
玩家:
"""
Created on Mon Jun 14 10:39:16 2021
@author: Graven
"""
import pygame as pg
from projectile import Projectile
# Créer une première classe qui représente le joueur
class Player(pg.sprite.Sprite) :
def __init__(self, game):
super().__init__()
self.game = game
self.health = 100
self.max_health = 100
self.chargeState = 0
self.attack = 0.5
self.max_charge = 100
self.velocity = 3
self.image = pg.image.load('assets/player.png')
self.rect = self.image.get_rect()
self.rect.x = 450
self.rect.y = 500
self.all_projectile = pg.sprite.Group()
self.charge_projectile = False
def damage(self, amout):
self.health -= amout
if self.health <= 0 :
self.game.game_over()
def move_right(self):
# si le joueur n'est pas en collision avec un monstre
if not self.game.check_collision(self, self.game.all_monsters):
self.rect.x += self.velocity
def move_left(self):
self.rect.x -= self.velocity
def launch_projectile(self):
# Créer une nouvelle instance de la classe projectile
self.all_projectile.add(Projectile(self))
def update_health_bar(self, surface, max_charge):
# Définir une couleur pour la jauge de vie(vert) et son arrière plan (gris)
if max_charge < self.max_charge :
bar_color = (111, 210, 46)
else:
bar_color = (255, 128, 0)
back_bar_color = (60, 63,60)
# Définir la position de la jauge de vie et sa largeur/épaisseur
bar_position = [self.rect.x +50, self.rect.y + 20, self.health, 7] # Définir la position de l'arrière plan dela jauge
back_bar_position = [self.rect.x + 50, self.rect.y + 20, self.max_health, 7]
# Dessiner la barre de vie
pg.draw.rect(surface, back_bar_color, back_bar_position)
pg.draw.rect(surface, bar_color, bar_position)
怪物
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 14 18:48:46 2021
@author: Graven
"""
import pygame as pg
import random
# Création d'une classe qui gère la notion de monstre
class Monster(pg.sprite.Sprite):
def __init__(self, game):
self.game = game
super().__init__()
self.max_health = 60 + random.randint(0,60)
self.health = self.max_health
self.attack = 0.3
self.image = pg.image.load('assets/mummy.png')
self.rect = self.image.get_rect()
self.rect.x = 1080 + random.randint(0, 300)
self.rect.y = 540
self.velocity = random.randint(1,3)
def damage(self, amount):
self.health -= amount
if self.health <= 0 :
# Réapparaitre comme un nouveau monstre
self.rect.x = 1080 + random.randint(0, 300)
self.max_health = 60 + random.randint(0,60)
self.health = self.max_health
self.velocity = random.randint(1,3)
def update_health_bar(self, surface):
# Définir une couleur pour la jauge de vie(vert) et son arrière plan (gris)
bar_color, back_bar_color = (111, 210, 46), (60, 63,60)
# Définir la position de la jauge de vie et sa largeur/épaisseur
bar_position = [self.rect.x + 10, self.rect.y - 20, self.health, 5]
# Définir la position de l'arrière plan dela jauge
back_bar_position = [self.rect.x + 10, self.rect.y - 20, self.max_health, 5]
# Dessiner la barre de vie
pg.draw.rect(surface, back_bar_color, back_bar_position)
pg.draw.rect(surface, bar_color, bar_position)
def forward(self):
# si le monster n'est pas en collision avec le joueur
if not self.game.check_collision(self, self.game.all_players):
self.rect.x -= self.velocity
else:
# Si le monstre est en collision avec le joueur, inflige des degats
self.game.player.damage(self.attack)
投射物:
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 14 11:41:52 2021
@author: Graven
"""
import pygame as pg
# définir la classe qui gère le projectile de notre joueur
class Projectile(pg.sprite.Sprite):
#définir le constructeur
def __init__(self, player):
super().__init__()
self.velocity = 5
self.player = player
self.image = pg.image.load('assets/projectile.png')
self.rect = self.image.get_rect()
self.damage = int(self.player.attack * min(self.player.chargeState, self.player.max_charge)**1.1)
self.image = pg.transform.scale(self.image, (self.damage, self.damage))
self.rect.x = player.rect.x + 95
self.rect.y = player.rect.y + 115 - self.damage/2
self.origin_image = self.image
self.angle = 0
def rotate(self):
# Tourner le projectile
self.angle += 2
self.image = pg.transform.rotozoom(self.origin_image, self.angle, 1)
self.rect = self.image.get_rect(center = self.rect.center)
def remove(self):
self.player.all_projectile.remove(self)
def move(self):
self.rect.x += self.velocity
# self.rotate()
# centre_proj = self.rect.center
# print('centre_proj',centre_proj)
# Vérifier su le projectile entre en collision avec un monstre
for monstre_rencontre in self.player.game.check_collision(self, self.player.game.all_monsters):
# Attribuer les dégats
monstre_rencontre.damage(self.damage)
#supprimer le projectile
self.remove()
# Vérifier si le projectie n'est plus présent sur l'écran
if self.rect.x > 1080:
# Supprimer le projectile
self.remove()
pygame.event.get()
获取所有消息并将它们从队列中删除。请参阅文档:
This will get all the messages and remove them from the queue. [...]
如果在多个事件循环中调用pygame.event.get()
,则只有一个循环接收事件,而不是所有循环都接收所有事件。因此,有些事件似乎被遗漏了。
每帧获取一次事件并在多个循环中使用它们或将事件列表传递给处理它们的函数和方法:
class Game:
# [...]
def update(self, screen, screenSize, eventList):
# [...]
for event in eventList:
# [...]
while running :
eventList = pg.event.get()
# [...]
if game.is_playing:
# Déclencher les instructions de la partie
game.update(screen, screenSize, eventList)
# [...]
for event in eventList:
# [...]