반응형

캐릭터에 이동에 관성을 적용해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
// Get the input direction and handle the movement/deceleration.
// As good practice, you should replace UI actions with custom gameplay actions.
Vector2 direction = Input.GetVector("ui_left""ui_right""ui_up""ui_down");
if (direction != Vector2.Zero)
{
    velocity.X = direction.X * Speed;
}
else
{
    velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed);
}
 

 

CharacterBody2D를 상속한 스크립트의 _PhysicsProcess()에는 위와 같은 키 입력 처리 코드가 있다.

 

1
2
3
4
5
6
7
8
9
10
11
// Get the input direction and handle the movement/deceleration.
// As good practice, you should replace UI actions with custom gameplay actions.
Vector2 direction = Input.GetVector("ui_left""ui_right""ui_up""ui_down");
if (direction != Vector2.Zero)
{
    velocity.X = direction.X * Speed;
}
else
{
    velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed * (float)delta);
}
 

 

위와 같이 수정한다.

 

방향키를 떼는 순간 한번에 정지하지 않고 관성이 적용된다.

 

하지만 위 코드는 빠르게 방향을 바꾸는 경우엔 관성이 적용되지 않는다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
// Get the input direction and handle the movement/deceleration.
// As good practice, you should replace UI actions with custom gameplay actions.
Vector2 direction = Input.GetVector("ui_left""ui_right""ui_up""ui_down");
if (direction != Vector2.Zero)
{
    //velocity.X = direction.X * Speed;
    velocity.X = Mathf.MoveToward(Velocity.X, direction.X * Speed, Speed * (float)delta);
}
else
{
    velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed * (float)delta);
}
 

 

위와 같이 수정한다.

좀 더 빠른(느린) 방향 전환이 필요하다면 MoveToward()의 Speed * (float)delta에 적당한 수치를 곱한다.

 

빠르게 방향을 바꾸어도 관성이 적용되어 슈퍼 마리오 같은 움직임을 보인다.

 

※ 참고

Using CharacterBody2D/3D

 

반응형
Posted by J-sean
:
반응형

움직이던 물체의 속도가 갑자기 0이 되는 것은 자연스럽지 못하다. 자연스럽게 천천히 멈추는 캐릭터를 만들어 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import pygame
 
pygame.init()
pygame.display.set_caption("Super fun game development")
screen = pygame.display.set_mode((640480))
clock = pygame.time.Clock()
running = True
 
player = pygame.image.load("player.png").convert()
player.set_colorkey(player.get_at((00)))
player_size = (player.get_width()*1.5, player.get_height()*1.5)
player = pygame.transform.scale(player, player_size)
player_pos = player.get_rect()
player_pos.center = (screen.get_width()/2, screen.get_height()/2)
player_speed = 4
player_direction = -1
 
left_released = False
right_released = False
slipcount = 0
slipduration = 60
# 캐릭터 미끄러지는 동작 관련 변수들.
 
while running:    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            running = False
 
        # 왼쪽, 오른쪽 방향키를 떼는 순간.
        if event.type == pygame.KEYUP and event.key == pygame.K_LEFT:
            left_released = True
            right_released = False
            slipcount = 0    
        elif event.type == pygame.KEYUP and event.key == pygame.K_RIGHT:
            right_released = True
            left_released = False
            slipcount = 0
        # 캐릭터의 미끄러지는 동작이 끝나기 전에 반대 방향 키를 누르는 경우에 대비.
 
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        if player_direction > 0:
            player = pygame.transform.flip(player, TrueFalse)
            player_direction = -1
        player_pos.move_ip(-player_speed, 0)
    if keys[pygame.K_RIGHT]:
        if player_direction < 0:
            player = pygame.transform.flip(player, TrueFalse)
            player_direction = 1            
        player_pos.move_ip(player_speed, 0)
    
    # 왼쪽으로 이동 중 키를 놓았을때 slipduration 프레임 동안 미끄러진다.
    if left_released == True:
        player_pos.move_ip(-pygame.math.lerp(player_speed, 0, (slipcount/slipduration)), 0)
        slipcount += 1
 
        # sliupduration이 지나면 초기화.
        if slipcount > slipduration:
            slipcount = 0
            left_released = False
    
    # 오른쪽으로 이동 중 키를 놓았을때 slipduration 프레임 동안 미끄러진다.
    if right_released == True:
        player_pos.move_ip(pygame.math.lerp(player_speed, 0, (slipcount/slipduration)), 0)
        slipcount += 1
 
        # sliupduration이 지나면 초기화.
        if slipcount > slipduration:
            slipcount = 0
            right_released = False
        
    screen.fill("black")
    screen.blit(player, player_pos)
    
    pygame.display.flip()
    clock.tick(60)
 
pygame.quit()
 

 

 

공룡이 바로 멈추지 않고 약간 더 움직인다.

 

이번엔 관성이 적용된 것처럼 천천히 출발하고 천천히 멈추는 캐릭터를 만들어 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import pygame
 
pygame.init()
pygame.display.set_caption("Super fun game development")
screen = pygame.display.set_mode((640480))
clock = pygame.time.Clock()
running = True
 
player = pygame.image.load("player.png").convert()
player.set_colorkey(player.get_at((00)))
player_size = (player.get_width()*1.5, player.get_height()*1.5)
player = pygame.transform.scale(player, player_size)
player_pos = player.get_rect()
player_pos.center = (screen.get_width()/2, screen.get_height()/2)
player_direction = -1
 
player_speed = 0
player_speed_step = 0.1
player_max_speed = 4
# 속도 관련 변수들.
 
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            running = False
 
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        if player_direction > 0:
            player = pygame.transform.flip(player, TrueFalse)
            player_direction = -1
        if (abs(player_speed) <= player_max_speed):
            player_speed -= player_speed_step
            if player_speed < -player_max_speed:
                player_speed = -player_max_speed
    # 왼쪽 방향키를 누르면 속도가 음의 방향으로 player_speed_step 씩 증가하다
    # player_max_speed 에서 멈춘다.
 
    if keys[pygame.K_RIGHT]:
        if player_direction < 0:
            player = pygame.transform.flip(player, TrueFalse)
            player_direction = 1
        if (abs(player_speed) <= player_max_speed):
            player_speed += player_speed_step
            if player_speed > player_max_speed:
                player_speed = player_max_speed
    # 오른쪽 방향키를 누르면 속도가 양의 방향으로 player_speed_step 씩 증가하다
    # player_max_speed 에서 멈춘다.
 
    # 왼쪽으로 가는 도중 오른쪽 방향키를 동시에 누른다고 오른쪽으로 가지는
    # 않지만 오른쪽을 바라본다. 하지만 오른쪽으로 가는 도중 왼쪽 방향키를
    # 동시에 눌러도 바라보는 방향이 바뀌지는 않는다. 이유는 왼쪽 방향키
    # 검사보다 오른쪽 방향키 검사(오른쪽으로 바라보게 하는)가 나중에 오기
    # 때문이다. 두 방향 중 나중에 검사하는 오른쪽 방향이 항상 적용되는 것이다.
 
    if not keys[pygame.K_LEFT] and not keys[pygame.K_RIGHT]:
        if player_speed > 0:
            player_speed -= player_speed_step
        elif player_speed < 0:
            player_speed += player_speed_step
    # 오른쪽이나 왼쪽 방향키를 누르고 있지 않으면 속도가 0에 가까워진다.
    
    if abs(player_speed) < 0.1:
        player_speed = 0
    # 속도의 절대값이 0.1보다 작으면 0으로 변경한다.
 
    player_pos.move_ip(player_speed, 0)
 
    screen.fill("black")
    screen.blit(player, player_pos)
    
    pygame.display.flip()
    clock.tick(60)
 
pygame.quit()
 

 

 

매 프레임마다 player_speed_step 만큼 속도가 증감된다.

 

반응형
Posted by J-sean
: