반응형

다른 스크립트에 선언된 변수에 접근해 보자.

 

첫 번째 캐릭터를 생성하고 스크립트를 추가한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using Godot;
 
public partial class Character1 : Sprite2D
{
    public int a = 10;
 
    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
    }
 
    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(double delta)
    {
    }
}
 

 

 

두 번째 캐릭터를 생성하고 스크립트를 추가한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using Godot;
 
public partial class Character2 : Sprite2D
{
    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
        GD.Print(GetNode<Character1>("../../Character_1/Sprite2D").a);
    }
 
    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(double delta)
    {
    }
}
 

 

 

두 캐릭터를 자식 노드로 갖는 씬을 생성한다. 두 캐릭터는 부모 자식 관계가 아닌 형제 관계로 설정한다.

 

게임을 실행하면 Output 창에 Character1의 멤버 변수 a가 출력된다.

 

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

2D 환경에서 엠비언트 라이트를 조절해 보자.

 

2D 환경을 준비하고 스프라이트를 배치한다.

 

CanvasModulate 노드를 추가한다.

 

Inspector - Color 속성을 클릭하고 원하는 색상을 선택한다.

 

CanvasModulate 노드는 지정한 색상으로 씬을 어둡게 한다.

 

이번엔 DirectionalLight2D 노드를 추가한다. 기본적으로 태양처럼 동작하기 때문에 스프라이트에 흰색이 추가돼 밝아진다.

 

반대로 동작시키기 위해 Blend Mode 속성을 Subtract로 바꾸고 Color 속성을 녹색으로 바꾸면 스프라이트에서 녹색이 제외된다.

 

※ 참고

2D lights and shadows

 

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

마우스 커서를 보이지 않게 하자.

 

1
2
3
4
public override void _Ready()
{
    Input.MouseMode = Input.MouseModeEnum.ConfinedHidden;
}
 

 

 

Input.MouseModeEnum.Hidden을 사용하면 마우스 커서가 게임 화면 안에 있을때만 보이지 않는다.

게임 화면 밖으로 나가면 보이기 때문에 전체 화면으로 게임을 실행해도 화면 끝에서 보일 수 있다.

 

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

보글보글 같은 플랫폼 게임에서 볼 수 있는 캐릭터와 플랫폼의 한 쪽 방향 충돌 체크를 구현해 보자.

 

화면과 같이 Sprite2D, StaticBody2D, CollisionShape2D를 이용해 배경과 바닥을 구성한다.

 

gound.jpg
0.20MB

 

화면과 같이 Sprite2D, StaticBody2D, CollisionShape2D를 이용해 플랫폼을 구성한다.

CollisionShape2D - One Way Collision 속성을 체크한다.

필요하다면 Sprite2D - Transform - Scale을 조절한다.

 

Platform.png
0.01MB

 

화면과 같이 CharacterBody2D, Sprite2D, CollisionShape2D를 이용해 플레이어를 구성한다.

플레이어는 스크립트를 추가한다.

 

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
using Godot;
 
public partial class Player : CharacterBody2D
{
    public const float Speed = 300.0f;
    public const float JumpVelocity = -600.0f;
    // 플랫폼에 올라갈 수 있을 정도의 점프
 
    // Get the gravity from the project settings to be synced with RigidBody nodes.
    public float gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
 
    public override void _PhysicsProcess(double delta)
    {
        Vector2 velocity = Velocity;
 
        // Add the gravity.
        if (!IsOnFloor())
            velocity.Y += gravity * (float)delta;
 
        // Handle Jump.
        if (Input.IsActionJustPressed("ui_accept"&& IsOnFloor())
            velocity.Y = JumpVelocity;
 
        // 플랫폼에서 내려오기
        if (Input.IsActionJustPressed("ui_down"&& IsOnFloor())
            Position += new Vector2(01);
 
        // 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");
        // direction 벡터는 키 입력이 반영되어 길이가 1인 normalized vector 값이 설정된다.
        // 예를들어 오른쪽 방향키가 눌렸다면 (1, 0), 아래 방향키가 눌렸다면 (0, 1),
        // 왼쪽+위 방향키가 눌렸다면 (-0.707, -0.707)이 설정된다.
        if (direction != Vector2.Zero)
        {
            velocity.X = direction.X * Speed;
        }
        else
        {
            velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed);
        }
 
        Velocity = velocity;
        MoveAndSlide();
    }
}
 

 

 

플레이어 스크립트를 위와 같이 작성한다.

 

그라운드, 플랫폼, 플레이어로 메인 씬을 구성한다.

 

게임을 실행하고 플랫폼에서 동작을 테스트 한다.

 

※ 참고

Using CharacterBody2d/3D

CharacterBody2D

 

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

트윈을 사용해 캐릭터를 이동해 보자.

 

씬에 스프라이트를 생성하고 스크립트를 추가한다.

 

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
using Godot;
 
public partial class control : Sprite2D
{
    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
    }
 
    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(double delta)
    {
        // IsMouseButtonPressed()는 짧게 한 번 클릭해도 여러번 True를 반환 할 수 있다.
        // 정확히 한 번만 호출되어야 한다면 Input.IsActionJustPressed()를 사용하자.
        if (Input.IsMouseButtonPressed(MouseButton.Left))
        {
            Tween tween = CreateTween().SetParallel(true);
            // SetParallel(true) 다음에 추가되는 트위너들은 모두 동시에 실행된다.
                        
            tween.TweenProperty(this"rotation_degrees"903.0f).AsRelative();
            // 클릭 한 번에 IsMouseButtonPressed()가 여러번 true를 반환하기 때문에
            // 90도 이상 회전하는 것처럼 보일 수 있다.
            // Asrelative()가 없다면 월드 좌표계 90도로 회전하고 더 이상 회전하지 않는다.
 
            tween.TweenProperty(this"position", GetGlobalMousePosition(),
                3.0f).SetTrans(Tween.TransitionType.Elastic).SetEase(Tween.EaseType.Out);
            // Godot Object 인수로 this 대신 GetNode("/root/Sprite2D") 또는
            // GetNode("../Sprite2D")를 넣을 수 있다.
 
            //tween.TweenCallback(Callable.From(()=>GD.Print("Finished."))).SetDelay(1.0f);
            tween.TweenCallback(Callable.From(Lastcall)).SetDelay(3.0f);
            // 임의의 함수(Lastcall)를 호출한다. SetDelay()로 트위너의 동작이 모두 끝난 후
            // 호출되도록 할 수 있다.
        }
    }
 
    public void Lastcall()
    {
        GD.Print("Finished.");
    }
}
 

 

 

Tween을 사용해 이동하는 코드를 작성한다.

 

 

 

※ 참고

Tween

 

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

캐릭터의 더블 점프를 구현해 보자.

 

CharacterBody2D 노드를 이용해 캐릭터를 만든다.

 

● CharacterBody2D - control.cs 스크립트를 추가

● Sprite2D - Texture 지정

● CollsionShape2D - Shape 속성 설정

 

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
using Godot;
 
public partial class control : CharacterBody2D
{
    public const float Speed = 300.0f;
    public const float JumpVelocity = -400.0f;
 
    // Get the gravity from the project settings to be synced with RigidBody nodes.
    public float gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
 
    private bool isFirstJump = false;
 
    public override void _PhysicsProcess(double delta)
    {
        Vector2 velocity = Velocity;
 
        // Add the gravity.
        if (!IsOnFloor())
            velocity.Y += gravity * (float)delta;
 
        // Handle First Jump.
        if (Input.IsActionJustPressed("ui_accept"&& IsOnFloor())
        {
            velocity.Y = JumpVelocity;
            isFirstJump = true;
        }
        // Handle Second Jump.
        else if (Input.IsActionJustPressed("ui_accept"&& isFirstJump == true)
        {
            velocity.Y = JumpVelocity;
            isFirstJump = false;
        }
 
        // 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);
        }
 
        Velocity = velocity;
        MoveAndSlide();
    }
}
 

 

 

더블 점프 구현을 위한 control.cs 스크립트는 위와 같이 작성한다.

 

Node2D 노드를 이용해 Ground 를 만든다.

 

● StaticBody2D

● Sprite2D - Texture 지정(ground.jpg)

● CollisionShape2D - Shape 속성을 Sprite2D 땅 부분에 맞게 설정

 

gound.jpg
0.20MB

 

Node 노드를 이용해 전체 게임을 구성한다.

 

위에서 만든 캐릭터와 그라운드를 Node 노드의 자식노드로 추가한다. (Instantiate Child Scene)

 

 

배경 이외의 부분이 보이지 않도록 윈도우 사이즈를 적당히 조절한다.

 

게임을 실행하고 이중 점프를 테스트 한다.

 

※ 참고

Using CharacterBody2D/3D

CharacterBody2D

2D movement overview

 

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

키보드와 마우스 입력을 간단히 확인해 보자.

 

노드에 스크립트를 추가한다.

 

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
using Godot;
 
public partial class Main : Node
{
    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
    }
 
    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(double delta)
    {
        if(Input.IsMouseButtonPressed(MouseButton.Left))
        {
            GD.Print($"Mouse Left Button: {GetViewport().GetMousePosition()}");
        }
        if(Input.IsMouseButtonPressed(MouseButton.Right))
        {
            GD.Print($"Mouse Right Button: {GetViewport().GetMousePosition()}");
        }
        if(Input.IsKeyPressed(Key.Escape))
        {
            GD.Print("Escape Key");
            //GetTree().Quit();
        }
    }
}
 

 

 

마우스와 키보드 입력을 감지하는 코드를 작성한다. IsMouseButtonPressed()와 IsKeyPressed()는 버튼이나 키가 눌려있는 동안 계속해서 true를 반환한다. 눌리거나 떼는 순간만 반응하고 싶다면 아래 함수를 사용한다.

Input.IsActionJustPressed()
Input.IsActionJustReleased()

 

버튼이나 키가 눌리면 Output창에 표시된다.

 

1
2
3
4
5
6
7
8
9
10
using Godot;
 
public partial class Script : Node2D
{
    public override void _Input(InputEvent @event)
    {
        if (@event.IsActionPressed("ui_accept"))
            GD.Print(@event.AsText());
    }
}
 

 

_Input()와 InputEvent를 사용하는 코드를 작성한다. InputEvent.IsActionPressed()는 눌리는 순간 한 번만 반응한다.

 

Input Map에 등록된 목록을 사용할 수 있다.

 

ui_accept로 등록된 Enter키나 Space키가 눌리면 AsText()에 의해 키 이름(Enter/Space)이 출력된다.

 

 

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
using Godot;
 
public partial class Script : Node2D
{
    public override void _Input(InputEvent @event)
    {
        if (@event is InputEventMouseButton mouseEvent && mouseEvent.Pressed)
        {
            switch (mouseEvent.ButtonIndex)
            {
                case MouseButton.Left:
                    GD.Print(@event.AsText() + " at: " + mouseEvent.Position);
                    break;
                case MouseButton.Right:
                    GD.Print(@event.AsText() + " at: " + GetViewport().GetMousePosition());
                    // mouseEvent.position과 GetViewport().GetMousePosition()는 같은
                    // 결과를 출력한다.
                    break;
                case MouseButton.WheelUp:
                    GD.Print(@event.AsText());
                    break;
            }
        }
    }
}
 

 

이번엔 버튼 동작을 구분하는 코드를 입력한다.

 

버튼 동작과 위치가 표시된다.

 

※ 참고

Input Handling

 

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

추가한 캐릭터를 삭제해 보자.

 

Sprite2D 노드를 추가하고 이름을 Character로 바꾼다. Texture 속성에 이미지를 넣고 스크립트를 추가한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using Godot;
 
public partial class Character : Sprite2D
{
    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
    }
 
    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override async void _Process(double delta)
    {
        await ToSignal(GetTree().CreateTimer(1.0), SceneTreeTimer.SignalName.Timeout);
        QueueFree();
    }
}
 

 

 

1초 대기 후 큐에서 삭제하는 스크립트를 작성한다.

 

새로운 씬을 만들고 Node 노드를 생성해서 Main으로 이름을 바꾸고 스크립트를 추가한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using Godot;
 
public partial class Main : Node
{
    [Export]
    public PackedScene CharacterScene { get; set; }
 
    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
    }
 
    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(double delta)
    {
        if (Input.IsActionJustPressed("lclick"))
        {
            Character character = CharacterScene.Instantiate<Character>();
            character.Position = GetViewport().GetMousePosition();
 
            AddChild(character);
        }
    }
}
 

 

 

왼쪽 마우스 버튼을 클릭하면 캐릭터를 생성하는 스크립트를 작성한다.

 

 

Project Settings - Input Map 에 마우스 클릭 액션을 추가한다.

 

Main 씬에서 Build 버튼을 클릭한다. Inspector에 CharacterScene 속성이 생기면 Character.tscn을 추가한다.

 

Main 씬을 실행하고 왼쪽 버튼을 클릭하면 스프라이트가 표시되고 1초 후 사라진다.

 

이번엔 특정 액션(마우스 오른쪽 버튼 클릭) 발생시 모든 캐릭터를 한번에 삭제해 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using Godot;
 
public partial class Character : Sprite2D
{
    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
    }
 
    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override async void _Process(double delta)
    {
        //await ToSignal(GetTree().CreateTimer(1.0), SceneTreeTimer.SignalName.Timeout);
        //QueueFree();
    }
}
 

 

 

캐릭터 클래스에서 1초 대기 후 큐에서 삭제하는 코드를 삭제한다.

 

 

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
using Godot;
 
public partial class Main : Node
{
    [Export]
    public PackedScene CharacterScene { get; set; }
 
    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
    }
 
    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(double delta)
    {
        if (Input.IsActionJustPressed("lclick"))
        {
            Character character = CharacterScene.Instantiate<Character>();
            character.Position = GetViewport().GetMousePosition();
 
            AddChild(character);
        }
        if (Input.IsActionJustPressed("rclick"))
        {
            GetTree().CallGroup("chargroup", Node.MethodName.QueueFree);
        }
    }
}
 

 

 

메인 클래스에서 마우스 우클릭시 "chargroup"에 속한 노드의 QueueFree()를 호출하는 코드를 작성한다.

 

Character씬에서 Node 탭 - Group 탭에서 chargroup을 추가한다.

 

Godot의 group은 다른 게임엔진의 tag와 같은 역할을 한다.

 

마우스 왼쪽 버튼을 클릭하면 스프라이트가 생성되고 오른쪽 버튼을 클릭하면 모두 사라진다.

 

※ 참고

Node - void QueueFree()

Groups

 

반응형
Posted by J-sean
: