1 module d2d.toolkit.game;
2 
3 import d2d;
4 
5 import std.datetime;
6 
7 /// Class for easily creating a window
8 abstract class Game
9 {
10 private:
11 	int _width = 800, _height = 480;
12 	Bitmap _icon = null;
13 	Window _window = null;
14 	string _title = "Game";
15 	int _fps = 60;
16 	StopWatch _stopwatch;
17 	WindowFlags _flags = WindowFlags.Default;
18 	ShaderProgram _postShader = null;
19 
20 protected:
21 	/// Window start width, will not update afterwards
22 	@property ref int windowWidth()
23 	{
24 		return _width;
25 	}
26 
27 	/// Window start height, will not update afterwards
28 	@property ref int windowHeight()
29 	{
30 		return _height;
31 	}
32 
33 	/// Window icon, will not update afterwards
34 	@property ref Bitmap windowIcon()
35 	{
36 		return _icon;
37 	}
38 
39 	/// Window title, will not update afterwards
40 	@property ref string windowTitle()
41 	{
42 		return _title;
43 	}
44 
45 	/// Max FPS, will not update afterwards
46 	@property ref int maxFPS()
47 	{
48 		return _fps;
49 	}
50 
51 	/// Window start flags, will not update afterwards
52 	@property ref WindowFlags flags()
53 	{
54 		return _flags;
55 	}
56 
57 	/// Handle to the window.
58 	@property Window window()
59 	{
60 		return _window;
61 	}
62 
63 	/// Optional post processing shader.
64 	@property ref ShaderProgram postShader()
65 	{
66 		return _postShader;
67 	}
68 
69 	/// Start function will get called before window is created. Variables can be changed here.
70 	abstract void start();
71 
72 	/// Load function thats meant for loading content.
73 	abstract void load();
74 
75 	/// Will get called every frame before `draw`.
76 	abstract void update(float delta);
77 
78 	/// Draw code goes here, `window.display` is not needed.
79 	abstract void draw();
80 
81 	/// Happens when some window event gets called.
82 	void onEvent(Event event);
83 
84 public:
85 	/// Starts the window and calls all functions
86 	void run()
87 	{
88 		start();
89 
90 		_window = new Window(_width, _height, _title, _flags);
91 
92 		if (_icon is null)
93 		{
94 			_icon = new Bitmap(
95 				[
96 				    0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
97 				    0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00ffffff,
98 				    0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xff9c9c9c, 0xff000000, 0xff000000, 0xff000000, 0xff383838, 0xffcccccc, 0xffffffff,
99 				    0xffffffff, 0xff000000, 0xff303030, 0xff303030, 0xff303030, 0xff1c1c1c, 0xff000000, 0xff9c9c9c, 0xffcccccc, 0xff000000, 0xff292929, 0xff303030, 0xff292929, 0xff000000, 0xff6d6d6d, 0xffffffff,
100 				    0xffffffff, 0xff000000, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xff707070, 0xff131313, 0xff000000, 0xffcccccc, 0xff303030, 0xffb7b7b7, 0xffcccccc, 0xffb7b7b7, 0xff131313, 0xff000000, 0xffffffff,
101 				    0xffffffff, 0xff000000, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xff555555, 0xff000000, 0xff9c9c9c, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xff1e1e1e, 0xff000000, 0xffffffff,
102 				    0xffffffff, 0xff000000, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffa7a7a7, 0xff000000, 0xff6d6d6d, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffb0b0b0, 0xff000000, 0xff555555, 0xffffffff,
103 				    0xffffffff, 0xff000000, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffb0b0b0, 0xff000000, 0xff727272, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xff333333, 0xff0d0d0d, 0xffa7a7a7, 0xffffffff,
104 				    0xffffffff, 0xff000000, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xff8b8b8b, 0xff000000, 0xff909090, 0xffcccccc, 0xffcccccc, 0xff545454, 0xff000000, 0xff5b5b5b, 0xffcccccc, 0xffffffff,
105 				    0xffffffff, 0xff000000, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xff444444, 0xff060606, 0xffb7b7b7, 0xffcccccc, 0xff545454, 0xff000000, 0xff454545, 0xffcccccc, 0xffcccccc, 0xffffffff,
106 				    0xffffffff, 0xff000000, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xff545454, 0xff000000, 0xff343434, 0xffcccccc, 0xff545454, 0xff000000, 0xff303030, 0xffcccccc, 0xffcccccc, 0xffcccccc, 0xffffffff,
107 				    0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff303030, 0xffa7a7a7, 0xffb0b0b0, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
108 				    0xffffffff, 0xff303030, 0xff303030, 0xff303030, 0xff303030, 0xff454545, 0xffcccccc, 0xffcccccc, 0xffb7b7b7, 0xff303030, 0xff303030, 0xff303030, 0xff303030, 0xff303030, 0xff303030, 0xffffffff,
109 				    0x00ffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00ffffff,
110 				    0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
111 				    0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
112 			    ], 16, 16, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
113 		}
114 
115 		_window.setIcon(_icon);
116 
117 		FPSLimiter limiter;
118 		if (_fps > 0)
119 			limiter = new FPSLimiter(_fps);
120 
121 		load();
122 
123 		Event event;
124 		TickDuration delta;
125 		while (_window.open)
126 		{
127 			_stopwatch.start();
128 			while (_window.pollEvent(event))
129 			{
130 				if (event.type == Event.Type.Quit)
131 					_window.close();
132 				else
133 					onEvent(event);
134 			}
135 
136 			update(delta.to!("seconds", float));
137 
138 			draw();
139 
140 			if (_postShader !is null)
141 				_window.display(_postShader);
142 			else
143 				_window.display();
144 
145 			if (limiter !is null)
146 				limiter.wait();
147 
148 			_stopwatch.stop();
149 			delta = _stopwatch.peek();
150 			_stopwatch.reset();
151 		}
152 	}
153 }