MoonWorks/src/Game.cs

159 lines
4.6 KiB
C#
Raw Normal View History

2021-01-20 03:34:26 +00:00
using System.Collections.Generic;
using SDL2;
2021-01-20 02:06:10 +00:00
using MoonWorks.Audio;
2021-01-20 03:34:26 +00:00
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Window;
2021-03-25 22:57:26 +00:00
using System.Text;
2021-01-19 07:29:07 +00:00
namespace MoonWorks
{
public abstract class Game
{
2021-01-23 07:43:48 +00:00
public const double MAX_DELTA_TIME = 0.1;
2021-01-19 07:29:07 +00:00
private bool quit = false;
private double timestep;
ulong currentTime = SDL.SDL_GetPerformanceCounter();
double accumulator = 0;
2021-01-19 19:24:23 +00:00
bool debugMode;
2021-01-19 07:29:07 +00:00
public OSWindow Window { get; }
2021-01-19 07:29:07 +00:00
public GraphicsDevice GraphicsDevice { get; }
2021-01-20 02:06:10 +00:00
public AudioDevice AudioDevice { get; }
public Inputs Inputs { get; }
2021-01-19 07:29:07 +00:00
private Dictionary<PresentMode, RefreshCS.Refresh.PresentMode> moonWorksToRefreshPresentMode = new Dictionary<PresentMode, RefreshCS.Refresh.PresentMode>
{
{ PresentMode.Immediate, RefreshCS.Refresh.PresentMode.Immediate },
{ PresentMode.Mailbox, RefreshCS.Refresh.PresentMode.Mailbox },
{ PresentMode.FIFO, RefreshCS.Refresh.PresentMode.FIFO },
{ PresentMode.FIFORelaxed, RefreshCS.Refresh.PresentMode.FIFORelaxed }
};
2021-01-19 19:24:23 +00:00
public Game(
WindowCreateInfo windowCreateInfo,
PresentMode presentMode,
int targetTimestep = 60,
bool debugMode = false
) {
2021-01-19 07:29:07 +00:00
timestep = 1.0 / targetTimestep;
if (SDL.SDL_Init(SDL.SDL_INIT_VIDEO | SDL.SDL_INIT_TIMER | SDL.SDL_INIT_GAMECONTROLLER) < 0)
{
System.Console.WriteLine("Failed to initialize SDL!");
return;
}
2021-01-20 02:06:10 +00:00
Logger.Initialize();
Inputs = new Inputs();
2021-01-19 07:29:07 +00:00
Window = new OSWindow(windowCreateInfo);
2021-01-19 07:29:07 +00:00
2021-01-19 19:24:23 +00:00
GraphicsDevice = new GraphicsDevice(
Window.Handle,
moonWorksToRefreshPresentMode[presentMode],
debugMode
);
2021-01-20 02:06:10 +00:00
AudioDevice = new AudioDevice();
2021-01-19 19:24:23 +00:00
this.debugMode = debugMode;
2021-01-19 07:29:07 +00:00
}
public void Run()
{
while (!quit)
{
var newTime = SDL.SDL_GetPerformanceCounter();
double frameTime = (newTime - currentTime) / (double)SDL.SDL_GetPerformanceFrequency();
2021-01-23 07:43:48 +00:00
if (frameTime > MAX_DELTA_TIME)
2021-01-19 07:29:07 +00:00
{
2021-01-23 07:43:48 +00:00
frameTime = MAX_DELTA_TIME;
2021-01-19 07:29:07 +00:00
}
currentTime = newTime;
accumulator += frameTime;
if (!quit)
{
while (accumulator >= timestep)
{
2021-01-20 04:23:09 +00:00
HandleSDLEvents();
Inputs.Update();
AudioDevice.Update();
2021-01-19 07:29:07 +00:00
Update(timestep);
accumulator -= timestep;
}
double alpha = accumulator / timestep;
2021-01-26 22:09:10 +00:00
Draw(timestep, alpha);
2021-01-19 07:29:07 +00:00
}
}
}
2021-01-20 04:23:09 +00:00
private void HandleSDLEvents()
{
while (SDL.SDL_PollEvent(out var _event) == 1)
{
switch (_event.type)
{
case SDL.SDL_EventType.SDL_QUIT:
quit = true;
break;
2021-03-25 22:57:26 +00:00
case SDL.SDL_EventType.SDL_TEXTINPUT:
HandleTextInput(_event);
break;
2021-01-20 04:23:09 +00:00
}
}
}
2021-01-19 07:29:07 +00:00
protected abstract void Update(double dt);
protected abstract void Draw(double dt, double alpha);
2021-03-25 22:57:26 +00:00
private void HandleTextInput(SDL2.SDL.SDL_Event evt)
{
// Based on the SDL2# LPUtf8StrMarshaler
unsafe
{
int bytes = MeasureStringLength(evt.text.text);
if (bytes > 0)
{
/* UTF8 will never encode more characters
* than bytes in a string, so bytes is a
* suitable upper estimate of size needed
*/
char* charsBuffer = stackalloc char[bytes];
int chars = Encoding.UTF8.GetChars(
evt.text.text,
bytes,
charsBuffer,
bytes
);
for (int i = 0; i < chars; i += 1)
{
Inputs.OnTextInput(charsBuffer[i]);
}
}
}
}
private unsafe static int MeasureStringLength(byte* ptr)
{
int bytes;
for (bytes = 0; *ptr != 0; ptr += 1, bytes += 1);
return bytes;
}
2021-01-19 07:29:07 +00:00
}
}