如何制作射击游戏中的hitmarker效果? - Pygame

问题描述

我想使用 pygame 制作类似射击游戏的命中标记效果

当您点击“resized_egg”时,hitmarker 会出现大约 0.2 秒。像这样:

I wanna make a hitmarker effect like this

我用 screen.blit() 尝试过,但我没有成功。

# [...]
egg = pygame.image.load("egg.png")
resized_egg = pygame.transform.scale(egg,(282,352))
pygame.image.load("hitmarker.png")
# [...]

while Loop: # main game loop
    for event in pygame.event.get():
        if event.type == QUIT:
            Loop = False


        if event.type == MOUSEBUTTONDOWN:
            if event.button == 1: # 1 == left click
                egg_rect = resized_egg.get_rect(topleft = (260,150))
                if egg_rect.collidepoint(event.pos):
                    # [...]
#[...]

解决方法

您应该使用 list(或 pygame.sprite.Group)来保持带有 current_time + 200 ms 的命中框

并且在每个循环中,如果需要将其从列表中删除,您应该检查列表中的每个命中框。

然后你应该从列表中绘制所有的命中框。


工作示例:

一开始我创建空列表

all_items = []

在循环中我得到

current_time = pygame.time.get_ticks()

当我单击鼠标按钮时,我使用 remove_at

将项目添加到此列表中
        x,y = event.pos

        item = {
            'rect': pygame.Rect(x-10,y-10,20,20),'remove_at': current_time + 500,# 500ms = 0.5s
        }

        all_items.append(item)

稍后我使用 for-loop 只保留具有 remove_at > current_time 的项目

    keep_items = []
    
    for item in all_items:
        if item['remove_at'] > current_time:
            keep_items.append(item)
        else:
            print('removed:',item)
            
    all_items = keep_items

然后我从这个列表中提取所有项目:

    for item in all_items:    
        pygame.draw.rect(screen,RED,item['rect'])

完整代码:

import pygame

# --- constants --- (UPPER_CASE_NAMES)

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600

FPS = 25 # for more than 220 it has no time to update screen

BLACK = (0,0)
WHITE = (255,255,255)
RED   = (255,0)

# --- functions --- (lower_case_names)

# --- main ---

pygame.init()

screen = pygame.display.set_mode( (SCREEN_WIDTH,SCREEN_HEIGHT) )

all_items = []

# --- mainloop ---

clock = pygame.time.Clock()

running = True
while running:

    current_time = pygame.time.get_ticks()
    
    # --- events ---

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

        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_ESCAPE:
                running = False
    
        elif event.type == pygame.MOUSEBUTTONDOWN:
            x,y = event.pos
            item = {
                'rect': pygame.Rect(x-10,# 500ms = 0.5s
            }
            all_items.append(item)
            print("add at:",x,y)
            
    # --- changes/moves/updates ---

    # filter objects
    
    keep_items = []
    
    for item in all_items:
        if item['remove_at'] > current_time:
            keep_items.append(item)
        else:
            print('removed:',item)
            
    all_items = keep_items
    
    # --- draws ---

    screen.fill(BLACK)

    for item in all_items:    
        pygame.draw.rect(screen,item['rect'])
    
    pygame.display.flip()

    # --- FPS ---

    ms = clock.tick(FPS)
    #pygame.display.set_caption('{}ms'.format(ms)) # 40ms for 25FPS,16ms for 60FPS
    fps = clock.get_fps()
    pygame.display.set_caption('FPS: {}'.format(fps))
    
# --- end ---

pygame.quit()