如何在pygame中平滑移动 [英] How to make smooth movement in pygame

查看:74
本文介绍了如何在pygame中平滑移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我和我的一个朋友刚刚开始在 repl.it 上学习使用 pygame 进行编程,这是我们的第一个真正的"游戏.我们想要制作一个像点击式冒险一样的老派项目.

然而,我们对角色的移动有一个问题,如果我们点击屏幕上的某个地方,角色就会传送".但我们希望它看起来尽可能平滑.

所以基本上,我们想要摆脱传送"取而代之的是从角色当前位置到鼠标位置的平滑逐帧过渡.

我们已经尝试减慢 while 循环的速度,以便我们可以在每次执行 while 循环时投射角色,但这只会使整个站点崩溃,我们还尝试在 repl.it 之外执行此操作以防万一是该网站的问题,但在那里也不起作用.

#PMC = 字符#mpos = 鼠标位置#mstate=鼠标按钮的状态(0表示没有按下任何东西,1表示鼠标#按钮被按下)#charspeed = 角色移动的速度 (=1px)``#---鼠标点击时PMC移动---------------#---x,y = mpos x2,y2 = characterpos如果 mstate == (1,0,0):#print('x: ', x, ' y: ', y, ' x2: ', x2, ' y2: ', y2) #debugging_positions而 x2 != x:如果x2>x:x2-=字符速度screen.blit(pmc, (x2-46, y2-184))如果x2<x:x2+=字符速度screen.blit(pmc, (x2-46, y2-184))而 y2 != y:如果y2>y:y2 -= 字符速度screen.blit(pmc, (x2-46, y2-184))如果y2<y:y2 += 字符速度screen.blit(pmc, (x2-46, y2-184))

解决方案

你有一个游戏循环,所以使用它.只需在每一帧中将角色移动某个位置即可.例如,每帧按 step 移动字符:

step = 1如果 x2 + 步长 <= x:x2 += 步elif x2 - 步 >= x:x2 -= 步别的:x2 = x如果 y2 + step <= y:y2 += 步elif y2 - 步 >= y:y2 -= 步骤别的:y2 = y


对于更复杂的解决方案,您必须计算

导入pygameLERP_FACTOR = 0.05最小距离 = 25最大距离 = 100def FollowMe(pops, fpos):target_vector = pygame.math.Vector2(*pops)follower_vector = pygame.math.Vector2(*fpos)new_follower_vector = pygame.math.Vector2(*fpos)距离 = follower_vector.distance_to(target_vector)如果距离>最小距离:direction_vector = (target_vector - follower_vector)/距离min_step = max(0, distance - maximum_distance)max_step = 距离 - minimum_distancestep_distance = min_step + (max_step - min_step) * LERP_FACTORnew_follower_vector = follower_vector + direction_vector * step_distance返回(new_follower_vector.x,new_follower_vector.y)pygame.init()窗口 = pygame.display.set_mode((500, 500))时钟 = pygame.time.Clock()追随者 = (100, 100)运行 = 真运行时:时钟滴答(60)对于 pygame.event.get() 中的事件:如果 event.type == pygame.QUIT:运行 = 错误玩家 = pygame.mouse.get_pos()追随者 = FollowMe(玩家,追随者)window.fill(0)pygame.draw.circle(window, (0, 0, 255), player, 10)pygame.draw.circle(window, (255, 0, 0), (round(follower[0]), round(follower[1])), 10)pygame.display.flip()

A friend of mine and me are just starting to learn to program with pygame on repl.it and for our first "real" project we want to make an old school like point'n'click adventure.

However, we have a problem with the movement of the character, if we click somewhere on the screen the character just "teleports" there but we want it to look as smooth as possible.

So basically, we want to get rid of the "teleporting" of the character and instead have a smooth frame-by-frame transition from the characters current position to the mouse position.

We've already tried to slow down the while loops so that we could project the character each time the while loop is executed but that just crashes the whole site, we also tried to do it outside of repl.it in case it was a problem with the website but it didn't work there either.

#PMC = Character
#mpos = the mouse position 
#mstate= the state of the mouse buttons (0 if nothing is pressed, 1 if a mouse 
#button is pressed) 
#charspeed = the speed at which the character moves (=1px)
  ```
#---PMC movement when mouse click-----------------------
    #---x,y = mpos   x2,y2 = characterpos
    if mstate == (1,0,0):
      #print('x: ', x, ' y: ', y, '   x2: ', x2, ' y2: ', y2) #debugging_positions

      
      while x2 != x:
        if x2>x:
          x2-=charspeed
          screen.blit(pmc, (x2-46, y2-184))
        if x2<x:
          x2+=charspeed
          screen.blit(pmc, (x2-46, y2-184))
          
      while y2 != y:
        if y2>y:
          y2 -= charspeed
          screen.blit(pmc, (x2-46, y2-184))
        if y2<y:
          y2 += charspeed
          screen.blit(pmc, (x2-46, y2-184))

解决方案

You have a game loop, so use it. Just move the character by a certain position in each frame. For instance mov the character by step per frame:

step = 1

if x2 + step <= x:
    x2 += step
elif x2 - step >= x:
    x2 -= step
else:
    x2 = x

if y2 + step <= y:
    y2 += step
elif y2 - step >= y:
    y2 -= step
else:
    y2 = y


For a more sophisticated solution, you've to compute the Euclidean distance form the point to the target. Use pygame.math.Vector2 for the computation.

Compute the distance from between the follower and the sprite and the unit direction vector from (follower_x, follower_y) to (mainsprite_x, mainsprite_y). The Unit Vector can be computed by dividing the direction vector by the distance or by normalizing (normalize()) the direction vector:

target_vector = Vector2(mainsprite_x, mainsprite_y)
follower_vector = Vector2(follower_x, follower_y)

distance = follower_vector.distance_to(target_vector)
direction_vector = target_vector - follower_vector
if distance > 0:
    direction_vector /= distance

Now you can define an exact step_distance and move to follower int direction of the sprite:

if distance > 0:
    new_follower_vector = follower_vector + direction_vector * step_distance.

Define a maximum_distance and a minimum_distance. The minimum step distance is:

min_step = max(0, distance - maximum_distance)

The maximum step distance is

max_step = distance - minimum_distance

Put it all together:

minimum_distance    = 0
maximum_distance    = 10000
target_vector       = Vector2(mainsprite_x, mainsprite_y)
follower_vector     = Vector2(follower_x, follower_y)
new_follower_vector = Vector2(follower_x, follower_y)

distance = follower_vector.distance_to(target_vector)
if distance > minimum_distance:
    direction_vector    = (target_vector - follower_vector) / distance
    min_step            = max(0, distance - maximum_distance)
    max_step            = distance - minimum_distance
    step_distance       = min_step + (max_step - min_step) * LERP_FACTOR
    new_follower_vector = follower_vector + direction_vector * step_distance


Minimal example:

import pygame

LERP_FACTOR      = 0.05
minimum_distance = 25
maximum_distance = 100

def FollowMe(pops, fpos):
    target_vector       = pygame.math.Vector2(*pops)
    follower_vector     = pygame.math.Vector2(*fpos)
    new_follower_vector = pygame.math.Vector2(*fpos)

    distance = follower_vector.distance_to(target_vector)
    if distance > minimum_distance:
        direction_vector    = (target_vector - follower_vector) / distance
        min_step            = max(0, distance - maximum_distance)
        max_step            = distance - minimum_distance
        step_distance       = min_step + (max_step - min_step) * LERP_FACTOR
        new_follower_vector = follower_vector + direction_vector * step_distance

    return (new_follower_vector.x, new_follower_vector.y) 

pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()

follower = (100, 100)
run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    player   = pygame.mouse.get_pos()
    follower = FollowMe(player, follower)

    window.fill(0)  
    pygame.draw.circle(window, (0, 0, 255), player, 10)
    pygame.draw.circle(window, (255, 0, 0), (round(follower[0]), round(follower[1])), 10)
    pygame.display.flip()

这篇关于如何在pygame中平滑移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆