【问题标题】:How do I move an image smoothly after clicking in pygame?在pygame中点击后如何平滑移动图像?
【发布时间】:2020-09-24 02:09:01
【问题描述】:

我决定用 pygame 来制作我的游戏,这是我目前编写的代码:

from typing import Tuple
import pygame
from PIL import ImageGrab

# finding the height of the screen by taking a screenshot.
img = ImageGrab.grab()
(WIDTH, HEIGHT) = (img.size)

x = WIDTH / 2 - 470
y = HEIGHT / 2 - 400

fistx1 = x - 80
fistx2 = fistx1;

fisty1 = y + 40

fisty2 = y - 50
pygame.init()

clock = pygame.time.Clock()

RESOLUTION = (WIDTH, HEIGHT)

BACKGROUND_COLOR: Tuple[int, int, int] = (79, 205, 109)

MOVESPEED = 5

# window stuff
window = pygame.display.set_mode(RESOLUTION, flags=pygame.RESIZABLE, depth=32)
pygame.display.set_caption("The Connection")
window.fill(BACKGROUND_COLOR)

running = True

# all images for the game here
player_image = pygame.image.load("Connector.png")
player_fist1_image = pygame.image.load("Connector_hand.png")
player_fist2_image = player_fist1_image

while running:
    pressed = pygame.key.get_pressed()
    clicked = pygame.mouse.get_pressed();
    class Player():
        def __init__(self, hp, image, fist1image, fist2image):
            global fisty1, fistx1, fisty2
            self.hp = hp
            self.image = image
            self.fist1image = fist1image
            self.fist2image = fist2image

            window.blit(self.image, (x, y))
            window.blit(self.fist1image, (fistx1, fisty1))
            window.blit(self.fist2image, (fistx2, fisty2))

        def move(self, movespeed):
            global x, y, fistx1, fisty1, fisty2
            if pressed[pygame.K_a]:
                x -= movespeed
                fistx1 -= movespeed
            elif pressed[pygame.K_d]:
                x += movespeed
                fistx1 += movespeed
            elif pressed[pygame.K_w]:
                y -= movespeed
                fisty1 -= movespeed
                fisty2 -= movespeed
            elif pressed[pygame.K_s]:
                y += movespeed
                fisty1 += movespeed
                fisty2 += movespeed

        def deal_damage(self, damage):
            global x, y, fistx1, fisty1
            fistx1 -= 25
            window.fill(BACKGROUND_COLOR);
            window.blit(self.fist1image, (fistx1, fisty1));
            pygame.display.flip();

    # this is the function we use to actually call it. This is more helpful and less confusing for an idiot like me
    def actual_deal():
        main_player.deal_damage(25);


    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            try:
                pygame.quit()
            except pygame.error:
                pass
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                actual_deal();

    window.fill(BACKGROUND_COLOR)

    main_player = Player(100, player_image, fist1image=player_fist1_image, fist2image=player_fist2_image)
    main_player.move(movespeed=MOVESPEED)

    pygame.display.flip()
    clock.tick(60);

就上下文而言,拳头必须先向前再向后。但是,拳头移动不顺畅,有两个问题:

  1. 看起来不太好。我想向其他人展示这个,所以我希望它看起来不错。

  2. 当我收回拳头时,看起来它们一开始并没有向前移动。我必须在两者之间添加time.sleep,但我不愿意这样做。

这是我出拳时得到的输出: 放置在扰流板中,以免打扰

如您所见,它以块状方式移动。如果你想看到我想要的输出,然后用 WASD 键移动角色,看看角色移动的流畅程度。我想要同样的拳头。

如果重要的话,我正在使用 pycharm 来编写代码,并从命令提示符运行它。我也有 Windows 10。

最后,我尝试通过这样做来改变帧率:

以下是我已经看过的问题:

clock.tick(360);

但无济于事。

我看过这些问题:


smooth movement in pygame

https://gamedev.stackexchange.com/questions/48227/smooth-movement-pygame

【问题讨论】:

    标签: python python-3.x pygame frame-rate


    【解决方案1】:

    我可以发现其中的几个。首先,函数和类定义应该在主循环之外,因为在循环中一遍又一遍地定义相同的东西没有任何意义。其次,您调用pygame.display.flip 两次,这是不需要的。 Flip 应该只调用一次,否则会导致闪烁。第三,您正在绘制__init__ 方法并每帧创建一个新实例。通常,一个实例只创建一次,并且该实例的一些方法可以对该实例执行某些操作。因此,不要在__init__ 中绘图,而是创建一个名为draw 的新方法。

    现在回答你的问题,因为:

    1. 您一次将其移动 25 帧,因此它一次跳过 25 个像素并在新位置再次绘制。
    2. 您正在使用pygame.MOUSEBUTTONDOWN。此函数每次点击仅返回一次 true。因此,如果您按住鼠标按钮,它将不起作用,因为它在第一帧返回True,之后返回None。要不断更新鼠标状态,需要使用pygame.mouse.get_pressed()

    实现了我上面提到的所有内容的新代码(注意:我将图像更改为表面以使其工作,因此您可能想再次将其更改为图像):

    from typing import Tuple
    import pygame
    from PIL import ImageGrab
    
    # finding the height of the screen by taking a screenshot.
    img = ImageGrab.grab()
    (WIDTH, HEIGHT) = (img.size)
    
    x = WIDTH / 2 - 470
    y = HEIGHT / 2 - 400
    
    fistx1 = x - 80
    fistx2 = fistx1;
    
    fisty1 = y + 40
    
    fisty2 = y - 50
    pygame.init()
    
    clock = pygame.time.Clock()
    
    RESOLUTION = (WIDTH, HEIGHT)
    
    BACKGROUND_COLOR: Tuple[int, int, int] = (79, 205, 109)
    
    MOVESPEED = 5
    
    # window stuff
    window = pygame.display.set_mode(RESOLUTION, flags=pygame.RESIZABLE, depth=32)
    pygame.display.set_caption("The Connection")
    window.fill(BACKGROUND_COLOR)
    
    running = True
    
    # all images for the game here
    player_image = pygame.Surface((50, 50)).convert()
    player_fist1_image = pygame.Surface((10, 10)).convert()
    player_fist2_image = player_fist1_image
    
    class Player():
        def __init__(self, hp, image, fist1image, fist2image):
            global fisty1, fistx1, fisty2
            self.hp = hp
            self.image = image
            self.fist1image = fist1image
            self.fist2image = fist2image
    
        def move(self, movespeed):
            global x, y, fistx1, fisty1, fisty2
            if pressed[pygame.K_a]:
                x -= movespeed
                fistx1 -= movespeed
            elif pressed[pygame.K_d]:
                x += movespeed
                fistx1 += movespeed
            elif pressed[pygame.K_w]:
                y -= movespeed
                fisty1 -= movespeed
                fisty2 -= movespeed
            elif pressed[pygame.K_s]:
                y += movespeed
                fisty1 += movespeed
                fisty2 += movespeed
    
        def draw(self):
            window.blit(self.image, (x, y))
            window.blit(self.fist1image, (fistx1, fisty1))
            window.blit(self.fist2image, (fistx2, fisty2))
    
        def deal_damage(self, damage):
            global x, y, fistx1, fisty1
            mousePressed = pygame.mouse.get_pressed()
            if mousePressed[0]:
                fistx1 -= 1
            window.fill(BACKGROUND_COLOR);
            window.blit(self.fist1image, (fistx1, fisty1));
            #pygame.display.flip();
    
    main_player = Player(100, player_image, fist1image=player_fist1_image, fist2image=player_fist2_image)
    
    # this is the function we use to actually call it. This is more helpful and less confusing for an idiot like me
    def actual_deal():
        main_player.deal_damage(25);
    
    while running:
        pressed = pygame.key.get_pressed()
        clicked = pygame.mouse.get_pressed();
    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
                try:
                    pygame.quit()
                except pygame.error:
                    pass
    
        window.fill(BACKGROUND_COLOR)
        main_player.move(movespeed=MOVESPEED)
        main_player.deal_damage(50)
        main_player.draw()
    
        pygame.display.flip()
        clock.tick(60);
    

    编辑:忘了提及这一点,但您在 deal_damage 方法中采用了 damage 参数但没有使用它。

    【讨论】:

    • 但是有一个问题:我怎样才能使当我单击鼠标按钮时,例如一毫秒,第一个对象移动相同的距离?我不希望它在我按住鼠标按钮时离开,如果你明白我想说的话。
    • 第一个对象是哪个。它移动的距离与?
    • 如果您不想让它继续移动,那么您可以使用 pygame.MOUSEBUTTONDOWN 但这会破坏答案的目的。
    • 我其实已经想通了。我只是在单击时让它移动了很远,然后当您释放鼠标按钮时,它以相同的方式将其拉回来。
    【解决方案2】:

    添加到@hippozhipos 答案。使用class 的一大好处是您不需要使用global 变量。您只需将它们设置为属性。

    您还试图在游戏循环中退出。 如果runningFalse,它将退出您的游戏循环并自行退出。

    也不需要在循环之外填充,因为它每帧都会填充。

    我提供了一个最小的工作示例来说明如何实现这一点。

    import pygame
    from PIL import ImageGrab
    
    class Player():
        def __init__(self, img, x, y, window):
            self.fist = img
            self.pos = (x - 80, y + 40)
            self.win = window
    
        def move(self, movespeed, pressed):
            # here we maintain the players position with self.pos
            # this allows you to have multiple instances
            # with different positions
            x, y = self.pos
            if pressed[pygame.K_a]:
                x -= movespeed
            elif pressed[pygame.K_d]:
                x += movespeed
            elif pressed[pygame.K_w]:
                y -= movespeed
            elif pressed[pygame.K_s]:
                y += movespeed
    
            self.pos = (x, y)
        
        def display(self):
            self.win.blit(self.fist, self.pos)
    
    pygame.init()
    screenshot = ImageGrab.grab()
    WIDTH, HEIGHT = screenshot.size
    RESOLUTION = (WIDTH, HEIGHT)
    BACKGROUND_COLOR = (79, 205, 109)
    MOVESPEED = 5
    
    window = pygame.display.set_mode(RESOLUTION, flags=pygame.RESIZABLE, depth=32)
    pygame.display.set_caption("The Connection")
    
    clock = pygame.time.Clock()
    # this is whatever your image is
    img = pygame.image.load('fist.png')
    x = int(WIDTH / 2 - 470)
    y = int(HEIGHT / 2 - 400)
    main_player = Player(img=img, x=x, y=y, window=window)
    
    running = True
    while running:
        pressed = pygame.key.get_pressed()
    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
    
        main_player.move(movespeed=MOVESPEED, pressed=pressed)
    
        window.fill(BACKGROUND_COLOR)
        main_player.display()
    
        pygame.display.flip()
        clock.tick(60)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-14
      • 2013-11-10
      • 1970-01-01
      • 2020-11-21
      • 2021-01-13
      • 2021-04-06
      • 1970-01-01
      相关资源
      最近更新 更多