我正在使用 Pygame 在 Python 中开发一个简单的格斗游戏输入缓冲区,并且我试图让它尽可能接近实际格斗游戏的工作方式。我在尝试添加对对角线输入的支持时遇到了问题。我有输入缓冲区的工作版本,并且我正在寻找有关如何将对角线输入集成到现有代码中的指导。这是到目前为止该程序的代码:
https://paste.pythondiscord.com/WWFQ
如您所见,我尝试将四个对角线同时映射到两个键,例如 wa、sd 等,但这不起作用,因为输入没有显示在缓冲区中,或者它只是在一个键之间进行选择基本方向和其他方向。任何帮助或建议将不胜感激
我尝试使用集合来检查组合键,如下所示:
elif event.type == pygame.KEYDOWN:
key = pygame.key.name(event.key)
if key in ['w', 'a', 's', 'd']:
buffer.append(key)
elif 'w' in buffer and 'a' in buffer: # W + A (diagonal)
buffer.append('wa')
elif 'w' in buffer and 'd' in buffer: # W + D (diagonal)
buffer.append('wd')
elif 's' in buffer and 'a' in buffer: # S + A (diagonal)
buffer.append('sa')
elif 's' in buffer and 'd' in buffer: # S + D (diagonal)
buffer.append('sd')
但是对角线的图像不会显示在屏幕上。例如,如果我按下后退 (S+A),缓冲区只会显示彼此相邻的向上输入和后退输入,而不是向下后退的图像。
缓冲区检查需要在
KEYDOWN
事件处理程序之外进行。合理的地方是在缓冲区间隙检查中添加 else
条件。
类似:
# Check if it's time to clear the buffer
current_time = pygame.time.get_ticks()
if current_time - last_input_time >= buffer_store_time * 1000:
buffer.clear()
special_move_executed = {move["name"]: False for move in special_moves}
else: # check the buffer for diagonals
if 'w' in buffer and 'a' in buffer: # W + A (diagonal)
buffer.remove('w')
buffer.remove('a')
buffer.append('wa')
您没有将
i
、j
和 k
键添加到缓冲区,因此您需要添加这些键才能使特殊移动检测起作用。另请注意,您的某些特殊动作无法被检测到,例如,火焰拳需要down
+ right
+ light attack
,但在检测到down forward
和down
时,缓冲区处理将替换
right
。因此,我认为您需要对缓冲区进行两次检查,一次用于对角线替换,仅检查最后一个缓冲的键,另一次用于较长时间的不活动以清除缓冲区。
这是完整的代码清单,我用系统字体中包含的字母或箭头替换了您的图像。
import pygame
import sys
# Initialize Pygame
pygame.init()
# Set up display
screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Fighting Game Input Buffer")
# Set up fonts
# font = pygame.font.Font(None, 36) # this doesn't include arrows
# grab the first installed font
font = pygame.font.SysFont(pygame.font.get_fonts()[0], 36)
# Load Input Images
if False:
#Cardinal Directions
up_image = pygame.image.load("up.png")
down_image = pygame.image.load("down.png")
left_image = pygame.image.load("left.png")
right_image = pygame.image.load("right.png")
#Diagonal Directions
upback_image = pygame.image.load("upback.png")
upforward_image = pygame.image.load("upforward.png")
downback_image = pygame.image.load("downback.png")
downforward_image = pygame.image.load("downforward.png")
#Attack Buttons
light_image = pygame.image.load("L.png")
medium_image = pygame.image.load("M.png")
heavy_image = pygame.image.load("H.png")
special_image = pygame.image.load("S.png")
else: # render fonts
color = pygame.Color("turquoise")
#Cardinal Directions
up_image = font.render("↑", True, color)
down_image = font.render("↓", True, color)
left_image = font.render("←", True, color)
right_image = font.render("→", True, color)
#Diagonal Directions -
upback_image = pygame.transform.rotate(up_image, 45) # ↖ isn't in the font.
upforward_image = pygame.transform.rotate(up_image, -45)
downback_image = pygame.transform.rotate(down_image, -45)
downforward_image = pygame.transform.rotate(down_image, 45)
#Attack Buttons
attack_color = pygame.Color("firebrick")
light_image = font.render("L", True, attack_color)
medium_image = font.render("M", True, attack_color)
heavy_image = font.render("H", True, attack_color)
special_image = font.render("S", True, attack_color)
# Dictionary to Map Keys to Images
key_to_image = {
'w': up_image,
'a': left_image,
's': down_image,
'd': right_image,
'u': light_image,
'i': medium_image,
'j': heavy_image,
'k': special_image,
'wa': upback_image, # W + A (diagonal)
'wd': upforward_image, # W + D (diagonal)
'sa': downback_image, # S + A (diagonal)
'sd': downforward_image,# S + D (diagonal)
}
# Input buffer parameters
buffer = []
buffer_store_time = 0.4 # in seconds
max_buffer_size = 10
last_input_time = pygame.time.get_ticks()
# List of special moves
special_moves = [
{"name": "Flame Punch", "sequence": ['s', 'd', 'u']},
{"name": "Tornado Kick", "sequence": ['s', 'a', 'u']},
{"name": "Rising Uppercut", "sequence": ['d', 's', 'd', 'k']},
{"name": "Surging Heat", "sequence": ['s', 's', 'k']}
# Add more special moves here
]
# Flags to track if special moves are executed
special_move_executed = {move["name"]: False for move in special_moves}
# Main game loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
# Add the key to the buffer
key = pygame.key.name(event.key)
# if key in ['w', 'a', 's', 'd']:
if key in ['w', 'a', 's', 'd', 'i', 'j', 'k']:
buffer.append(key)
# Check if the buffer is full and replace the oldest input
if len(buffer) > max_buffer_size:
buffer.pop(0)
# Update the last input time
last_input_time = pygame.time.get_ticks()
# Check if it's time to clear the buffer
current_time = pygame.time.get_ticks()
if current_time - last_input_time >= buffer_store_time * 1000:
buffer.clear()
special_move_executed = {move["name"]: False for move in special_moves}
else: # check the buffer for diagonals
if 'w' in buffer and 'a' in buffer: # W + A (diagonal)
buffer.remove('w')
buffer.remove('a')
buffer.append('wa')
if 'w' in buffer and 'd' in buffer: # W + D (diagonal)
buffer.remove('w')
buffer.remove('d')
buffer.append('wd')
if 's' in buffer and 'a' in buffer: # S + A (diagonal)
buffer.remove('s')
buffer.remove('a')
buffer.append('sa')
if 's' in buffer and 'd' in buffer: # S + D (diagonal)
buffer.remove('s')
buffer.remove('d')
buffer.append('sd')
# Check for special moves
for move in special_moves:
if buffer[-len(move["sequence"]):] == move["sequence"]:
special_move_executed[move["name"]] = True
# Draw the buffer and special move messages on the screen
screen.fill("white")
# Render the images for each key in the buffer
x_position = 20
for key in buffer:
if key in key_to_image:
key_image = key_to_image[key]
screen.blit(key_image, (x_position, 20))
x_position += key_image.get_width() + 5 # Adjust the spacing
y_position = 60
for move in special_moves:
if special_move_executed[move["name"]]:
special_move_text = font.render(move["name"] + " Executed!", True, "red")
screen.blit(special_move_text, (20, y_position))
y_position += 40
pygame.display.flip()