[Godot] RayCast2D C# Example

Godot 2023. 9. 27. 17:45 |
반응형

RayCast2D C# 예제.

 

씬을 준비하고 RayCast2D와 스크립트를 추가한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public override void _Draw()
    {
        DrawLine(GetNode<RayCast2D>("RayCast2D").Position,
            GetNode<RayCast2D>("RayCast2D").Position +
            GetNode<RayCast2D>("RayCast2D").TargetPosition,
            new Color(1000.5f), 5);
        // Ray를 확인할 수 있도록 선으로 표시한다.
    }
 
    public override void _PhysicsProcess(double delta)
    {    
        if (GetNode<RayCast2D>("RayCast2D").IsColliding())
        {
            Node obj = GetNode<RayCast2D>("RayCast2D").GetCollider() as Node;            
            GD.Print(obj.Name);
            // Ray와 충돌한 오브젝트의 이름을 출력한다.
        }
   ...
 

 

 

스크립트를 작성하고 실행하면 Ray와 충돌하는 오브젝트의 이름이 출력된다.

 

※ 참고

RayCast2D

 

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

Instantiate로 생성한 씬을 반복 재사용해 보자.

 

스프라이트 하나를 생성하고 씬으로 저장(Player.tscn)한다.

 

res:// 에 스크립트를 생성하고 Autoload에 추가한다.

 

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
using Godot;
 
public partial class Control : Node
{
    public PackedScene Scene;
    public Timer timer;
    public Sprite2D Sprite;
 
    public override void _Ready()
    {
        // C# has no preload, so you have to always use ResourceLoader.Load<PackedScene>().
        Scene = ResourceLoader.Load<PackedScene>("res://Player.tscn");
        Sprite = Scene.Instantiate<Sprite2D>();
 
        timer = new Timer();
        timer.Connect("timeout", Callable.From(OnTimeOut));
        timer.WaitTime = 1.0;
        AddChild(timer);
        timer.Start();        
    }
    
    public override void _Process(double delta)
    {        
    }
 
    public void OnTimeOut()
    {
 
        Sprite.Position = new Vector2(GD.RandRange(0, (int)GetViewport().GetVisibleRect().Size.X),
            GD.RandRange(0, (int)GetViewport().GetVisibleRect().Size.Y));
        if (Sprite.GetParent() == null )
        {
            AddChild(Sprite);
            // Adds a child node. Nodes can have any number of children, but every child must have
            // a unique name. Child nodes are automatically deleted when the parent node is deleted,
            // so an entire scene can be removed by deleting its topmost node.
        }
        else
        {
            RemoveChild(Sprite);
            // Removes a child node. The node is NOT deleted and must be deleted manually.
        }
    }
}
 

 

 

RemoveChild()로 제거한 자식 노드는 삭제되지는 않는다. AddChild()로 다시 추가 할 수 있다.

 

게임을 실행하면 씬에 스프라이트가 반복해서 나타났다 사라진다.

 

게임이 실행된 상태에서 Remote 탭을 확인하면 GlobalControl의 자식 노드로 Sprite2D가 반복적으로 추가됐다 삭제 된다.

 

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

게임 실행 중 잠시 동안 비동기 대기해 보자.

 

Timer를 Node2D 자식 노드로 등록하고 이름을 NodeTimer로 바꾼다. Wait Time 속성은 3으로 변경한다.

 

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
using Godot;
 
public partial class node_2d : Node2D
{
    // Called when the node enters the scene tree for the first time.
    public override async void _Ready()
    {
        Timer timer = GetNode<Timer>("NodeTimer");
        timer.Start();
        GD.Print("Timer started.");
 
        await ToSignal(timer, Timer.SignalName.Timeout);
        GD.Print("Node Timer Timeout.");
 
        await ToSignal(timer, Timer.SignalName.Timeout);
        GD.Print("Node Timer Timeout.");
 
        timer.Stop();
 
        await ToSignal(GetTree().CreateTimer(1.0), SceneTreeTimer.SignalName.Timeout);
        GD.Print("Tree Timer Timeout.");
        
        await ToSignal(GetTree().CreateTimer(1.0), SceneTreeTimer.SignalName.Timeout);
        GD.Print("Tree Timer Timeout.");
 
        GD.Print("End");
    }
 
    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(double delta)
    {
    }
}
 

 

 

Node2D 노드에 스크립트를 추가하고 위와 같이 작성한다.

NodeTimer를 시작하고 3초 간격으로 "Node Timer Timeout." 메세지를 두 번 출력한다.

같은 동작을 구현하기 위해 SceneTree의 CreateTimer()를 사용할 수도 있다. 위 예에서는 1초 간격으로 "Tree Timer Timeout."메세지를 두 번 출력한다.

 

Output 창에 결과가 표시된다.

 

※ 참고

Heads up display

C# signals

 

반응형
Posted by J-sean
:

C# Type Class 타입 클래스

C# 2022. 7. 20. 00:12 |
반응형

Type 클래스를 사용해 보자.

 

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
using System;
using System.Reflection;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //Type t = typeof(String);
            //Type t = Type.GetType("System.String");
            String str = "";
            Type t = str.GetType();
            // Gets a Type object that represents the specified type.
 
            MethodInfo[] methods = t.GetMethods();
            foreach (MethodInfo method in methods)
            {
                // String 클래스의 Substring 함수는 2개의 오버로딩 함수가 있다.
                if (method.Name == "Substring")
                {
                    Console.WriteLine("- Method: " + method.Name);
 
                    ParameterInfo[] parameters = method.GetParameters();
                    foreach (ParameterInfo parameter in parameters)
                    {
                        Console.WriteLine("Parameter: " + parameter.Name);
                    }
                }
            }
 
            Console.WriteLine();
 
            MethodInfo substr = t.GetMethod("Substring"new Type[] { typeof(int), typeof(int) });
            // Searches for the specified method whose parameters match the specified generic
            // parameter count, argument types and modifiers, using the specified binding constraints.
 
            Object result = substr.Invoke("Hello, World!"new Object[] { 75 });
            // Invokes the method or constructor represented by the current instance, using the
            // specified parameters.
 
            Console.WriteLine("{0} returned \"{1}\".", substr, result);
        }
    }
}
 

 

소스를 빌드하고 실행한다.

 

 

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

2022.04.05 - [C#] - C# Joystick(Gamepad) Input Check - 조이스틱(게임패드) 입력 확인 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
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
using System.Threading;
using System.Diagnostics;
 
using HidSharp;
using HidSharp.Utility;
using HidSharp.Reports;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            HidSharpDiagnostics.EnableTracing = true;
            HidSharpDiagnostics.PerformStrictChecks = true;
 
            DeviceList list = DeviceList.Local;
            list.Changed += (sender, e) => Console.WriteLine("Device list changed.");
 
            HidDevice[] hidDeviceList = list.GetHidDevices().ToArray();
 
            foreach (HidDevice dev in hidDeviceList)
            {
                if (!dev.ToString().Contains("gamepad"))
                {
                    Console.WriteLine(dev.GetProductName() + " is not a gamepad.");
                    continue;
                }
 
                try
                {
                    ReportDescriptor reportDescriptor = dev.GetReportDescriptor();
 
                    Debug.Assert(dev.GetMaxInputReportLength() == reportDescriptor.MaxInputReportLength);
                    Debug.Assert(dev.GetMaxOutputReportLength() == reportDescriptor.MaxOutputReportLength);
                    Debug.Assert(dev.GetMaxFeatureReportLength() == reportDescriptor.MaxFeatureReportLength);
 
                    foreach (DeviceItem deviceItem in reportDescriptor.DeviceItems)
                    {
                        {
                            HidStream hidStream;
                            if (dev.TryOpen(out hidStream))
                            {
                                Console.WriteLine(dev.GetProductName() + " opened.");
                                hidStream.ReadTimeout = Timeout.Infinite;
 
                                using (hidStream)
                                {
                                    byte[] inputReportBuffer = new byte[dev.GetMaxInputReportLength()];
                                    HidSharp.Reports.Input.HidDeviceInputReceiver inputReceiver =
                                        reportDescriptor.CreateHidDeviceInputReceiver();
                                    HidSharp.Reports.Input.DeviceItemInputParser inputParser =
                                        deviceItem.CreateDeviceItemInputParser();
 
                                    inputReceiver.Start(hidStream);
 
                                    while (true)
                                    {
                                        if (inputReceiver.WaitHandle.WaitOne(1000))
                                        {
                                            if (!inputReceiver.IsRunning) { break; } // Disconnected?
 
                                            Report report;
                                            while (inputReceiver.TryRead(inputReportBuffer, 0out report))
                                            {
                                                if (inputParser.TryParseReport(inputReportBuffer, 0, report) && inputParser.HasChanged)
                                                {
                                                    //inputParser.HasChanged는 버튼을 누르거나 놓는 등 상태가 변경되는 경우를 뜻한다.
 
                                                    //Console.WriteLine(BitConverter.ToString(inputReportBuffer));
 
                                                    if (inputReportBuffer[3== 0x00)
                                                    {
                                                        Console.WriteLine("Left");
                                                    }
                                                    else if (inputReportBuffer[3== 0xFF)
                                                    {
                                                        Console.WriteLine("Right");
                                                    }
                                                    else if (inputReportBuffer[4== 0x00)
                                                    {
                                                        Console.WriteLine("Up");
                                                    }
                                                    else if (inputReportBuffer[4== 0xFF)
                                                    {
                                                        Console.WriteLine("Down");
                                                    }
                                                    else if (inputReportBuffer[5== 0x1F)
                                                    {
                                                        Console.WriteLine("X");
                                                    }
                                                    else if (inputReportBuffer[5== 0x2F)
                                                    {
                                                        Console.WriteLine("A");
                                                    }
                                                    else if (inputReportBuffer[5== 0x4F)
                                                    {
                                                        Console.WriteLine("B");
                                                    }
                                                    else if (inputReportBuffer[5== 0x8F)
                                                    {
                                                        Console.WriteLine("Y");
                                                    }
                                                    else if (inputReportBuffer[6== 0x01)
                                                    {
                                                        Console.WriteLine("L Shoulder");
                                                    }
                                                    else if (inputReportBuffer[6== 0x02)
                                                    {
                                                        Console.WriteLine("R Shoulder");
                                                    }
                                                    else if (inputReportBuffer[6== 0x10)
                                                    {
                                                        Console.WriteLine("Select");
                                                    }
                                                    else if (inputReportBuffer[6== 0x20)
                                                    {
                                                        Console.WriteLine("Start");
                                                    }
                                                }
                                            }
                                        }
 
                                        if (Console.KeyAvailable)
                                        {
                                            ConsoleKeyInfo consoleKeyInfo = Console.ReadKey(true);
 
                                            if (consoleKeyInfo.Key == ConsoleKey.Escape)
                                            {
                                                Console.WriteLine("User stopped.");
                                                break;
                                                //hidStream.Close();
                                            }
                                        }
                                    }
                                }
 
                                Console.WriteLine("Gamepad closed.");
                            }
                            else
                            {
                                Console.WriteLine("Failed to open device.");
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
        }
    }
}
 

 

소스를 입력하고 빌드한다.

 

 

프로그램을 실행하고 게임패드의 버튼을 누르면 어떤 버튼이 눌리는지 표시된다.

 

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

컴퓨터에 연결된 모든 HID(Human Interface Devices)를 확인하고 조이스틱(게임패드)의 입력을 체크해 보자.

 

HidSharp를 설치한다.

 

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
using System.Threading;
using System.Diagnostics;
 
using HidSharp;
using HidSharp.Utility;
using HidSharp.Reports;
 
namespace ConsoleApp1
{
    class Program
    {
        static void WriteDeviceItemInputParserResult(HidSharp.Reports.Input.DeviceItemInputParser parser)
        {
            while (parser.HasChanged)
            {
                int changedIndex = parser.GetNextChangedIndex();
                DataValue previousDataValue = parser.GetPreviousValue(changedIndex);
                DataValue dataValue = parser.GetValue(changedIndex);
 
                Console.WriteLine(string.Format("  {0}: {1} -> {2}", (Usage)dataValue.Usages.FirstOrDefault(),
                    previousDataValue.GetPhysicalValue(), dataValue.GetPhysicalValue()));
            }
        }
 
        static void Main(string[] args)
        {
            HidSharpDiagnostics.EnableTracing = true;
            HidSharpDiagnostics.PerformStrictChecks = true;
 
            DeviceList list = DeviceList.Local;
            list.Changed += (sender, e) => Console.WriteLine("Device list changed.");
 
            Device[] allDeviceList = list.GetAllDevices().ToArray();
            Console.WriteLine("■ All device list:");
            foreach (Device dev in allDeviceList)
            {
                Console.WriteLine("- Name: " + dev.ToString() + "\n" + "  Path: " + dev.DevicePath);
            }
 
            Console.WriteLine("-----------------------------------------------");
 
            Stopwatch stopwatch = Stopwatch.StartNew();
            HidDevice[] hidDeviceList = list.GetHidDevices().ToArray();
 
            Console.WriteLine("■ HID device list (took {0} ms to get {1} devices):",
                              stopwatch.ElapsedMilliseconds, hidDeviceList.Length);
 
            foreach (HidDevice dev in hidDeviceList)
            {
                Console.WriteLine("- Name: " + dev);
                Console.WriteLine("  Path: " + dev.DevicePath);
 
                try
                {
                    ReportDescriptor reportDescriptor = dev.GetReportDescriptor();
 
                    // Lengths should match.
                    Debug.Assert(dev.GetMaxInputReportLength() == reportDescriptor.MaxInputReportLength);
                    Debug.Assert(dev.GetMaxOutputReportLength() == reportDescriptor.MaxOutputReportLength);
                    Debug.Assert(dev.GetMaxFeatureReportLength() == reportDescriptor.MaxFeatureReportLength);
 
                    foreach (DeviceItem deviceItem in reportDescriptor.DeviceItems)
                    {
                        foreach (uint usage in deviceItem.Usages.GetAllValues())
                        {
                            Console.WriteLine(string.Format("  Usage: {0:X4} {1}", usage, (Usage)usage));
                        }
 
                        {
                            Console.WriteLine("Opening device for 20 seconds...");
 
                            HidStream hidStream;
                            if (dev.TryOpen(out hidStream))
                            {
                                Console.WriteLine("Opened device.");
                                hidStream.ReadTimeout = Timeout.Infinite;
 
                                using (hidStream)
                                {
                                    byte[] inputReportBuffer = new byte[dev.GetMaxInputReportLength()];
                                    HidSharp.Reports.Input.HidDeviceInputReceiver inputReceiver = 
                                        reportDescriptor.CreateHidDeviceInputReceiver();
                                    HidSharp.Reports.Input.DeviceItemInputParser inputParser = 
                                        deviceItem.CreateDeviceItemInputParser();
 
                                    inputReceiver.Start(hidStream);
 
                                    int startTime = Environment.TickCount;
                                    while (true)
                                    {
                                        if (inputReceiver.WaitHandle.WaitOne(1000))
                                        {
                                            if (!inputReceiver.IsRunning) { break; } // Disconnected?
 
                                            Report report;
                                            while (inputReceiver.TryRead(inputReportBuffer, 0out report))
                                            {
                                                // Parse the report if possible.
                                                // This will return false if (for example) the report applies to a different DeviceItem.
                                                if (inputParser.TryParseReport(inputReportBuffer, 0, report))
                                                {
                                                    WriteDeviceItemInputParserResult(inputParser);
                                                }
                                            }
                                        }
 
                                        uint elapsedTime = (uint)(Environment.TickCount - startTime);
                                        if (elapsedTime >= 20000) { break; } // Stay open for 20 seconds.
                                    }
 
                                }
 
                                Console.WriteLine("Closed device.");
                            }
                            else
                            {
                                Console.WriteLine("Failed to open device.");
                            }
 
                            Console.WriteLine("  ---------------------------------------------");
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
        }
    }
}
 

 

소스를 입력하고 빌드한다.

 

 

프로그램을 실행하면 연결된 모든 디바이스와 HID가 표시되고 open 가능한 디바이스(usb gamepad)는 입력을 받아 표시한다.

포커스가 다른 프로그램에 있어도 디바이스의 입력을 확인 할 수 있다.

 

 

각 버튼이 눌렸을때 inputReportBuffer의 변화되는 내용을 확인해 보면 아래와 같다.

(첫 번째 바이트의 '01'은 Report ID인거 같다)

 

1
Console.WriteLine(BitConverter.ToString(inputReportBuffer));
 

 

01-80-80-7F-7F-0F-00-00
01-80-80-00-7F-0F-00-00
  GenericDesktopX: 127 -> 0

01-80-80-7F-7F-0F-00-00
01-80-80-FF-7F-0F-00-00
  GenericDesktopX: 127 -> 255

01-80-80-7F-7F-0F-00-00
01-80-80-7F-00-0F-00-00
  GenericDesktopY: 127 -> 0
  
01-80-80-7F-7F-0F-00-00
01-80-80-7F-FF-0F-00-00
  GenericDesktopY: 127 -> 255
※게임패드의 방향버튼은 기본이(버튼이 눌리지 않았을때) 127

01-80-80-7F-7F-0F-00-00
01-80-80-7F-7F-1F-00-00
  Button1: 0 -> 1

01-80-80-7F-7F-0F-00-00
01-80-80-7F-7F-2F-00-00
  Button2: 0 -> 1
  
01-80-80-7F-7F-0F-00-00
01-80-80-7F-7F-4F-00-00
  Button3: 0 -> 1

01-80-80-7F-7F-0F-00-00
01-80-80-7F-7F-8F-00-00
  Button4: 0 -> 1
※게임패드의 버튼은 기본이(버튼이 눌리지 않았을때) 0

 

※ HidSharp

 

반응형
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.TreatControlCAsInput = true;
            // Prevent example from ending if CTL+C is pressed.
            ConsoleKeyInfo consoleKeyInfo;
 
            for (int i = 0; i < 10; i++)
            {
                while (Console.KeyAvailable)
                {
                    consoleKeyInfo = Console.ReadKey(true);
                    // Obtains the next character or function key pressed by the user.
                    // 'true' to not display the pressed key; otherwise, false.
 
                    if ((consoleKeyInfo.Modifiers & ConsoleModifiers.Control) != 0
                        && consoleKeyInfo.Key == ConsoleKey.C)
                    // if (consoleKeyInfo.Key == ConsoleKey.Escape)
                    {
                        Console.WriteLine("Stopped.");
                        return;
                    }
                }
                // 모든 입력을 바로 처리하기 위해(입력 버퍼 비우기) if()가 아닌 while() 사용.
 
                Console.WriteLine(i + 1);
                System.Threading.Thread.Sleep(1000);
            }
        }
    }
}
 

 

소스를 입력하고 빌드한다.

 

프로그램을 실행하고 Ctrl+C를 누르면 정지된다.

 

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

이미지 파일을 Drag & Drop으로 열어보자.

 

WinForm에 PictureBox를 적당히 배치한다.

 

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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
            pictureBox1.AllowDrop = true;
            // 인텔리센스에는 pictureBox1.AllowDrop가 표시되지 않는다.
            // 하지만 사용은 가능하며 인텔리센스를 사용하고 싶다면 아래처럼
            // Control로 형변환해서 해도 된다.
            // ((Control)pictureBox1).AllowDrop = true;
        }
 
        private void pictureBox1_DragOver(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy;
            }
        }
 
        private void pictureBox1_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
                // 드롭된 파일들의 전체 경로명을 반환.
                foreach (string file in files)
                {
                    if (file.EndsWith("jpg"|| file.EndsWith("JPG"))
                    {
                        // JPG 파일만 디스플레이
                        pictureBox1.Image = System.Drawing.Image.FromFile(file);
                    }
                }
            }
        }
    }
}
 

 

소스를 입력하고 빌드한다.

 

프로그램을 실행하고 PictureBox 위로 JPG파일을 드래그 & 드롭한다.

 

이미지가 표시된다.

 

반응형
Posted by J-sean
: