Jump to content

Multi-threaded game loop, attempt number 1!


XerShade

Recommended Posts

Not sure if this should go here or not, but will try it out anyways.

 

Anyhow coded me up a simple multi-threaded loop for my game Esmiylara Online and though I would share. Needs to be optimized though, very optimized.

Demo of the code in action: https://www.youtube.com/channel/UCgedQWDNldjmHiFJvjN3Hxg

using Esmiylara.Online.Client.Media.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using SFML.Graphics;
using SFML.Audio;
using SFML.System;
using SFML.Window;
using Timer = Esmiylara.Online.Components.Timer;
using KeyEventArgs = SFML.Window.KeyEventArgs;
using System.Windows.Forms;

namespace Esmiylara.Online.Client
{
    /// <summary>
    /// Esmiylara Online game engine, defines engine functions.
    /// </summary>
    public static partial class Engine
    {
        private static Thread cpu;
        private static Thread gpu;

        private static bool RunEngine;

        static SfmlWindow win;

        public static void Run()
        {
            if (!RunEngine)
                thread();
        }

        public static void Stop()
        {
            RunEngine = false;
        }

        private static void thread()
        {
            RunEngine = true;

            cpu = new Thread(() =>
            {
                Timer tickMove = new Timer(1000 / 60);

                while (RunEngine)
                {
                    if(tickMove.CheckInterval())
                    {
                        if (TempCode.Move.Up)
                        {
                            TempCode.Direction = TempCode.DIR_UP;
                            if (TempCode.Y - 1 > TempCode.MinY) { TempCode.Y -= (TempCode.Movement * 1); }
                        }
                        if (TempCode.Move.Down)
                        {
                            TempCode.Direction = TempCode.DIR_DOWN;
                            if (TempCode.Y + 1 < TempCode.MaxY) { TempCode.Y += (TempCode.Movement * 1); }
                        }
                        if (TempCode.Move.Left)
                        {
                            TempCode.Direction = TempCode.DIR_LEFT;
                            if (TempCode.X - 1 > TempCode.MinX) { TempCode.X -= (TempCode.Movement * 1); }
                        }
                        if (TempCode.Move.Right)
                        {
                            TempCode.Direction = TempCode.DIR_RIGHT;
                            if (TempCode.X + 1 < TempCode.MaxX) { TempCode.X += (TempCode.Movement * 1); }
                        }

                        if (TempCode.Move.Up || TempCode.Move.Down || TempCode.Move.Left || TempCode.Move.Right)
                            TempCode.Step = (TempCode.Step >= 60 - (TempCode.Movement * 2)) ? 0 : TempCode.Step + (TempCode.Movement * 2);
                        else
                            TempCode.Step = 0;

                        tickMove.Update();
                    }

                    if (TempCode.Test.CPU)
                    {
                        Thread.Sleep(TempCode.Random.Next(50, 200));
                    }
                }
            });
            cpu.Start();

            gpu = new Thread(() =>
            {
                Timer tickMove = new Timer(1000 / 60);
                Image sprite_img = new Image("whitemage_f.png");
                Texture sprite_tex = new Texture(sprite_img);
                Sprite sprite = new Sprite(sprite_tex);

                win = new SfmlWindow();
                win.Closed += (a, b) => { RunEngine = false; };
                win.KeyReleased += Win_KeyReleased;
                win.KeyPressed += Win_KeyPressed;

                while (RunEngine)
                {
                    if (tickMove.CheckInterval())
                    {
                        win.Clear(Color.Green);

                        int st = (TempCode.Step / ((60 - (TempCode.Movement * 2)) / 4));
                        st = (st >= 4) ? 3 : st;

                        sprite.Position = new Vector2f(TempCode.X - 16, TempCode.Y - 48);
                        sprite.TextureRect = new IntRect(32 * st, 48 * TempCode.Direction, 32, 48);

                        win.Draw(sprite);

                        win.Display();
                        win.DispatchEvents();

                        if (TempCode.Test.GPU)
                        {
                            Thread.Sleep(TempCode.Random.Next(50, 200));
                        }

                        tickMove.Update();
                    }
                }

                sprite.Dispose();
                sprite_tex.Dispose();
                sprite_img.Dispose();
                sprite = null;
                sprite_tex = null;
                sprite_img = null;

                win.Dispose();
                win = null;
            });
            gpu.Start();

            while (RunEngine)
            {
                Thread.Sleep(1);
                Application.DoEvents();

                if (win != null && win.IsOpen)
                    win.DispatchEvents();
            }

            cpu = null;
            gpu = null;
        }

        private static void Win_KeyPressed(object sender, KeyEventArgs e)
        {
            switch(e.Code)
            {
                case Keyboard.Key.Up:
                    TempCode.Move.Up = true;
                    TempCode.Move.Down = false;
                    break;
                case Keyboard.Key.Down:
                    TempCode.Move.Up = false;
                    TempCode.Move.Down = true;
                    break;
                case Keyboard.Key.Left:
                    TempCode.Move.Left = true;
                    TempCode.Move.Right = false;
                    break;
                case Keyboard.Key.Right:
                    TempCode.Move.Left = false;
                    TempCode.Move.Right = true;
                    break;
                case Keyboard.Key.LShift:
                    TempCode.Movement = 2;
                    break;
            }
        }

        private static void Win_KeyReleased(object sender, KeyEventArgs e)
        {
            switch (e.Code)
            {
                case Keyboard.Key.Up:
                case Keyboard.Key.Down:
                    TempCode.Move.Up = false;
                    TempCode.Move.Down = false;
                    break;
                case Keyboard.Key.Left:
                case Keyboard.Key.Right:
                    TempCode.Move.Left = false;
                    TempCode.Move.Right = false;
                    break;
                case Keyboard.Key.LShift:
                    TempCode.Movement = 1;
                    break;
                case Keyboard.Key.Num1:
                    TempCode.Test.CPU = false;
                    TempCode.Test.GPU = false;
                    break;
                case Keyboard.Key.Num2:
                    TempCode.Test.CPU = !TempCode.Test.CPU;
                    TempCode.Test.GPU = false;
                    break;
                case Keyboard.Key.Num3:
                    TempCode.Test.CPU = false;
                    TempCode.Test.GPU = !TempCode.Test.CPU;
                    break;
            }
        }

        public static class TempCode
        {
            public static int X;
            public static int Y;
            public static int Direction;
            public static int Movement = 1;

            public static int MinX = 16;
            public static int MinY = 48;
            public static int MaxX = 1024 - 16;
            public static int MaxY = 576 - 48;
            public static int Step = 0;

            public const int DIR_UP = 3;
            public const int DIR_DOWN = 0;
            public const int DIR_LEFT = 1;
            public const int DIR_RIGHT = 2;

            public static Random Random;

            static TempCode()
            {
                X = (1024 / 2) - (32 / 2);
                Y = (576 / 2) - (48 / 2);
                Direction = DIR_DOWN;
                Random = new Random();
            }

            public static class Move
            {
                public static bool Up;
                public static bool Down;
                public static bool Left;
                public static bool Right;
            }


            public static class Test
            {
                public static bool CPU;
                public static bool GPU;
            }
        }
    }
}

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...