1 /**
2 *   Copyright: © 2012-2014 Anton Gushcha
3 *   License: Subject to the terms of the MIT license, as written in the included LICENSE file.
4 *   Authors:  NCrashed <ncrashed@gmail.com>,
5 *             LeMarwin <lemarwin42@gmail.com>,
6 *             Nazgull09 <nazgull90@gmail.com>
7 */
8 module ant.app;
9 
10 import std.stdio;
11 import std.process;
12 import std.exception;
13 import std.conv;
14 import std.string;
15 import std.concurrency;
16 import core.time;
17 import core.thread;
18 
19 import derelict.sdl2.sdl;
20 import derelict.sdl2.ttf;
21 
22 import devol.singleton;
23 import devol.population;
24 
25 import ant.progtype;
26 import ant.util;
27 
28 class App: Singleton!App
29 {
30 public:
31 	this()
32 	{
33 		version(linux)
34 			DerelictSDL2.load();
35 		version(Windows)
36 			DerelictSDL2.load();
37 			
38 		writeln("Loaded derelict");
39 		
40 		enforce(SDL_Init(SDL_INIT_EVERYTHING) == 0, text("Could not initialize SDL: ", SDL_GetError()));
41 		writeln("SDL initilized!");
42 		
43 		/*if(TTF_Init() < 0)
44 		{
45 			writefln("Could not initialize SDL_TTF: %s.\n", SDL_GetError());
46 			return;
47 		}*/
48 		
49 		window = SDL_CreateWindow("Ant evolution!", 100, 100, 1024, 1024, SDL_WINDOW_SHOWN);
50 	    enforce(window !is null, "Failed to create window! ", SDL_GetError().fromStringz);
51 	    writeln("Window is created!");
52 	    
53 		renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
54 		enforce(renderer !is null, "Failed to create renderer! ", SDL_GetError().fromStringz);
55 		
56 		auto info = new SDL_RendererInfo();
57 		SDL_GetRendererInfo(renderer, info);
58 		writeln("Renderer is initialized! Information: ", info.name.fromStringz);
59 		
60 		empty = loadSurface("../media/textures/Empty.bmp");
61 		food = loadSurface("../media/textures/Cherry.bmp");
62 		wall = loadSurface("../media/textures/Wall.bmp");
63 		
64 		ants[Ant.Faces.NORTH] = loadSurface("../media/textures/AntN.bmp");
65 		ants[Ant.Faces.SOUTH] = loadSurface("../media/textures/AntS.bmp");
66 		ants[Ant.Faces.EAST] = loadSurface("../media/textures/AntE.bmp");
67 		ants[Ant.Faces.WEST] = loadSurface("../media/textures/AntW.bmp");
68 		
69 		SDL_RenderClear(renderer);
70 		eventThreadTid = spawn(&eventThread, thisTid);
71 	}
72 	
73 	bool shouldExit()
74 	{
75 	    static bool done = false;
76 	    
77 	    auto res = receiveTimeout(10.dur!"msecs", (bool v) {});
78 	    if(res) done = true;
79 	    
80 	    return done;
81 	}
82 	
83 	static void eventThread(Tid tid)
84 	{
85 	    Thread.getThis.isDaemon(true);
86 		SDL_Event event;
87 
88 		
89 		bool done = false;
90 		while ( !done && SDL_WaitEvent(&event) ) 
91 		{
92 		    const ubyte* state = SDL_GetKeyboardState(null);
93 			switch (event.type) {
94 				case SDL_KEYDOWN:
95 				    if(state[SDL_SCANCODE_ESCAPE])
96 				    {
97 				        tid.send(true);
98 			        }
99 				break;
100 				default:
101 				
102 				break;
103 			}
104 		}
105 	}
106 	
107 	SDL_Texture* loadSurface(string name)
108 	{
109 	    SDL_Surface* bmp = SDL_LoadBMP(name.toStringz);
110 	    if(bmp is null)
111 	    {
112 	        enforce(false, text("Failed to load surface ", name, "! ", SDL_GetError().fromStringz));
113 	    }
114 	    
115         SDL_Texture* tex = SDL_CreateTextureFromSurface(renderer, bmp);
116         SDL_FreeSurface(bmp);
117         if (tex is null)
118         {
119             enforce(false, text("Failed to create texture from surface  ", name, "! ", SDL_GetError().fromStringz));
120         }
121         
122         return tex;
123 	}
124 	
125 	void clear()
126 	{
127 	    if(drawFrame) SDL_RenderClear(renderer);
128 	}
129 	
130     void draw(SDL_Texture* tex, uint x, uint y, uint w, uint h)
131     {
132         if(drawFrame)
133             SDL_RenderCopy(renderer, tex, null, new SDL_Rect(x, y, w, h));
134         
135     }
136     
137     void present()
138     {
139         drawFrame = !drawFrame; 
140         SDL_RenderPresent(renderer);
141     }
142     
143 	~this()
144 	{
145 	    SDL_DestroyTexture(empty);
146 	    SDL_DestroyTexture(food);
147 	    SDL_DestroyTexture(wall);
148 	    foreach(tex; ants)
149 	    {
150 	        SDL_DestroyTexture(tex);
151 	    }
152 	    
153 		SDL_DestroyRenderer(renderer);
154         SDL_DestroyWindow(window);
155         SDL_Quit();
156     }
157 	
158 	SDL_Texture* empty;
159 	SDL_Texture* food;
160 	SDL_Texture* wall;
161 	SDL_Texture*[Ant.Faces] ants;
162 	SDL_Texture* screen;
163 	
164     private
165     {
166         SDL_Window* window;
167         SDL_Renderer* renderer;
168         SDL_Event event;
169         bool drawFrame = true;
170         Tid eventThreadTid;
171 	}
172 }
173 
174