state.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. #include "eruta.h"
  2. #include "mem.h"
  3. #include "state.h"
  4. #include "camera.h"
  5. #include "sound.h"
  6. #include "tilemap.h"
  7. #include "tileio.h"
  8. #include "dynar.h"
  9. #include "draw.h"
  10. #include "mode.h"
  11. #include "fifi.h"
  12. #include "rh.h"
  13. #include "toruby.h"
  14. #include "event.h"
  15. #include "area.h"
  16. #include "thing.h"
  17. #include "sprite.h"
  18. #include "scegra.h"
  19. #include "monolog.h"
  20. #include "callrb.h"
  21. #include "store.h"
  22. #include "zori.h"
  23. /* The data struct contains all global state and other data of the application.
  24. */
  25. struct State_ {
  26. /* State flags. */
  27. BOOL busy;
  28. BOOL fullscreen;
  29. BOOL audio;
  30. /* Graphics mode. XXX: I think???? :P */
  31. int32_t modeno;
  32. /*
  33. There are two fonts for now, ttf and font. Font is a plain font
  34. for emergency use, ttf is the normal font for the console.
  35. */
  36. ALLEGRO_FONT * font;
  37. ALLEGRO_FONT * ttf;
  38. /* Some default colors */
  39. ALLEGRO_COLOR colors[STATE_COLORS];
  40. /* Display */
  41. ALLEGRO_DISPLAY * display;
  42. ALLEGRO_EVENT_QUEUE * queue;
  43. char * errmsg;
  44. /* FPS handling. */
  45. double fpsnow, fpstime, fps;
  46. int frames;
  47. /* Background image that can be set behind the tile map. */
  48. ALLEGRO_BITMAP * background_image;
  49. /* Background color, in case of no tile map */
  50. ALLEGRO_COLOR background_color;
  51. /* Active tile map, linked from and loaded through a Store ID. */
  52. Tilemap * active_map;
  53. int active_map_id;
  54. /* Does the area needs to be displayed or not. */
  55. int show_area;
  56. /* Does the graph needs to be displayed or not */
  57. int show_graph;
  58. /* Does the FPS counter needs to be displayed or not? */
  59. int show_fps;
  60. /* Logical and physical game objects. This one is always active, regardless of the tile map. */
  61. Area * area;
  62. // View camera for the area, tile map and particle engine.
  63. Camera * camera;
  64. /* Mode is removed, this will be handled on the scripting side. */
  65. /* Sprite subsystem */
  66. SpriteList * sprites;
  67. /* Ruby subsystem */
  68. Ruby * ruby;
  69. /*
  70. The ruby and error message GUI console.
  71. Implemented in C so it's usable even if there are script bugs.
  72. */
  73. struct zori_console * console;
  74. /* The current actor, controlled by the player. */
  75. Thing * actor;
  76. };
  77. /** State variable. */
  78. static State * global_state_ = NULL;
  79. /** Various loggers. One for stdout if not on windows,
  80. * one to a file and one to the Console */
  81. int state_console_logf(char * file, int line, char * level,
  82. void * data, char * format, va_list args) {
  83. struct zori_console * console = data;
  84. if (console) {
  85. zori_console_printf(console, "%s %s %d:", level, file, line);
  86. return zori_console_vprintf(console, format, args);
  87. }
  88. return -1;
  89. }
  90. DEFINE_STDERR_LOGGER(state_stderr_logger);
  91. DEFINE_FILE_LOGGER(state_file_logger);
  92. DEFINE_LOGGER(state_console_logger, state_console_logf, NULL);
  93. /** Gets the global state data, or NULL if not set. */
  94. State * state_get() {
  95. return global_state_;
  96. }
  97. /** Sets the given state data as the global state data for this apllication.
  98. * returns the *previous* state data pointer or NULL if it was not set yet.
  99. */
  100. State * state_set(State * state) {
  101. State * oldstate = global_state_;
  102. global_state_ = state;
  103. return oldstate;
  104. }
  105. /** Returns the state's active tile map. */
  106. Tilemap * state_active_map(State * state) {
  107. if(!state) return NULL;
  108. return state->active_map;
  109. }
  110. /** Sets the state's active tile map. Also sets it in the state's area, and
  111. disables all previous camera panners and lockins, and sets up a basic lockin on
  112. map layer 0 if the map is not NULL. */
  113. Tilemap * state_active_map_(State * state, Tilemap * map) {
  114. if(!state) return NULL;
  115. if (state->area) {
  116. area_tilemap_(state->area, map);
  117. }
  118. if (state->camera) {
  119. camera_freepanners(state->camera);
  120. camera_freelockins(state->camera);
  121. }
  122. state->active_map = map;
  123. if(state->active_map) {
  124. tilemap_layer_lockin(state->active_map, 0, state->camera);
  125. }
  126. return state->active_map;
  127. }
  128. /** Gets the store index of the state's active tile map, or -1 if none set. */
  129. int state_active_map_id(State * state) {
  130. if(!state) return -1;
  131. return state->active_map_id;
  132. }
  133. /** Sets the state's active tile from the Store system index.
  134. * Returns negative on failure, or the index set. Disables the active tile map if index is < 0 */
  135. int state_active_map_id_(State * state, int index) {
  136. Tilemap * map;
  137. if (!state) return -1;
  138. if (index < 0) {
  139. state->active_map_id = -1;
  140. state_active_map_(state, NULL);
  141. return -1;
  142. }
  143. map = store_get_other(index, RESOR_TILEMAP);
  144. if (!map) {
  145. // refuse to load nonexisting map
  146. return -2;
  147. }
  148. state_active_map_(state, map);
  149. return -1;
  150. }
  151. /** Returns the state's area. */
  152. Area * state_area(State * state) {
  153. if (!state) return NULL;
  154. return state->area;
  155. }
  156. /** Return's the state's sprite list */
  157. SpriteList * state_sprites(State * state) {
  158. if (!state) return NULL;
  159. return state->sprites;
  160. }
  161. /** Allocates a state struct */
  162. State * state_alloc() {
  163. return STRUCT_ALLOC(State);
  164. }
  165. /** Frees a state struct. */
  166. void state_free(State * self) {
  167. /* Shut down audio */
  168. audio_done();
  169. spritelist_free(self->sprites);
  170. self->sprites = NULL;
  171. area_free(self->area);
  172. self->area = NULL;
  173. /* Disable the active tile map */
  174. state_active_map_id_(self, -1);
  175. /* Disable gui. */
  176. zori_shutdown();
  177. rh_free(self->ruby);
  178. self->console = NULL; /* disable console immediately. */
  179. /* Deallocate stored objects. */
  180. store_done();
  181. // font_free(self->font);
  182. al_destroy_display(self->display);
  183. camera_free(self->camera);
  184. al_uninstall_system();
  185. /* End logging. */
  186. monolog_done();
  187. STRUCT_FREE(self);
  188. }
  189. /** Sets error message for state and returns NULL. */
  190. State * state_errmsg_(State * state, char * mesg) {
  191. state->errmsg = mesg;
  192. return NULL;
  193. }
  194. /** Gets error message for state. */
  195. char * state_errmsg(State * state) {
  196. return state->errmsg;
  197. }
  198. /** Registers an event source for this state */
  199. State * state_eventsource(State * state, ALLEGRO_EVENT_SOURCE * src) {
  200. al_register_event_source(state->queue, src);
  201. return state;
  202. }
  203. /** Gets a color from the state' color list. NOT bound checked! */
  204. ALLEGRO_COLOR state_color(State * state, int color) {
  205. return state->colors[color];
  206. }
  207. /** Sets a color to the state' color list. NOT bound checked! */
  208. ALLEGRO_COLOR state_color_f(State * state, int color,
  209. float r, float g, float b, float a) {
  210. return state->colors[color] = al_map_rgba_f(r, g, b, a);
  211. }
  212. /** Gets Ruby interpreter for state. */
  213. Ruby * state_ruby(State * state) {
  214. return state->ruby;
  215. }
  216. /** Gets console intepreter for state. */
  217. struct zori_console * state_console(State * state) {
  218. return state->console;
  219. }
  220. /* Creates a new sprite in the sprite list. */
  221. Sprite * state_new_sprite(State * state) {
  222. SpriteList * list = state_sprites(state);
  223. return spritelist_new_sprite(list);
  224. }
  225. /* Creates a new sprite in the sprite list and returns it's id. */
  226. int state_new_sprite_id(State * state) {
  227. SpriteList * list = state_sprites(state);
  228. return spritelist_new_sprite_id(list);
  229. }
  230. /* Returns a sprite from the state's sprite list. */
  231. Sprite * state_sprite(State * state, int index) {
  232. SpriteList * list = state_sprites(state);
  233. return spritelist_sprite(list, index);
  234. }
  235. /* Loads a layer of a sprite from a vpath. Sprite layer is in
  236. ulpcss format. */
  237. int state_sprite_load_builtin
  238. (State * state, int sprite_index, int layer_index, char * vpath, int layout) {
  239. return spritelist_load_sprite_layer_with_builtin_layout(
  240. state_sprites(state), sprite_index, layer_index, vpath, layout
  241. );
  242. }
  243. /* Gets a thing from the state's area. */
  244. Thing * state_thing(State * state, int index) {
  245. Area * area = state_area(state);
  246. return area_thing(area, index);
  247. }
  248. /* Makes a new dynamic thing in the state's active area. */
  249. Thing * state_newthing(State * state, int kind,
  250. int x, int y, int z, int w, int h) {
  251. Area * area = state_area(state);
  252. return area_new_thing(area, kind, x, y, z, w, h);
  253. }
  254. /* Makes a new dynamic thing and returns it's index, or
  255. negative if it could not be created. */
  256. int state_newthingindex(State * state, int kind,
  257. int x, int y, int z, int w, int h) {
  258. Area * area = state_area(state);
  259. return area_new_thing_id(area, kind, x, y, z, w, h);
  260. }
  261. /* Looks op both the Thing and the Sprite by index and
  262. * links the Thing to the Sprite. Returns the sprite index set or negative on error.
  263. * Both sprite and thing must already exist for this to work.
  264. */
  265. int state_thing_sprite_(State * state, int thing_index, int sprite_index) {
  266. Thing * thing; Sprite * sprite;
  267. thing = state_thing(state, thing_index);
  268. if (!thing) { return -1; }
  269. sprite = state_sprite(state, sprite_index);
  270. if (!sprite) { return -2; }
  271. thing_sprite_(thing, sprite);
  272. return sprite_index;
  273. }
  274. /* Looks up the thing by index and set it's pose. Returns negative on error,
  275. or if sucessful, the pose set. */
  276. int state_thing_pose_(State * state, int thing_index, int pose) {
  277. Thing * thing;
  278. thing = state_thing(state, thing_index);
  279. if(!thing) return -1;
  280. thing_pose_(thing, pose);
  281. return pose;
  282. }
  283. /* Looks up the thing by index and set it's direction. Returns negative on error,
  284. or if sucessful, the direction set. */
  285. int state_thing_direction_(State * state, int thing_index, int direction) {
  286. Thing * thing;
  287. thing = state_thing(state, thing_index);
  288. if(!thing) return -1;
  289. thing_direction_(thing, direction);
  290. return direction;
  291. }
  292. /* Looks up the thing by index and let the state's camera track it.
  293. * If index is negative, stop tracking in stead.
  294. */
  295. int state_camera_track_(State * state, int thing_index) {
  296. Thing * thing;
  297. if (thing_index < 0) {
  298. camera_track_(state_camera(state), NULL);
  299. return -2;
  300. }
  301. thing = state_thing(state, thing_index);
  302. if(!thing) return -1;
  303. camera_track_(state_camera(state), thing);
  304. thing_direction_(thing, thing_index);
  305. return thing_index;
  306. }
  307. /* Sets up the state's camera to track the numbered thing. */
  308. int state_cameratrackthing(State * state, int thing_index) {
  309. Thing * thing = state_thing(state, thing_index);
  310. if (thing) {
  311. camera_track_(state_camera(state), thing);
  312. return 0;
  313. }
  314. return -1;
  315. }
  316. /* Lock in the state's camera to the current active tile map's given layer.
  317. * Returns negative if no tile map is currently active.
  318. */
  319. int state_lockin_maplayer(State * state, int layer) {
  320. if(!state_active_map(state)) {
  321. return -1;
  322. } else {
  323. tilemap_layer_lockin(state_active_map(state), layer, state_camera(state));
  324. }
  325. return 0;
  326. }
  327. /* Loads a named tile map from the map folder. */
  328. /* This function is obsolete. Load tile maps though script / store now.
  329. int state_loadtilemap_vpath(State * self, char * vpath) {
  330. TilemapLoadExtra extra;
  331. extra.area = self->area;
  332. self->loadingmap = fifi_load_vpath(tilemap_fifi_load, &extra, vpath);
  333. if(!self->loadingmap) return -1;
  334. tilemap_free(self->nowmap);
  335. self->nowmap = self->loadingmap;
  336. return 0;
  337. }
  338. */
  339. /* Sets the state current active actor to the thing with the given index.
  340. * Does not change if no such thing is found;
  341. */
  342. /* Obsolete. The scripts manage the active actor now.
  343. int state_actorindex_(State * self, int thing_index) {
  344. Thing * thing;
  345. thing = state_thing(self, thing_index);
  346. if(!thing) return -1;
  347. self->actor = thing;
  348. return thing_index;
  349. }
  350. */
  351. /* Returns the current active actor of the state. */
  352. /* Obsolete. The scripts manage the active actor now.
  353. Thing * state_actor(State * self) {
  354. if(!self) return NULL;
  355. return self->actor;
  356. }
  357. */
  358. #define STATE_MODES 10
  359. int state_initjoystick(State * self) {
  360. int num, index, snum, sindex, bnum, bindex, anum, aindex;
  361. (void) self;
  362. if(!al_install_joystick()) return FALSE;
  363. num = al_get_num_joysticks();
  364. LOG_NOTE("Found %d joysticks:\n", num);
  365. for(index = 0; index < num; index ++) {
  366. ALLEGRO_JOYSTICK * joy = al_get_joystick(index);
  367. if(!al_get_joystick_active(joy)) continue;
  368. LOG_NOTE("Joystick nr %d, name: %s,", index, al_get_joystick_name(joy));
  369. snum = al_get_joystick_num_sticks(joy);
  370. LOG_NOTE("\n%d sticks: ", snum);
  371. for(sindex = 0; sindex < snum; sindex++) {
  372. LOG_NOTE("%s, ", al_get_joystick_stick_name(joy, sindex));
  373. anum = al_get_joystick_num_axes(joy, sindex);
  374. LOG_NOTE("%d axes: ", anum);
  375. for (aindex = 0; aindex < anum; aindex++) {
  376. LOG_NOTE("%s, ",
  377. al_get_joystick_axis_name(joy, sindex, aindex));
  378. }
  379. }
  380. bnum = al_get_joystick_num_buttons(joy);
  381. LOG_NOTE("\n%d buttons: ", bnum);
  382. for(bindex = 0; bindex < bnum; bindex++) {
  383. LOG_NOTE("%s, ", al_get_joystick_button_name(joy, bindex));
  384. }
  385. LOG_NOTE(".\n");
  386. }
  387. LOG_NOTE("\n");
  388. return num;
  389. }
  390. /** Initializes the state. It opens the screen, keyboards,
  391. interpreter, etc. Get any error with state_errmsg if
  392. this returns NULL. */
  393. State * state_init(State * self, BOOL fullscreen) {
  394. if(!self) return NULL;
  395. int flags = 0;
  396. // initialize logging first
  397. if (!monolog_init()) {
  398. return state_errmsg_(self, "Could not init logging.");
  399. }
  400. // Initialize loggers
  401. monolog_add_logger(NULL, &state_stderr_logger);
  402. monolog_add_logger(fopen("eruta.log", "a"), &state_file_logger);
  403. // initialize log levels
  404. LOG_ENABLE_ERROR();
  405. LOG_ENABLE_WARNING();
  406. LOG_ENABLE_NOTE();
  407. LOG_NOTE("Starting logging", "");
  408. self->busy = TRUE;
  409. self->fullscreen = fullscreen;
  410. self->audio = FALSE;
  411. state_errmsg_(self, "OK!");
  412. // Initialize Ruby scripting
  413. self->ruby = rh_new();
  414. if(!self->ruby) {
  415. return state_errmsg_(self, "Could not init Ruby.\n");
  416. }
  417. tr_init(self->ruby);
  418. // Initialize Allegro 5 and addons
  419. if (!al_init()) {
  420. return state_errmsg_(self, "Could not init Allegro.\n");
  421. }
  422. al_init_image_addon();
  423. al_init_font_addon();
  424. al_init_primitives_addon();
  425. if(!al_init_ttf_addon()) {
  426. return state_errmsg_(self, "Could not init TTF extension.\n");
  427. }
  428. // Install the keyboard handler
  429. if (!al_install_keyboard()) {
  430. return state_errmsg_(self, "Error installing keyboard.\n");
  431. }
  432. // install mouse handler
  433. if (!al_install_mouse()) {
  434. return state_errmsg_(self, "Error installing mouse.\n");
  435. }
  436. // install joystick
  437. if(!state_initjoystick(self)) {
  438. perror("Joysticks not started.");
  439. }
  440. /* Set up the audio system */
  441. self->audio = audio_init();
  442. if(!self->audio) {
  443. perror("Sound not started.");
  444. }
  445. // Use full screen mode if needed.
  446. if(self->fullscreen) {
  447. flags = ALLEGRO_FULLSCREEN | ALLEGRO_GENERATE_EXPOSE_EVENTS;
  448. } else {
  449. /* flags = ALLEGRO_FULLSCREEN_WINDOW | ALLEGRO_GENERATE_EXPOSE_EVENTS; */
  450. }
  451. // flags |= ALLEGRO_OPENGL;
  452. al_set_new_display_flags(flags);
  453. /* al_set_new_display_option(ALLEGRO_VSYNC, 2, ALLEGRO_SUGGEST); */
  454. // Create a window to display things on: 640x480 pixels.
  455. // self->display = al_create_display(1280, 960);
  456. self->display = al_create_display(SCREEN_W, SCREEN_H);
  457. if (!self->display) {
  458. return state_errmsg_(self, "Error creating display.\n");
  459. }
  460. // al_resize_display(self->display, SCREEN_W, SCREEN_H);
  461. // initialize the file finder, so we can start to load the data files
  462. if(!fifi_init()) {
  463. return state_errmsg_(self, "Could not find data folder!\n");
  464. }
  465. // initialize the resource storage so we can store the data files
  466. if(!store_init()) {
  467. return state_errmsg_(self, "Could not initialize data store.\n");
  468. }
  469. // Tuffy.ttf
  470. // "OpenBaskerville-0.0.53.otf"
  471. #define STATE_FONTNAME "GranaPadano.ttf"
  472. #define STATE_FONT_INDEX 20000
  473. if(!store_load_ttf_font(STATE_FONT_INDEX, "font/" STATE_FONTNAME, -16, 0)) {
  474. return state_errmsg_(self, "Error loading " STATE_FONTNAME);
  475. }
  476. self->font = store_get_font(STATE_FONT_INDEX);
  477. // fifi_loadfont(STATE_FONTNAME, 16, 0);
  478. if (!self->font) {
  479. return state_errmsg_(self, "Error loading " STATE_FONTNAME);
  480. }
  481. state_color_f(self, STATE_WHITE, 1, 1, 1, 1);
  482. state_color_f(self, STATE_BLACK, 0, 0, 0, 1);
  483. // Start the event queue to handle keyboard input and our timer
  484. self->queue = al_create_event_queue();
  485. state_eventsource(self, al_get_keyboard_event_source());
  486. state_eventsource(self, al_get_display_event_source(self->display));
  487. state_eventsource(self, al_get_mouse_event_source());
  488. state_eventsource(self, al_get_joystick_event_source());
  489. al_set_window_title(self->display, "Eruta!");
  490. // set up fps counter. Start with assuming we have 60 fps.
  491. self->fps = 60.0;
  492. self->fpstime = al_get_time();
  493. self->frames = 60;
  494. /* No active map yet. */
  495. state_active_map_id_(self, -1);
  496. /* Background color. */
  497. self->background_color = al_map_rgb(64,128,64);
  498. // set up camera
  499. self->camera = camera_new(-100, -100, SCREEN_W, SCREEN_H);
  500. if(!self->camera) {
  501. return state_errmsg_(self, "Out of memory when allocating camera.");
  502. }
  503. /* Set up Zori GUI. */
  504. {
  505. struct zori_style style;
  506. memset(&style, 0, sizeof(style));
  507. style.text.font = self->font;
  508. style.text.color = color_rgb(255,255,255);
  509. style.back.color = color_rgba(64,0,0, 191);
  510. if ( !ZORI_ID_OK_P(zori_start(&style)) ) {
  511. return state_errmsg_(self, "Out of memory when allocating GUI.");
  512. }
  513. }
  514. /* Set up console. */
  515. {
  516. struct zori_style style;
  517. memset(&style, 0, sizeof(style));
  518. style.text.font = self->font;
  519. style.text.color = color_rgb(255,255,255);
  520. style.back.color = color_rgba(64,0,0, 191);
  521. Rebox bounds = { {20, 20} , {600, 400} };
  522. self->console = zori_console_new(1, &bounds, &style);
  523. if(!self->console) {
  524. return state_errmsg_(self, "Out of memory when allocating console.");
  525. }
  526. }
  527. zori_console_puts(self->console, "Zori Console started ok!");
  528. // set up ruby callback for console commands
  529. zori_console_command_(self->console, rh_run_console_command, self->ruby);
  530. // set up logging to console
  531. monolog_add_logger(self->console, &state_console_logger);
  532. /* Initialize Area. */
  533. self->area = area_new();
  534. /* Initialize sprite list. */
  535. self->sprites = spritelist_new();
  536. /* Show all by default. */
  537. self->show_area = TRUE;
  538. self->show_fps = TRUE;
  539. self->show_graph= TRUE;
  540. return self;
  541. }
  542. /** Sets the state's busy status to false */
  543. BOOL state_done(State * state) {
  544. state->busy = FALSE;
  545. return state->busy;
  546. }
  547. /** Returns true if the state is busy false if not. */
  548. BOOL state_busy(State * self) {
  549. return self->busy;
  550. }
  551. /* Scales and moves the display to achieve resolution independence. */
  552. void state_scale_display(State * self) {
  553. int real_w = al_get_display_width(self->display);
  554. int real_h = al_get_display_height(self->display);
  555. int scale_x = real_w / SCREEN_W;
  556. int scale_y = real_h / SCREEN_H;
  557. int scale = (scale_x < scale_y) ? scale_x : scale_y;
  558. int offset_x= (real_w - (SCREEN_W * scale)) / 2;
  559. int offset_y= (real_h - (SCREEN_H * scale)) / 2;
  560. /*
  561. al_draw_textf(state_font(self), COLOR_WHITE,
  562. 100, 100, 0, "SCALE: w: %d, h: %d, sx: %d, sy: %d, s: %d, ox:%d, oy:%d",
  563. real_w, real_h, scale_x, scale_y, scale, offset_x, offset_y);
  564. */
  565. ALLEGRO_TRANSFORM transform;
  566. al_identity_transform(&transform);
  567. /* Now draw black bars to cover the usused areas. */
  568. if (offset_y > 0) {
  569. al_draw_filled_rectangle(-offset_x , -offset_y, real_w, 0, al_map_rgb(0,0,0));
  570. al_draw_filled_rectangle(-offset_x , SCREEN_H, real_w, SCREEN_H+offset_y, al_map_rgb(0,0,0));
  571. }
  572. if (offset_x > 0) {
  573. al_draw_filled_rectangle(-offset_x , -offset_y, 0, real_h, al_map_rgb(0,0,0));
  574. al_draw_filled_rectangle(SCREEN_W , -offset_y, SCREEN_W + offset_x, real_h, al_map_rgb(0,0,0));
  575. }
  576. al_scale_transform(&transform, scale, scale);
  577. al_translate_transform(&transform, offset_x, offset_y);
  578. al_use_transform(&transform);
  579. /* al_set_clipping_rectangle(offset_x, offset_y, SCREEN_W, SCREEN_H); */
  580. }
  581. /* Draws all inside the state that needs to be drawn. */
  582. void state_draw(State * self) {
  583. int layer;
  584. /* Draw background color if no map active. */
  585. if (!self->active_map) {
  586. al_clear_to_color(self->background_color);
  587. }
  588. /* Draw the layers of the map and area interleaved. */
  589. for (layer = 0; layer < TILEMAP_PANES; layer++) {
  590. if (self->active_map) {
  591. /* Shadows should be drawn *before* the blends, otherwise both won't
  592. * look good when combined with each other. The problem with that is,
  593. * though that shadows are then not cast on the sprites.
  594. * Perhaps sprites will need separate shadows???
  595. */
  596. tilemap_draw_layer_tiles(self->active_map, self->camera, layer);
  597. tilemap_draw_layer_shadows(self->active_map, self->camera, layer);
  598. tilemap_draw_layer_blends(self->active_map, self->camera, layer);
  599. }
  600. if (self->area && self->show_area) {
  601. area_draw_layer(self->area, self->camera, layer);
  602. }
  603. }
  604. /* Draw UI scene graph */
  605. if (self->show_graph) {
  606. zori_draw_all();
  607. }
  608. /* Draw the particles from the particle engine. */
  609. // alpsshower_draw(&shower, state_camera(state));
  610. /* Draw fps if needed. */
  611. if (self->show_fps) {
  612. al_draw_textf(state_font(self), COLOR_WHITE,
  613. 10, 10, 0, "FPS: %.0f", state_fps(self));
  614. }
  615. /* Draw the ui and the console (will autohide if not active). */
  616. zori_draw_all();
  617. state_scale_display(self);
  618. }
  619. /* Updates the state's display. */
  620. void state_flip_display(State * self) {
  621. al_flip_display();
  622. state_frames_update(self);
  623. }
  624. /* Updates the state's elements. */
  625. void state_update(State * self) {
  626. mrb_value mval;
  627. // alpsshower_update(&shower, state_frametime(state));
  628. if (self->active_map) {
  629. tilemap_update(self->active_map, state_frametime(self));
  630. }
  631. if (self->area) {
  632. area_update(self->area, state_frametime(self));
  633. }
  634. camera_update(self->camera);
  635. // call ruby update callback
  636. callrb_on_update(self);
  637. // Update the scene graph (after the Ruby upate so anty ruby side-changes take
  638. // effect immediately.
  639. scegra_update(state_frametime(self));
  640. zori_update(state_frametime(self));
  641. }
  642. /** Polls the state's event queue, and gets the next event and stores it in
  643. * event. if it is available. Returns true if there is an event of false if
  644. * not.
  645. */
  646. int state_poll(State * state, ALLEGRO_EVENT * event) {
  647. return al_get_next_event(state->queue, event);
  648. }
  649. /** Polls the state's event queue, and gets the next event and returns it.
  650. * returns nul if out of memory or no event was available.
  651. * You must free the result of this function with event_free
  652. */
  653. ALLEGRO_EVENT * state_pollnew(State * state) {
  654. ALLEGRO_EVENT event, * result;
  655. if(state_poll(state, &event)) {
  656. result = event_alloc();
  657. if(!result) return NULL;
  658. (*result) = event; // copy data
  659. return result; // return pointer
  660. }
  661. return NULL;
  662. }
  663. /** Return the state's default font. */
  664. ALLEGRO_FONT * state_font(State * state) {
  665. if(!state) return NULL;
  666. return state->font;
  667. }
  668. /** Call this every frame to update the FPS and frames value */
  669. void state_frames_update(State * state) {
  670. double now = al_get_time();
  671. state->frames++;
  672. if((now - state->fpstime) > 1.0) {
  673. double realfps;
  674. /* Measure only last second of frames, which means FPS gets updated every second or so. */
  675. realfps = ((double)state->frames) / (now - state->fpstime);
  676. /* Display and use a rounded value for FPS, the number after the comma is normally due to jitter anyway. */
  677. state->fps = floor(realfps + 0.5);
  678. /* A little trick, to prefent jerkyness,
  679. * keep half the frames; and half the time */
  680. state->frames = state->frames / 2;
  681. state->fpstime = now - 0.5;
  682. }
  683. }
  684. /** Returns the amount of frames rendered during this second. */
  685. int state_frames(State * state) {
  686. return state->frames;
  687. }
  688. /** Returns the FPS value. */
  689. double state_fps(State * state) {
  690. return state->fps;
  691. }
  692. /** Returns the Frame time value. */
  693. double state_frametime(State * state) {
  694. if( state->fps < 20.0) return 1.0 / 20.0;
  695. return 1.0 / state->fps;
  696. }
  697. /** Returns the camera of the state. */
  698. Camera * state_camera(State * state) {
  699. if(!state) return NULL;
  700. return state->camera;
  701. }
  702. /* Get display state */
  703. int global_state_show_fps() {
  704. State * state = state_get();
  705. if (!state) return FALSE;
  706. return state->show_fps;
  707. }
  708. /* Set display state */
  709. int global_state_show_fps_(int show) {
  710. State * state = state_get();
  711. if (!state) return FALSE;
  712. return state->show_fps = show;
  713. }
  714. /* Get display state */
  715. int global_state_show_graph() {
  716. State * state = state_get();
  717. if (!state) return FALSE;
  718. return state->show_graph;
  719. }
  720. /* Set display state */
  721. int global_state_show_graph_(int show) {
  722. State * state = state_get();
  723. if (!state) return FALSE;
  724. return state->show_graph = show;
  725. }
  726. /* Get display state */
  727. int global_state_show_area() {
  728. State * state = state_get();
  729. if (!state) return FALSE;
  730. return state->show_area;
  731. }
  732. /* Set display state */
  733. int global_state_show_area_(int show) {
  734. State * state = state_get();
  735. if (!state) return FALSE;
  736. return state->show_area = show;
  737. }
  738. /* Get display state of physics */
  739. int global_state_show_physics() {
  740. State * state = state_get();
  741. if (!state) return FALSE;
  742. return area_draw_physics(state->area);
  743. }
  744. /* Set display state of physics */
  745. int global_state_show_physics_(int show) {
  746. State * state = state_get();
  747. if (!state) return FALSE;
  748. area_draw_physics_(state->area, show);
  749. return show;
  750. }
  751. /* Core functionality of Eruta, implemented on the state. */
  752. /* Ideas about starting the game and progressing
  753. * Normally, the game will have different modes. The game will start in
  754. * intro mode, which automatically changes into main menu mode.
  755. * From main menu mode a game may be loaded or a new game may be started.
  756. *
  757. * When the game starts, the generic startup and settings scripts must be loaded.
  758. * They influence the design of the main menu.
  759. *
  760. * To begin, we must implement the new game start. When a new game is started,
  761. * the game start script is loaded. Then, unless instructed differently,
  762. * map number 0001 is loaded. As always, when a map is loaded,
  763. * the map's corresponding script is loaded. The game has an area of "savable"
  764. * data which is initialized either by loading the game or by the new game script.
  765. *
  766. * Before the game is saved, the save game script is loaded. Likewise before
  767. * the game is loaded the load game script is loaded.
  768. *
  769. * Once the game is running, the main game script is loaded and call-backs
  770. * are used to communicate with it. This is the mechanism that allows part of the game
  771. * to be implemented in script.
  772. *
  773. * Needed scripts so far: start.mrb, newgame.mrb, loadgame.mrb, savegame.mrb,
  774. * main.mrb, and one map_0001.mrb, etc for every map. Other scripts can be loaded by
  775. * these scripts for modulization, but only from the script directory.
  776. *
  777. */
  778. /* Preloads a tile map from the given vpath. Returns the loaded map, or
  779. NULL if not loaded.
  780. Tilemap * state_preloadmap_vpath(State * state, const char * vpath) {
  781. return NULL;
  782. }
  783. */
  784. /* Preloads a tile map with the given map number. Returns the loaded map, or
  785. NULL if not loaded.
  786. Tilemap * state_preloadmap_index(State * state, int index) {
  787. return NULL;
  788. }
  789. */
  790. /* Tints a layer of the sprite that belongs to a thing.*/
  791. int state_thing_tint_layer
  792. (State * state, int thing_index, int layer_index, int r, int g, int b, int a) {
  793. Thing * thing = state_thing(state, thing_index);
  794. Color color = al_map_rgba(r, g, b, a);
  795. if (!thing) { return -1; }
  796. thing_tint_layer(thing, layer_index, color);
  797. return 0;
  798. }
  799. /* Transforms a mask color of an image in storage into an alpha. */
  800. int state_image_mask_to_alpha(State * state, int store_index, int r, int g, int b) {
  801. Image * image = store_get_bitmap(store_index);
  802. Color color = al_map_rgb(r, g, b);
  803. (void) state;
  804. if (!image) return -1;
  805. al_convert_mask_to_alpha(image, color);
  806. return store_index;
  807. }
  808. /* Transforms an image in storage where the average is assigned to the alpha value. */
  809. int state_image_average_to_alpha(State * state, int store_index, int r, int g, int b) {
  810. Image * image = store_get_bitmap(store_index);
  811. Color color = al_map_rgb(r, g, b);
  812. (void) state;
  813. if (!image) return -1;
  814. draw_convert_average_to_alpha(image, color);
  815. return store_index;
  816. }
  817. /* Returns the first unused thing ID that is greater than minimum. */
  818. int state_get_unused_thing_id() {
  819. return area_get_unused_thing_id(state_area(state_get()));
  820. }
  821. /* Returns the first unused sprite ID that is greater than minimum. */
  822. int state_get_unused_sprite_id() {
  823. return spritelist_get_unused_sprite_id(state_sprites(state_get()));
  824. }
  825. /** Deletes a sprite from the sprite list of the state. */
  826. int state_delete_sprite(int index) {
  827. return spritelist_delete_sprite(state_sprites(state_get()), index);
  828. }
  829. /** Deletes a thing from the things of the state's area. */
  830. int state_delete_thing(int index) {
  831. return area_delete_thing(state_area(state_get()), index);
  832. }