12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040 |
- #include "eruta.h"
- #include "mem.h"
- #include "state.h"
- #include "camera.h"
- #include "sound.h"
- #include "tilemap.h"
- #include "tileio.h"
- #include "dynar.h"
- #include "draw.h"
- #include "mode.h"
- #include "fifi.h"
- #include "rh.h"
- #include "toruby.h"
- #include "event.h"
- #include "area.h"
- #include "thing.h"
- #include "sprite.h"
- #include "scegra.h"
- #include "monolog.h"
- #include "callrb.h"
- #include "store.h"
- #include "zori.h"
- #include "zori_screen.h"
- #include "zori_console.h"
- #include "zori_button.h"
- #include "zori_page.h"
- #include "zori_menu.h"
- #include "ui.h"
- /* The data struct contains all global state and other data of the application.
- */
- struct State_ {
- /* State flags. */
- BOOL busy;
- BOOL fullscreen;
- BOOL audio;
-
- /* Graphics mode. XXX: I think???? :P */
- int32_t modeno;
-
- /*
- There are two fonts for now, ttf and font. Font is a plain font
- for emergency use, ttf is the normal font for the console.
- */
- ALLEGRO_FONT * font;
- ALLEGRO_FONT * ttf;
- /* Some default colors */
- ALLEGRO_COLOR colors[STATE_COLORS];
-
-
-
- /* Display */
- ALLEGRO_DISPLAY * display;
-
- ALLEGRO_EVENT_QUEUE * queue;
- char * errmsg;
-
-
- /* FPS handling. */
- double fpsnow, fpstime, fps;
- int frames;
-
- /* Background image that can be set behind the tile map. */
- ALLEGRO_BITMAP * background_image;
-
- /* Background color, in case of no tile map */
- ALLEGRO_COLOR background_color;
-
-
- /* Active tile map, linked from and loaded through a Store ID. */
- Tilemap * active_map;
- int active_map_id;
-
- /* Does the area needs to be displayed or not. */
- int show_area;
-
- /* Does the graph needs to be displayed or not */
- int show_graph;
-
- /* Does the FPS counter needs to be displayed or not? */
- int show_fps;
-
- /* Logical and physical game objects. This one is always active, regardless of the tile map. */
- Area * area;
- /* View camera for the area, tile map and particle engine. */
- Camera * camera;
-
- /* Mode is removed, this will be handled on the scripting side. */
-
- /* Sprite subsystem */
- SpriteList * sprites;
- /* Ruby subsystem */
- Ruby * ruby;
- /*
- The ruby and error message GUI console.
- Implemented in C so it's usable even if there are script bugs.
- */
- struct zori_console * console;
-
- /* GUI data. */
- struct ui_state ui;
-
-
- /* The current actor, controlled by the player. */
- Thing * actor;
-
- };
- /** State variable. */
- static State * global_state_ = NULL;
- /** Various loggers. One for stdout if not on windows,
- * one to a file and one to the Console */
- int state_console_logf(char * file, int line, char * level,
- void * data, char * format, va_list args) {
- struct zori_console * console = data;
- if (console) {
- zori_console_printf(console, "%s %s %d:", level, file, line);
- return zori_console_vprintf(console, format, args);
- }
- return -1;
- }
- DEFINE_STDERR_LOGGER(state_stderr_logger);
- DEFINE_FILE_LOGGER(state_file_logger);
- DEFINE_LOGGER(state_console_logger, state_console_logf, NULL);
-
- /** Gets the global state data, or NULL if not set. */
- State * state_get() {
- return global_state_;
- }
- /** Sets the given state data as the global state data for this apllication.
- * returns the *previous* state data pointer or NULL if it was not set yet.
- */
- State * state_set(State * state) {
- State * oldstate = global_state_;
- global_state_ = state;
- return oldstate;
- }
- /** Returns the state's active tile map. */
- Tilemap * state_active_map(State * state) {
- if(!state) return NULL;
- return state->active_map;
- }
- /** Sets the state's active tile map. Also sets it in the state's area, and
- disables all previous camera panners and lockins, and sets up a basic lockin on
- map layer 0 if the map is not NULL. */
- Tilemap * state_active_map_(State * state, Tilemap * map) {
- if(!state) return NULL;
-
- if (state->area) {
- area_tilemap_(state->area, map);
- }
-
- if (state->camera) {
- camera_freepanners(state->camera);
- camera_freelockins(state->camera);
- }
-
- state->active_map = map;
-
- if(state->active_map) {
- tilemap_layer_lockin(state->active_map, 0, state->camera);
- }
-
- return state->active_map;
- }
- /** Gets the store index of the state's active tile map, or -1 if none set. */
- int state_active_map_id(State * state) {
- if(!state) return -1;
- return state->active_map_id;
- }
- /** Sets the state's active tile from the Store system index.
- * Returns negative on failure, or the index set. Disables the active tile map if index is < 0 */
- int state_active_map_id_(State * state, int index) {
- Tilemap * map;
- if (!state) return -1;
- if (index < 0) {
- state->active_map_id = -1;
- state_active_map_(state, NULL);
- return -1;
- }
- map = store_get_other(index, RESOR_TILEMAP);
- if (!map) {
- // refuse to load nonexisting map
- return -2;
- }
- state_active_map_(state, map);
- return -1;
- }
- /** Returns the state's area. */
- Area * state_area(State * state) {
- if (!state) return NULL;
- return state->area;
- }
- /** Return's the state's sprite list */
- SpriteList * state_sprites(State * state) {
- if (!state) return NULL;
- return state->sprites;
- }
- /** Allocates a state struct */
- State * state_alloc() {
- return STRUCT_ALLOC(State);
- }
- /** Frees a state struct. */
- void state_free(State * self) {
-
- /* Shut down audio */
- audio_done();
-
- spritelist_free(self->sprites);
- self->sprites = NULL;
- area_free(self->area);
- self->area = NULL;
- /* Disable the active tile map */
- state_active_map_id_(self, -1);
- /* Disable gui. */
- zori_shutdown();
-
- rh_free(self->ruby);
- self->console = NULL; /* disable console immediately. */
- /* Deallocate stored objects. */
- store_done();
-
- // font_free(self->font);
- al_destroy_display(self->display);
- camera_free(self->camera);
- al_uninstall_system();
-
- /* End logging. */
- monolog_done();
- STRUCT_FREE(self);
- }
- /** Sets error message for state and returns NULL. */
- State * state_errmsg_(State * state, char * mesg) {
- state->errmsg = mesg;
- return NULL;
- }
- /** Gets error message for state. */
- char * state_errmsg(State * state) {
- return state->errmsg;
- }
- /** Registers an event source for this state */
- State * state_eventsource(State * state, ALLEGRO_EVENT_SOURCE * src) {
- al_register_event_source(state->queue, src);
- return state;
- }
- /** Gets a color from the state' color list. NOT bound checked! */
- ALLEGRO_COLOR state_color(State * state, int color) {
- return state->colors[color];
- }
- /** Sets a color to the state' color list. NOT bound checked! */
- ALLEGRO_COLOR state_color_f(State * state, int color,
- float r, float g, float b, float a) {
- return state->colors[color] = al_map_rgba_f(r, g, b, a);
- }
- /** Gets Ruby interpreter for state. */
- Ruby * state_ruby(State * state) {
- return state->ruby;
- }
- /** Gets console intepreter for state. */
- struct zori_console * state_console(State * state) {
- return state->console;
- }
- /* Creates a new sprite in the sprite list. */
- Sprite * state_new_sprite(State * state) {
- SpriteList * list = state_sprites(state);
- return spritelist_new_sprite(list);
- }
- /* Creates a new sprite in the sprite list and returns it's id. */
- int state_new_sprite_id(State * state) {
- SpriteList * list = state_sprites(state);
- return spritelist_new_sprite_id(list);
- }
- /* Returns a sprite from the state's sprite list. */
- Sprite * state_sprite(State * state, int index) {
- SpriteList * list = state_sprites(state);
- return spritelist_sprite(list, index);
- }
- /* Loads a layer of a sprite from a vpath. Sprite layer is in
- ulpcss format. */
- int state_sprite_load_builtin
- (State * state, int sprite_index, int layer_index, char * vpath, int layout) {
- return spritelist_load_sprite_layer_with_builtin_layout(
- state_sprites(state), sprite_index, layer_index, vpath, layout
- );
- }
- /* Gets a thing from the state's area. */
- Thing * state_thing(State * state, int index) {
- Area * area = state_area(state);
- return area_thing(area, index);
- }
- /* Makes a new dynamic thing in the state's active area. */
- Thing * state_newthing(State * state, int kind,
- int x, int y, int z, int w, int h) {
- Area * area = state_area(state);
- return area_new_thing(area, kind, x, y, z, w, h);
- }
- /* Makes a new dynamic thing and returns it's index, or
- negative if it could not be created. */
- int state_newthingindex(State * state, int kind,
- int x, int y, int z, int w, int h) {
-
- Area * area = state_area(state);
- return area_new_thing_id(area, kind, x, y, z, w, h);
- }
- /* Looks op both the Thing and the Sprite by index and
- * links the Thing to the Sprite. Returns the sprite index set or negative on error.
- * Both sprite and thing must already exist for this to work.
- */
- int state_thing_sprite_(State * state, int thing_index, int sprite_index) {
- Thing * thing; Sprite * sprite;
- thing = state_thing(state, thing_index);
- if (!thing) { return -1; }
- sprite = state_sprite(state, sprite_index);
- if (!sprite) { return -2; }
- thing_sprite_(thing, sprite);
- return sprite_index;
- }
- /* Looks up the thing by index and set it's pose. Returns negative on error,
- or if sucessful, the pose set. */
- int state_thing_pose_(State * state, int thing_index, int pose) {
- Thing * thing;
- thing = state_thing(state, thing_index);
- if(!thing) return -1;
- thing_pose_(thing, pose);
- return pose;
- }
-
- /* Looks up the thing by index and set it's direction. Returns negative on error,
- or if sucessful, the direction set. */
- int state_thing_direction_(State * state, int thing_index, int direction) {
- Thing * thing;
- thing = state_thing(state, thing_index);
- if(!thing) return -1;
- thing_direction_(thing, direction);
- return direction;
- }
-
- /* Looks up the thing by index and let the state's camera track it.
- * If index is negative, stop tracking in stead.
- */
- int state_camera_track_(State * state, int thing_index) {
- Thing * thing;
- if (thing_index < 0) {
- camera_track_(state_camera(state), NULL);
- return -2;
- }
- thing = state_thing(state, thing_index);
- if(!thing) return -1;
- camera_track_(state_camera(state), thing);
- thing_direction_(thing, thing_index);
- return thing_index;
- }
- /* Sets up the state's camera to track the numbered thing. */
- int state_cameratrackthing(State * state, int thing_index) {
- Thing * thing = state_thing(state, thing_index);
- if (thing) {
- camera_track_(state_camera(state), thing);
- return 0;
- }
- return -1;
- }
- /* Lock in the state's camera to the current active tile map's given layer.
- * Returns negative if no tile map is currently active.
- */
- int state_lockin_maplayer(State * state, int layer) {
- if(!state_active_map(state)) {
- return -1;
- } else {
- tilemap_layer_lockin(state_active_map(state), layer, state_camera(state));
- }
- return 0;
- }
- /* Loads a named tile map from the map folder. */
- /* This function is obsolete. Load tile maps though script / store now.
- int state_loadtilemap_vpath(State * self, char * vpath) {
- TilemapLoadExtra extra;
- extra.area = self->area;
- self->loadingmap = fifi_load_vpath(tilemap_fifi_load, &extra, vpath);
- if(!self->loadingmap) return -1;
- tilemap_free(self->nowmap);
- self->nowmap = self->loadingmap;
- return 0;
- }
- */
- /* Sets the state current active actor to the thing with the given index.
- * Does not change if no such thing is found;
- */
- /* Obsolete. The scripts manage the active actor now.
- int state_actorindex_(State * self, int thing_index) {
- Thing * thing;
- thing = state_thing(self, thing_index);
- if(!thing) return -1;
- self->actor = thing;
- return thing_index;
- }
- */
- /* Returns the current active actor of the state. */
- /* Obsolete. The scripts manage the active actor now.
- Thing * state_actor(State * self) {
- if(!self) return NULL;
- return self->actor;
- }
- */
- #define STATE_MODES 10
- int state_initjoystick(State * self) {
- int num, index, snum, sindex, bnum, bindex, anum, aindex;
- (void) self;
- if(!al_install_joystick()) return FALSE;
- num = al_get_num_joysticks();
- LOG_NOTE("Found %d joysticks:\n", num);
- for(index = 0; index < num; index ++) {
- ALLEGRO_JOYSTICK * joy = al_get_joystick(index);
- if(!al_get_joystick_active(joy)) continue;
- LOG_NOTE("Joystick nr %d, name: %s,", index, al_get_joystick_name(joy));
- snum = al_get_joystick_num_sticks(joy);
- LOG_NOTE("\n%d sticks: ", snum);
- for(sindex = 0; sindex < snum; sindex++) {
- LOG_NOTE("%s, ", al_get_joystick_stick_name(joy, sindex));
- anum = al_get_joystick_num_axes(joy, sindex);
- LOG_NOTE("%d axes: ", anum);
- for (aindex = 0; aindex < anum; aindex++) {
- LOG_NOTE("%s, ",
- al_get_joystick_axis_name(joy, sindex, aindex));
- }
- }
-
- bnum = al_get_joystick_num_buttons(joy);
- LOG_NOTE("\n%d buttons: ", bnum);
- for(bindex = 0; bindex < bnum; bindex++) {
- LOG_NOTE("%s, ", al_get_joystick_button_name(joy, bindex));
- }
- LOG_NOTE(".\n");
- }
- LOG_NOTE("\n");
- return num;
- }
- /* Initialize the GUI for the Eruta engine. */
- State * state_init_gui(State * self, BOOL fullscreen) {
- ui_state_init(&self->ui);
- }
- /** Initializes the state. It opens the screen, keyboards,
- interpreter, etc. Get any error with state_errmsg if
- this returns NULL. */
- State * state_init(State * self, BOOL fullscreen) {
- if(!self) return NULL;
- int flags = 0;
- // initialize logging first
- if (!monolog_init()) {
- return state_errmsg_(self, "Could not init logging.");
- }
- // Initialize loggers
- monolog_add_logger(NULL, &state_stderr_logger);
- monolog_add_logger(fopen("eruta.log", "a"), &state_file_logger);
- // initialize log levels
- LOG_ENABLE_ERROR();
- LOG_ENABLE_WARNING();
- LOG_ENABLE_NOTE();
- LOG_NOTE("Starting logging", "");
-
-
- self->busy = TRUE;
- self->fullscreen = fullscreen;
- self->audio = FALSE;
- state_errmsg_(self, "OK!");
- // Initialize Ruby scripting
- self->ruby = rh_new();
- if(!self->ruby) {
- return state_errmsg_(self, "Could not init Ruby.\n");
- }
- tr_init(self->ruby);
-
- // Initialize Allegro 5 and addons
- if (!al_init()) {
- return state_errmsg_(self, "Could not init Allegro.\n");
- }
- al_init_image_addon();
- al_init_font_addon();
- al_init_primitives_addon();
- if(!al_init_ttf_addon()) {
- return state_errmsg_(self, "Could not init TTF extension.\n");
- }
- // Install the keyboard handler
- if (!al_install_keyboard()) {
- return state_errmsg_(self, "Error installing keyboard.\n");
- }
-
- // install mouse handler
- if (!al_install_mouse()) {
- return state_errmsg_(self, "Error installing mouse.\n");
- }
-
- // install joystick
- if(!state_initjoystick(self)) {
- perror("Joysticks not started.");
- }
- /* Set up the audio system */
- self->audio = audio_init();
- if(!self->audio) {
- perror("Sound not started.");
- }
- // Use full screen mode if needed.
- if(self->fullscreen) {
- flags = ALLEGRO_FULLSCREEN | ALLEGRO_GENERATE_EXPOSE_EVENTS;
- } else {
- /* flags = ALLEGRO_FULLSCREEN_WINDOW | ALLEGRO_GENERATE_EXPOSE_EVENTS; */
- }
- // flags |= ALLEGRO_OPENGL;
-
- al_set_new_display_flags(flags);
- /* al_set_new_display_option(ALLEGRO_VSYNC, 2, ALLEGRO_SUGGEST); */
- // Create a window to display things on: 640x480 pixels.
- // self->display = al_create_display(1280, 960);
- self->display = al_create_display(SCREEN_W, SCREEN_H);
- if (!self->display) {
- return state_errmsg_(self, "Error creating display.\n");
- }
-
-
-
- // al_resize_display(self->display, SCREEN_W, SCREEN_H);
-
- // initialize the file finder, so we can start to load the data files
- if(!fifi_init()) {
- return state_errmsg_(self, "Could not find data folder!\n");
- }
-
- // initialize the resource storage so we can store the data files
- if(!store_init()) {
- return state_errmsg_(self, "Could not initialize data store.\n");
- }
- // Tuffy.ttf
- // "OpenBaskerville-0.0.53.otf"
- #define STATE_FONTNAME "GranaPadano.ttf"
- #define STATE_FONT_INDEX 20000
-
- if(!store_load_ttf_font(STATE_FONT_INDEX, "font/" STATE_FONTNAME, -16, 0)) {
- return state_errmsg_(self, "Error loading " STATE_FONTNAME);
- }
-
- self->font = store_get_font(STATE_FONT_INDEX);
-
- // fifi_loadfont(STATE_FONTNAME, 16, 0);
- if (!self->font) {
- return state_errmsg_(self, "Error loading " STATE_FONTNAME);
- }
- state_color_f(self, STATE_WHITE, 1, 1, 1, 1);
- state_color_f(self, STATE_BLACK, 0, 0, 0, 1);
- // Start the event queue to handle keyboard input and our timer
- self->queue = al_create_event_queue();
- state_eventsource(self, al_get_keyboard_event_source());
- state_eventsource(self, al_get_display_event_source(self->display));
- state_eventsource(self, al_get_mouse_event_source());
- state_eventsource(self, al_get_joystick_event_source());
- al_set_window_title(self->display, "Eruta!");
- // set up fps counter. Start with assuming we have 60 fps.
- self->fps = 60.0;
- self->fpstime = al_get_time();
- self->frames = 60;
- /* No active map yet. */
- state_active_map_id_(self, -1);
-
- /* Background color. */
- self->background_color = al_map_rgb(64,128,64);
-
- // set up camera
- self->camera = camera_new(-100, -100, SCREEN_W, SCREEN_H);
- if(!self->camera) {
- return state_errmsg_(self, "Out of memory when allocating camera.");
- }
-
- /* Set up GUI. */
- if (!state_init_gui(self, fullscreen)) return NULL;
-
- /* Set up console. */
- {
- struct zori_style style;
- memset(&style, 0, sizeof(style));
- style.text.font = self->font;
- style.text.color = color_rgb(255,255,255);
- style.back.color = color_rgba(64,0,0, 191);
- Rebox bounds = { {20, 20} , {600, 400} };
- self->console = zori_console_new(1, &bounds, &style);
- if(!self->console) {
- return state_errmsg_(self, "Out of memory when allocating console.");
- }
- }
- zori_console_puts(self->console, "Zori Console started ok!");
- // set up ruby callback for console commands
- zori_console_command_(self->console, rh_run_console_command, self->ruby);
- // set up logging to console
- monolog_add_logger(self->console, &state_console_logger);
-
- /* Initialize Area. */
- self->area = area_new();
-
- /* Initialize sprite list. */
- self->sprites = spritelist_new();
-
- /* Show all by default. */
- self->show_area = TRUE;
- self->show_fps = TRUE;
- self->show_graph= TRUE;
-
-
-
-
- return self;
- }
- /** Sets the state's busy status to false */
- BOOL state_done(State * state) {
- state->busy = FALSE;
- return state->busy;
- }
- /** Returns true if the state is busy false if not. */
- BOOL state_busy(State * self) {
- return self->busy;
- }
- /* Scales and moves the display to achieve resolution independence. */
- void state_scale_display(State * self) {
- int real_w = al_get_display_width(self->display);
- int real_h = al_get_display_height(self->display);
- int scale_x = real_w / SCREEN_W;
- int scale_y = real_h / SCREEN_H;
- int scale = (scale_x < scale_y) ? scale_x : scale_y;
- int offset_x= (real_w - (SCREEN_W * scale)) / 2;
- int offset_y= (real_h - (SCREEN_H * scale)) / 2;
- /*
- al_draw_textf(state_font(self), COLOR_WHITE,
- 100, 100, 0, "SCALE: w: %d, h: %d, sx: %d, sy: %d, s: %d, ox:%d, oy:%d",
- real_w, real_h, scale_x, scale_y, scale, offset_x, offset_y);
- */
- ALLEGRO_TRANSFORM transform;
- al_identity_transform(&transform);
- /* Now draw black bars to cover the usused areas. */
- if (offset_y > 0) {
- al_draw_filled_rectangle(-offset_x , -offset_y, real_w, 0, al_map_rgb(0,0,0));
- al_draw_filled_rectangle(-offset_x , SCREEN_H, real_w, SCREEN_H+offset_y, al_map_rgb(0,0,0));
- }
- if (offset_x > 0) {
- al_draw_filled_rectangle(-offset_x , -offset_y, 0, real_h, al_map_rgb(0,0,0));
- al_draw_filled_rectangle(SCREEN_W , -offset_y, SCREEN_W + offset_x, real_h, al_map_rgb(0,0,0));
- }
-
- al_scale_transform(&transform, scale, scale);
- al_translate_transform(&transform, offset_x, offset_y);
- al_use_transform(&transform);
- /* al_set_clipping_rectangle(offset_x, offset_y, SCREEN_W, SCREEN_H); */
-
-
- }
- /* Draws all inside the state that needs to be drawn. */
- void state_draw(State * self) {
- int layer;
-
- /* Draw background color if no map active. */
- if (!self->active_map) {
- al_clear_to_color(self->background_color);
- }
-
- /* Draw the layers of the map and area interleaved. */
- for (layer = 0; layer < TILEMAP_PANES; layer++) {
- if (self->active_map) {
- /* Shadows should be drawn *before* the blends, otherwise both won't
- * look good when combined with each other. The problem with that is,
- * though that shadows are then not cast on the sprites.
- * Perhaps sprites will need separate shadows???
- */
- tilemap_draw_layer_tiles(self->active_map, self->camera, layer);
- tilemap_draw_layer_shadows(self->active_map, self->camera, layer);
- tilemap_draw_layer_blends(self->active_map, self->camera, layer);
- }
- if (self->area && self->show_area) {
- area_draw_layer(self->area, self->camera, layer);
- }
- }
-
- /* Draw UI scene graph */
- if (self->show_graph) {
- zori_draw_all();
- }
- /* Draw the particles from the particle engine. */
- // alpsshower_draw(&shower, state_camera(state));
-
-
- /* Draw fps if needed. */
- if (self->show_fps) {
- al_draw_textf(state_font(self), COLOR_WHITE,
- 10, 10, 0, "FPS: %.0f", state_fps(self));
- }
-
- /* Draw the ui and the console (will autohide if not active). */
- zori_draw_all();
- state_scale_display(self);
- }
- /* Updates the state's display. */
- void state_flip_display(State * self) {
- al_flip_display();
- state_frames_update(self);
- }
- /* Updates the state's elements. */
- void state_update(State * self) {
- mrb_value mval;
- // alpsshower_update(&shower, state_frametime(state));
-
- if (self->active_map) {
- tilemap_update(self->active_map, state_frametime(self));
- }
-
- if (self->area) {
- area_update(self->area, state_frametime(self));
- }
-
- camera_update(self->camera);
- // call ruby update callback
- callrb_on_update(self);
- // Update the scene graph (after the Ruby upate so anty ruby side-changes take
- // effect immediately.
- scegra_update(state_frametime(self));
-
- zori_update(state_frametime(self));
-
- }
- /** Polls the state's event queue, and gets the next event and stores it in
- * event. if it is available. Returns true if there is an event of false if
- * not.
- */
- int state_poll(State * state, ALLEGRO_EVENT * event) {
- return al_get_next_event(state->queue, event);
- }
- /** Polls the state's event queue, and gets the next event and returns it.
- * returns nul if out of memory or no event was available.
- * You must free the result of this function with event_free
- */
- ALLEGRO_EVENT * state_pollnew(State * state) {
- ALLEGRO_EVENT event, * result;
-
- if(state_poll(state, &event)) {
- result = event_alloc();
- if(!result) return NULL;
- (*result) = event; // copy data
- return result; // return pointer
- }
- return NULL;
- }
- /** Return the state's default font. */
- ALLEGRO_FONT * state_font(State * state) {
- if(!state) return NULL;
- return state->font;
- }
- /** Call this every frame to update the FPS and frames value */
- void state_frames_update(State * state) {
- double now = al_get_time();
- state->frames++;
- if((now - state->fpstime) > 1.0) {
- double realfps;
- /* Measure only last second of frames, which means FPS gets updated every second or so. */
- realfps = ((double)state->frames) / (now - state->fpstime);
- /* Display and use a rounded value for FPS, the number after the comma is normally due to jitter anyway. */
- state->fps = floor(realfps + 0.5);
- /* A little trick, to prefent jerkyness,
- * keep half the frames; and half the time */
- state->frames = state->frames / 2;
- state->fpstime = now - 0.5;
- }
- }
- /** Returns the amount of frames rendered during this second. */
- int state_frames(State * state) {
- return state->frames;
- }
- /** Returns the FPS value. */
- double state_fps(State * state) {
- return state->fps;
- }
- /** Returns the Frame time value. */
- double state_frametime(State * state) {
- if( state->fps < 20.0) return 1.0 / 20.0;
- return 1.0 / state->fps;
- }
- /** Returns the camera of the state. */
- Camera * state_camera(State * state) {
- if(!state) return NULL;
- return state->camera;
- }
- /* Get display state */
- int global_state_show_fps() {
- State * state = state_get();
- if (!state) return FALSE;
- return state->show_fps;
- }
- /* Set display state */
- int global_state_show_fps_(int show) {
- State * state = state_get();
- if (!state) return FALSE;
- return state->show_fps = show;
- }
- /* Get display state */
- int global_state_show_graph() {
- State * state = state_get();
- if (!state) return FALSE;
- return state->show_graph;
- }
- /* Set display state */
- int global_state_show_graph_(int show) {
- State * state = state_get();
- if (!state) return FALSE;
- return state->show_graph = show;
- }
- /* Get display state */
- int global_state_show_area() {
- State * state = state_get();
- if (!state) return FALSE;
- return state->show_area;
- }
- /* Set display state */
- int global_state_show_area_(int show) {
- State * state = state_get();
- if (!state) return FALSE;
- return state->show_area = show;
- }
- /* Get display state of physics */
- int global_state_show_physics() {
- State * state = state_get();
- if (!state) return FALSE;
- return area_draw_physics(state->area);
- }
- /* Set display state of physics */
- int global_state_show_physics_(int show) {
- State * state = state_get();
- if (!state) return FALSE;
- area_draw_physics_(state->area, show);
- return show;
- }
- /* Core functionality of Eruta, implemented on the state. */
- /* Ideas about starting the game and progressing
- * Normally, the game will have different modes. The game will start in
- * intro mode, which automatically changes into main menu mode.
- * From main menu mode a game may be loaded or a new game may be started.
- *
- * When the game starts, the generic startup and settings scripts must be loaded.
- * They influence the design of the main menu.
- *
- * To begin, we must implement the new game start. When a new game is started,
- * the game start script is loaded. Then, unless instructed differently,
- * map number 0001 is loaded. As always, when a map is loaded,
- * the map's corresponding script is loaded. The game has an area of "savable"
- * data which is initialized either by loading the game or by the new game script.
- *
- * Before the game is saved, the save game script is loaded. Likewise before
- * the game is loaded the load game script is loaded.
- *
- * Once the game is running, the main game script is loaded and call-backs
- * are used to communicate with it. This is the mechanism that allows part of the game
- * to be implemented in script.
- *
- * Needed scripts so far: start.mrb, newgame.mrb, loadgame.mrb, savegame.mrb,
- * main.mrb, and one map_0001.mrb, etc for every map. Other scripts can be loaded by
- * these scripts for modulization, but only from the script directory.
- *
- */
- /* Preloads a tile map from the given vpath. Returns the loaded map, or
- NULL if not loaded.
- Tilemap * state_preloadmap_vpath(State * state, const char * vpath) {
-
- return NULL;
- }
- */
- /* Preloads a tile map with the given map number. Returns the loaded map, or
- NULL if not loaded.
- Tilemap * state_preloadmap_index(State * state, int index) {
- return NULL;
- }
- */
- /* Tints a layer of the sprite that belongs to a thing.*/
- int state_thing_tint_layer
- (State * state, int thing_index, int layer_index, int r, int g, int b, int a) {
- Thing * thing = state_thing(state, thing_index);
- Color color = al_map_rgba(r, g, b, a);
- if (!thing) { return -1; }
- thing_tint_layer(thing, layer_index, color);
- return 0;
- }
- /* Transforms a mask color of an image in storage into an alpha. */
- int state_image_mask_to_alpha(State * state, int store_index, int r, int g, int b) {
- Image * image = store_get_bitmap(store_index);
- Color color = al_map_rgb(r, g, b);
- (void) state;
- if (!image) return -1;
- al_convert_mask_to_alpha(image, color);
- return store_index;
- }
- /* Transforms an image in storage where the average is assigned to the alpha value. */
- int state_image_average_to_alpha(State * state, int store_index, int r, int g, int b) {
- Image * image = store_get_bitmap(store_index);
- Color color = al_map_rgb(r, g, b);
- (void) state;
- if (!image) return -1;
- draw_convert_average_to_alpha(image, color);
- return store_index;
- }
- /* Returns the first unused thing ID that is greater than minimum. */
- int state_get_unused_thing_id() {
- return area_get_unused_thing_id(state_area(state_get()));
- }
- /* Returns the first unused sprite ID that is greater than minimum. */
- int state_get_unused_sprite_id() {
- return spritelist_get_unused_sprite_id(state_sprites(state_get()));
- }
- /** Deletes a sprite from the sprite list of the state. */
- int state_delete_sprite(int index) {
- return spritelist_delete_sprite(state_sprites(state_get()), index);
- }
- /** Deletes a thing from the things of the state's area. */
- int state_delete_thing(int index) {
- return area_delete_thing(state_area(state_get()), index);
- }
|