/// <summary> /// Sets up a window and enters the gameloop. (Code after this call won't run until the game has exited.) /// </summary> public static void Run(float speed = 100f) { SDL.Init(SDL.InitFlags.EVERYTHING); IMG.Init(IMG.InitFlags.EVERYTHING); Mix.Init(Mix.InitFlags.EVERYTHING); TTF.Init(); //open window SDL.SetHint(SDL.HINT_RENDER_VSYNC, "1"); SDL.SetHint(SDL.HINT_RENDER_SCALE_QUALITY, "2"); WindowHandle = SDL.CreateWindow("HatlessEngine", SDL.WINDOWPOS_UNDEFINED, SDL.WINDOWPOS_UNDEFINED, 800, 600, SDL.WindowFlags.WINDOW_SHOWN | SDL.WindowFlags.WINDOW_RESIZABLE | SDL.WindowFlags.WINDOW_INPUT_FOCUS); RendererHandle = SDL.CreateRenderer(WindowHandle, -1, (uint)(SDL.RendererFlags.RENDERER_ACCELERATED | SDL.RendererFlags.RENDERER_PRESENTVSYNC)); SDL.SetRenderDrawBlendMode(RendererHandle, SDL.BlendMode.BLENDMODE_BLEND); Window.SetIcon(); //add default view that spans the current window new View("default", new Rectangle(Point.Zero, Window.Size), new Rectangle(Point.Zero, new Point(1f, 1f))); //initialize audio system and let Resources handle sound expiration Mix.OpenAudio(44100, SDL.AUDIO_S16SYS, 2, 4096); Mix.AllocateChannels((int)(speed * 2)); //might want to dynamically create and remove channels during runtime Mix.ChannelFinished(new Mix.ChannelFinishedDelegate(Resources.SoundChannelFinished)); Mix.HookMusicFinished(new Mix.MusicFinishedDelegate(Resources.MusicFinished)); //initialize loop StepsPerSecond = speed; Running = true; if (Started != null) { Started(null, EventArgs.Empty); } Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); //do a step before the first draw can occur Step(); long lastStepTick = 0; long lastDrawTick = 0; long lastStepTime = 0; long lastDrawTime = 0; while (Running) { //perform step when needed if (stopWatch.ElapsedTicks >= lastStepTick + TicksPerStep) { if (CatchUpSteps) { lastStepTick = lastStepTick + TicksPerStep; } else { lastStepTick = stopWatch.ElapsedTicks; } Step(); _ActualSPS = (int)(Stopwatch.Frequency / (stopWatch.ElapsedTicks - lastStepTime)); lastStepTime = stopWatch.ElapsedTicks; } //perform draw when ready for a new one if (!RenderframeReady && Running && stopWatch.ElapsedTicks >= lastDrawTick + TicksPerDraw) { lastDrawTick = lastDrawTick + TicksPerDraw; Draw(); _ActualFPS = (int)(Stopwatch.Frequency / (stopWatch.ElapsedTicks - lastDrawTime)); lastDrawTime = stopWatch.ElapsedTicks; } } //cleanup and uninitialization Resources.UnloadAllExternalResources(); Log.CloseAllStreams(); Input.CloseGamepads(); SDL.DestroyWindow(WindowHandle); WindowHandle = IntPtr.Zero; SDL.DestroyRenderer(RendererHandle); RendererHandle = IntPtr.Zero; Mix.CloseAudio(); SDL.Quit(); IMG.Quit(); Mix.Quit(); TTF.Quit(); }
static void Main(string[] args) { SDL.Init(InitFlags.Everything); Log.Priorities.SetAll(LogPriority.Verbose); Log.OutputFunction = (cat, prio, msg) => { Console.WriteLine($"[{prio}] {cat}: {msg}"); }; Log.Message(LogCategory.Application, LogPriority.Debug, "Foo and bar!?"); TTF.Init(); Events.Watch += (ref Event e) => { //Console.WriteLine(e.ToString()); }; Console.WriteLine("Registering timer"); int callbackCount = 0; IDisposable?d = null; d = SDLSharp.Timer.AddTimer(500, n => { Console.WriteLine($"{n}: Timer callback {callbackCount++}"); if (callbackCount > 4 && d != null) { Console.WriteLine("I've had it with this callback business!"); d.Dispose(); } return(500 * (uint)callbackCount); }); Console.WriteLine($"{d} registered"); Console.WriteLine("Ok, here we go:"); Console.WriteLine($"Running SDL version {SDL.RuntimeVersion} {SDL.RuntimeRevision} {SDL.RuntimeRevisionNumber}"); Console.WriteLine($"\tSDL_image version {Image.RuntimeVersion}"); Console.WriteLine($"\tSDL_ttf version {TTF.RuntimeVersion}"); Console.WriteLine($"Video drivers: {string.Join("; ", Video.Drivers)}"); Console.WriteLine($"Audio drivers: {string.Join("; ", Audio.Drivers)}"); Console.WriteLine($"Audio input devices: {string.Join("; ", Audio.InputDevices)}"); Console.WriteLine($"Audio output devices: {string.Join("; ", Audio.InputDevices)}"); if (Clipboard.HasText()) { Console.Write("Clipboard contains: "); Console.WriteLine(Clipboard.GetText()); } else { Console.Write("Clipboard is empty. An empty string looks like: "); Console.WriteLine(Clipboard.GetText()); } foreach (var display in Video.Displays) { Console.WriteLine($"Display {display.Index}"); Console.WriteLine($" Name={display.Name}"); Console.WriteLine($" Bounds={display.Bounds}"); Console.WriteLine($" UsableBounds={display.UsableBounds}"); Console.WriteLine($" DPI={display.DPI}"); Console.WriteLine($" Modes.Current={display.Modes.Current}"); Console.WriteLine($" Modes.Desktop={display.Modes.Desktop}"); for (int i = 0; i < display.Modes.Count; ++i) { Console.WriteLine($" Modes.[{i}]={display.Modes[i]}"); } } for (int i = 0; i < Renderer.Drivers.Count; ++i) { var ri = Renderer.Drivers[i]; Console.WriteLine($"Render driver {i}"); Console.WriteLine($" Name={ri.Name}"); Console.WriteLine($" Flags={ri.Flags}"); Console.WriteLine($" MaxTextureWidth={ri.MaxTextureWidth}"); Console.WriteLine($" MaxTextureHeight={ri.MaxTextureHeight}"); for (int j = 0; j < ri.Formats.Count; ++j) { Console.WriteLine($" Formats.[{j}]={PixelFormat.GetName(ri.Formats[j])}"); } } foreach (var joy in Joystick.Devices) { Console.WriteLine($"{joy}"); Console.WriteLine($"\tGuid={joy.Guid}"); Console.WriteLine($"\tName={joy.Name}"); Console.WriteLine($"\tIsController={joy.IsController}"); using (var j = joy.Open()) { Console.WriteLine($"\t\tOpened {j}"); Console.WriteLine($"\t\tID={j.ID}"); Console.WriteLine($"\t\tName={j.Name}"); Console.WriteLine($"\t\tGuid={j.Guid}"); Console.WriteLine($"\t\tPowerLevel={j.PowerLevel}"); Console.WriteLine($"\t\tNumAxes={j.Axes.Count}"); Console.WriteLine($"\t\tButtons={j.Buttons.Count}"); Console.WriteLine($"\t\tHats={j.Hats.Count}"); Console.WriteLine($"\t\tBalls={j.Balls.Count}"); } if (joy.IsController) { using (var c = joy.OpenController()) { foreach (var axis in Enum.GetValues(typeof(GameControllerAxis)).Cast <GameControllerAxis>()) { if (axis == GameControllerAxis.Invalid || axis == GameControllerAxis.Max) { continue; } var b = c.Axes.GetBind(axis); Console.WriteLine($"\t\tAxis[{axis}/{GameController.AxisName(axis)}].Bind={b}"); } foreach (var btn in Enum.GetValues(typeof(GameControllerButton)).Cast <GameControllerButton>()) { if (btn == GameControllerButton.Invalid || btn == GameControllerButton.Max) { continue; } var b = c.Buttons.GetBind(btn); Console.WriteLine($"\t\tButtons[{btn}/{GameController.ButtonName(btn)}].Bind={b}"); } Console.WriteLine($"\t\tMapping={c.Mapping}"); } } } foreach (var dev in Audio.OutputDevices) { var fmt = new AudioStreamFormat(44000, AudioDataFormat.Float32Bit, 1, 0, 1024); var changes = AllowedAudioStreamChange.Any; Console.Write($"Requesting {fmt} from audio output '{dev}' allowing changes to {changes}..."); try { using (var a = Audio.OpenOutput(dev, changes, fmt, out var obtained)) { Console.WriteLine($"\tgot {obtained}"); } } catch (Exception ex) { Console.WriteLine($"\tFailed w/ error: {ex}"); } } foreach (var dev in Audio.InputDevices) { var fmt = new AudioStreamFormat(44000, AudioDataFormat.Float32Bit, 1, 0, 1024); var changes = AllowedAudioStreamChange.Any; Console.Write($"Requesting {fmt} from audio input '{dev}' allowing changes to {changes}..."); try { using (var a = Audio.OpenInput(dev, changes, fmt, out var obtained)) { Console.WriteLine($"\tgot {a} with format {obtained}"); } } catch (Exception ex) { Console.WriteLine($"\tFailed w/ error: {ex}"); } } Mixer.Open(44100, AudioDataFormat.Float32Bit, 2, 1024); Mixer.Init(MixerLoaders.MP3); Console.WriteLine($"Opened the mixer hz={Mixer.DeviceFrequency} f={Mixer.DeviceFormat} ch={Mixer.DeviceChannels}"); Console.WriteLine($"\tAvailable music decoders {string.Join("; ", MusicTrack.Decoders)}"); Console.WriteLine($"\tAvailable chunk decoders {string.Join("; ", MixerChunk.Decoders)}"); PrintChannels(); Mixer.Channels.Count = 8; PrintChannels(); using var caketown = MusicTrack.Load("./assets/Caketown 1.mp3"); Console.WriteLine($"Loaded {caketown}"); Task.Run(async() => { Mixer.Music.Play(caketown); Mixer.Music.Finished += (se, ev) => Console.WriteLine("Music finished"); await Task.Delay(1000); Mixer.Music.Pause(); Console.WriteLine($"{caketown} paused"); await Task.Delay(1000); Mixer.Music.Resume(); Console.WriteLine($"{caketown} resumed"); await Task.Delay(1000); Mixer.Music.Rewind(); Console.WriteLine($"{caketown} rewound"); await Task.Delay(1000); Console.WriteLine($"{caketown} fading out"); Mixer.Music.FadeOut(1000); Console.WriteLine($"{caketown} faded out"); Mixer.Music.Halt(); Console.WriteLine($"{caketown} halted"); }); using var alarm = MixerChunk.Load("./assets/wobbleboxx.com/Rise01.wav"); var flags = WindowFlags.Shown | WindowFlags.Resizable; using (var window = Video.CreateWindow("Foo änd bar", Window.UndefinedPosition, Window.UndefinedPosition, 600, 400, flags)) using (var renderer = Renderer.Create(window, -1, RendererFlags.Accelerated)) { Console.WriteLine($"Created window {window}"); Mixer.Channels.ChannelFinished += (se, ev) => Console.WriteLine($"{ev.Channel} finished"); window.SetHitTest((Window w, in SDLSharp.Point p) => { Console.WriteLine($"Hit test at {(System.Drawing.Point)p} in window '{w}'"); Events.Current.Push((Action)(() => { if (Mixer.Channels.Play(alarm, 1)) { Console.Write("Playing sound "); } else { Console.Write("NOT playing sound "); } PrintChannels(); })); return(HitTestResult.Normal); });