8 Commits
Author SHA1 Message Date
Simon Lübeß aa70d99e31 Fin 2022-02-14 20:36:48 +01:00
Simon Lübeß c8cc2f442a Added ColorHSV 2022-02-14 20:36:07 +01:00
Simon Lübeß 574f54e32b Added Window.SetIcon 2022-02-14 20:35:35 +01:00
Simon Lübeß 58cf92fb57 Renderer2D limit instances per batch 2022-02-14 20:19:19 +01:00
Simon Lübeß f49acf34a1 Added particle system 2022-02-13 23:56:58 +01:00
Simon Lübeß 7f11b982ee Added text and restart 2022-02-13 22:51:55 +01:00
Simon Lübeß d9e34b27a3 Rocket Game 2022-02-13 15:22:45 +01:00
Simon Lübeß e61c53400f Added DeltaTime 2022-02-13 15:22:18 +01:00
14 changed files with 925 additions and 8 deletions
+4 -1
View File
@@ -27,7 +27,10 @@ namespace GlitchyEngine
* The number of frames that have been finished since the timer was started. * The number of frames that have been finished since the timer was started.
*/ */
public uint64 FrameCount => _frameCount; public uint64 FrameCount => _frameCount;
/// The interval in seconds from the last frame to the current one.
public float DeltaTime => (float)_frameTime.TotalSeconds;
/** /**
* Initializes a new instance of a GameTime. * Initializes a new instance of a GameTime.
*/ */
@@ -250,6 +250,18 @@ namespace GlitchyEngine
[CLink] [CLink]
static extern IntBool IsWindowUnicode(HWND whnd); static extern IntBool IsWindowUnicode(HWND whnd);
public Result<void> SetIcon(StringView filePath)
{
HICON hIcon = LoadImageW(0, filePath.ToScopedNativeWChar!(), .Icon, 0, 0, .LoadFromFile);
if (hIcon == 0)
return .Err;
// WM_SETICON 0x0080
SendMessageW(_windowHandle, 0x0080, 1 /* ICON_BIG */, (int)hIcon);
return .Ok;
}
private static LRESULT MessageHandler(HWND hwnd, uint32 uMsg, WPARAM wParam, LPARAM lParam) private static LRESULT MessageHandler(HWND hwnd, uint32 uMsg, WPARAM wParam, LPARAM lParam)
{ {
void* windowPtr = (void*)GetWindowLongPtrW(hwnd, GWL_USERDATA); void* windowPtr = (void*)GetWindowLongPtrW(hwnd, GWL_USERDATA);
+18 -5
View File
@@ -133,6 +133,9 @@ namespace GlitchyEngine.Renderer
private static Effect s_currentEffect; private static Effect s_currentEffect;
private static Effect s_currentCircleEffect; private static Effect s_currentCircleEffect;
private static int s_InstancesPerDrawCall = 1024;
private static int s_MaxInstancesPerDrawCall = 8192;
private static void InitEffect() private static void InitEffect()
{ {
Debug.Profiler.ProfileFunction!(); Debug.Profiler.ProfileFunction!();
@@ -204,10 +207,10 @@ namespace GlitchyEngine.Renderer
s_batchBinding.SetVertexBufferSlot(s_instanceBuffer, 1); s_batchBinding.SetVertexBufferSlot(s_instanceBuffer, 1);
s_rawInstances = new BatchVertex[1024]; s_rawInstances = new BatchVertex[s_InstancesPerDrawCall];
s_setInstances = 0; s_setInstances = 0;
s_instanceQueue = new List<QueueQuad>(1024); s_instanceQueue = new List<QueueQuad>(s_InstancesPerDrawCall);
} }
{ {
@@ -240,9 +243,9 @@ namespace GlitchyEngine.Renderer
s_circleBatchBinding.SetVertexBufferSlot(s_circleInstanceBuffer, 1); s_circleBatchBinding.SetVertexBufferSlot(s_circleInstanceBuffer, 1);
s_rawCircleInstances = new CircleBatchVertex[1024]; s_rawCircleInstances = new CircleBatchVertex[s_InstancesPerDrawCall];
s_circleInstanceQueue = new List<QueueCircle>(1024); s_circleInstanceQueue = new List<QueueCircle>(s_InstancesPerDrawCall);
} }
} }
@@ -391,6 +394,11 @@ namespace GlitchyEngine.Renderer
private static void QueueQuadInstance(Matrix transform, ColorRGBA color, Texture2D texture, float depth, Vector4 uvTransform) private static void QueueQuadInstance(Matrix transform, ColorRGBA color, Texture2D texture, float depth, Vector4 uvTransform)
{ {
s_instanceQueue.Add(QueueQuad(transform, color, texture ?? s_whiteTexture, depth, uvTransform)); s_instanceQueue.Add(QueueQuad(transform, color, texture ?? s_whiteTexture, depth, uvTransform));
if (s_instanceQueue.Count >= s_MaxInstancesPerDrawCall)
{
Flush();
}
} }
/// Adds a circle instance to the instance queue. /// Adds a circle instance to the instance queue.
@@ -398,6 +406,11 @@ namespace GlitchyEngine.Renderer
private static void QueueCircleInstance(Matrix transform, ColorRGBA color, Texture2D texture, float depth, Vector4 uvTransform, float innerRadius) private static void QueueCircleInstance(Matrix transform, ColorRGBA color, Texture2D texture, float depth, Vector4 uvTransform, float innerRadius)
{ {
s_circleInstanceQueue.Add(QueueCircle(transform, color, texture ?? s_whiteTexture, depth, uvTransform, innerRadius)); s_circleInstanceQueue.Add(QueueCircle(transform, color, texture ?? s_whiteTexture, depth, uvTransform, innerRadius));
if (s_circleInstanceQueue.Count >= s_MaxInstancesPerDrawCall)
{
Flush();
}
} }
private static void FlushInstances() private static void FlushInstances()
@@ -670,9 +683,9 @@ namespace GlitchyEngine.Renderer
public static void DrawCircle(Vector3 position, Vector2 size, Texture2D texture, ColorRGBA color = .White, float innerRadius = 1.0f, Vector4 uvTransform = .(0, 0, 1, 1)) public static void DrawCircle(Vector3 position, Vector2 size, Texture2D texture, ColorRGBA color = .White, float innerRadius = 1.0f, Vector4 uvTransform = .(0, 0, 1, 1))
{ {
#if DEBUG
Debug.Profiler.ProfileRendererFunction!(); Debug.Profiler.ProfileRendererFunction!();
#if DEBUG
Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene."); Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene.");
#endif #endif
+5
View File
@@ -110,5 +110,10 @@ namespace GlitchyEngine
} }
public extern void Update(); public extern void Update();
/**
* Sets the Icon of the window to the given file.
*/
public extern Result<void> SetIcon(StringView filePath);
} }
} }
+3
View File
@@ -6,3 +6,6 @@ Name = "Sandbox"
TargetType = "BeefGUIApplication" TargetType = "BeefGUIApplication"
StartupObject = "GlitchyEngine.Program" StartupObject = "GlitchyEngine.Program"
ProcessorMacros = ["NOT_GAMMA_TEST", "SANDBOX_2D"] ProcessorMacros = ["NOT_GAMMA_TEST", "SANDBOX_2D"]
[Platform.Windows]
IconFile = "$(ProjectDir)/content/RocketGame/RocketIcon.ico"
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.
+43
View File
@@ -0,0 +1,43 @@
using GlitchyEngine.Math;
using System;
namespace Sandbox
{
struct ColorHSV
{
public float H;
public float S;
public float V;
public this(float h, float s, float v)
{
H = h;
S = s;
V = v;
}
public static explicit operator ColorRGB(ColorHSV hsv)
{
float c = hsv.V * hsv.S;
float x = c * (1.0f - Math.Abs((hsv.H / 60.0f) % 2.0f - 1.0f));
float m = hsv.V - c;
ColorRGB rgb_ = ?;
if (hsv.H < 60.0f)
rgb_ = ColorRGB(c, x, 0);
else if (hsv.H < 120.0f)
rgb_ = ColorRGB(x, c, 0);
else if (hsv.H < 180.0f)
rgb_ = ColorRGB(0, c, x);
else if (hsv.H < 240.0f)
rgb_ = ColorRGB(0, x, c);
else if (hsv.H < 300.0f)
rgb_ = ColorRGB(x, 0, c);
else if (hsv.H < 360.0f)
rgb_ = ColorRGB(c, 0, x);
return .(rgb_.Red + m, rgb_.Green + m, rgb_.Blue + m);
}
}
}
+229
View File
@@ -0,0 +1,229 @@
using System;
using GlitchyEngine;
using GlitchyEngine.Events;
using System.Diagnostics;
using GlitchLog;
using GlitchyEngine.ImGui;
using ImGui;
using GlitchyEngine.Renderer;
using GlitchyEngine.Math;
using GlitchyEngine.World;
using GlitchyEngine.Renderer.Text;
using System.IO;
using msdfgen;
using System.Collections;
using System.Diagnostics;
namespace Sandbox
{
class GameLayer : Layer
{
GraphicsContext _context ~ _?.ReleaseRef();
BlendState _alphaBlendState ~ _?.ReleaseRef();
Font _font ~ _.ReleaseRef();
DepthStencilState _depthStencilState ~ _.ReleaseRef();
Rocket _rocket ~ delete _;
OrthographicCamera _camera ~ delete _;
List<Obstacle> _obstacles = new List<Obstacle>() ~ DeleteContainerAndItems!(_);
FontRenderer.PreparedText pressSpaceToStart ~ _.ReleaseRef();
FontRenderer.PreparedText pressSpaceToRestart ~ _.ReleaseRef();
ColorHSV worldColor = .(0, 0.5f, 1.0f);
[AllowAppend]
public this() : base("Example")
{
Application.Get().Window.IsVSync = false;
_context = Application.Get().Window.Context..AddRef();
BlendStateDescription blendDesc = .();
blendDesc.RenderTarget[0] = .(true, .SourceAlpha, .InvertedSourceAlpha, .Add, .SourceAlpha, .InvertedSourceAlpha, .Add, .All);
_alphaBlendState = new BlendState(blendDesc);
_font = new Font("C:\\Windows\\Fonts\\arial.ttf", 64, true, 'A', 16);
_camera = new .()
{
NearPlane = -10,
FarPlane = 10,
Height = 5,
Width = 5 * _context.SwapChain.AspectRatio
}..Update();
DepthStencilStateDescription dssDesc = .()
{
DepthEnabled = false
};
_depthStencilState = new DepthStencilState(dssDesc);
pressSpaceToStart = FontRenderer.PrepareText(_font, "Press [SPACE]", 1);
pressSpaceToRestart = FontRenderer.PrepareText(_font, "YOU DIED!\nPress [SPACE] to restart", 0.5f);
InitGame();
}
private void InitGame()
{
_rocket = new Rocket();
_rocket.Obstacles = _obstacles;
InitStarField();
}
Vector4[] points = new Vector4[1000] ~ delete _;
Random startRandom = new .() ~ delete _;
private void InitStarField()
{
for (int i < points.Count)
{
Vector4 v = .();
v.X = startRandom.Next(-1000, 1000) / 2000f * _camera.Width;
v.Y = startRandom.Next(-1000, 1000) / 2000f * _camera.Height;
v.Z = startRandom.Next(0, 1000) / 2000.0f;
v.W = startRandom.Next(1000, 3000) / 1000.0f;
points[i] = v;
}
}
private float lastObstacle = 0.0f;
public override void Update(GameTime gameTime)
{
worldColor.H += gameTime.DeltaTime * 18 * _rocket.FlightSpeed;
worldColor.H %= 360.0f;
ColorRGBA wColor = .((ColorRGB)worldColor, 1.0f);
float screenWidth = _camera.Width;
Obstacle.ScreenWidth = screenWidth / 2.0f;
lastObstacle += Obstacle.Speed * gameTime.DeltaTime;
if (lastObstacle <= -Obstacle.ScreenWidth)
{
_obstacles.Add(new Obstacle());
lastObstacle += 2.5f;
_obstacles.Back.Position.X = Obstacle.ScreenWidth + 1.0f;
_obstacles.Back.Position.Y = Obstacle.random.Next(-1000, 1000) / 1000f;
}
for (int i < _obstacles.Count)
{
_obstacles[i].Update(gameTime);
if (_obstacles[i].Dead)
{
delete _obstacles[i];
_obstacles.RemoveAt(i);
i--;
}
}
_rocket.Update(gameTime);
Obstacle.Speed = -_rocket.FlightSpeed;
RenderCommand.Clear(null, .Black);
// Draw test geometry
RenderCommand.SetRenderTarget(null);
RenderCommand.BindRenderTargets();
RenderCommand.SetViewport(_context.SwapChain.BackbufferViewport);
RenderCommand.SetBlendState(_alphaBlendState);
RenderCommand.SetDepthStencilState(_depthStencilState);
Renderer2D.BeginScene(_camera, .BackToFront);
DrawStartField(gameTime);
Renderer2D.EndScene();
Renderer2D.BeginScene(_camera, .BackToFront);
Renderer2D.DrawQuad(Vector3(0, 2.75f, 1), Vector2(screenWidth, 1), 0, wColor);
Renderer2D.DrawQuad(Vector3(0, -2.75f, 1), Vector2(screenWidth, 1), 0, wColor);
for (Obstacle obs in _obstacles)
{
obs.Draw(wColor);
}
_rocket.Draw();
var scorePrep = FontRenderer.PrepareText(_font, scope $"{_rocket.Score}", 1.0f);
FontRenderer.DrawText(scorePrep, -scorePrep.AdvanceX / 2, 1.5f, .Black);
FontRenderer.DrawText(scorePrep, -scorePrep.AdvanceX / 2 + 0.1f, 1.6f, .(230, 230, 230));
scorePrep.ReleaseRef();
if (!_rocket.Started)
{
float f = (float)Math.Cos(gameTime.TotalTime.TotalSeconds) * 0.5f + 0.55f;
FontRenderer.DrawText(pressSpaceToStart, -pressSpaceToStart.AdvanceX / 2f, 0, .(1, 0, 0, f));
}
if (_rocket.Dead)
{
float f = (float)Math.Cos(gameTime.TotalTime.TotalSeconds) * 0.5f + 0.55f;
FontRenderer.DrawText(pressSpaceToRestart, -pressSpaceToRestart.AdvanceX / 2f, 0, .(1, 0, 0, f));
}
Renderer2D.EndScene();
}
private void DrawStartField(GameTime gameTime)
{
for (int i < points.Count)
{
points[i].X -= _rocket.FlightSpeed * gameTime.DeltaTime * points[i].Z;
if (points[i].X < _camera.Left)
{
points[i].X = _camera.Right + startRandom.Next(500, 1500) / 1000.0f;
}
Renderer2D.DrawCircle(Vector3(points[i].XY, 5), .(0.01f * points[i].W), Color.White);
}
}
public override void OnEvent(Event event)
{
EventDispatcher dispatcher = EventDispatcher(event);
dispatcher.Dispatch<ImGuiRenderEvent>(scope (e) => OnImGuiRender(e));
dispatcher.Dispatch<WindowResizeEvent>(scope (e) => OnWindowResize(e));
}
private bool OnImGuiRender(ImGuiRenderEvent e)
{
return false;
}
private bool OnWindowResize(WindowResizeEvent e)
{
_camera.Width = _camera.Height * e.Width / (float)e.Height;
_camera.Update();
return false;
}
}
}
+213
View File
@@ -0,0 +1,213 @@
using System;
using GlitchyEngine.Math;
namespace Sandbox
{
struct Line2D
{
public Vector2 Start;
public Vector2 End;
public this(Vector2 start, Vector2 end)
{
Start = start;
End = end;
}
/// Returns true if the given point lies on the line.
public bool OnLine(Vector2 point)
{
Vector2 startToPoint = point - Start;
Vector2 startToEnd = End - Start;
float cross = cross(startToPoint, startToEnd);
if(!MathHelper.IsZero(cross))
return false;
if(Math.Abs(startToEnd.X) >= Math.Abs(startToEnd.Y))
{
return (startToEnd.X > 0.0f) ?
(Start.X <= point.X && point.X <= End.X) :
(End.X <= point.X && point.X <= Start.X);
}
else
{
return (startToEnd.Y > 0.0f) ?
(Start.Y <= point.Y && point.Y <= End.Y) :
(End.Y <= point.Y && point.Y <= Start.Y);
}
}
[Inline]
private float cross(Vector2 v, Vector2 w)
{
return v.X * w.Y - v.Y * w.X;
}
public enum LineIntersection
{
case Collinear(Line2D IntersectionLine);
case CollinearNoIntersect;
case Parallel;
case Intersection(Vector2 Point);
case None;
}
private Result<(float Start, float End)> IntervalIntersection(float startA, float endA, float startB, float endB)
{
if(startB > endA || startA > endB)
return .Err;
else
{
float start = Math.Max(startA, startB);
float end = Math.Min(endA, endB);
return .Ok((start, end));
}
}
public LineIntersection Intersects(Line2D line)
{
Vector2 A = this.Start;
Vector2 B = this.End;
Vector2 C = line.Start;
Vector2 D = line.End;
float numR = ((A.Y-C.Y) * (D.X-C.X) - (A.X-C.X) * (D.Y-C.Y));
float den = ((B.X-A.X) * (D.Y-C.Y)-(B.Y-A.Y) * (D.X-C.X));
float r = numR / den;
float s = ((A.Y-C.Y) * (B.X-A.X) - (A.X-C.X) * (B.Y-A.Y)) / den;
if((0 <= r && r <= 1) && (0 <= s && s <= 1))
{
Vector2 P = A + r * (B - A);
return .Intersection(P);
}
else if(MathHelper.IsZero(den))
{
if(MathHelper.IsZero(numR))
{
Vector2 AtoB = B - A;
Vector2 CtoD = D - C;
float r_dot_r = Vector2.Dot(AtoB, AtoB);
// t0 = (q p) · r / (r · r)
float t0 = Vector2.Dot((C - A), AtoB) / r_dot_r;
// t1 = (q + s p) · r / (r · r) = t0 + s · r / (r · r)
float t1 = t0 + Vector2.Dot(CtoD, AtoB) / r_dot_r;
// do interval intersection
if(Vector2.Dot(CtoD, AtoB) < 0)
{
Swap!(t0, t1);
}
if(IntervalIntersection(t0, t1, 0, 1) case .Ok(let intersection))
{
return .Collinear(Line2D(A + intersection.Start * AtoB, A + intersection.End * AtoB));
}
else
{
return .CollinearNoIntersect;
}
}
else
{
return .Parallel;
}
}
return .None;
}
public static void TestIntersects()
{
{
Line2D line = .(.(0, 0), .(4, 0));
Line2D intersecting = .(.(2, 2), .(2, -2));
var result = line.Intersects(intersecting);
Vector2 intersection;
Runtime.Assert(result case .Intersection(out intersection));
Runtime.Assert(intersection == .(2, 0));
}
{
Line2D line = .(.(0, -1), .(5, 2));
Line2D intersecting = .(.(1, 3), .(4, -2));
var result = line.Intersects(intersecting);
Vector2 intersection;
Runtime.Assert(result case .Intersection(out intersection));
Runtime.Assert(intersection == .(2.5f, 0.5f));
}
{
Line2D line = .(.(-1, 0), .(1, 0));
Line2D collinear = .(.(2, 0), .( 4, 0));
var result = line.Intersects(collinear);
Runtime.Assert(result case .CollinearNoIntersect);
}
{
Line2D line = .(.(-1, 0), .(2, 0));
Line2D collinear = .(.(1, 0), .( 4, 0));
var result = line.Intersects(collinear);
Line2D intersection;
Runtime.Assert(result case .Collinear(out intersection));
Runtime.Assert(intersection.Start == .(1, 0));
Runtime.Assert(intersection.End == .(2, 0));
}
{
Line2D line = .(.(-1, 5), .(2, 5));
Line2D collinear = .(.(4, 5), .(1, 5));
var result = line.Intersects(collinear);
Line2D intersection;
Runtime.Assert(result case .Collinear(out intersection));
Runtime.Assert(intersection.Start == .(1, 5));
Runtime.Assert(intersection.End == .(2, 5));
}
}
/*
public bool Intersects(Line2D line)
{
float x1 = Start.X;
float x2 = End.X;
float x3 = line.Start.X;
float x4 = line.End.X;
float y1 = Start.Y;
float y2 = End.Y;
float y3 = line.Start.Y;
float y4 = line.End.Y;
float t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
float u = ((x1 - x3) * (y1 - y2) - (y1 - y3) * (x1 - x2)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
return (0.0f <= t && t <= 1.0f && 0.0f <= u && u <= 1.0f);
}
*/
}
}
+46
View File
@@ -0,0 +1,46 @@
using GlitchyEngine;
using GlitchyEngine.Math;
using GlitchyEngine.Renderer;
using System;
namespace Sandbox
{
class Obstacle
{
public Vector2 Position;
public float HoleSize = 4.5f;
public static float Speed = -2.0f;
public static float ScreenWidth;
public static Random random = new .() ~ delete _;
public bool Dead;
public void Update(GameTime gameTime)
{
Position.X += Speed * gameTime.DeltaTime;
if (Position.X < -ScreenWidth - 1)
{
Dead = true;
}
}
static Matrix mat = Matrix.Scaling(2.5f, 5, 1) * Matrix.RotationZ(MathHelper.PiOverFour);
public void Draw(ColorRGBA color)
{
Matrix matty = mat;
matty.Translation.X = Position.X;
matty.Translation.Y = Position.Y - HoleSize;
Renderer2D.DrawQuad(matty, color);
matty.Translation.Y = Position.Y + HoleSize;
Renderer2D.DrawQuad(matty, color);
}
}
}
+133
View File
@@ -0,0 +1,133 @@
using GlitchyEngine.Math;
using GlitchyEngine;
using System;
using GlitchyEngine.Renderer;
namespace Sandbox
{
class ParticleSystem
{
struct Particle
{
public bool IsAlive;
public Vector2 Position;
public float Rotation;
public float Scale;
public Vector2 Velocity;
public float AngularVelocity;
public float LiveTime;
public Color Color;
}
private Random _random = new .() ~ delete _;
private Particle[] _particles ~ delete _;
private int _freeParticles;
public float EmissionRate;
public float EmissionAngle;
public Vector2 EmissionDirection;
public float EmissionVelocity;
public float EmissionSize;
public float EmissionSizeVariance;
public float LiveTime;
public float LiveTimeVariance;
public Vector2 Position;
public bool Emit;
public Color EmmisionColor = .White;
public this(int maxParticles)
{
_particles = new Particle[maxParticles];
_freeParticles = maxParticles;
}
private float _emission = 0.0f;
public void Update(GameTime gameTime)
{
for (var particle in ref _particles)
{
if (!particle.IsAlive)
continue;
particle.LiveTime -= gameTime.DeltaTime;
if (particle.LiveTime < 0.0f)
{
particle.IsAlive = false;
_freeParticles++;
}
particle.Position += particle.Velocity * gameTime.DeltaTime;
particle.Rotation += particle.AngularVelocity * gameTime.DeltaTime;
}
if (Emit)
{
_emission += gameTime.DeltaTime * EmissionRate;
while (_emission >= 1.0f)
{
Emit();
_emission--;
}
}
}
public void Draw()
{
for (let particle in _particles)
{
if(particle.IsAlive)
Renderer2D.DrawQuad(particle.Position, .(particle.Scale), particle.Rotation, particle.Color);
}
}
private Particle* GetFreeParticle()
{
for (ref Particle particle in ref _particles)
{
if (!particle.IsAlive)
return &particle;
}
return null;
}
private void Emit()
{
if (_freeParticles == 0)
return;
Particle* particle = GetFreeParticle();
if (particle == null)
return;
particle.IsAlive = true;
particle.Position = Position;
particle.Rotation = 0;
particle.Scale = EmissionSize + (float)_random.NextDoubleSigned() * EmissionSizeVariance;
float angle = Math.Atan2(EmissionDirection.Y, EmissionDirection.X);
angle += (float)_random.NextDoubleSigned() * EmissionAngle;
Vector2 direction = .(Math.Cos(angle), Math.Sin(angle));
particle.Velocity = direction * EmissionVelocity;
particle.AngularVelocity = 0;//EmissionVelocity;
particle.LiveTime = LiveTime + (float)_random.NextDoubleSigned() * LiveTimeVariance;
particle.Color = EmmisionColor;
_freeParticles--;
}
}
}
+213
View File
@@ -0,0 +1,213 @@
using GlitchyEngine.Renderer;
using GlitchyEngine.Math;
using GlitchyEngine;
using System;
using System.Collections;
namespace Sandbox
{
class Rocket
{
Texture2D _rocketTexture ~ _?.ReleaseRef();
private Vector2 _gravity = .(0, -9.81f);
public float Power = 50;
public float FlightSpeed = 2;
private Vector2 _acceleration = .(0, 0);
private Vector2 _speed;
private Vector2 _position;
private Vector2 _direction;
private Line2D _rocketLine;
private float _rotation = -MathHelper.PiOverTwo;
public bool Dead;
public bool Started = false;
public List<Obstacle> Obstacles;
public int Score = 0;
public Vector2 Position => _position;
public Vector2 Direction => _direction;
ParticleSystem _particleSystem ~ delete _;
public this()
{
_rocketTexture = new Texture2D("content/RocketGame/Rocket.dds");
_rocketTexture.SamplerState = SamplerStateManager.PointClamp;
_particleSystem = new ParticleSystem(1024)
{
LiveTime = 1.0f,
LiveTimeVariance = 0.5f,
Emit = true,
};
}
public void Update(GameTime gameTime)
{
do
{
FlightSpeed = Dead ? 0.0f : 2.0f;
if (Dead && Input.IsKeyPressing(Key.Space))
{
Dead = false;
Started = false;
_speed = .Zero;
Score = 0;
}
else if (!Started)
{
_position = .Zero;
if (Input.IsKeyPressing(Key.Space))
Started = true;
else
break;
}
UpdatePosition(gameTime);
if (Started)
CheckDead();
}
UpdateParticles(gameTime);
}
private void UpdateParticles(GameTime gameTime)
{
_particleSystem.Position = Position - Direction * 0.4f;
_particleSystem.EmissionDirection = -Direction;
_particleSystem.EmissionVelocity = FlightSpeed * 2;
_particleSystem.EmissionAngle = MathHelper.PiOverFour / 2;
_particleSystem.Emit = !Dead;
if (Input.IsKeyPressing(Key.Space))
{
_particleSystem.EmissionRate = 100;
_particleSystem.EmissionSize = 0.125f;
_particleSystem.EmissionSizeVariance = 0.025f;
_particleSystem.EmmisionColor = .(255, 106, 0);
}
else if (Input.IsKeyReleasing(Key.Space))
{
_particleSystem.EmissionRate = 10;
_particleSystem.EmissionSize = 0.075f;
_particleSystem.EmissionSizeVariance = 0.025f;
_particleSystem.EmmisionColor = .(140, 126, 93);
}
_particleSystem.Update(gameTime);
}
public void Draw()
{
_particleSystem.Draw();
Renderer2D.DrawQuad(Vector3(_position, 5), .One, _rotation, _rocketTexture, .White);
}
private void UpdatePosition(GameTime gameTime)
{
_acceleration.Y = 0;
if (!Dead && Input.IsKeyPressed(Key.Space))
{
_acceleration.Y += Power;
}
Vector2 newSpeed = _speed + (_acceleration + _gravity) * gameTime.DeltaTime;
Vector2 newPosition = _position + newSpeed * gameTime.DeltaTime;
_speed = newSpeed;
_position = newPosition;
float ang = Math.Atan2(_speed.Y, 5) - MathHelper.PiOverTwo;
_rotation = ang;
_direction = Vector2.Normalize(_speed + .(5, 0));
_rocketLine = .(_position - _direction / 2.8f, _position + _direction / 2.4f);
}
const float worldBorder = 2.1f;
private void CheckDead()
{
if (Math.Abs(_position.Y) >= worldBorder)
{
Dead = true;
_speed.Y *= -0.8f;
_position.Y = Math.Clamp(_position.Y, -worldBorder, worldBorder);
}
CheckObstacles();
}
private int scoreLine = -1;
private void CheckObstacles()
{
for (Obstacle obs in Obstacles)
{
//const float f = Vector2.One.Magnitude();
float f = Vector2.One.Magnitude();
Vector2 center = obs.Position;
Vector2 topCenter = center + .(0, obs.HoleSize);
Vector2 topTip = topCenter - .(0, 2.5f * f);
Vector2 topRight = topCenter - .(f, 0);
Vector2 topLeft = topCenter + .(f, 0);
Vector2 bottomCenter = center - .(0, obs.HoleSize);
Vector2 bottomTip = bottomCenter + .(0, 2.5f * f);
Vector2 bottomRight = bottomCenter - .(f, 0);
Vector2 bottomLeft = bottomCenter + .(f, 0);
Line2D bottomR = .(bottomTip, bottomRight);
Line2D bottomL = .(bottomTip, bottomLeft);
Line2D topR = .(topTip, topRight);
Line2D topL = .(topTip, topLeft);
if ((bottomR.Intersects(_rocketLine) case .Intersection) ||
(bottomL.Intersects(_rocketLine) case .Intersection) ||
(topR.Intersects(_rocketLine) case .Intersection) ||
(topL.Intersects(_rocketLine) case .Intersection))
{
Dead = true;
}
if (!Dead)
{
if (Line2D(bottomTip, topTip).Intersects(_rocketLine) case .Intersection)
{
scoreLine = @obs.Index;
}
else if (scoreLine == @obs.Index)
{
Score++;
scoreLine = -1;
}
}
}
}
}
}
+6 -2
View File
@@ -18,13 +18,17 @@ namespace Sandbox
{ {
public this() public this()
{ {
#if GAMMA_TEST Window.Title = "Single Stage to Highscore";
Window.SetIcon("content/RocketGame/RocketIcon.ico");
/*#if GAMMA_TEST
PushLayer(new GammaTestLayer()); PushLayer(new GammaTestLayer());
#elif SANDBOX_2D #elif SANDBOX_2D
PushLayer(new ExampleLayer2D()); PushLayer(new ExampleLayer2D());
#else #else
PushLayer(new ExampleLayer()); PushLayer(new ExampleLayer());
#endif #endif*/
PushLayer(new GameLayer());
} }
[Export, LinkName("CreateApplication")] [Export, LinkName("CreateApplication")]