mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Compare commits
8
Commits
scripting
...
RocketGame
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa70d99e31 | ||
|
|
c8cc2f442a | ||
|
|
574f54e32b | ||
|
|
58cf92fb57 | ||
|
|
f49acf34a1 | ||
|
|
7f11b982ee | ||
|
|
d9e34b27a3 | ||
|
|
e61c53400f |
@@ -28,6 +28,9 @@ namespace GlitchyEngine
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -250,6 +250,18 @@ namespace GlitchyEngine
|
||||
[CLink]
|
||||
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)
|
||||
{
|
||||
void* windowPtr = (void*)GetWindowLongPtrW(hwnd, GWL_USERDATA);
|
||||
|
||||
@@ -133,6 +133,9 @@ namespace GlitchyEngine.Renderer
|
||||
private static Effect s_currentEffect;
|
||||
private static Effect s_currentCircleEffect;
|
||||
|
||||
private static int s_InstancesPerDrawCall = 1024;
|
||||
private static int s_MaxInstancesPerDrawCall = 8192;
|
||||
|
||||
private static void InitEffect()
|
||||
{
|
||||
Debug.Profiler.ProfileFunction!();
|
||||
@@ -204,10 +207,10 @@ namespace GlitchyEngine.Renderer
|
||||
|
||||
s_batchBinding.SetVertexBufferSlot(s_instanceBuffer, 1);
|
||||
|
||||
s_rawInstances = new BatchVertex[1024];
|
||||
s_rawInstances = new BatchVertex[s_InstancesPerDrawCall];
|
||||
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_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)
|
||||
{
|
||||
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.
|
||||
@@ -398,6 +406,11 @@ namespace GlitchyEngine.Renderer
|
||||
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));
|
||||
|
||||
if (s_circleInstanceQueue.Count >= s_MaxInstancesPerDrawCall)
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
#if DEBUG
|
||||
Debug.Profiler.ProfileRendererFunction!();
|
||||
|
||||
#if DEBUG
|
||||
Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene.");
|
||||
#endif
|
||||
|
||||
|
||||
@@ -110,5 +110,10 @@ namespace GlitchyEngine
|
||||
}
|
||||
|
||||
public extern void Update();
|
||||
|
||||
/**
|
||||
* Sets the Icon of the window to the given file.
|
||||
*/
|
||||
public extern Result<void> SetIcon(StringView filePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,3 +6,6 @@ Name = "Sandbox"
|
||||
TargetType = "BeefGUIApplication"
|
||||
StartupObject = "GlitchyEngine.Program"
|
||||
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.
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,17 @@ namespace Sandbox
|
||||
{
|
||||
public this()
|
||||
{
|
||||
#if GAMMA_TEST
|
||||
Window.Title = "Single Stage to Highscore";
|
||||
Window.SetIcon("content/RocketGame/RocketIcon.ico");
|
||||
|
||||
/*#if GAMMA_TEST
|
||||
PushLayer(new GammaTestLayer());
|
||||
#elif SANDBOX_2D
|
||||
PushLayer(new ExampleLayer2D());
|
||||
#else
|
||||
PushLayer(new ExampleLayer());
|
||||
#endif
|
||||
#endif*/
|
||||
PushLayer(new GameLayer());
|
||||
}
|
||||
|
||||
[Export, LinkName("CreateApplication")]
|
||||
|
||||
Reference in New Issue
Block a user