Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Scene generators #44

Merged
merged 6 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/check-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Restore tools
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Restore tools
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed Ion.Examples/Ion.Examples.Breakout/Assets/Ball1.png
Binary file not shown.
Binary file not shown.
20 changes: 13 additions & 7 deletions Ion.Examples/Ion.Examples.Breakout/Ion.Examples.Breakout.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,29 @@
</PropertyGroup>
<ItemGroup>
<None Remove="appsettings.json" />
<None Remove="Assets\15-Breakout-Tiles.png" />
<None Remove="Assets\49-Breakout-Tiles.png" />
<None Remove="Assets\58-Breakout-Tiles.png" />
</ItemGroup>
<ItemGroup>
<Content Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Assets\15-Breakout-Tiles.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\49-Breakout-Tiles.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Assets\58-Breakout-Tiles.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Ion\Ion.Extensions.Coroutines\Ion.Extensions.Coroutines.csproj" />
<ProjectReference Include="..\..\Ion\Ion.Extensions.Scenes.Generators\Ion.Extensions.Scenes.Generators.csproj" PrivateAssets="all" ReferenceOutputAssembly="false" OutputItemType="Analyzer" />
<ProjectReference Include="..\..\Ion\Ion\Ion.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Assets\Ball1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Assets\Block1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Assets\bonk.wav">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
33 changes: 17 additions & 16 deletions Ion.Examples/Ion.Examples.Breakout/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
builder.Services.AddIon(builder.Configuration, graphics =>
{
graphics.Output = GraphicsOutput.Window;
graphics.ClearColor = Color.DarkSlateGray;
graphics.ClearColor = new Color(0x333);
});

builder.Services.AddSingleton<BreakoutSystems>();
Expand All @@ -34,14 +34,14 @@ public class BreakoutSystems(IWindow window, IInputState input, ISpriteBatch spr
private readonly Color[] _blockColors = new Color[ROWS * COLS];
private readonly RectangleF[] _blockRects = new RectangleF[ROWS * COLS];

private Vector2 _blockSize = new(100, 25f);
private Vector2 _blockSize = new(192f, 64f);
private readonly float _blockGap = 10f;
private readonly float _playerGap = 150f;
private readonly float _bottomGap = 20f;

private RectangleF _playerRect = new(0, 0, 160, 20f);
private RectangleF _paddleRect = new(0, 0, 244f, 64f);

private RectangleF _ballRect = new(0, 0, 20f, 20f);
private RectangleF _ballRect = new(0, 0, 32f, 32f);
private Vector2 _ballVelocity = Vector2.Zero;
private readonly float _initialBallSpeed = 200f;
private float _ballSpeed = 200f;
Expand All @@ -54,7 +54,7 @@ public class BreakoutSystems(IWindow window, IInputState input, ISpriteBatch spr

private Texture2D _blockTexture = default!;
private Texture2D _ballTexture = default!;
private readonly RectangleF _ballSprite = new RectangleF(1, 1, 14, 14);
private Texture2D _paddleTexture = default!;

private SoundEffect _bonkSound = default!;
private SoundEffect _pingSound = default!;
Expand All @@ -66,8 +66,9 @@ public class BreakoutSystems(IWindow window, IInputState input, ISpriteBatch spr
[Init]
public void SetupBlocks(GameTime dt, GameLoopDelegate next)
{
_blockTexture = assets.Load<Texture2D>("Block1.png");
_ballTexture = assets.Load<Texture2D>("Ball1.png");
_blockTexture = assets.Load<Texture2D>("15-Breakout-Tiles.png");
_paddleTexture = assets.Load<Texture2D>("49-Breakout-Tiles.png");
_ballTexture = assets.Load<Texture2D>("58-Breakout-Tiles.png");
_bonkSound = assets.Load<SoundEffect>("Bonk.wav");
_pingSound = assets.Load<SoundEffect>("Ping.mp3");
_scoreFontSet = assets.Load<FontSet>("BungeeRegular", "Bungee-Regular.ttf");
Expand All @@ -88,7 +89,7 @@ public void SetupBlocks(GameTime dt, GameLoopDelegate next)
window.Size = new Vector2((COLS * _blockSize.X) + ((COLS + 1) * _blockGap), (ROWS * _blockSize.Y) + ((ROWS + 1) * _blockGap) + _playerGap + _blockSize.Y + _bottomGap);
window.IsResizable = false;

_playerRect.Location = new Vector2(Math.Clamp(input.MousePosition.X - (_playerRect.Height / 2f), 0, window.Width - _playerRect.Width), window.Size.Y - (_blockSize.Y + _bottomGap));
_paddleRect.Location = new Vector2(Math.Clamp(input.MousePosition.X - (_paddleRect.Height / 2f), 0, window.Width - _paddleRect.Width), window.Size.Y - (_blockSize.Y + _bottomGap));

_repositionBlocks();

Expand Down Expand Up @@ -121,11 +122,11 @@ public void Update(GameTime dt, GameLoopDelegate next)
}


if (isMouseGrabbed) _playerRect.X = Math.Clamp(input.MousePosition.X - (_playerRect.Height / 2f), 0, window.Width - _playerRect.Width);
if (isMouseGrabbed) _paddleRect.X = Math.Clamp(input.MousePosition.X - (_paddleRect.Height / 2f), 0, window.Width - _paddleRect.Width);

if (_ballIsCaptured)
{
_ballRect.Location = _playerRect.Location + new Vector2((_playerRect.Width - _ballRect.Width) / 2f, -(_ballRect.Height + 1));
_ballRect.Location = _paddleRect.Location + new Vector2((_paddleRect.Width - _ballRect.Width) / 2f, -(_ballRect.Height + 1));

if (input.Pressed(MouseButton.Left) && isMouseGrabbed)
{
Expand Down Expand Up @@ -170,7 +171,7 @@ public void Update(GameTime dt, GameLoopDelegate next)
// Ball to player collisions
if (_ballRect.Bottom > 250 && _ballVelocity.Y > 0)
{
RectangleF.Intersect(ref _ballRect, ref _playerRect, out var intersection);
RectangleF.Intersect(ref _ballRect, ref _paddleRect, out var intersection);

if (intersection.IsEmpty is false)
{
Expand Down Expand Up @@ -237,12 +238,12 @@ public void Render(GameTime dt, GameLoopDelegate next)
for (var col = 0; col < COLS; col++)
{
var i = (row * COLS) + col;
if (_blockStates[i]) spriteBatch.Draw(_blockTexture, _blockRects[i], color: _blockColors[i]);
if (_blockStates[i]) spriteBatch.Draw(_blockTexture, _blockRects[i]);//, color: _blockColors[i]);
}
}

spriteBatch.Draw(_blockTexture, _playerRect, color: Color.DarkBlue);
spriteBatch.Draw(_ballTexture, _ballRect, color: Color.DarkRed, sourceRectangle: _ballSprite);
spriteBatch.Draw(_paddleTexture, _paddleRect);//, color: Color.DarkBlue);
spriteBatch.Draw(_ballTexture, _ballRect);//, color: Color.DarkRed);
spriteBatch.DrawString(_scoreFont, $"Score: {_score}", new Vector2(20f), Color.Red);

next(dt);
Expand All @@ -269,12 +270,12 @@ private void _handlePlayerCollision(ref RectangleF intersection)
{
_ballVelocity.X *= -1f;
_ballVelocity = Vector2.Normalize(_ballVelocity);
_ballRect.X = intersection.Left == _playerRect.Left ? _playerRect.X - (_ballRect.Width+1) : _playerRect.Right + 1;
_ballRect.X = intersection.Left == _paddleRect.Left ? _paddleRect.X - (_ballRect.Width+1) : _paddleRect.Right + 1;
return;
}

_ballVelocity.Y *= -1f;
var offsetFromPaddle = (_ballRect.Left - _playerRect.X) / (_playerRect.Width - _ballRect.Width);
var offsetFromPaddle = (_ballRect.Left - _paddleRect.X) / (_paddleRect.Width - _ballRect.Width);

_ballVelocity = Vector2.Lerp(_paddleBounceMin, _paddleBounceMax, offsetFromPaddle);

Expand Down
2 changes: 1 addition & 1 deletion Ion.Examples/Ion.Examples.Breakout/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
},
"Ion": {
"Title": "Ion Breakout Example",
"MaxFPS": 500,
"MaxFPS": 120,
"Debug": {
"TraceEnabled": true
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Ion\Ion.Extensions.Coroutines\Ion.Extensions.Coroutines.csproj" />
<ProjectReference Include="..\..\Ion\Ion.Extensions.Scenes.Generators\Ion.Extensions.Scenes.Generators.csproj" PrivateAssets="all" ReferenceOutputAssembly="false" OutputItemType="Analyzer" />
<ProjectReference Include="..\..\Ion\Ion\Ion.csproj" />
</ItemGroup>
</Project>
126 changes: 67 additions & 59 deletions Ion.Examples/Ion.Examples.Scenes/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using Ion.Extensions.Scenes;
using Ion.Extensions.Coroutines;

using Ion.Examples.Scenes;

var builder = IonApplication.CreateBuilder(args);

builder.Services.AddDebugUtils(builder.Configuration);
Expand All @@ -28,16 +30,17 @@
game.UseEvents();
game.UseVeldridGraphics();


game.UseFirst((GameLoopDelegate next, IInputState input, ICoroutineRunner coroutine) =>
{
IEnumerator CountDown(int from)
{
while (from >= 0)
while (from > 0)
{
Console.WriteLine("Countdown: " + from--);
yield return Wait.Until(() => input.Pressed(Key.Space));
yield return Wait.For(TimeSpan.FromSeconds(1));
}

Console.WriteLine("Countdown done!");
}

return dt =>
Expand Down Expand Up @@ -67,7 +70,7 @@ IEnumerator CountDown(int from)
{
var logFrameNumber = Throttler.Wrap(TimeSpan.FromSeconds(0.5), (dt) =>
{
Console.WriteLine($"Frame: {dt.Frame}!");
//Console.WriteLine($"Frame: {dt.Frame}!");
});

return dt =>
Expand All @@ -88,15 +91,15 @@ IEnumerator CountDown(int from)
{
var flip = false;
var switchScene = Throttler.Wrap(TimeSpan.FromSeconds(3), (dt) => {
eventEmitter.EmitChangeScene(flip ? (int)Scenes.MainMenu : (int)Scenes.Gameplay);
eventEmitter.EmitChangeScene(flip ? Scene.MainMenu : Scene.Gameplay);
flip = !flip;
});

return dt =>
{
if (events.On<int>(out var e)) Console.WriteLine($"Int event! {e.Data}");
next(dt);
switchScene(dt);
//switchScene(dt);
};
});

Expand All @@ -115,7 +118,7 @@ IEnumerator CountDown(int from)
};
});

game.UseScene((int)Scenes.MainMenu, scene =>
game.UseScene(Scene.MainMenu, scene =>
{
scene.UseRender((GameLoopDelegate next, ISpriteBatch spriteBatch) =>
{
Expand All @@ -129,7 +132,7 @@ IEnumerator CountDown(int from)
scene.UseSystem<TestMiddleware>();
});

game.UseScene((int)Scenes.Gameplay, scene =>
game.UseScene(Scene.Gameplay, scene =>
{
scene.UseRender((GameLoopDelegate next, ISpriteBatch spriteBatch) =>
{
Expand All @@ -145,71 +148,76 @@ IEnumerator CountDown(int from)

game.Run();

enum Scenes
{
MainMenu = 1,
Gameplay,
}

public partial class TestMiddleware
namespace Ion.Examples.Scenes
{
private readonly Queue<float> _frameTimes = new Queue<float>();

public TestMiddleware()
public enum Scene
{
Console.WriteLine("TestMiddleware Constructor");
MainMenu = 1,
Gameplay,
Test,
}

[First]
public void CoolFirstMiddleware(GameTime dt, GameLoopDelegate next)
public partial class TestMiddleware
{
//Console.WriteLine($"Class First {dt.Frame}");
next(dt);
}
private readonly Queue<float> _frameTimes = new();

[FixedUpdate]
public GameLoopDelegate FancyFixedUpdate(GameLoopDelegate next)
{
Console.WriteLine("Class Fixed Update SETUP");
uint count = 0;
return dt =>
public TestMiddleware()
{
Console.WriteLine("TestMiddleware Constructor");
}

[First]
public void CoolFirstMiddleware(GameTime dt, GameLoopDelegate next)
{
count++;
//Console.WriteLine($"Class Fixed Update inside {count++}");
//Console.WriteLine($"Class First {dt.Frame}");
next(dt);
};
}
}

[Render]
public GameLoopDelegate Render(GameLoopDelegate next)
{
var stopwatch = new Stopwatch();
[FixedUpdate]
public GameLoopDelegate FancyFixedUpdate(GameLoopDelegate next)
{
Console.WriteLine("Class Fixed Update SETUP");
uint count = 0;
return dt =>
{
count++;
//Console.WriteLine($"Class Fixed Update inside {count++}");
next(dt);
};
}

return dt =>
[Render]
public GameLoopDelegate Render(GameLoopDelegate next)
{
stopwatch.Restart();
next(dt);
stopwatch.Stop();
_frameTimes.Enqueue((float)stopwatch.Elapsed.TotalSeconds);
while (_frameTimes.Count > 60) _frameTimes.Dequeue();
};
var stopwatch = new Stopwatch();

return dt =>
{
stopwatch.Restart();
next(dt);
stopwatch.Stop();
_frameTimes.Enqueue((float)stopwatch.Elapsed.TotalSeconds);
while (_frameTimes.Count > 60) _frameTimes.Dequeue();
};
}
}
}

static class Throttler
{
public static Action<GameTime> Wrap(TimeSpan interval, Action<GameTime> action)
static class Throttler
{
var total = 0f;

return (dt) =>
public static Action<GameTime> Wrap(TimeSpan interval, Action<GameTime> action)
{
total += dt.Delta;
if (total > interval.TotalSeconds)
var total = 0f;

return (dt) =>
{
total = 0;
action(dt);
}
};
total += dt.Delta;
if (total > interval.TotalSeconds)
{
total = 0;
action(dt);
}
};
}
}
}

}
Loading
Loading