/****** ******/ #include "../globals.h" #include "interface.h" #include "r_gl.h" #include "r_soft.h" int interfaceInit() { g_video_width = getTablePairValueInt(g_settings, "v_width"); g_video_height = getTablePairValueInt(g_settings, "v_height"); g_video_fullscreen = getTablePairValueInt(g_settings, "v_fullscreen"); #if _WIN32 | _WIN64 | __APPLE__ SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER); #else SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTTHREAD); #endif interfaceSetRenderer(getTablePairValueInt(g_settings, "v_renderer")); /* load our global fonts */ g_font_large = newFont(); loadFontFromMemory(g_font_large, badfont_large_png, badfont_large_png_length, 16, 32); setFontScale(g_font_large, 2.0f, 2.0f); g_font_medium = newFont(); loadFontFromMemory(g_font_medium, badfont_medium_png, badfont_medium_png_length, 16, 32); setFontScale(g_font_medium, 2.0f, 2.0f); /* load our ui sprites */ spritesheet_ui = newSpritesheet(); loadSpritesheetFromMemory(spritesheet_ui, ui_png, ui_png_length, 64, 64, 8); setSpritesheetScale(spritesheet_ui, 2.0f, 2.0f); /* load menu bg */ menu_bg = newSpritesheet(); loadSpritesheetFromMemory(menu_bg, menu_bg_png, menu_bg_png_length, 1280, 480, 1); setSpritesheetScale(menu_bg, 2.0f, 2.0f); /* set up our display */ g_r_Init(); g_screen = screen; // for state(s) to access 'em SDL_Delay(100); g_video_width = (SDL_GetVideoSurface())->w; g_video_height = (SDL_GetVideoSurface())->h; /* reinit to deal with some window managers on X */ g_r_Reinit(); SDL_WM_SetCaption("timesynk", NULL); /* set our video tickrate/refresh vars */ vid_tickrate = (1000.0f / getTablePairValueFloat(g_settings, "v_fps")); // target 60 tickrate g_cap_framerate = getTablePairValueInt(g_settings, "v_framecap"); setPTime(&g_tick_time, 0, 0, getTablePairValueInt(g_settings, "tickrate")); vid_frames = 0; /* */ /* set up our tickrate into a PTime structure */ sleep_time.n = (1000000000/53); sleep_time.m = sleep_time.n/1000000; printf("tickrate: %ld\n", sleep_time.n); /* set up unicode, important to TSEvent */ SDL_EnableUNICODE(SDL_ENABLE); /* load global elements, i.e., fps counter */ g_elements = newElementList(); struct Dimension dimen = { 0, 0, 128, 32 }; g_element_fps = newElement(E_TYPE_TEXT, 0, g_r_setupElement, dimen); setElementValue(g_element_fps, 0); setElementFont(g_element_fps, g_font_medium); g_element_fps->target = g_screen; addElementToList(g_elements, g_element_fps); /* is it wrong to use function pointers to (vaguely) mimic Object oriented states? */ g_initState = initModulesState; g_freeState = freeModulesState; g_handleState = handleModulesState; g_processState = processModulesState; g_renderState = renderModulesState; g_switch_state = 0; return 0; } int interfaceRun() { struct PTime current_time; // time at start of loop struct PTime last_time; // time at end of last loop struct PTime delta_time; // difference between current_time and last_time getPTime(¤t_time); SDL_Event event; struct TSEvent ts_event; // SDL->TS event structure /* begin our main loop */ g_initState(); while(g_running) { last_time = current_time; getPTime(¤t_time); getPTimeDiff(&delta_time, ¤t_time, &last_time); // handle input and pass to state while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: ts_event.type = TS_KEYBOARD; ts_event.keyboard.key.scancode = event.key.keysym.scancode; ts_event.keyboard.key.mod = event.key.keysym.mod; ts_event.keyboard.key.sym = event.key.keysym.sym; ts_event.keyboard.key.unicode = event.key.keysym.unicode; ts_event.keyboard.state = TS_KEYDOWN; g_handleState(ts_event); break; case SDL_KEYUP: ts_event.type = TS_KEYBOARD; ts_event.keyboard.key.scancode = event.key.keysym.scancode; ts_event.keyboard.key.mod = event.key.keysym.mod; ts_event.keyboard.key.sym = event.key.keysym.sym; ts_event.keyboard.key.unicode = event.key.keysym.unicode; ts_event.keyboard.state = TS_KEYUP; g_handleState(ts_event); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: ts_event.type = TS_MOUSECLICK; ts_event.mouseclick.button = event.button.button; ts_event.mouseclick.state = event.button.state; ts_event.mouseclick.x = event.button.x; ts_event.mouseclick.y = event.button.y; g_handleState(ts_event); break; // TODO: USER_EVENT will call here, with a subtype of GAME_TICK as called by subtype of NET_RECEIVE. Within GAME_TICK, we will run game logic (gameTick() or some such) if a game is indeed running. case SDL_QUIT: g_running = 0; break; default: break; } } // do state processing g_processState(delta_time.n); // now we move on to rendering // clear out the screen :) g_clearScreen(); // draw state g_renderState(); // draw global elements g_renderElements(g_elements); // update fps counter vid_frames++; if (current_time.s - count_time.s >= 1) { struct PTime delta_fps_time; getPTimeDiff(&delta_fps_time, ¤t_time, &count_time); int fps = vid_frames / delta_fps_time.s; count_time = current_time; vid_frames = 0; setElementValue(g_element_fps, fps); } // render updates to screen g_renderScreen(); // cap framerate if bool is set! if (g_cap_framerate) { int64_t delay_ns = sleep_time.n - delta_time.n; if (delay_ns < 0) { printf("uhoh, delay took %ld, so we wait for %ld\n", delta_time.n, delay_ns); delay_ns = 0; } doNanoSleep(delay_ns); } // switch states if running state requested it. if (g_switch_state == 1) { g_freeState(); // free old state g_initState(); // init new state, setting up state pointers g_switch_state = 0; } } return 0; } int interfaceClose() { g_freeState(); g_r_Close(); SDL_FreeSurface(screen); SDL_Quit(); return 0; } int interfaceSetVideo() { if ((screen = SDL_SetVideoMode(g_video_width, g_video_height, 32, SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE|g_video_fullscreen)) == NULL){ return 1; } return 0; } int interfaceSetRenderer(int render_id) { switch(render_id) { case R_OPENGL: g_loadSpritesheet = &r_gl_loadSpritesheet; g_renderElements = &r_gl_renderElements; g_renderElement = &r_gl_renderElement; g_renderSprite = &r_gl_renderSprite; g_r_Init = &r_gl_Init; g_r_Reinit = &r_gl_Init; g_r_Close = &r_gl_Close; g_renderScreen = &r_gl_renderScreen; g_clearScreen = &r_gl_clearScreen; g_r_setupElement = &r_gl_setupElement; g_r_cleanElement = &r_gl_cleanElement; return R_OPENGL; break; case R_SOFTWARE: g_loadSpritesheet = &loadSpritesheetFromFile; g_renderElements = &r_soft_renderElements; g_renderElement = &r_soft_renderElement; g_renderSprite = &r_soft_drawSprite; g_r_Init = &r_soft_Init; g_r_Reinit = &r_soft_Init; g_r_Close = &r_soft_Close; g_renderScreen = &r_soft_renderScreen; g_clearScreen = &r_soft_clearScreen; g_r_setupElement = &r_soft_setupElement; g_r_cleanElement = &r_soft_cleanElement; return R_SOFTWARE; break; default: return -1; break; } return -2; } void genElementDimensions(struct Element *element) { if (element == NULL) return; int width; //int height; int temp = 0; switch(element->type) { case E_TYPE_TEXT: element->dimen.w = ((struct TextElement *)element->data)->length * ((struct Font*)element->font)->s_width; element->dimen.h = ((struct Font*)element->font)->s_height; break; case E_TYPE_BUTTON: width = ((struct TextElement *)element->data)->length * ((struct Font*)element->font)->s_width + (6*spritesheet_ui->scale_x); temp = spritesheet_ui->s_width*2; // minimum width element->dimen.w = ( temp > width ? temp : width ); element->dimen.h = spritesheet_ui->s_height; break; } } int getElementX(struct Element *element) { return element->dimen.x+(element->sx*(g_video_width/3)); } int getElementY(struct Element *element) { return element->dimen.y+(element->sy*(g_video_height/3)); }