By continuing you indicate that you have read and agree to our Terms of service and Privacy policy
By continuing you indicate that you have read and agree to our Terms of service and Privacy policy
Popular Releases
Popular Libraries
New Libraries
Top Authors
Trending Kits
Trending Discussions
Learning
godot | 3.4.4-stable |
phaser | Phaser v3.55.2 |
libgdx | 1.10.0 |
aseprite | Aseprite v1.3-beta14 |
Babylon.js |
godot 3.4.4-stable |
phaser Phaser v3.55.2 |
libgdx 1.10.0 |
aseprite Aseprite v1.3-beta14 |
Babylon.js |
by godotengine c++
47538 NOASSERTION
Godot Engine – Multi-platform 2D and 3D game engine
by photonstorm javascript
30320 MIT
Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
by libgdx java
19612 NOASSERTION
Desktop/Android/HTML5/iOS Java game development framework
by aseprite c++
16876
Animated sprite editor & pixel art tool (Windows, macOS, Linux)
by BabylonJS typescript
16566 Apache-2.0
Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.
by bevyengine rust
15512 NOASSERTION
A refreshingly simple data-driven game engine built in Rust
by cocos2d c++
15461
Cocos2d-x is a suite of open-source, cross-platform, game-development tools used by millions of developers all over the world.
by Anuken java
14308 GPL-3.0
The automation tower defense game
by liabru javascript
12647 MIT
a 2D rigid body physics engine for the web ▲● ■
by godotengine c++
47538 NOASSERTION
Godot Engine – Multi-platform 2D and 3D game engine
by photonstorm javascript
30320 MIT
Phaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
by libgdx java
19612 NOASSERTION
Desktop/Android/HTML5/iOS Java game development framework
by aseprite c++
16876
Animated sprite editor & pixel art tool (Windows, macOS, Linux)
by BabylonJS typescript
16566 Apache-2.0
Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.
by bevyengine rust
15512 NOASSERTION
A refreshingly simple data-driven game engine built in Rust
by cocos2d c++
15461
Cocos2d-x is a suite of open-source, cross-platform, game-development tools used by millions of developers all over the world.
by Anuken java
14308 GPL-3.0
The automation tower defense game
by liabru javascript
12647 MIT
a 2D rigid body physics engine for the web ▲● ■
by bevyengine rust
15512 NOASSERTION
A refreshingly simple data-driven game engine built in Rust
by tobspr javascript
4851 GPL-3.0
shapez.io is an open source base building game inspired by factorio! Available on web & steam
by jynew csharp
4611 NOASSERTION
金庸群侠传3D重制版
by o3de c++
4538 NOASSERTION
Open 3D Engine (O3DE) is an Apache 2.0-licensed multi-platform 3D engine that enables developers and content creators to build AAA games, cinema-quality 3D worlds, and high-fidelity simulations without any fees or commercial obligations.
by UnityTechnologies csharp
3966 Apache-2.0
Unity Open Project #1: Chop Chop
by FlaxEngine c++
3219 NOASSERTION
Flax Engine – multi-platform 3D game engine
by derrod python
2928 GPL-3.0
Legendary - A free and open-source replacement for the Epic Games Launcher
by Heroic-Games-Launcher typescript
2830 GPL-3.0
A Native GOG and Epic Games Launcher for Linux, Windows and Mac.
by Tencent c++
2646 NOASSERTION
Write your game with TypeScript in UE4 or Unity. Puerts can be pronounced as pu-erh TS(普洱TS)
by bevyengine rust
15512 NOASSERTION
A refreshingly simple data-driven game engine built in Rust
by tobspr javascript
4851 GPL-3.0
shapez.io is an open source base building game inspired by factorio! Available on web & steam
by jynew csharp
4611 NOASSERTION
金庸群侠传3D重制版
by o3de c++
4538 NOASSERTION
Open 3D Engine (O3DE) is an Apache 2.0-licensed multi-platform 3D engine that enables developers and content creators to build AAA games, cinema-quality 3D worlds, and high-fidelity simulations without any fees or commercial obligations.
by UnityTechnologies csharp
3966 Apache-2.0
Unity Open Project #1: Chop Chop
by FlaxEngine c++
3219 NOASSERTION
Flax Engine – multi-platform 3D game engine
by derrod python
2928 GPL-3.0
Legendary - A free and open-source replacement for the Epic Games Launcher
by Heroic-Games-Launcher typescript
2830 GPL-3.0
A Native GOG and Epic Games Launcher for Linux, Windows and Mac.
by Tencent c++
2646 NOASSERTION
Write your game with TypeScript in UE4 or Unity. Puerts can be pronounced as pu-erh TS(普洱TS)
1
157 Libraries
1392
2
110 Libraries
10096
3
63 Libraries
33694
4
56 Libraries
1041
5
48 Libraries
8733
6
39 Libraries
206
7
33 Libraries
243
8
33 Libraries
149
9
27 Libraries
178
10
25 Libraries
704
Game engine libraries are reusable components that can be used to build a game. They can provide a wide range of functionality, from rendering, input, and sound to artificial intelligence, physics, and networking. The most popular game engines are commercial products that require licenses and support. However, there are also many open-source alternatives. Some of these projects have been around for years and have a large following; others are just getting started.
OpenRA is a modern reimplementation of the classic Command & Conquer series. It provides an API that wraps various other libraries that allow you to make games with little effort. Pyxel is a pixel art editor built on top of Pygame and Pygame Zero. It allows you to draw sprites, animations, and tilesets for your game in an easy-to-use interface with plenty of customizations. openmw is a reimplementation of Morrowind's engine that uses Python instead of C/C++ code. This makes it much easier to use than the original Morrowind engine and allows developers to add new features easily without having any knowledge of C++ or C programming languages. Popular open source Game engine libraries among developers include
Python is a versatile language that finds use in many areas. One of these areas is gaming. Popular video games like Battlefield 2, Pirates of the Caribbean, among others use Python programming for a number of its functionalities and add-ons. With the advancement in the gaming industry, Python language has proved to be an exceptional choice by the developers for rapid prototyping of video games.
Panda3D
Panda3D is an open-source and completely free-to-use engine for realtime 3D games, visualisations, simulations, experiments and more. Some of the features are: –
Cocos2d
Cocos2d is an open-source software framework that can be used to build games, apps and other cross-platform GUI based interactive programs. Cocos2d-x is an open-source game framework written in C++. Some of the features are: –
Kivy
Kivy is an open-source and cross-platform Python library for rapid development of applications. Kivy runs on Linux, Windows, OS X, Android, iOS, and Raspberry Pi and can natively use most inputs, protocols and devices. Some of the features are: –
Pygame
Pygame is an open-source Python library for making multimedia applications like games built on top of the excellent SDL library. This library is a combination of C, Python, Native and OpenGL. Some of the features are: –
Pyglet
Pyglet is an open-sourced, cross-platform windowing and multimedia library for Python. It is a powerful Python library that can be used for developing games and other visually-rich applications on Windows, Mac OS X and Linux. Some of the features are: –
Are you struggling to make impossible decisions?
You might have some help. My eight-year-old daughter was playing with the Magic 8-Ball and told me she makes her important decisions based on it! I tried it, and it was pretty amusing and even sometimes helpful. Reminded me of the Staples Easy Button.
The Magic 8-Ball was invented in 1946 by Albert C. Carter and Abe Bookman and is currently manufactured by Mattel. Carter was inspired by a spirit writing device used by his mother, a clairvoyant. Interestingly over the 76 years, the Magic 8-Ball has undergone very minimal changes.
If you can't get your hand on one, there are many virtual ones that use a pseudorandom number generator (PRNG) on the same 20 possible answers.
If you are looking for critical decisions, then in the Magic 8-Ball style - "Don't count on it."
The kandi kit shares public libraries that simulate the Magic 8-Ball, PRNG, interesting Magic 8-Ball scripts for developer responses, and a DIY electronic device.
Game engine libraries are reusable components that can be used to build a game. They can provide a wide range of functionality, from rendering, input, and sound to artificial intelligence, physics, and networking. The most popular game engines are commercial products that require licenses and support. However, there are also many open-source alternatives. Some of these projects have been around for years and have a large following; others are just getting started.
OpenRA is a modern reimplementation of the classic Command & Conquer series. It provides an API that wraps various other libraries that allow you to make games with little effort. Pyxel is a pixel art editor built on top of Pygame and Pygame Zero. It allows you to draw sprites, animations, and tilesets for your game in an easy-to-use interface with plenty of customizations. openmw is a reimplementation of Morrowind's engine that uses Python instead of C/C++ code. This makes it much easier to use than the original Morrowind engine and allows developers to add new features easily without having any knowledge of C++ or C programming languages. Popular open source Game engine libraries among developers include
Python is a versatile language that finds use in many areas. One of these areas is gaming. Popular video games like Battlefield 2, Pirates of the Caribbean, among others use Python programming for a number of its functionalities and add-ons. With the advancement in the gaming industry, Python language has proved to be an exceptional choice by the developers for rapid prototyping of video games.
Panda3D
Panda3D is an open-source and completely free-to-use engine for realtime 3D games, visualisations, simulations, experiments and more. Some of the features are: –
Cocos2d
Cocos2d is an open-source software framework that can be used to build games, apps and other cross-platform GUI based interactive programs. Cocos2d-x is an open-source game framework written in C++. Some of the features are: –
Kivy
Kivy is an open-source and cross-platform Python library for rapid development of applications. Kivy runs on Linux, Windows, OS X, Android, iOS, and Raspberry Pi and can natively use most inputs, protocols and devices. Some of the features are: –
Pygame
Pygame is an open-source Python library for making multimedia applications like games built on top of the excellent SDL library. This library is a combination of C, Python, Native and OpenGL. Some of the features are: –
Pyglet
Pyglet is an open-sourced, cross-platform windowing and multimedia library for Python. It is a powerful Python library that can be used for developing games and other visually-rich applications on Windows, Mac OS X and Linux. Some of the features are: –
Are you struggling to make impossible decisions?
You might have some help. My eight-year-old daughter was playing with the Magic 8-Ball and told me she makes her important decisions based on it! I tried it, and it was pretty amusing and even sometimes helpful. Reminded me of the Staples Easy Button.
The Magic 8-Ball was invented in 1946 by Albert C. Carter and Abe Bookman and is currently manufactured by Mattel. Carter was inspired by a spirit writing device used by his mother, a clairvoyant. Interestingly over the 76 years, the Magic 8-Ball has undergone very minimal changes.
If you can't get your hand on one, there are many virtual ones that use a pseudorandom number generator (PRNG) on the same 20 possible answers.
If you are looking for critical decisions, then in the Magic 8-Ball style - "Don't count on it."
The kandi kit shares public libraries that simulate the Magic 8-Ball, PRNG, interesting Magic 8-Ball scripts for developer responses, and a DIY electronic device.
QUESTION
Unity App: How to check available space left on Android / IOS device
Asked 2022-Apr-16 at 14:01I am developing a game (iOS/Android with Unity Game Engine) that requires to download resources to be stored locally on device. I wish to check free space on device to send an error message before download starts in case it's not enough.
How can I check it? I couldn't find any clear procedure on my research.
ANSWER
Answered 2022-Apr-16 at 14:01It varies by platform so isn’t a simple answer. The free Unity plugin Simple Disk Utils handles it for you on Windows, Mac, Android and iOS and full source code is available on GitHub so you can see for yourself how it’s achieved on the different platforms.
QUESTION
OpenTK doesn't render the color of my triangle
Asked 2022-Apr-03 at 07:08I am learning to program a game engine which is why I followed a tutorial, with that tutorial I have gotten this far and even though my code is identical to theirs (theirs did work in the videos) its not working the way it is meant to. The triangle stays black no matter what. There is not any errors.
Main Program Script:
1 using System;
2using OpenTK.Mathematics;
3using OpenTK.Windowing.Desktop;
4using OpenTK.Windowing.Common;
5using System.Drawing;
6using OpenTK.Graphics.OpenGL4;
7using System.IO;
8
9namespace Game_Engine
10{
11 public static class Program
12 {
13 static void Main(string[] args)
14 {
15 Console.WriteLine("Hello World!");
16
17 GameWindowSettings gws = GameWindowSettings.Default;
18 NativeWindowSettings nws = NativeWindowSettings.Default;
19 gws.IsMultiThreaded = false;
20 gws.RenderFrequency = 60;
21 gws.UpdateFrequency = 60;
22
23 nws.APIVersion = Version.Parse("4.1.0");
24 nws.AutoLoadBindings = true;
25 nws.Size = new Vector2i(1280, 720);
26 nws.Title = "Horizon";
27
28
29
30 GameWindow window = new GameWindow(gws, nws);
31
32 window.UpdateFrame += (FrameEventArgs args) => {
33
34
35 };
36
37 ShaderProgram shaderProgram = new ShaderProgram(){id = 0};
38 window.Load += () =>
39 {
40 Console.WriteLine("Hello");
41 ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
42 };
43
44 window.RenderFrame += (FrameEventArgs args) =>
45 {
46 GL.UseProgram( shaderProgram.id );
47
48 GL.ClearColor(1.0f, 0.0f, 0.0f, 0.0f);
49 GL.Clear(ClearBufferMask.ColorBufferBit);
50
51 float[] verts = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f };
52 float[] color = { 1f, 0, 0, 0, 1f ,0 ,0, 0, 1f };
53
54 int vao = GL.GenVertexArray();
55 int vertices = GL.GenBuffer();
56 int colors = GL.GenBuffer();
57 GL.BindVertexArray(vao);
58 GL.BindBuffer(BufferTarget.ArrayBuffer, vertices);
59 GL.BufferData( BufferTarget.ArrayBuffer, verts.Length * sizeof(float), verts, BufferUsageHint.StaticCopy);
60 GL.EnableVertexAttribArray( 0 );
61 GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );
62
63 GL.BindBuffer(BufferTarget.ArrayBuffer, colors);
64 GL.BufferData(BufferTarget.ArrayBuffer, color.Length * sizeof(float), color, BufferUsageHint.StaticCopy);
65 GL.EnableVertexAttribArray(1);
66 GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0);
67
68
69
70 GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
71
72 GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
73 GL.BindVertexArray(0);
74 GL.DeleteBuffer(vertices);
75 GL.DeleteBuffer(colors);
76 GL.DeleteVertexArray( vao );
77
78
79
80 window.SwapBuffers();
81 };
82
83 window.Run();
84
85 }
86
87
88
89 private static Shader LoadShader(string shaderLocation, ShaderType type)
90 {
91 int shaderId = GL.CreateShader( type );
92 GL.ShaderSource( shaderId, File.ReadAllText( shaderLocation ) );
93 GL.CompileShader( shaderId );
94 string infoLog = GL.GetShaderInfoLog( shaderId );
95 if (!string.IsNullOrEmpty(infoLog))
96 {
97 throw new Exception(infoLog);
98 }
99
100 return new Shader() { id = shaderId };
101 }
102
103 private static ShaderProgram LoadShaderProgram( string vertextShaderLocation, string fragmentShaderLocation)
104 {
105 int shaderProgramId = GL.CreateProgram();
106
107 Shader vertextShader = LoadShader(vertextShaderLocation, ShaderType.VertexShader);
108 Shader fragmentShader = LoadShader(fragmentShaderLocation, ShaderType.FragmentShader);
109
110 GL.AttachShader(shaderProgramId, vertextShader.id);
111 GL.AttachShader(shaderProgramId, fragmentShader.id);
112 GL.LinkProgram(shaderProgramId);
113 GL.DetachShader(shaderProgramId, vertextShader.id);
114 GL.DetachShader(shaderProgramId, fragmentShader.id);
115 GL.DeleteShader(vertextShader.id);
116 GL.DeleteShader(fragmentShader.id);
117
118 string infoLog = GL.GetProgramInfoLog(shaderProgramId);
119 if (!string.IsNullOrEmpty(infoLog))
120 {
121 throw new Exception(infoLog);
122 }
123
124 return new ShaderProgram() { id = shaderProgramId };
125 }
126
127
128 public struct Shader
129 {
130 public int id;
131 }
132
133 public struct ShaderProgram
134 {
135 public int id;
136 }
137 }
138}
139
Fragment Shader (in glsl):
1 using System;
2using OpenTK.Mathematics;
3using OpenTK.Windowing.Desktop;
4using OpenTK.Windowing.Common;
5using System.Drawing;
6using OpenTK.Graphics.OpenGL4;
7using System.IO;
8
9namespace Game_Engine
10{
11 public static class Program
12 {
13 static void Main(string[] args)
14 {
15 Console.WriteLine("Hello World!");
16
17 GameWindowSettings gws = GameWindowSettings.Default;
18 NativeWindowSettings nws = NativeWindowSettings.Default;
19 gws.IsMultiThreaded = false;
20 gws.RenderFrequency = 60;
21 gws.UpdateFrequency = 60;
22
23 nws.APIVersion = Version.Parse("4.1.0");
24 nws.AutoLoadBindings = true;
25 nws.Size = new Vector2i(1280, 720);
26 nws.Title = "Horizon";
27
28
29
30 GameWindow window = new GameWindow(gws, nws);
31
32 window.UpdateFrame += (FrameEventArgs args) => {
33
34
35 };
36
37 ShaderProgram shaderProgram = new ShaderProgram(){id = 0};
38 window.Load += () =>
39 {
40 Console.WriteLine("Hello");
41 ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
42 };
43
44 window.RenderFrame += (FrameEventArgs args) =>
45 {
46 GL.UseProgram( shaderProgram.id );
47
48 GL.ClearColor(1.0f, 0.0f, 0.0f, 0.0f);
49 GL.Clear(ClearBufferMask.ColorBufferBit);
50
51 float[] verts = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f };
52 float[] color = { 1f, 0, 0, 0, 1f ,0 ,0, 0, 1f };
53
54 int vao = GL.GenVertexArray();
55 int vertices = GL.GenBuffer();
56 int colors = GL.GenBuffer();
57 GL.BindVertexArray(vao);
58 GL.BindBuffer(BufferTarget.ArrayBuffer, vertices);
59 GL.BufferData( BufferTarget.ArrayBuffer, verts.Length * sizeof(float), verts, BufferUsageHint.StaticCopy);
60 GL.EnableVertexAttribArray( 0 );
61 GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );
62
63 GL.BindBuffer(BufferTarget.ArrayBuffer, colors);
64 GL.BufferData(BufferTarget.ArrayBuffer, color.Length * sizeof(float), color, BufferUsageHint.StaticCopy);
65 GL.EnableVertexAttribArray(1);
66 GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0);
67
68
69
70 GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
71
72 GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
73 GL.BindVertexArray(0);
74 GL.DeleteBuffer(vertices);
75 GL.DeleteBuffer(colors);
76 GL.DeleteVertexArray( vao );
77
78
79
80 window.SwapBuffers();
81 };
82
83 window.Run();
84
85 }
86
87
88
89 private static Shader LoadShader(string shaderLocation, ShaderType type)
90 {
91 int shaderId = GL.CreateShader( type );
92 GL.ShaderSource( shaderId, File.ReadAllText( shaderLocation ) );
93 GL.CompileShader( shaderId );
94 string infoLog = GL.GetShaderInfoLog( shaderId );
95 if (!string.IsNullOrEmpty(infoLog))
96 {
97 throw new Exception(infoLog);
98 }
99
100 return new Shader() { id = shaderId };
101 }
102
103 private static ShaderProgram LoadShaderProgram( string vertextShaderLocation, string fragmentShaderLocation)
104 {
105 int shaderProgramId = GL.CreateProgram();
106
107 Shader vertextShader = LoadShader(vertextShaderLocation, ShaderType.VertexShader);
108 Shader fragmentShader = LoadShader(fragmentShaderLocation, ShaderType.FragmentShader);
109
110 GL.AttachShader(shaderProgramId, vertextShader.id);
111 GL.AttachShader(shaderProgramId, fragmentShader.id);
112 GL.LinkProgram(shaderProgramId);
113 GL.DetachShader(shaderProgramId, vertextShader.id);
114 GL.DetachShader(shaderProgramId, fragmentShader.id);
115 GL.DeleteShader(vertextShader.id);
116 GL.DeleteShader(fragmentShader.id);
117
118 string infoLog = GL.GetProgramInfoLog(shaderProgramId);
119 if (!string.IsNullOrEmpty(infoLog))
120 {
121 throw new Exception(infoLog);
122 }
123
124 return new ShaderProgram() { id = shaderProgramId };
125 }
126
127
128 public struct Shader
129 {
130 public int id;
131 }
132
133 public struct ShaderProgram
134 {
135 public int id;
136 }
137 }
138}
139#version 400
140
141in vec3 color_in;
142
143out vec4 color_out;
144
145void main(){
146 color_out = vec4(color_in.r, color_in.g, color_in.b, 1);
147
148}
149
VertexShader (in glsl):
1 using System;
2using OpenTK.Mathematics;
3using OpenTK.Windowing.Desktop;
4using OpenTK.Windowing.Common;
5using System.Drawing;
6using OpenTK.Graphics.OpenGL4;
7using System.IO;
8
9namespace Game_Engine
10{
11 public static class Program
12 {
13 static void Main(string[] args)
14 {
15 Console.WriteLine("Hello World!");
16
17 GameWindowSettings gws = GameWindowSettings.Default;
18 NativeWindowSettings nws = NativeWindowSettings.Default;
19 gws.IsMultiThreaded = false;
20 gws.RenderFrequency = 60;
21 gws.UpdateFrequency = 60;
22
23 nws.APIVersion = Version.Parse("4.1.0");
24 nws.AutoLoadBindings = true;
25 nws.Size = new Vector2i(1280, 720);
26 nws.Title = "Horizon";
27
28
29
30 GameWindow window = new GameWindow(gws, nws);
31
32 window.UpdateFrame += (FrameEventArgs args) => {
33
34
35 };
36
37 ShaderProgram shaderProgram = new ShaderProgram(){id = 0};
38 window.Load += () =>
39 {
40 Console.WriteLine("Hello");
41 ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
42 };
43
44 window.RenderFrame += (FrameEventArgs args) =>
45 {
46 GL.UseProgram( shaderProgram.id );
47
48 GL.ClearColor(1.0f, 0.0f, 0.0f, 0.0f);
49 GL.Clear(ClearBufferMask.ColorBufferBit);
50
51 float[] verts = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f };
52 float[] color = { 1f, 0, 0, 0, 1f ,0 ,0, 0, 1f };
53
54 int vao = GL.GenVertexArray();
55 int vertices = GL.GenBuffer();
56 int colors = GL.GenBuffer();
57 GL.BindVertexArray(vao);
58 GL.BindBuffer(BufferTarget.ArrayBuffer, vertices);
59 GL.BufferData( BufferTarget.ArrayBuffer, verts.Length * sizeof(float), verts, BufferUsageHint.StaticCopy);
60 GL.EnableVertexAttribArray( 0 );
61 GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );
62
63 GL.BindBuffer(BufferTarget.ArrayBuffer, colors);
64 GL.BufferData(BufferTarget.ArrayBuffer, color.Length * sizeof(float), color, BufferUsageHint.StaticCopy);
65 GL.EnableVertexAttribArray(1);
66 GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0);
67
68
69
70 GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
71
72 GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
73 GL.BindVertexArray(0);
74 GL.DeleteBuffer(vertices);
75 GL.DeleteBuffer(colors);
76 GL.DeleteVertexArray( vao );
77
78
79
80 window.SwapBuffers();
81 };
82
83 window.Run();
84
85 }
86
87
88
89 private static Shader LoadShader(string shaderLocation, ShaderType type)
90 {
91 int shaderId = GL.CreateShader( type );
92 GL.ShaderSource( shaderId, File.ReadAllText( shaderLocation ) );
93 GL.CompileShader( shaderId );
94 string infoLog = GL.GetShaderInfoLog( shaderId );
95 if (!string.IsNullOrEmpty(infoLog))
96 {
97 throw new Exception(infoLog);
98 }
99
100 return new Shader() { id = shaderId };
101 }
102
103 private static ShaderProgram LoadShaderProgram( string vertextShaderLocation, string fragmentShaderLocation)
104 {
105 int shaderProgramId = GL.CreateProgram();
106
107 Shader vertextShader = LoadShader(vertextShaderLocation, ShaderType.VertexShader);
108 Shader fragmentShader = LoadShader(fragmentShaderLocation, ShaderType.FragmentShader);
109
110 GL.AttachShader(shaderProgramId, vertextShader.id);
111 GL.AttachShader(shaderProgramId, fragmentShader.id);
112 GL.LinkProgram(shaderProgramId);
113 GL.DetachShader(shaderProgramId, vertextShader.id);
114 GL.DetachShader(shaderProgramId, fragmentShader.id);
115 GL.DeleteShader(vertextShader.id);
116 GL.DeleteShader(fragmentShader.id);
117
118 string infoLog = GL.GetProgramInfoLog(shaderProgramId);
119 if (!string.IsNullOrEmpty(infoLog))
120 {
121 throw new Exception(infoLog);
122 }
123
124 return new ShaderProgram() { id = shaderProgramId };
125 }
126
127
128 public struct Shader
129 {
130 public int id;
131 }
132
133 public struct ShaderProgram
134 {
135 public int id;
136 }
137 }
138}
139#version 400
140
141in vec3 color_in;
142
143out vec4 color_out;
144
145void main(){
146 color_out = vec4(color_in.r, color_in.g, color_in.b, 1);
147
148}
149#version 330
150
151
152layout(location = 0) in vec3 vPosition;
153layout(location = 1) in vec3 vColors;
154
155out vec3 color_in;
156
157void main() {
158 color_in = vColors;
159 gl_Position = vec4( vPosition, 1.0 );
160
161}
162
I have tried everything I could with my very limited knowledge of OpenTK and nothing has changed. I have searched on the web and for answer they still have not helped
ANSWER
Answered 2022-Apr-03 at 07:08You actually assign the shader program to a local variable in the event callback function's scope. You need to assign it to the variable in scope of Main
:
1 using System;
2using OpenTK.Mathematics;
3using OpenTK.Windowing.Desktop;
4using OpenTK.Windowing.Common;
5using System.Drawing;
6using OpenTK.Graphics.OpenGL4;
7using System.IO;
8
9namespace Game_Engine
10{
11 public static class Program
12 {
13 static void Main(string[] args)
14 {
15 Console.WriteLine("Hello World!");
16
17 GameWindowSettings gws = GameWindowSettings.Default;
18 NativeWindowSettings nws = NativeWindowSettings.Default;
19 gws.IsMultiThreaded = false;
20 gws.RenderFrequency = 60;
21 gws.UpdateFrequency = 60;
22
23 nws.APIVersion = Version.Parse("4.1.0");
24 nws.AutoLoadBindings = true;
25 nws.Size = new Vector2i(1280, 720);
26 nws.Title = "Horizon";
27
28
29
30 GameWindow window = new GameWindow(gws, nws);
31
32 window.UpdateFrame += (FrameEventArgs args) => {
33
34
35 };
36
37 ShaderProgram shaderProgram = new ShaderProgram(){id = 0};
38 window.Load += () =>
39 {
40 Console.WriteLine("Hello");
41 ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
42 };
43
44 window.RenderFrame += (FrameEventArgs args) =>
45 {
46 GL.UseProgram( shaderProgram.id );
47
48 GL.ClearColor(1.0f, 0.0f, 0.0f, 0.0f);
49 GL.Clear(ClearBufferMask.ColorBufferBit);
50
51 float[] verts = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f };
52 float[] color = { 1f, 0, 0, 0, 1f ,0 ,0, 0, 1f };
53
54 int vao = GL.GenVertexArray();
55 int vertices = GL.GenBuffer();
56 int colors = GL.GenBuffer();
57 GL.BindVertexArray(vao);
58 GL.BindBuffer(BufferTarget.ArrayBuffer, vertices);
59 GL.BufferData( BufferTarget.ArrayBuffer, verts.Length * sizeof(float), verts, BufferUsageHint.StaticCopy);
60 GL.EnableVertexAttribArray( 0 );
61 GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );
62
63 GL.BindBuffer(BufferTarget.ArrayBuffer, colors);
64 GL.BufferData(BufferTarget.ArrayBuffer, color.Length * sizeof(float), color, BufferUsageHint.StaticCopy);
65 GL.EnableVertexAttribArray(1);
66 GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0);
67
68
69
70 GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
71
72 GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
73 GL.BindVertexArray(0);
74 GL.DeleteBuffer(vertices);
75 GL.DeleteBuffer(colors);
76 GL.DeleteVertexArray( vao );
77
78
79
80 window.SwapBuffers();
81 };
82
83 window.Run();
84
85 }
86
87
88
89 private static Shader LoadShader(string shaderLocation, ShaderType type)
90 {
91 int shaderId = GL.CreateShader( type );
92 GL.ShaderSource( shaderId, File.ReadAllText( shaderLocation ) );
93 GL.CompileShader( shaderId );
94 string infoLog = GL.GetShaderInfoLog( shaderId );
95 if (!string.IsNullOrEmpty(infoLog))
96 {
97 throw new Exception(infoLog);
98 }
99
100 return new Shader() { id = shaderId };
101 }
102
103 private static ShaderProgram LoadShaderProgram( string vertextShaderLocation, string fragmentShaderLocation)
104 {
105 int shaderProgramId = GL.CreateProgram();
106
107 Shader vertextShader = LoadShader(vertextShaderLocation, ShaderType.VertexShader);
108 Shader fragmentShader = LoadShader(fragmentShaderLocation, ShaderType.FragmentShader);
109
110 GL.AttachShader(shaderProgramId, vertextShader.id);
111 GL.AttachShader(shaderProgramId, fragmentShader.id);
112 GL.LinkProgram(shaderProgramId);
113 GL.DetachShader(shaderProgramId, vertextShader.id);
114 GL.DetachShader(shaderProgramId, fragmentShader.id);
115 GL.DeleteShader(vertextShader.id);
116 GL.DeleteShader(fragmentShader.id);
117
118 string infoLog = GL.GetProgramInfoLog(shaderProgramId);
119 if (!string.IsNullOrEmpty(infoLog))
120 {
121 throw new Exception(infoLog);
122 }
123
124 return new ShaderProgram() { id = shaderProgramId };
125 }
126
127
128 public struct Shader
129 {
130 public int id;
131 }
132
133 public struct ShaderProgram
134 {
135 public int id;
136 }
137 }
138}
139#version 400
140
141in vec3 color_in;
142
143out vec4 color_out;
144
145void main(){
146 color_out = vec4(color_in.r, color_in.g, color_in.b, 1);
147
148}
149#version 330
150
151
152layout(location = 0) in vec3 vPosition;
153layout(location = 1) in vec3 vColors;
154
155out vec3 color_in;
156
157void main() {
158 color_in = vColors;
159 gl_Position = vec4( vPosition, 1.0 );
160
161}
162ShaderProgram shaderProgram = new ShaderProgram() { id = 0 };
163window.Load += () =>
164{
165 Console.WriteLine("Hello");
166
167 // ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
168 shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
169};
170
QUESTION
Area2D Not Triggering Object in Godot
Asked 2022-Mar-23 at 23:20Here is my code: (just so you know I am a beginner and I just started this week, though I do have knowledge with other languages and game engines)
1func _on_Area2D_area_entered(area):
2 get_parent().get_node("Level 1/Area2D/Flag").rotation_degrees += 1
3
What I was trying to accomplish was that the Player GameObject would see if its in the area of the Flag, and if it is, the flag would rotate.
I am not sure where the issue is. I think it is probably in the second line. I provided a screenshot below if I did the setup wrong. I have looked at the other close questions asked on the same topic, but they did not answer my question.
The "Player" GameObject is the one with the script that contains the detection if its in the area2D.
ANSWER
Answered 2022-Mar-23 at 23:20If you want to check if the Area2D
is positioned correctly during runtime enable Debug -> Visible Collision Shapes.
If you want to check if _on_Area2D_area_entered
is running, add breakpoints (or use print).
Did you get an error?
If there isn't a Node
there, this expression will cause an error in runtime:
1func _on_Area2D_area_entered(area):
2 get_parent().get_node("Level 1/Area2D/Flag").rotation_degrees += 1
3get_parent().get_node("Level 1/Area2D/Flag")
4
If you want to be able to check, you can use get_node_or_null
and is_instance_valid
.
Since you didn't mention any error, I'm going to guess the method is not running.
If the method is not running, the most likely culprit is that - I'm guessing given then name of the method - you connected the "area_entered"
signal but intended to connect the "body_entered"
signal.
The "area_entered"
signal will trigger when another Area2D
enters the Area2D
. But I only see one Area2D
in your scene tree. On the other hand the "body_entered"
will trigger when a PhysicsBody2D
(e.g StaticBody2D
, KinematicBody2D
, RigidBody2D
) enters the Area2D
. In either case you get what entered as a parameter of the method.
Other reasons why the Area2D
might not be detecting what you want include no intersection of collision_layer
and collision_mask
and monitoring
being disabled.
And to dismiss a couple possible misconceptions:
"area_entered"
and "body_entered"
trigger when the Area2D
or PhysicsBody2D
respectively enter the Area2D
, not every frame they are inside. So rotation_degrees += 1
is not a rotation animation.if body == self:
.QUESTION
AnimationPlayer seek() using threading
Asked 2022-Mar-20 at 16:16I have a script attached to an AnimationPlayer
node and it does some long calculations,
so in order to avoid the game engine from hanging while those calculations take place
I created a separate thread for that function,
but the seek()
function doesn't update the animation despite adding update=true
I've narrowed it down to this simple example:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14
here's how the tree looks like:
so how to I get the seek()
to work or is there any workaround with what I'm trying to achieve?
Edit:
I tried applied the solution @Theraot gave & modified it to loop through all the animations
like this:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14func sep(thread:Thread):
15 var AnimationList=self.get_animation_list();
16 for animation_name in AnimationList:
17
18 self.current_animation=animation_name;
19 var ongoing_animation=self.get_animation(animation_name);
20 for track_indx in ongoing_animation.get_track_count():
21 for key_indx in ongoing_animation.track_get_key_count(track_indx):
22 var key_time=ongoing_animation.track_get_key_time(track_indx, key_indx);
23 self.seek(key_time,true);
24
25 Translate=false;
26 property_list_changed_notify();
27 thread.call_deferred("wait_to_finish")
28
29func Translate_Changed(new_val):
30
31 if _thread == null or _thread.is_active():
32 _thread = Thread.new();
33
34 _thread.start(self, "sep", _thread);
35
But when I run this for a big animation it gets stuck in between & the entire godot game engine hangs
I'm guessing it's a memory leak?
what am I trying to achieve?
I've actually created custom properties on a node and added those custom properties as keys in an AnimationPlayer
but these custom properties all effect position
, rotation
& other inbuilt properties.
so I thought by seek()
I could see the end result of all them combined and then key the position
, rotation
& other inbuilt properties to another AnimationPlayer
ANSWER
Answered 2022-Mar-20 at 12:34After testing, it appears to me that it works with a couple caveats:
Once done properly it works on Godot 3.2 or newer. However, starting with Godot 3.4 I could be more sloppy with how I handle the thread and it would still work.
First of all, you need to call wait_to_finish
when the thread ends. Not doing it will prevent proper cleanup. If you don't have code waiting for the thread to finish, you can add this at the end of the thread code:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14func sep(thread:Thread):
15 var AnimationList=self.get_animation_list();
16 for animation_name in AnimationList:
17
18 self.current_animation=animation_name;
19 var ongoing_animation=self.get_animation(animation_name);
20 for track_indx in ongoing_animation.get_track_count():
21 for key_indx in ongoing_animation.track_get_key_count(track_indx):
22 var key_time=ongoing_animation.track_get_key_time(track_indx, key_indx);
23 self.seek(key_time,true);
24
25 Translate=false;
26 property_list_changed_notify();
27 thread.call_deferred("wait_to_finish")
28
29func Translate_Changed(new_val):
30
31 if _thread == null or _thread.is_active():
32 _thread = Thread.new();
33
34 _thread.start(self, "sep", _thread);
35thread.call_deferred("wait_to_finish")
36
Using call_deferred
(or set_deferred
or emit_signal
) allows the thread to issue operations on the main thread.
By the way, you can reuse the thread by calling start
on it again after it finished. So you don't need to create a new Thread
each time. So you can do this:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14func sep(thread:Thread):
15 var AnimationList=self.get_animation_list();
16 for animation_name in AnimationList:
17
18 self.current_animation=animation_name;
19 var ongoing_animation=self.get_animation(animation_name);
20 for track_indx in ongoing_animation.get_track_count():
21 for key_indx in ongoing_animation.track_get_key_count(track_indx):
22 var key_time=ongoing_animation.track_get_key_time(track_indx, key_indx);
23 self.seek(key_time,true);
24
25 Translate=false;
26 property_list_changed_notify();
27 thread.call_deferred("wait_to_finish")
28
29func Translate_Changed(new_val):
30
31 if _thread == null or _thread.is_active():
32 _thread = Thread.new();
33
34 _thread.start(self, "sep", _thread);
35thread.call_deferred("wait_to_finish")
36if thread == null:
37 thread = Thread.new()
38
But! The thread will be running for the long computations, and you cannot call start
on it while it is running. A simple solution is to start another one:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14func sep(thread:Thread):
15 var AnimationList=self.get_animation_list();
16 for animation_name in AnimationList:
17
18 self.current_animation=animation_name;
19 var ongoing_animation=self.get_animation(animation_name);
20 for track_indx in ongoing_animation.get_track_count():
21 for key_indx in ongoing_animation.track_get_key_count(track_indx):
22 var key_time=ongoing_animation.track_get_key_time(track_indx, key_indx);
23 self.seek(key_time,true);
24
25 Translate=false;
26 property_list_changed_notify();
27 thread.call_deferred("wait_to_finish")
28
29func Translate_Changed(new_val):
30
31 if _thread == null or _thread.is_active():
32 _thread = Thread.new();
33
34 _thread.start(self, "sep", _thread);
35thread.call_deferred("wait_to_finish")
36if thread == null:
37 thread = Thread.new()
38if thread == null or thread.is_active():
39 thread = Thread.new()
40
I don't know if there are race conditions to be aware of. Take into consideration the possibility of two threads running at the same time.
But! that means that when the thread calls thread.call_deferred("wait_to_finish")
that would not be the correct one. So we are going to pass the thread
as parameter to the thread
.
This is how my code looks like:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14func sep(thread:Thread):
15 var AnimationList=self.get_animation_list();
16 for animation_name in AnimationList:
17
18 self.current_animation=animation_name;
19 var ongoing_animation=self.get_animation(animation_name);
20 for track_indx in ongoing_animation.get_track_count():
21 for key_indx in ongoing_animation.track_get_key_count(track_indx):
22 var key_time=ongoing_animation.track_get_key_time(track_indx, key_indx);
23 self.seek(key_time,true);
24
25 Translate=false;
26 property_list_changed_notify();
27 thread.call_deferred("wait_to_finish")
28
29func Translate_Changed(new_val):
30
31 if _thread == null or _thread.is_active():
32 _thread = Thread.new();
33
34 _thread.start(self, "sep", _thread);
35thread.call_deferred("wait_to_finish")
36if thread == null:
37 thread = Thread.new()
38if thread == null or thread.is_active():
39 thread = Thread.new()
40tool
41extends AnimationPlayer
42export(float,0,1,0.1) var aniTimer = 0.0 setget aniTimer_Changed
43var _thread:Thread
44
45func sep(thread:Thread):
46 seek(aniTimer, true)
47 # calculations #
48 thread.call_deferred("wait_to_finish")
49
50func aniTimer_Changed(new_val):
51 aniTimer=new_val
52 if _thread == null or _thread.is_active():
53 _thread = Thread.new()
54
55 # warning-ignore:return_value_discarded
56 _thread.start(self, "sep", _thread)
57
QUESTION
Using Microsoft Authentication Library (MSAL) in Unity for SSO in iOS app
Asked 2022-Mar-16 at 09:31We develop a bunch of augmented reality applications for our company. The applications are based on the game engine Unity (currently in the version 2020.3.7f1). Now, we're facing the point that we'd like to implement a SSO method in our apps, so every member of our company authenticates himself with his company user credentials. To authenticate the user we want to / have to use the Microsoft identity platform and thus the Microsoft Authentication Library (MSAL).
We already created an client on Azure with a client id, redirect uri, authority uri, endpoint, tenant, etc and it was tested successfully with an official sample project by Microsoft (https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-ios).
But now we stuck at the point to establish this process in Unity. We created the MSAL library dll (https://github.com/AzureAD/microsoft-authentication-library-for-dotnet), imported it into Unity and called it by using the namespace Microsoft.Identity.Client. Due to security reasons we're only allowed to use PublicClientApplicationBuilder (which makes totally sense) so we need the web based login screen. The problem is that we can't implement a web view in Unity where the user can sign in to Microsoft and we can parse the received token out of the web view into our app for further communications.
We did a lot of internet research to find a solution but there are only some posts about MSAL in Unity in combination with Android and other posts which reference to the git repos I mentioned before.
How can we use MSAL in Unity for iOS devices?
Example code:
1 IPublicClientApplication PublicClientApp = PublicClientApplicationBuilder
2 .Create(kClientID)
3 .WithRedirectUri(kRedirectUri)
4 .WithAuthority(new Uri(kAuthority))
5 .Build();
6 IEnumerable<string> scopes = new List<string> { "https://graph.microsoft.com/.default" };
7 AuthenticationResult result;
8 result = await PublicClientApp.AcquireTokenInteractive(scopes)
9 .ExecuteAsync();
10
11 result = await PublicClientApp
12 .AcquireTokenInteractive(scopes)
13 .WithParentActivityOrWindow(new object)
14 .ExecuteAsync();
15
16 Debug.Log(result.AccessToken);
17
ANSWER
Answered 2021-Nov-16 at 13:45The standard solution for mobile is the AppAuth pattern, which involves use of an integrated system browser to sign the user in. See this code example article for how that looks, so that you understand the required behaviour.
So it looks like they key thing to do with iOS is to avoid logins via webviews and tell MSAL to use an ASWebAuthenticationSession window - this Microsoft article explains how.
QUESTION
Why is only 1 Depth/Stencil buffer needed, even when the swap chain is tripple buffered DirectX12
Asked 2022-Mar-15 at 12:27I am learning DirectX12 programming. And one thing that has me confused is in all the tutorials I read, they only create a single depth/stencil buffer even when triple/double buffering is used with the swap chain. Wouldn't you need a depth/stencil buffer for each frame?
Code in question:
1 D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
2 dsvHeapDesc.NumDescriptors = 1; //why only 1?
3 dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
4 dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
5 if(FAILED(device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&dsDescriptorHeap))))
6 {
7 MessageBoxW(NULL, L"Failed to create depth buffer descriptor heap!", L"Error", MB_OK | MB_ICONERROR);
8 return -1;
9 }
10 D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {};
11 depthStencilDesc.Format = DXGI_FORMAT_D32_FLOAT;
12 depthStencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
13 depthStencilDesc.Flags = D3D12_DSV_FLAG_NONE;
14
15 D3D12_CLEAR_VALUE depthOptimizedClearValue = {};
16 depthOptimizedClearValue.Format = DXGI_FORMAT_D32_FLOAT;
17 depthOptimizedClearValue.DepthStencil.Depth = 1.0f;
18 depthOptimizedClearValue.DepthStencil.Stencil = 0;
19
20 device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D32_FLOAT, width, height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL), D3D12_RESOURCE_STATE_DEPTH_WRITE, &depthOptimizedClearValue, IID_PPV_ARGS(&depthStencilBuffer));
21 depthStencilBuffer->SetName(L"Depth/Stencil Resource Heap");
22 device->CreateDepthStencilView(depthStencilBuffer, &depthStencilDesc, dsDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
23
24
ANSWER
Answered 2022-Mar-15 at 12:27Generally speaking, "intermediate resources" (such as depth stencils and intermediate render targets) are not presented on the screen.
So when one swapchain is ready to present (and you start recording next frame commands), those resources can be safely overridden, since the content is ready within the swap chain.
The only exception for those resources are generally buffers that are uploaded from cpu, for them it is needed to have one per frame (since you will start to copy data while another command list is still executing).
QUESTION
How to structure a project in Monogame
Asked 2022-Mar-14 at 17:18I'm trying to create a PC version of a cord-driven turn-based boardgame. I went for the Monogame framework in c#. I'm still learning C# and Monogame and I'm reading all about how it is important to "split" the code in the data/game engine part and the graphics/GUI part. So trying to pursue this, I have the following in mind.
Graphics/GUI
Here I define all the classes relative to the screens (game - menus), GUI components like labels and buttons and possibly even mouse and keyboard inputs (the logic being the user has to click on something in the gui in order to perform an action).
Data or Game logic/Engine
Still not even sure on how I should call this part of the project, here I would put all the logic of the game. The classes of player, cards, "IA", rules etc... would be defined here.
My difficulty is now to understand how to connect this two parts but still maintain the "loosely coupled" approach. I was thinking that maybe the objects or better the instances of the game logic part would have to subscribe to events (such as button_click) defined in the GUI part...but can I even subscribe to events of another class? Is this the correct way?
I admit I'm still trying to fully understand the event driven concept, but is this the right way of doing stuff in c# and Monogame? I apologize for the vague topic/question but thanks in advance.
ANSWER
Answered 2022-Mar-14 at 17:18I don't know anything about Monogame, but generally it's a good idea to organise any kind of application into layers like this, as long as you don't make the code overly complicated by doing so. Your idea to separate the UI code from the game logic sounds like a good start.
First, think of your application as an onion, with a series of concentric layers. Your proposed structure has only two layers, but that's OK. A larger application may benefit from more layers, e.g. a data access layer if you were to store the state of the game in a database, but there's no need to add extra layers just for the sake of having more layers.
Your outermost layer would contain the UI code, typically this is known as the presentation layer.
Your innermost layer would contain the game logic, typically this is known as the domain layer. A good rule of thumb for whether something belongs in the domain layer is to ask, does this represent something that a user of your application (or a player of your game) who's not a developer would recognise?
Second, remember that each layer can make calls to code in the same layer, or to code in in other layers inside it, but not to code in layers outside it. So projects in the presentation layer can have references to projects in the domain layer, but projects in the domain layer can't have references to projects in the presentation layer. If you've got circular references between the two layers then it's a sign that something in one of the layers actually belongs in the other layer.
Here's another answer to a similar question about layering an application, albeit not in the context of a game: https://stackoverflow.com/a/70315655/16563198
On the second part of the question, if you want to use events then it's probably best to handle any events in the presentation layer and have the event handlers make calls into the domain layer (but disclaimer, I don't know Monogame).
QUESTION
Godot Invalid to get index 'x' (On Base: 'Node (a.gd)')
Asked 2022-Jan-21 at 10:30im trying to hold a path to a game object (bat.tscn) in a script and use it to instanceate a object from a different script. Name of the script that holds the variable is called a.gd and the one that is responsible for instantiating is b.gd and the name of the variable is x. But for some reason every time i try to use the variable it gives me an error;
1Invalid to get index 'x' (On Base: 'Node (a.gd)')
2
a.gd;
1Invalid to get index 'x' (On Base: 'Node (a.gd)')
2func _process(delta):
3var SlotOne = $"res://Objects/Weapons/Bat.tscn
4
b.gd;
1Invalid to get index 'x' (On Base: 'Node (a.gd)')
2func _process(delta):
3var SlotOne = $"res://Objects/Weapons/Bat.tscn
4onready var InvManager = get_node("../a") #gets the script.
5
6func _physics_process(delta):
7 changeWeapons()
8
9func changeWeapons():
10 if Input.is_key_pressed(KEY_1):
11 load(InvManager.SlotOne)
12 elif Input.is_key_pressed(KEY_2):
13 print("2")
14 elif Input.is_key_pressed(KEY_3):
15 print("3")
16 elif Input.is_key_pressed(KEY_4):
17 print("4")
18
any ideas how can i fix this issue? Im pretty new to the game engine so im kinda stuck here.
ANSWER
Answered 2022-Jan-19 at 13:08also a possible explanation is that instead of using or instancing the node you are trying to access it
so first try to add the node to the main scene like this
1Invalid to get index 'x' (On Base: 'Node (a.gd)')
2func _process(delta):
3var SlotOne = $"res://Objects/Weapons/Bat.tscn
4onready var InvManager = get_node("../a") #gets the script.
5
6func _physics_process(delta):
7 changeWeapons()
8
9func changeWeapons():
10 if Input.is_key_pressed(KEY_1):
11 load(InvManager.SlotOne)
12 elif Input.is_key_pressed(KEY_2):
13 print("2")
14 elif Input.is_key_pressed(KEY_3):
15 print("3")
16 elif Input.is_key_pressed(KEY_4):
17 print("4")
18get_tree().current_scene().add_child("#the path to a.gd")
19
but anyways only the code can can tell us what is wrong
QUESTION
Copy output of custom target in one CSPROJ into another CSPROJ
Asked 2022-Jan-14 at 05:57So I'm developing a game engine framework for myself in C#/.NET and I have been trying to simplify building shader files (the rendering engine consumes SPIR-V files, which I want to generate from GLSL source). My current approach has been to use a custom .targets file which is imported into a CSPROJ, and that file defines a custom target like this:
1<Target
2 Name="Vert"
3 AfterTargets="Build">
4 <MakeDir Directories="$(OutputPath)%(VertShader.RelativeDir)"/>
5 <Exec Command='"$(ENGINE_ROOT)\tools\glslang\windows-x64\glslangValidator.exe" -V %(VertShader.Identity) %(VertShader.OptLevel) -o $(OutputPath)%(VertShader.Identity).spv'></Exec>
6</Target>
7
The general idea behind this is it takes VertShader items, runs the .vert file through glslang, and spits the output .vert.spv file into the build output directory. This works great, almost.
The problem is, if I have Project A that has a bunch of shaders, and then Project B which has a reference to Project A, I want to copy the .vert.spv shaders that Project A generates into the build output directory of Project B, but I haven't had much luck wrangling the target syntax to do what I want.
Is there any way I can get this working the way I'm describing?
ANSWER
Answered 2022-Jan-14 at 02:16I am not sure I understand your problem correctly, but if you want your .vert.spv copied to another folder use File.Copy()
QUESTION
Algorithm to fill arbitrary marked/selected tiles on a square grid with the smallest number of rectangles?
Asked 2022-Jan-12 at 15:58What I am asking here is an algorithm question. I'm not asking for specifics of how to do it in the programming language I'm working in or with the framework and libraries I'm currently using. I want to know how to do this in principle.
As a hobby, I am working on an open source virtual reality remake of the 1992 first-person shooter game Wolfenstein 3D. My program will support classic mods and map packs for WOLF3D made in the original format from the 90s. This means that my program will not know in advance what the maps are going to be. They are loaded in at runtime from user provided files.
A Wolfenstein 3D map is a 2D square grid of normally 64x64 tiles. let's assume I have a 2D array of bools which return true if a particular tile can be traversed by the player and false if the tile will never be traversable no matter what happens in the game.
I want to generate rectangular collision objects for a modern game engine which will prevent collisions into non traversable tiles on the map. Right now, I have a small collision object on each surface of each wall tile with a traversible tile next to it and that is very inefficient because it makes way more collision objects than necessary. What I should have instead is a smaller number of large rectangles which fill all of the squares on the grid where that 2D array I mentioned has a false value to indicate non-traversible.
When I search for any algorithms or research that might have been done for problems similar to this, I find lots of information about rectangle packing for the purposes of making texture atlases for games, which packs rectangles into a square, but I haven't found anything that tries to pack the smallest number of rectangles into an arbitrary set of selected / marked square tiles.
The naive approach which occurs to me is to first make 64 rectangles representing 64 rows and then chop out whatever squares are traversible. but I suspect that there's got to be an algorithm which can do better, meaning that it can fill the same spaces with a smaller number of rectangles. Maybe something that starts with my naive approach and then checks each rectangle for adjacent rectangles which it could merge with? But I'm not sure how far to take that approach or if it will even truly reduce the number of rectangles.
The result doesn't have to be perfect. I am just fishing here to see if anyone has any magic tricks that could take me even a little bit beyond the naive approach.
Has anyone done this before? What is it called? Just knowing what some of the vocabulary words I would need to even talk about this are would help. Thanks!
(later edit)
Here is some sample input as comma-separated values. The 1s represent the area that must be filled with the rectangles while the 0s represent the area that should not be filled with the rectangles.
I expect that the result would be a list of sets of 4 integers where each set represents a rectangle like this:
My program is in C# but I'm sure I can translate anything in a normal mainstream general purpose programming language or psuedocode.
ANSWER
Answered 2022-Jan-12 at 14:461Mark all tiles as not visited
2For each tile:
3 skip if the tile is not a top-left corner or was visited before
4 # now, the tile is a top-left corner
5 expand right until top-right corner is found
6 expand down
7 save the rectangle
8 mark all tiles in the rectangle as visited
9
However simplistic it looks, it will likely generate minimal number of rectangles - simply because we need at least one rectangle per pair of top corners.
For faster downward expansion, it makes sense to precompute a table holding sum of all element top and left from the tile (aka integral image).
For non-overlapping rectangles, worst case complexity for an n x n
"image" should not exceed O(n^3)
. If rectangles can overlap (would result in smaller number of them), integral image optimization is not applicable and the worst case will be O(n^4)
.
Community Discussions contain sources that include Stack Exchange Network
QUESTION
Unity App: How to check available space left on Android / IOS device
Asked 2022-Apr-16 at 14:01I am developing a game (iOS/Android with Unity Game Engine) that requires to download resources to be stored locally on device. I wish to check free space on device to send an error message before download starts in case it's not enough.
How can I check it? I couldn't find any clear procedure on my research.
ANSWER
Answered 2022-Apr-16 at 14:01It varies by platform so isn’t a simple answer. The free Unity plugin Simple Disk Utils handles it for you on Windows, Mac, Android and iOS and full source code is available on GitHub so you can see for yourself how it’s achieved on the different platforms.
QUESTION
OpenTK doesn't render the color of my triangle
Asked 2022-Apr-03 at 07:08I am learning to program a game engine which is why I followed a tutorial, with that tutorial I have gotten this far and even though my code is identical to theirs (theirs did work in the videos) its not working the way it is meant to. The triangle stays black no matter what. There is not any errors.
Main Program Script:
1 using System;
2using OpenTK.Mathematics;
3using OpenTK.Windowing.Desktop;
4using OpenTK.Windowing.Common;
5using System.Drawing;
6using OpenTK.Graphics.OpenGL4;
7using System.IO;
8
9namespace Game_Engine
10{
11 public static class Program
12 {
13 static void Main(string[] args)
14 {
15 Console.WriteLine("Hello World!");
16
17 GameWindowSettings gws = GameWindowSettings.Default;
18 NativeWindowSettings nws = NativeWindowSettings.Default;
19 gws.IsMultiThreaded = false;
20 gws.RenderFrequency = 60;
21 gws.UpdateFrequency = 60;
22
23 nws.APIVersion = Version.Parse("4.1.0");
24 nws.AutoLoadBindings = true;
25 nws.Size = new Vector2i(1280, 720);
26 nws.Title = "Horizon";
27
28
29
30 GameWindow window = new GameWindow(gws, nws);
31
32 window.UpdateFrame += (FrameEventArgs args) => {
33
34
35 };
36
37 ShaderProgram shaderProgram = new ShaderProgram(){id = 0};
38 window.Load += () =>
39 {
40 Console.WriteLine("Hello");
41 ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
42 };
43
44 window.RenderFrame += (FrameEventArgs args) =>
45 {
46 GL.UseProgram( shaderProgram.id );
47
48 GL.ClearColor(1.0f, 0.0f, 0.0f, 0.0f);
49 GL.Clear(ClearBufferMask.ColorBufferBit);
50
51 float[] verts = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f };
52 float[] color = { 1f, 0, 0, 0, 1f ,0 ,0, 0, 1f };
53
54 int vao = GL.GenVertexArray();
55 int vertices = GL.GenBuffer();
56 int colors = GL.GenBuffer();
57 GL.BindVertexArray(vao);
58 GL.BindBuffer(BufferTarget.ArrayBuffer, vertices);
59 GL.BufferData( BufferTarget.ArrayBuffer, verts.Length * sizeof(float), verts, BufferUsageHint.StaticCopy);
60 GL.EnableVertexAttribArray( 0 );
61 GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );
62
63 GL.BindBuffer(BufferTarget.ArrayBuffer, colors);
64 GL.BufferData(BufferTarget.ArrayBuffer, color.Length * sizeof(float), color, BufferUsageHint.StaticCopy);
65 GL.EnableVertexAttribArray(1);
66 GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0);
67
68
69
70 GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
71
72 GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
73 GL.BindVertexArray(0);
74 GL.DeleteBuffer(vertices);
75 GL.DeleteBuffer(colors);
76 GL.DeleteVertexArray( vao );
77
78
79
80 window.SwapBuffers();
81 };
82
83 window.Run();
84
85 }
86
87
88
89 private static Shader LoadShader(string shaderLocation, ShaderType type)
90 {
91 int shaderId = GL.CreateShader( type );
92 GL.ShaderSource( shaderId, File.ReadAllText( shaderLocation ) );
93 GL.CompileShader( shaderId );
94 string infoLog = GL.GetShaderInfoLog( shaderId );
95 if (!string.IsNullOrEmpty(infoLog))
96 {
97 throw new Exception(infoLog);
98 }
99
100 return new Shader() { id = shaderId };
101 }
102
103 private static ShaderProgram LoadShaderProgram( string vertextShaderLocation, string fragmentShaderLocation)
104 {
105 int shaderProgramId = GL.CreateProgram();
106
107 Shader vertextShader = LoadShader(vertextShaderLocation, ShaderType.VertexShader);
108 Shader fragmentShader = LoadShader(fragmentShaderLocation, ShaderType.FragmentShader);
109
110 GL.AttachShader(shaderProgramId, vertextShader.id);
111 GL.AttachShader(shaderProgramId, fragmentShader.id);
112 GL.LinkProgram(shaderProgramId);
113 GL.DetachShader(shaderProgramId, vertextShader.id);
114 GL.DetachShader(shaderProgramId, fragmentShader.id);
115 GL.DeleteShader(vertextShader.id);
116 GL.DeleteShader(fragmentShader.id);
117
118 string infoLog = GL.GetProgramInfoLog(shaderProgramId);
119 if (!string.IsNullOrEmpty(infoLog))
120 {
121 throw new Exception(infoLog);
122 }
123
124 return new ShaderProgram() { id = shaderProgramId };
125 }
126
127
128 public struct Shader
129 {
130 public int id;
131 }
132
133 public struct ShaderProgram
134 {
135 public int id;
136 }
137 }
138}
139
Fragment Shader (in glsl):
1 using System;
2using OpenTK.Mathematics;
3using OpenTK.Windowing.Desktop;
4using OpenTK.Windowing.Common;
5using System.Drawing;
6using OpenTK.Graphics.OpenGL4;
7using System.IO;
8
9namespace Game_Engine
10{
11 public static class Program
12 {
13 static void Main(string[] args)
14 {
15 Console.WriteLine("Hello World!");
16
17 GameWindowSettings gws = GameWindowSettings.Default;
18 NativeWindowSettings nws = NativeWindowSettings.Default;
19 gws.IsMultiThreaded = false;
20 gws.RenderFrequency = 60;
21 gws.UpdateFrequency = 60;
22
23 nws.APIVersion = Version.Parse("4.1.0");
24 nws.AutoLoadBindings = true;
25 nws.Size = new Vector2i(1280, 720);
26 nws.Title = "Horizon";
27
28
29
30 GameWindow window = new GameWindow(gws, nws);
31
32 window.UpdateFrame += (FrameEventArgs args) => {
33
34
35 };
36
37 ShaderProgram shaderProgram = new ShaderProgram(){id = 0};
38 window.Load += () =>
39 {
40 Console.WriteLine("Hello");
41 ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
42 };
43
44 window.RenderFrame += (FrameEventArgs args) =>
45 {
46 GL.UseProgram( shaderProgram.id );
47
48 GL.ClearColor(1.0f, 0.0f, 0.0f, 0.0f);
49 GL.Clear(ClearBufferMask.ColorBufferBit);
50
51 float[] verts = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f };
52 float[] color = { 1f, 0, 0, 0, 1f ,0 ,0, 0, 1f };
53
54 int vao = GL.GenVertexArray();
55 int vertices = GL.GenBuffer();
56 int colors = GL.GenBuffer();
57 GL.BindVertexArray(vao);
58 GL.BindBuffer(BufferTarget.ArrayBuffer, vertices);
59 GL.BufferData( BufferTarget.ArrayBuffer, verts.Length * sizeof(float), verts, BufferUsageHint.StaticCopy);
60 GL.EnableVertexAttribArray( 0 );
61 GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );
62
63 GL.BindBuffer(BufferTarget.ArrayBuffer, colors);
64 GL.BufferData(BufferTarget.ArrayBuffer, color.Length * sizeof(float), color, BufferUsageHint.StaticCopy);
65 GL.EnableVertexAttribArray(1);
66 GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0);
67
68
69
70 GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
71
72 GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
73 GL.BindVertexArray(0);
74 GL.DeleteBuffer(vertices);
75 GL.DeleteBuffer(colors);
76 GL.DeleteVertexArray( vao );
77
78
79
80 window.SwapBuffers();
81 };
82
83 window.Run();
84
85 }
86
87
88
89 private static Shader LoadShader(string shaderLocation, ShaderType type)
90 {
91 int shaderId = GL.CreateShader( type );
92 GL.ShaderSource( shaderId, File.ReadAllText( shaderLocation ) );
93 GL.CompileShader( shaderId );
94 string infoLog = GL.GetShaderInfoLog( shaderId );
95 if (!string.IsNullOrEmpty(infoLog))
96 {
97 throw new Exception(infoLog);
98 }
99
100 return new Shader() { id = shaderId };
101 }
102
103 private static ShaderProgram LoadShaderProgram( string vertextShaderLocation, string fragmentShaderLocation)
104 {
105 int shaderProgramId = GL.CreateProgram();
106
107 Shader vertextShader = LoadShader(vertextShaderLocation, ShaderType.VertexShader);
108 Shader fragmentShader = LoadShader(fragmentShaderLocation, ShaderType.FragmentShader);
109
110 GL.AttachShader(shaderProgramId, vertextShader.id);
111 GL.AttachShader(shaderProgramId, fragmentShader.id);
112 GL.LinkProgram(shaderProgramId);
113 GL.DetachShader(shaderProgramId, vertextShader.id);
114 GL.DetachShader(shaderProgramId, fragmentShader.id);
115 GL.DeleteShader(vertextShader.id);
116 GL.DeleteShader(fragmentShader.id);
117
118 string infoLog = GL.GetProgramInfoLog(shaderProgramId);
119 if (!string.IsNullOrEmpty(infoLog))
120 {
121 throw new Exception(infoLog);
122 }
123
124 return new ShaderProgram() { id = shaderProgramId };
125 }
126
127
128 public struct Shader
129 {
130 public int id;
131 }
132
133 public struct ShaderProgram
134 {
135 public int id;
136 }
137 }
138}
139#version 400
140
141in vec3 color_in;
142
143out vec4 color_out;
144
145void main(){
146 color_out = vec4(color_in.r, color_in.g, color_in.b, 1);
147
148}
149
VertexShader (in glsl):
1 using System;
2using OpenTK.Mathematics;
3using OpenTK.Windowing.Desktop;
4using OpenTK.Windowing.Common;
5using System.Drawing;
6using OpenTK.Graphics.OpenGL4;
7using System.IO;
8
9namespace Game_Engine
10{
11 public static class Program
12 {
13 static void Main(string[] args)
14 {
15 Console.WriteLine("Hello World!");
16
17 GameWindowSettings gws = GameWindowSettings.Default;
18 NativeWindowSettings nws = NativeWindowSettings.Default;
19 gws.IsMultiThreaded = false;
20 gws.RenderFrequency = 60;
21 gws.UpdateFrequency = 60;
22
23 nws.APIVersion = Version.Parse("4.1.0");
24 nws.AutoLoadBindings = true;
25 nws.Size = new Vector2i(1280, 720);
26 nws.Title = "Horizon";
27
28
29
30 GameWindow window = new GameWindow(gws, nws);
31
32 window.UpdateFrame += (FrameEventArgs args) => {
33
34
35 };
36
37 ShaderProgram shaderProgram = new ShaderProgram(){id = 0};
38 window.Load += () =>
39 {
40 Console.WriteLine("Hello");
41 ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
42 };
43
44 window.RenderFrame += (FrameEventArgs args) =>
45 {
46 GL.UseProgram( shaderProgram.id );
47
48 GL.ClearColor(1.0f, 0.0f, 0.0f, 0.0f);
49 GL.Clear(ClearBufferMask.ColorBufferBit);
50
51 float[] verts = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f };
52 float[] color = { 1f, 0, 0, 0, 1f ,0 ,0, 0, 1f };
53
54 int vao = GL.GenVertexArray();
55 int vertices = GL.GenBuffer();
56 int colors = GL.GenBuffer();
57 GL.BindVertexArray(vao);
58 GL.BindBuffer(BufferTarget.ArrayBuffer, vertices);
59 GL.BufferData( BufferTarget.ArrayBuffer, verts.Length * sizeof(float), verts, BufferUsageHint.StaticCopy);
60 GL.EnableVertexAttribArray( 0 );
61 GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );
62
63 GL.BindBuffer(BufferTarget.ArrayBuffer, colors);
64 GL.BufferData(BufferTarget.ArrayBuffer, color.Length * sizeof(float), color, BufferUsageHint.StaticCopy);
65 GL.EnableVertexAttribArray(1);
66 GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0);
67
68
69
70 GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
71
72 GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
73 GL.BindVertexArray(0);
74 GL.DeleteBuffer(vertices);
75 GL.DeleteBuffer(colors);
76 GL.DeleteVertexArray( vao );
77
78
79
80 window.SwapBuffers();
81 };
82
83 window.Run();
84
85 }
86
87
88
89 private static Shader LoadShader(string shaderLocation, ShaderType type)
90 {
91 int shaderId = GL.CreateShader( type );
92 GL.ShaderSource( shaderId, File.ReadAllText( shaderLocation ) );
93 GL.CompileShader( shaderId );
94 string infoLog = GL.GetShaderInfoLog( shaderId );
95 if (!string.IsNullOrEmpty(infoLog))
96 {
97 throw new Exception(infoLog);
98 }
99
100 return new Shader() { id = shaderId };
101 }
102
103 private static ShaderProgram LoadShaderProgram( string vertextShaderLocation, string fragmentShaderLocation)
104 {
105 int shaderProgramId = GL.CreateProgram();
106
107 Shader vertextShader = LoadShader(vertextShaderLocation, ShaderType.VertexShader);
108 Shader fragmentShader = LoadShader(fragmentShaderLocation, ShaderType.FragmentShader);
109
110 GL.AttachShader(shaderProgramId, vertextShader.id);
111 GL.AttachShader(shaderProgramId, fragmentShader.id);
112 GL.LinkProgram(shaderProgramId);
113 GL.DetachShader(shaderProgramId, vertextShader.id);
114 GL.DetachShader(shaderProgramId, fragmentShader.id);
115 GL.DeleteShader(vertextShader.id);
116 GL.DeleteShader(fragmentShader.id);
117
118 string infoLog = GL.GetProgramInfoLog(shaderProgramId);
119 if (!string.IsNullOrEmpty(infoLog))
120 {
121 throw new Exception(infoLog);
122 }
123
124 return new ShaderProgram() { id = shaderProgramId };
125 }
126
127
128 public struct Shader
129 {
130 public int id;
131 }
132
133 public struct ShaderProgram
134 {
135 public int id;
136 }
137 }
138}
139#version 400
140
141in vec3 color_in;
142
143out vec4 color_out;
144
145void main(){
146 color_out = vec4(color_in.r, color_in.g, color_in.b, 1);
147
148}
149#version 330
150
151
152layout(location = 0) in vec3 vPosition;
153layout(location = 1) in vec3 vColors;
154
155out vec3 color_in;
156
157void main() {
158 color_in = vColors;
159 gl_Position = vec4( vPosition, 1.0 );
160
161}
162
I have tried everything I could with my very limited knowledge of OpenTK and nothing has changed. I have searched on the web and for answer they still have not helped
ANSWER
Answered 2022-Apr-03 at 07:08You actually assign the shader program to a local variable in the event callback function's scope. You need to assign it to the variable in scope of Main
:
1 using System;
2using OpenTK.Mathematics;
3using OpenTK.Windowing.Desktop;
4using OpenTK.Windowing.Common;
5using System.Drawing;
6using OpenTK.Graphics.OpenGL4;
7using System.IO;
8
9namespace Game_Engine
10{
11 public static class Program
12 {
13 static void Main(string[] args)
14 {
15 Console.WriteLine("Hello World!");
16
17 GameWindowSettings gws = GameWindowSettings.Default;
18 NativeWindowSettings nws = NativeWindowSettings.Default;
19 gws.IsMultiThreaded = false;
20 gws.RenderFrequency = 60;
21 gws.UpdateFrequency = 60;
22
23 nws.APIVersion = Version.Parse("4.1.0");
24 nws.AutoLoadBindings = true;
25 nws.Size = new Vector2i(1280, 720);
26 nws.Title = "Horizon";
27
28
29
30 GameWindow window = new GameWindow(gws, nws);
31
32 window.UpdateFrame += (FrameEventArgs args) => {
33
34
35 };
36
37 ShaderProgram shaderProgram = new ShaderProgram(){id = 0};
38 window.Load += () =>
39 {
40 Console.WriteLine("Hello");
41 ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
42 };
43
44 window.RenderFrame += (FrameEventArgs args) =>
45 {
46 GL.UseProgram( shaderProgram.id );
47
48 GL.ClearColor(1.0f, 0.0f, 0.0f, 0.0f);
49 GL.Clear(ClearBufferMask.ColorBufferBit);
50
51 float[] verts = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f };
52 float[] color = { 1f, 0, 0, 0, 1f ,0 ,0, 0, 1f };
53
54 int vao = GL.GenVertexArray();
55 int vertices = GL.GenBuffer();
56 int colors = GL.GenBuffer();
57 GL.BindVertexArray(vao);
58 GL.BindBuffer(BufferTarget.ArrayBuffer, vertices);
59 GL.BufferData( BufferTarget.ArrayBuffer, verts.Length * sizeof(float), verts, BufferUsageHint.StaticCopy);
60 GL.EnableVertexAttribArray( 0 );
61 GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0 );
62
63 GL.BindBuffer(BufferTarget.ArrayBuffer, colors);
64 GL.BufferData(BufferTarget.ArrayBuffer, color.Length * sizeof(float), color, BufferUsageHint.StaticCopy);
65 GL.EnableVertexAttribArray(1);
66 GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0);
67
68
69
70 GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
71
72 GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
73 GL.BindVertexArray(0);
74 GL.DeleteBuffer(vertices);
75 GL.DeleteBuffer(colors);
76 GL.DeleteVertexArray( vao );
77
78
79
80 window.SwapBuffers();
81 };
82
83 window.Run();
84
85 }
86
87
88
89 private static Shader LoadShader(string shaderLocation, ShaderType type)
90 {
91 int shaderId = GL.CreateShader( type );
92 GL.ShaderSource( shaderId, File.ReadAllText( shaderLocation ) );
93 GL.CompileShader( shaderId );
94 string infoLog = GL.GetShaderInfoLog( shaderId );
95 if (!string.IsNullOrEmpty(infoLog))
96 {
97 throw new Exception(infoLog);
98 }
99
100 return new Shader() { id = shaderId };
101 }
102
103 private static ShaderProgram LoadShaderProgram( string vertextShaderLocation, string fragmentShaderLocation)
104 {
105 int shaderProgramId = GL.CreateProgram();
106
107 Shader vertextShader = LoadShader(vertextShaderLocation, ShaderType.VertexShader);
108 Shader fragmentShader = LoadShader(fragmentShaderLocation, ShaderType.FragmentShader);
109
110 GL.AttachShader(shaderProgramId, vertextShader.id);
111 GL.AttachShader(shaderProgramId, fragmentShader.id);
112 GL.LinkProgram(shaderProgramId);
113 GL.DetachShader(shaderProgramId, vertextShader.id);
114 GL.DetachShader(shaderProgramId, fragmentShader.id);
115 GL.DeleteShader(vertextShader.id);
116 GL.DeleteShader(fragmentShader.id);
117
118 string infoLog = GL.GetProgramInfoLog(shaderProgramId);
119 if (!string.IsNullOrEmpty(infoLog))
120 {
121 throw new Exception(infoLog);
122 }
123
124 return new ShaderProgram() { id = shaderProgramId };
125 }
126
127
128 public struct Shader
129 {
130 public int id;
131 }
132
133 public struct ShaderProgram
134 {
135 public int id;
136 }
137 }
138}
139#version 400
140
141in vec3 color_in;
142
143out vec4 color_out;
144
145void main(){
146 color_out = vec4(color_in.r, color_in.g, color_in.b, 1);
147
148}
149#version 330
150
151
152layout(location = 0) in vec3 vPosition;
153layout(location = 1) in vec3 vColors;
154
155out vec3 color_in;
156
157void main() {
158 color_in = vColors;
159 gl_Position = vec4( vPosition, 1.0 );
160
161}
162ShaderProgram shaderProgram = new ShaderProgram() { id = 0 };
163window.Load += () =>
164{
165 Console.WriteLine("Hello");
166
167 // ShaderProgram shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
168 shaderProgram = LoadShaderProgram("../../../../vertex_shader.glsl", "../../../../fragment_shader.glsl");
169};
170
QUESTION
Area2D Not Triggering Object in Godot
Asked 2022-Mar-23 at 23:20Here is my code: (just so you know I am a beginner and I just started this week, though I do have knowledge with other languages and game engines)
1func _on_Area2D_area_entered(area):
2 get_parent().get_node("Level 1/Area2D/Flag").rotation_degrees += 1
3
What I was trying to accomplish was that the Player GameObject would see if its in the area of the Flag, and if it is, the flag would rotate.
I am not sure where the issue is. I think it is probably in the second line. I provided a screenshot below if I did the setup wrong. I have looked at the other close questions asked on the same topic, but they did not answer my question.
The "Player" GameObject is the one with the script that contains the detection if its in the area2D.
ANSWER
Answered 2022-Mar-23 at 23:20If you want to check if the Area2D
is positioned correctly during runtime enable Debug -> Visible Collision Shapes.
If you want to check if _on_Area2D_area_entered
is running, add breakpoints (or use print).
Did you get an error?
If there isn't a Node
there, this expression will cause an error in runtime:
1func _on_Area2D_area_entered(area):
2 get_parent().get_node("Level 1/Area2D/Flag").rotation_degrees += 1
3get_parent().get_node("Level 1/Area2D/Flag")
4
If you want to be able to check, you can use get_node_or_null
and is_instance_valid
.
Since you didn't mention any error, I'm going to guess the method is not running.
If the method is not running, the most likely culprit is that - I'm guessing given then name of the method - you connected the "area_entered"
signal but intended to connect the "body_entered"
signal.
The "area_entered"
signal will trigger when another Area2D
enters the Area2D
. But I only see one Area2D
in your scene tree. On the other hand the "body_entered"
will trigger when a PhysicsBody2D
(e.g StaticBody2D
, KinematicBody2D
, RigidBody2D
) enters the Area2D
. In either case you get what entered as a parameter of the method.
Other reasons why the Area2D
might not be detecting what you want include no intersection of collision_layer
and collision_mask
and monitoring
being disabled.
And to dismiss a couple possible misconceptions:
"area_entered"
and "body_entered"
trigger when the Area2D
or PhysicsBody2D
respectively enter the Area2D
, not every frame they are inside. So rotation_degrees += 1
is not a rotation animation.if body == self:
.QUESTION
AnimationPlayer seek() using threading
Asked 2022-Mar-20 at 16:16I have a script attached to an AnimationPlayer
node and it does some long calculations,
so in order to avoid the game engine from hanging while those calculations take place
I created a separate thread for that function,
but the seek()
function doesn't update the animation despite adding update=true
I've narrowed it down to this simple example:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14
here's how the tree looks like:
so how to I get the seek()
to work or is there any workaround with what I'm trying to achieve?
Edit:
I tried applied the solution @Theraot gave & modified it to loop through all the animations
like this:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14func sep(thread:Thread):
15 var AnimationList=self.get_animation_list();
16 for animation_name in AnimationList:
17
18 self.current_animation=animation_name;
19 var ongoing_animation=self.get_animation(animation_name);
20 for track_indx in ongoing_animation.get_track_count():
21 for key_indx in ongoing_animation.track_get_key_count(track_indx):
22 var key_time=ongoing_animation.track_get_key_time(track_indx, key_indx);
23 self.seek(key_time,true);
24
25 Translate=false;
26 property_list_changed_notify();
27 thread.call_deferred("wait_to_finish")
28
29func Translate_Changed(new_val):
30
31 if _thread == null or _thread.is_active():
32 _thread = Thread.new();
33
34 _thread.start(self, "sep", _thread);
35
But when I run this for a big animation it gets stuck in between & the entire godot game engine hangs
I'm guessing it's a memory leak?
what am I trying to achieve?
I've actually created custom properties on a node and added those custom properties as keys in an AnimationPlayer
but these custom properties all effect position
, rotation
& other inbuilt properties.
so I thought by seek()
I could see the end result of all them combined and then key the position
, rotation
& other inbuilt properties to another AnimationPlayer
ANSWER
Answered 2022-Mar-20 at 12:34After testing, it appears to me that it works with a couple caveats:
Once done properly it works on Godot 3.2 or newer. However, starting with Godot 3.4 I could be more sloppy with how I handle the thread and it would still work.
First of all, you need to call wait_to_finish
when the thread ends. Not doing it will prevent proper cleanup. If you don't have code waiting for the thread to finish, you can add this at the end of the thread code:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14func sep(thread:Thread):
15 var AnimationList=self.get_animation_list();
16 for animation_name in AnimationList:
17
18 self.current_animation=animation_name;
19 var ongoing_animation=self.get_animation(animation_name);
20 for track_indx in ongoing_animation.get_track_count():
21 for key_indx in ongoing_animation.track_get_key_count(track_indx):
22 var key_time=ongoing_animation.track_get_key_time(track_indx, key_indx);
23 self.seek(key_time,true);
24
25 Translate=false;
26 property_list_changed_notify();
27 thread.call_deferred("wait_to_finish")
28
29func Translate_Changed(new_val):
30
31 if _thread == null or _thread.is_active():
32 _thread = Thread.new();
33
34 _thread.start(self, "sep", _thread);
35thread.call_deferred("wait_to_finish")
36
Using call_deferred
(or set_deferred
or emit_signal
) allows the thread to issue operations on the main thread.
By the way, you can reuse the thread by calling start
on it again after it finished. So you don't need to create a new Thread
each time. So you can do this:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14func sep(thread:Thread):
15 var AnimationList=self.get_animation_list();
16 for animation_name in AnimationList:
17
18 self.current_animation=animation_name;
19 var ongoing_animation=self.get_animation(animation_name);
20 for track_indx in ongoing_animation.get_track_count():
21 for key_indx in ongoing_animation.track_get_key_count(track_indx):
22 var key_time=ongoing_animation.track_get_key_time(track_indx, key_indx);
23 self.seek(key_time,true);
24
25 Translate=false;
26 property_list_changed_notify();
27 thread.call_deferred("wait_to_finish")
28
29func Translate_Changed(new_val):
30
31 if _thread == null or _thread.is_active():
32 _thread = Thread.new();
33
34 _thread.start(self, "sep", _thread);
35thread.call_deferred("wait_to_finish")
36if thread == null:
37 thread = Thread.new()
38
But! The thread will be running for the long computations, and you cannot call start
on it while it is running. A simple solution is to start another one:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14func sep(thread:Thread):
15 var AnimationList=self.get_animation_list();
16 for animation_name in AnimationList:
17
18 self.current_animation=animation_name;
19 var ongoing_animation=self.get_animation(animation_name);
20 for track_indx in ongoing_animation.get_track_count():
21 for key_indx in ongoing_animation.track_get_key_count(track_indx):
22 var key_time=ongoing_animation.track_get_key_time(track_indx, key_indx);
23 self.seek(key_time,true);
24
25 Translate=false;
26 property_list_changed_notify();
27 thread.call_deferred("wait_to_finish")
28
29func Translate_Changed(new_val):
30
31 if _thread == null or _thread.is_active():
32 _thread = Thread.new();
33
34 _thread.start(self, "sep", _thread);
35thread.call_deferred("wait_to_finish")
36if thread == null:
37 thread = Thread.new()
38if thread == null or thread.is_active():
39 thread = Thread.new()
40
I don't know if there are race conditions to be aware of. Take into consideration the possibility of two threads running at the same time.
But! that means that when the thread calls thread.call_deferred("wait_to_finish")
that would not be the correct one. So we are going to pass the thread
as parameter to the thread
.
This is how my code looks like:
1extends AnimationPlayer
2tool
3export(float,0,1,0.1) var aniTimer = 0 setget aniTimer_Changed;
4var thread;
5
6func sep():
7 self.seek(aniTimer,true);
8 # calculations #
9
10func aniTimer_Changed(new_val):
11 aniTimer=new_val;
12 thread = Thread.new();
13 thread.start(self, "sep");
14func sep(thread:Thread):
15 var AnimationList=self.get_animation_list();
16 for animation_name in AnimationList:
17
18 self.current_animation=animation_name;
19 var ongoing_animation=self.get_animation(animation_name);
20 for track_indx in ongoing_animation.get_track_count():
21 for key_indx in ongoing_animation.track_get_key_count(track_indx):
22 var key_time=ongoing_animation.track_get_key_time(track_indx, key_indx);
23 self.seek(key_time,true);
24
25 Translate=false;
26 property_list_changed_notify();
27 thread.call_deferred("wait_to_finish")
28
29func Translate_Changed(new_val):
30
31 if _thread == null or _thread.is_active():
32 _thread = Thread.new();
33
34 _thread.start(self, "sep", _thread);
35thread.call_deferred("wait_to_finish")
36if thread == null:
37 thread = Thread.new()
38if thread == null or thread.is_active():
39 thread = Thread.new()
40tool
41extends AnimationPlayer
42export(float,0,1,0.1) var aniTimer = 0.0 setget aniTimer_Changed
43var _thread:Thread
44
45func sep(thread:Thread):
46 seek(aniTimer, true)
47 # calculations #
48 thread.call_deferred("wait_to_finish")
49
50func aniTimer_Changed(new_val):
51 aniTimer=new_val
52 if _thread == null or _thread.is_active():
53 _thread = Thread.new()
54
55 # warning-ignore:return_value_discarded
56 _thread.start(self, "sep", _thread)
57
QUESTION
Using Microsoft Authentication Library (MSAL) in Unity for SSO in iOS app
Asked 2022-Mar-16 at 09:31We develop a bunch of augmented reality applications for our company. The applications are based on the game engine Unity (currently in the version 2020.3.7f1). Now, we're facing the point that we'd like to implement a SSO method in our apps, so every member of our company authenticates himself with his company user credentials. To authenticate the user we want to / have to use the Microsoft identity platform and thus the Microsoft Authentication Library (MSAL).
We already created an client on Azure with a client id, redirect uri, authority uri, endpoint, tenant, etc and it was tested successfully with an official sample project by Microsoft (https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-ios).
But now we stuck at the point to establish this process in Unity. We created the MSAL library dll (https://github.com/AzureAD/microsoft-authentication-library-for-dotnet), imported it into Unity and called it by using the namespace Microsoft.Identity.Client. Due to security reasons we're only allowed to use PublicClientApplicationBuilder (which makes totally sense) so we need the web based login screen. The problem is that we can't implement a web view in Unity where the user can sign in to Microsoft and we can parse the received token out of the web view into our app for further communications.
We did a lot of internet research to find a solution but there are only some posts about MSAL in Unity in combination with Android and other posts which reference to the git repos I mentioned before.
How can we use MSAL in Unity for iOS devices?
Example code:
1 IPublicClientApplication PublicClientApp = PublicClientApplicationBuilder
2 .Create(kClientID)
3 .WithRedirectUri(kRedirectUri)
4 .WithAuthority(new Uri(kAuthority))
5 .Build();
6 IEnumerable<string> scopes = new List<string> { "https://graph.microsoft.com/.default" };
7 AuthenticationResult result;
8 result = await PublicClientApp.AcquireTokenInteractive(scopes)
9 .ExecuteAsync();
10
11 result = await PublicClientApp
12 .AcquireTokenInteractive(scopes)
13 .WithParentActivityOrWindow(new object)
14 .ExecuteAsync();
15
16 Debug.Log(result.AccessToken);
17
ANSWER
Answered 2021-Nov-16 at 13:45The standard solution for mobile is the AppAuth pattern, which involves use of an integrated system browser to sign the user in. See this code example article for how that looks, so that you understand the required behaviour.
So it looks like they key thing to do with iOS is to avoid logins via webviews and tell MSAL to use an ASWebAuthenticationSession window - this Microsoft article explains how.
QUESTION
Why is only 1 Depth/Stencil buffer needed, even when the swap chain is tripple buffered DirectX12
Asked 2022-Mar-15 at 12:27I am learning DirectX12 programming. And one thing that has me confused is in all the tutorials I read, they only create a single depth/stencil buffer even when triple/double buffering is used with the swap chain. Wouldn't you need a depth/stencil buffer for each frame?
Code in question:
1 D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
2 dsvHeapDesc.NumDescriptors = 1; //why only 1?
3 dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
4 dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
5 if(FAILED(device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&dsDescriptorHeap))))
6 {
7 MessageBoxW(NULL, L"Failed to create depth buffer descriptor heap!", L"Error", MB_OK | MB_ICONERROR);
8 return -1;
9 }
10 D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {};
11 depthStencilDesc.Format = DXGI_FORMAT_D32_FLOAT;
12 depthStencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
13 depthStencilDesc.Flags = D3D12_DSV_FLAG_NONE;
14
15 D3D12_CLEAR_VALUE depthOptimizedClearValue = {};
16 depthOptimizedClearValue.Format = DXGI_FORMAT_D32_FLOAT;
17 depthOptimizedClearValue.DepthStencil.Depth = 1.0f;
18 depthOptimizedClearValue.DepthStencil.Stencil = 0;
19
20 device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D32_FLOAT, width, height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL), D3D12_RESOURCE_STATE_DEPTH_WRITE, &depthOptimizedClearValue, IID_PPV_ARGS(&depthStencilBuffer));
21 depthStencilBuffer->SetName(L"Depth/Stencil Resource Heap");
22 device->CreateDepthStencilView(depthStencilBuffer, &depthStencilDesc, dsDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
23
24
ANSWER
Answered 2022-Mar-15 at 12:27Generally speaking, "intermediate resources" (such as depth stencils and intermediate render targets) are not presented on the screen.
So when one swapchain is ready to present (and you start recording next frame commands), those resources can be safely overridden, since the content is ready within the swap chain.
The only exception for those resources are generally buffers that are uploaded from cpu, for them it is needed to have one per frame (since you will start to copy data while another command list is still executing).
QUESTION
How to structure a project in Monogame
Asked 2022-Mar-14 at 17:18I'm trying to create a PC version of a cord-driven turn-based boardgame. I went for the Monogame framework in c#. I'm still learning C# and Monogame and I'm reading all about how it is important to "split" the code in the data/game engine part and the graphics/GUI part. So trying to pursue this, I have the following in mind.
Graphics/GUI
Here I define all the classes relative to the screens (game - menus), GUI components like labels and buttons and possibly even mouse and keyboard inputs (the logic being the user has to click on something in the gui in order to perform an action).
Data or Game logic/Engine
Still not even sure on how I should call this part of the project, here I would put all the logic of the game. The classes of player, cards, "IA", rules etc... would be defined here.
My difficulty is now to understand how to connect this two parts but still maintain the "loosely coupled" approach. I was thinking that maybe the objects or better the instances of the game logic part would have to subscribe to events (such as button_click) defined in the GUI part...but can I even subscribe to events of another class? Is this the correct way?
I admit I'm still trying to fully understand the event driven concept, but is this the right way of doing stuff in c# and Monogame? I apologize for the vague topic/question but thanks in advance.
ANSWER
Answered 2022-Mar-14 at 17:18I don't know anything about Monogame, but generally it's a good idea to organise any kind of application into layers like this, as long as you don't make the code overly complicated by doing so. Your idea to separate the UI code from the game logic sounds like a good start.
First, think of your application as an onion, with a series of concentric layers. Your proposed structure has only two layers, but that's OK. A larger application may benefit from more layers, e.g. a data access layer if you were to store the state of the game in a database, but there's no need to add extra layers just for the sake of having more layers.
Your outermost layer would contain the UI code, typically this is known as the presentation layer.
Your innermost layer would contain the game logic, typically this is known as the domain layer. A good rule of thumb for whether something belongs in the domain layer is to ask, does this represent something that a user of your application (or a player of your game) who's not a developer would recognise?
Second, remember that each layer can make calls to code in the same layer, or to code in in other layers inside it, but not to code in layers outside it. So projects in the presentation layer can have references to projects in the domain layer, but projects in the domain layer can't have references to projects in the presentation layer. If you've got circular references between the two layers then it's a sign that something in one of the layers actually belongs in the other layer.
Here's another answer to a similar question about layering an application, albeit not in the context of a game: https://stackoverflow.com/a/70315655/16563198
On the second part of the question, if you want to use events then it's probably best to handle any events in the presentation layer and have the event handlers make calls into the domain layer (but disclaimer, I don't know Monogame).
QUESTION
Godot Invalid to get index 'x' (On Base: 'Node (a.gd)')
Asked 2022-Jan-21 at 10:30im trying to hold a path to a game object (bat.tscn) in a script and use it to instanceate a object from a different script. Name of the script that holds the variable is called a.gd and the one that is responsible for instantiating is b.gd and the name of the variable is x. But for some reason every time i try to use the variable it gives me an error;
1Invalid to get index 'x' (On Base: 'Node (a.gd)')
2
a.gd;
1Invalid to get index 'x' (On Base: 'Node (a.gd)')
2func _process(delta):
3var SlotOne = $"res://Objects/Weapons/Bat.tscn
4
b.gd;
1Invalid to get index 'x' (On Base: 'Node (a.gd)')
2func _process(delta):
3var SlotOne = $"res://Objects/Weapons/Bat.tscn
4onready var InvManager = get_node("../a") #gets the script.
5
6func _physics_process(delta):
7 changeWeapons()
8
9func changeWeapons():
10 if Input.is_key_pressed(KEY_1):
11 load(InvManager.SlotOne)
12 elif Input.is_key_pressed(KEY_2):
13 print("2")
14 elif Input.is_key_pressed(KEY_3):
15 print("3")
16 elif Input.is_key_pressed(KEY_4):
17 print("4")
18
any ideas how can i fix this issue? Im pretty new to the game engine so im kinda stuck here.
ANSWER
Answered 2022-Jan-19 at 13:08also a possible explanation is that instead of using or instancing the node you are trying to access it
so first try to add the node to the main scene like this
1Invalid to get index 'x' (On Base: 'Node (a.gd)')
2func _process(delta):
3var SlotOne = $"res://Objects/Weapons/Bat.tscn
4onready var InvManager = get_node("../a") #gets the script.
5
6func _physics_process(delta):
7 changeWeapons()
8
9func changeWeapons():
10 if Input.is_key_pressed(KEY_1):
11 load(InvManager.SlotOne)
12 elif Input.is_key_pressed(KEY_2):
13 print("2")
14 elif Input.is_key_pressed(KEY_3):
15 print("3")
16 elif Input.is_key_pressed(KEY_4):
17 print("4")
18get_tree().current_scene().add_child("#the path to a.gd")
19
but anyways only the code can can tell us what is wrong
QUESTION
Copy output of custom target in one CSPROJ into another CSPROJ
Asked 2022-Jan-14 at 05:57So I'm developing a game engine framework for myself in C#/.NET and I have been trying to simplify building shader files (the rendering engine consumes SPIR-V files, which I want to generate from GLSL source). My current approach has been to use a custom .targets file which is imported into a CSPROJ, and that file defines a custom target like this:
1<Target
2 Name="Vert"
3 AfterTargets="Build">
4 <MakeDir Directories="$(OutputPath)%(VertShader.RelativeDir)"/>
5 <Exec Command='"$(ENGINE_ROOT)\tools\glslang\windows-x64\glslangValidator.exe" -V %(VertShader.Identity) %(VertShader.OptLevel) -o $(OutputPath)%(VertShader.Identity).spv'></Exec>
6</Target>
7
The general idea behind this is it takes VertShader items, runs the .vert file through glslang, and spits the output .vert.spv file into the build output directory. This works great, almost.
The problem is, if I have Project A that has a bunch of shaders, and then Project B which has a reference to Project A, I want to copy the .vert.spv shaders that Project A generates into the build output directory of Project B, but I haven't had much luck wrangling the target syntax to do what I want.
Is there any way I can get this working the way I'm describing?
ANSWER
Answered 2022-Jan-14 at 02:16I am not sure I understand your problem correctly, but if you want your .vert.spv copied to another folder use File.Copy()
QUESTION
Algorithm to fill arbitrary marked/selected tiles on a square grid with the smallest number of rectangles?
Asked 2022-Jan-12 at 15:58What I am asking here is an algorithm question. I'm not asking for specifics of how to do it in the programming language I'm working in or with the framework and libraries I'm currently using. I want to know how to do this in principle.
As a hobby, I am working on an open source virtual reality remake of the 1992 first-person shooter game Wolfenstein 3D. My program will support classic mods and map packs for WOLF3D made in the original format from the 90s. This means that my program will not know in advance what the maps are going to be. They are loaded in at runtime from user provided files.
A Wolfenstein 3D map is a 2D square grid of normally 64x64 tiles. let's assume I have a 2D array of bools which return true if a particular tile can be traversed by the player and false if the tile will never be traversable no matter what happens in the game.
I want to generate rectangular collision objects for a modern game engine which will prevent collisions into non traversable tiles on the map. Right now, I have a small collision object on each surface of each wall tile with a traversible tile next to it and that is very inefficient because it makes way more collision objects than necessary. What I should have instead is a smaller number of large rectangles which fill all of the squares on the grid where that 2D array I mentioned has a false value to indicate non-traversible.
When I search for any algorithms or research that might have been done for problems similar to this, I find lots of information about rectangle packing for the purposes of making texture atlases for games, which packs rectangles into a square, but I haven't found anything that tries to pack the smallest number of rectangles into an arbitrary set of selected / marked square tiles.
The naive approach which occurs to me is to first make 64 rectangles representing 64 rows and then chop out whatever squares are traversible. but I suspect that there's got to be an algorithm which can do better, meaning that it can fill the same spaces with a smaller number of rectangles. Maybe something that starts with my naive approach and then checks each rectangle for adjacent rectangles which it could merge with? But I'm not sure how far to take that approach or if it will even truly reduce the number of rectangles.
The result doesn't have to be perfect. I am just fishing here to see if anyone has any magic tricks that could take me even a little bit beyond the naive approach.
Has anyone done this before? What is it called? Just knowing what some of the vocabulary words I would need to even talk about this are would help. Thanks!
(later edit)
Here is some sample input as comma-separated values. The 1s represent the area that must be filled with the rectangles while the 0s represent the area that should not be filled with the rectangles.
I expect that the result would be a list of sets of 4 integers where each set represents a rectangle like this:
My program is in C# but I'm sure I can translate anything in a normal mainstream general purpose programming language or psuedocode.
ANSWER
Answered 2022-Jan-12 at 14:461Mark all tiles as not visited
2For each tile:
3 skip if the tile is not a top-left corner or was visited before
4 # now, the tile is a top-left corner
5 expand right until top-right corner is found
6 expand down
7 save the rectangle
8 mark all tiles in the rectangle as visited
9
However simplistic it looks, it will likely generate minimal number of rectangles - simply because we need at least one rectangle per pair of top corners.
For faster downward expansion, it makes sense to precompute a table holding sum of all element top and left from the tile (aka integral image).
For non-overlapping rectangles, worst case complexity for an n x n
"image" should not exceed O(n^3)
. If rectangles can overlap (would result in smaller number of them), integral image optimization is not applicable and the worst case will be O(n^4)
.
Community Discussions contain sources that include Stack Exchange Network
Share this Page
Get latest updates on Game Engine
Open Weaver – Develop Applications Faster with Open Source