簡體   English   中英

單擊pygame后如何平滑移動圖像?

[英]How do I move an image smoothly after clicking in pygame?

我決定在 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);

但無濟於事。

我看過這些問題:


pygame 中的平滑運動

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

我可以發現其中的幾個。 首先,函數和類定義應該在主循環之外,因為在循環中一遍又一遍地定義相同的東西沒有任何意義。 其次,您調用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參數但未使用它。

添加到@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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM