Prototype game engine for Heroes of Might & Magic, featuring a gameplay plot-twist...
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

397 lines
16KB

  1. -- Copyright (c) 2024 - Ognjen 'xolatile' Milan Robovic
  2. --
  3. -- GNU General Public Licence (version 3 or later)
  4. with ray;
  5. package body core is
  6. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  7. type terminal_colour is (
  8. grey, red, green, yellow, blue, pink,
  9. cyan, white
  10. );
  11. type terminal_effect is (
  12. normal, bold, italic, underline, blink, invert
  13. );
  14. ------------------------------------------------------------------------------------------
  15. type texture_data_array is array (natural range <>) of ray.texture;
  16. type sound_data_array is array (natural range <>) of ray.sound;
  17. type font_data_array is array (natural range <>) of ray.font;
  18. ------------------------------------------------------------------------------------------
  19. texture_count : integer := 0;
  20. sound_count : integer := 0;
  21. font_count : integer := 0;
  22. texture_array : access texture_data_array;
  23. sound_array : access sound_data_array;
  24. font_array : access font_data_array;
  25. ------------------------------------------------------------------------------------------
  26. procedure terminal (colour : in terminal_colour := white;
  27. effect : in terminal_effect := normal) is
  28. format : string := character'val (27) & "[" & character'val (terminal_effect'pos (effect) + 48) & ";3" & character'val (terminal_colour'pos (colour) + 48) & "m";
  29. begin
  30. put (format);
  31. end terminal;
  32. ------------------------------------------------------------------------------------------
  33. procedure echo (status : in echo_status;
  34. text : in string) is
  35. begin
  36. if not echo_mark (status) then
  37. return;
  38. end if;
  39. --
  40. put ("[");
  41. case status is
  42. when failure => terminal (red, bold); put ("Failure"); terminal;
  43. when warning => terminal (yellow, bold); put ("Warning"); terminal;
  44. when success => terminal (green, bold); put ("Success"); terminal;
  45. when comment => terminal (grey, bold); put ("Comment"); terminal;
  46. when import => terminal (cyan, bold); put (" <-- "); terminal;
  47. when export => terminal (blue, bold); put (" --> "); terminal;
  48. end case;
  49. put ("] ");
  50. --
  51. put_line (text);
  52. end echo;
  53. ------------------------------------------------------------------------------------------
  54. procedure dash is
  55. begin
  56. terminal (grey, bold);
  57. put ("------------------------------------------------------------------------------------------");
  58. put ("------------------------------------------------------------------------------------------");
  59. terminal;
  60. new_line;
  61. end dash;
  62. ------------------------------------------------------------------------------------------
  63. procedure semi_dash is
  64. begin
  65. terminal (grey, bold);
  66. put (" ");
  67. put ("------------------------------------------------------------------------------------------");
  68. terminal;
  69. new_line;
  70. end semi_dash;
  71. ------------------------------------------------------------------------------------------
  72. function c_string (ada_string : string) return string is
  73. begin
  74. return (ada_string & character'val (0));
  75. end c_string;
  76. ------------------------------------------------------------------------------------------
  77. function random (minimum, maximum : in integer) return integer is
  78. begin
  79. return ray.get_random (minimum, maximum);
  80. end random;
  81. ------------------------------------------------------------------------------------------
  82. function clip (value, minimum, maximum : in integer) return integer is
  83. begin
  84. if value < minimum then return minimum; end if;
  85. if value > maximum then return maximum; end if;
  86. --
  87. return value;
  88. end clip;
  89. ------------------------------------------------------------------------------------------
  90. function import_sprite (file_path : in string; frames, states : in integer) return sprite is
  91. this : sprite;
  92. begin
  93. texture_array (texture_count) := ray.load_texture (c_string (file_path));
  94. --
  95. texture_count := texture_count + 1;
  96. this.index := texture_count - 1;
  97. this.width := texture_array (this.index).width / frames;
  98. this.height := texture_array (this.index).height / states;
  99. this.frames := frames;
  100. this.states := states;
  101. --
  102. if this.width = 0 or this.height = 0 then
  103. echo (failure, "Sprite not imported: " & file_path);
  104. end if;
  105. --
  106. return this;
  107. end import_sprite;
  108. ------------------------------------------------------------------------------------------
  109. function import_font (file_path : in string; scale, space : in integer) return font is
  110. this : font;
  111. begin
  112. font_array (font_count) := ray.load_font (c_string (file_path));
  113. --
  114. font_count := font_count + 1;
  115. this.index := font_count - 1;
  116. this.scale := scale;
  117. this.space := space;
  118. --
  119. return this;
  120. end import_font;
  121. ------------------------------------------------------------------------------------------
  122. function import_song (file_path : in string) return song is
  123. this : song;
  124. begin
  125. sound_array (sound_count) := ray.load_sound (c_string (file_path));
  126. --
  127. sound_count := sound_count + 1;
  128. this.index := sound_count - 1;
  129. --
  130. return this;
  131. end import_song;
  132. ------------------------------------------------------------------------------------------
  133. procedure draw (data : in sprite;
  134. x : in integer := 0;
  135. y : in integer := 0;
  136. u : in integer := 0;
  137. v : in integer := 0;
  138. width : in integer := 0;
  139. height : in integer := 0;
  140. state : in integer := 0) is
  141. resize : vector := (0, 0);
  142. begin
  143. resize.x := (if width = 0 then data.width else width);
  144. resize.y := (if height = 0 then data.height else height);
  145. --
  146. ray.draw_texture (data => texture_array (data.index),
  147. uv => (float (if u = 0 then (animation_time mod data.frames) * data.width else u), float (v), float (resize.x), float (resize.y)),
  148. view => (float (x), float (y), float (resize.x) * float (zoom), float (resize.y) * float (zoom)));
  149. end draw;
  150. ------------------------------------------------------------------------------------------
  151. procedure write (text : in string := "";
  152. x : in integer := 0;
  153. y : in integer := 0;
  154. data : in font) is
  155. begin
  156. ray.draw_text (data => font_array (data.index),
  157. text => c_string (text),
  158. view => (float ((icon - data.scale) / 2 + x), float ((icon - data.scale) / 2 + y)),
  159. scale => float (data.scale),
  160. space => float (data.space));
  161. end write;
  162. ------------------------------------------------------------------------------------------
  163. function lowercase (text : in string) return string is
  164. result : string (1 .. text'length);
  165. begin
  166. for index in text'range loop
  167. if text (index) in 'A' .. 'Z' then
  168. result (index) := character'val (character'pos (text (index)) + 32);
  169. else
  170. result (index) := text (index);
  171. end if;
  172. end loop;
  173. --
  174. return result;
  175. end lowercase;
  176. ------------------------------------------------------------------------------------------
  177. function read_text_box return string is
  178. begin
  179. return to_string (text_box.data);
  180. end read_text_box;
  181. ------------------------------------------------------------------------------------------
  182. procedure write_text_box (text : in string) is
  183. begin
  184. text_box.data := to_unbounded_string (text);
  185. end write_text_box;
  186. ------------------------------------------------------------------------------------------
  187. function window_width return integer is begin return ray.get_screen_width; end window_width;
  188. function window_height return integer is begin return ray.get_screen_height; end window_height;
  189. ------------------------------------------------------------------------------------------
  190. procedure initialize is
  191. begin
  192. echo (comment, "Initializing core components...");
  193. --
  194. engine_active := true;
  195. texture_array := new texture_data_array (0 .. 1600);
  196. sound_array := new sound_data_array (0 .. 4);
  197. font_array := new font_data_array (0 .. 8);
  198. --
  199. echo (comment, "-- Setting trace log level to none (ignoring all default Raylib logs).");
  200. ray.set_trace_log_level (ray.log_none);
  201. --
  202. ray.set_window_flags (ray.flag_window_resizable);
  203. --
  204. echo (comment, "-- Initializing Raylib window data...");
  205. echo (comment, "-- -- Window title : Chads of Might & Magic");
  206. echo (comment, "-- -- Window width : 1800");
  207. echo (comment, "-- -- Window height : 900");
  208. ray.open_window (1800, 900, "Chads of Might & Magic");
  209. --
  210. echo (comment, "-- Initializing Raylib audio device data...");
  211. ray.open_audio_device;
  212. --
  213. ray.randomization (19970725);
  214. ray.set_target_fps (60);
  215. --
  216. echo (success, "Initialized core components.");
  217. end initialize;
  218. ------------------------------------------------------------------------------------------
  219. procedure deinitialize is
  220. begin
  221. echo (comment, "Deinitializing core components...");
  222. --
  223. engine_active := false;
  224. --
  225. echo (comment, "-- -- Unloading Raylib" & texture_count'image & " textures.");
  226. echo (comment, "-- -- Unloading Raylib" & sound_count'image & " sounds.");
  227. echo (comment, "-- -- Unloading Raylib" & font_count'image & " fonts.");
  228. --
  229. for index in 0 .. texture_count - 1 loop ray.unload_texture (texture_array (index)); end loop;
  230. for index in 0 .. sound_count - 1 loop ray.unload_sound (sound_array (index)); end loop;
  231. for index in 0 .. font_count - 1 loop ray.unload_font (font_array (index)); end loop;
  232. --
  233. echo (comment, "-- Deinitializing Raylib audio device data...");
  234. ray.close_audio_device;
  235. --
  236. echo (comment, "-- Deinitializing Raylib window data...");
  237. ray.close_window;
  238. --
  239. echo (success, "Deinitialized core components.");
  240. end deinitialize;
  241. ------------------------------------------------------------------------------------------
  242. procedure synchronize is
  243. signal : integer := signal_code'pos (signal_none);
  244. begin
  245. global_time := global_time + 1;
  246. global_time := global_time mod (gameplay_framerate * animation_framerate);
  247. gameplay_time := global_time mod (gameplay_framerate);
  248. animation_time := global_time / (gameplay_framerate / animation_framerate);
  249. framerate := integer (ray.get_fps);
  250. signal := ray.get_key_pressed;
  251. cursor.x := ray.get_mouse_x;
  252. cursor.y := ray.get_mouse_y;
  253. --
  254. ray.end_drawing;
  255. --
  256. if ray.exit_key_is_pressed then
  257. engine_active := false;
  258. end if;
  259. --
  260. if ray.mouse_button_is_pressed (ray.mouse_button_left) then cursor_mode := 1; end if;
  261. if ray.mouse_button_is_pressed (ray.mouse_button_right) then cursor_mode := 2; end if;
  262. if ray.mouse_button_is_pressed (ray.mouse_button_middle) then cursor_mode := 3; end if;
  263. if ray.mouse_button_is_released (ray.mouse_button_left) then cursor_mode := 0; end if;
  264. if ray.mouse_button_is_released (ray.mouse_button_right) then cursor_mode := 0; end if;
  265. if ray.mouse_button_is_released (ray.mouse_button_middle) then cursor_mode := 0; end if;
  266. --
  267. case signal is
  268. when 48 .. 57 => signal_mode := signal_code'val (signal - 48 + signal_code'pos (signal_0));
  269. when 65 .. 90 => signal_mode := signal_code'val (signal - 65 + signal_code'pos (signal_a));
  270. when 320 .. 329 => signal_mode := signal_code'val (signal - 320 + signal_code'pos (signal_kp_0));
  271. --
  272. when 0 => signal_mode := signal_none;
  273. when 32 => signal_mode := signal_space;
  274. when 96 => signal_mode := signal_grave;
  275. when 340 => signal_mode := signal_left_shift;
  276. when 341 => signal_mode := signal_left_control;
  277. when 333 => signal_mode := signal_kp_subtract;
  278. when 334 => signal_mode := signal_kp_add;
  279. when 256 => signal_mode := signal_escape;
  280. when 257 => signal_mode := signal_enter;
  281. when 258 => signal_mode := signal_tab;
  282. when 259 => signal_mode := signal_backspace;
  283. when 262 => signal_mode := signal_right;
  284. when 263 => signal_mode := signal_left;
  285. when 264 => signal_mode := signal_down;
  286. when 265 => signal_mode := signal_up;
  287. when others => signal_mode := signal_none;
  288. end case;
  289. --
  290. --~for index in reverse 0 .. block_count - 1 loop
  291. --~if core.cursor.x > block_array (index).x and core.cursor.x < block_array (index).width
  292. --~and core.cursor.y > block_array (index).y and core.cursor.y < block_array (index).height
  293. --~and core.cursor_mode = block_array (index).mode then
  294. --~block_array (index).action.all;
  295. --~core.cursor_mode := 0;
  296. --~exit;
  297. --~end if;
  298. --~end loop;
  299. --
  300. block_count := 0;
  301. --
  302. ray.begin_drawing;
  303. --
  304. ray.clear_background ((0, 0, 0, 255));
  305. end synchronize;
  306. ------------------------------------------------------------------------------------------
  307. procedure play (index : in integer) is begin ray.play_sound (sound_array (index)); end play;
  308. procedure stop (index : in integer) is begin ray.stop_sound (sound_array (index)); end stop;
  309. ------------------------------------------------------------------------------------------
  310. procedure overlay is
  311. begin
  312. ray.draw_rectangle (0, 0, window_width, window_height, (0, 0, 0, 127));
  313. end overlay;
  314. ------------------------------------------------------------------------------------------
  315. procedure block_queue (data : in block) is
  316. begin
  317. if block_count = block_limit - 1 then
  318. return;
  319. end if;
  320. --
  321. block_array (block_count) := data;
  322. --
  323. increment (block_count);
  324. end block_queue;
  325. ------------------------------------------------------------------------------------------
  326. procedure increment (value : in out integer) is begin value := value + 1; end increment;
  327. procedure decrement (value : in out integer) is begin value := value - 1; end decrement;
  328. ------------------------------------------------------------------------------------------
  329. procedure idle is begin null; end idle;
  330. procedure move_camera_up is begin core.camera.y := core.camera.y - 1; end move_camera_up;
  331. procedure move_camera_down is begin core.camera.y := core.camera.y + 1; end move_camera_down;
  332. procedure move_camera_left is begin core.camera.x := core.camera.x - 1; end move_camera_left;
  333. procedure move_camera_right is begin core.camera.x := core.camera.x + 1; end move_camera_right;
  334. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  335. end core;