#include <ui.h> /* * Create a macro to easily access SDL keypresses */ #define SDL_KEY e.key.keysym.sym extern std::vector<menuItem>optionsMenu; extern SDL_Window *window; /* * External references for updating player coords / current world. */ extern Player *player; extern World *currentWorld; /* * In the case of dialog, some NPC quests can be preloaded so that they aren't assigned until * the dialog box closes. Reference variables for that here. */ extern std::vector<int (*)(NPC *)> AIpreload; extern std::vector<NPC *> AIpreaddr; /* * Pressing ESC or closing the window will set this to false. */ extern bool gameRunning; /* * Freetype variables, and a GLuint for referencing rendered letters. */ static FT_Library ftl; static FT_Face ftf; static GLuint ftex[93]; static vec2 ftexwh[93]; static vec2 ftexbl[93]; static vec2 ftexad[93]; static unsigned char fontColor[3] = {255,255,255}; /* * Variables for dialog boxes / options. */ static char dialogBoxText[512]; static char *dialogOptText[4]; static float dialogOptLoc[4][3]; static unsigned char dialogOptCount = 0; static bool dialogPassive = false; static bool typeOutDone = true; extern Menu* currentMenu; extern Menu pauseMenu; Mix_Chunk *dialogClick; extern void mainLoop(void); /* * Toggled by pressing 'q', disables some controls when true. */ bool fadeEnable = false; bool fadeWhite = false; bool fadeFast = false; unsigned int fadeIntensity = 0; bool inBattle = false; Mix_Chunk *battleStart; Mix_Chunk *sanic; void Menu::gotoParent(){ if(parent == NULL){ currentMenu = NULL; updateConfig(); }else{ currentMenu = parent; } } void Menu::gotoChild(){ if(child == NULL){ currentMenu = this; }else{ currentMenu = child; } } namespace ui { /* * Mouse coordinates. */ vec2 mouse; static vec2 premouse={0,0}; /* * Variety of keydown bools */ bool edown; /* * Debugging flags. */ bool debug=false; bool posFlag=false; /* * Dialog stuff that needs to be 'public'. */ bool dialogBoxExists = false; bool dialogImportant = false; unsigned char dialogOptChosen = 0; unsigned int textWrapLimit = 110; /* * Current font size. Changing this WILL NOT change the font size, see setFontSize() for * actual font size changing. */ unsigned int fontSize; /* * Initialises the Freetype library, and sets a font size. */ void initFonts(void){ if(FT_Init_FreeType(&ftl)){ std::cout<<"Error! Couldn't initialize freetype."<<std::endl; abort(); } fontSize=0; memset(&ftex,0,93*sizeof(GLuint)); #ifdef DEBUG DEBUG_printf("Initialized FreeType2.\n",NULL); #endif // DEBUG dialogClick = Mix_LoadWAV("assets/click.wav"); battleStart = Mix_LoadWAV("assets/sounds/frig.wav"); sanic = Mix_LoadWAV("assets/sounds/sanic.wav"); Mix_Volume(1,50); } void destroyFonts(void){ FT_Done_Face(ftf); FT_Done_FreeType(ftl); Mix_FreeChunk(dialogClick); Mix_FreeChunk(battleStart); Mix_FreeChunk(sanic); } /* * Sets a new font family to use (*.ttf). */ void setFontFace(const char *ttf){ if(FT_New_Face(ftl,ttf,0,&ftf)){ std::cout<<"Error! Couldn't open "<<ttf<<"."<<std::endl; abort(); } #ifdef DEBUG DEBUG_printf("Using font %s\n",ttf); #endif // DEBUG } /* * Sets a new font size (default: 12). */ void setFontSize(unsigned int size){ unsigned int i,j; char *buf; fontSize=size; FT_Set_Pixel_Sizes(ftf,0,fontSize); /* * Pre-render 'all' the characters. */ glDeleteTextures(93,ftex); // delete[] any already-rendered textures glGenTextures(93,ftex); // Generate new texture name/locations? for(i=33;i<126;i++){ /* * Load the character from the font family file. */ if(FT_Load_Char(ftf,i,FT_LOAD_RENDER)){ std::cout<<"Error! Unsupported character "<<(char)i<<" ("<<i<<")."<<std::endl; abort(); } /* * Transfer the character's bitmap (?) to a texture for rendering. */ glBindTexture(GL_TEXTURE_2D,ftex[i-33]); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S ,GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T ,GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER ,GL_LINEAR ); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER ,GL_LINEAR ); glPixelStorei(GL_UNPACK_ALIGNMENT,1); /* * The just-created texture will render red-on-black if we don't do anything to it, so * here we create a buffer 4 times the size and transform the texture into an RGBA array, * making it white-on-black. */ buf = new char[ftf->glyph->bitmap.width * ftf->glyph->bitmap.rows * 4]; //(char *)malloc(ftf->glyph->bitmap.width*ftf->glyph->bitmap.rows*4); for(j=0;j<ftf->glyph->bitmap.width*ftf->glyph->bitmap.rows;j++){ buf[j*4 ]=fontColor[0]; buf[j*4+1]=fontColor[1]; buf[j*4+2]=fontColor[2]; buf[j*4+3]=ftf->glyph->bitmap.buffer[j]; } ftexwh[i-33].x=ftf->glyph->bitmap.width; ftexwh[i-33].y=ftf->glyph->bitmap.rows; ftexbl[i-33].x=ftf->glyph->bitmap_left; ftexbl[i-33].y=ftf->glyph->bitmap_top; ftexad[i-33].x=ftf->glyph->advance.x>>6; ftexad[i-33].y=ftf->glyph->advance.y>>6; glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,ftf->glyph->bitmap.width,ftf->glyph->bitmap.rows,0,GL_RGBA,GL_UNSIGNED_BYTE,buf); delete[] buf; //free(buf); } } /* * Set a color for font rendering (default: white). */ void setFontColor(unsigned char r,unsigned char g,unsigned char b){ fontColor[0]=r; fontColor[1]=g; fontColor[2]=b; } /* * Draws a character at the specified coordinates, aborting if the character is unknown. */ vec2 putChar(float x,float y,char c){ vec2 c1,c2; /* * Get the width and height of the rendered character. */ c1={x+ftexbl[c-33].x, y+ftexbl[c-33].y}; c2=ftexwh[c-33]; /* * Draw the character: */ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,ftex[c-33]); glPushMatrix(); glTranslatef(0,-c2.y,0); glBegin(GL_QUADS); glColor3ub(fontColor[0],fontColor[1],fontColor[2]); glTexCoord2f(0,1);glVertex2f(c1.x ,c1.y ); glTexCoord2f(1,1);glVertex2f(c1.x+c2.x,c1.y ); glTexCoord2f(1,0);glVertex2f(c1.x+c2.x,c1.y+c2.y); glTexCoord2f(0,0);glVertex2f(c1.x ,c1.y+c2.y); glEnd(); glPopMatrix(); glDisable(GL_TEXTURE_2D); /* * return the width. */ return ftexad[c-33];//(vec2){c2.x,ftexad[c-33].y}; } /* * Draw a string at the specified coordinates. */ float putString(const float x,const float y,const char *s){ unsigned int i=0; float xo=x,yo=y; vec2 add; /* * Loop on each character: */ do{ if(i && ((i / 110.0) == (i / 110))){ yo-=fontSize*1.05; xo=x; if(s[i] == ' ') i++; } if(s[i] == '\n' || s[i] == '\r' || s[i] == '\t'){ /*if(s[i] == '\n'){ yo-=fontSize*1.05; xo=x; */}else if(s[i]==' '){ // Handle spaces xo+=fontSize/2; }else if(s[i]=='\b'){ // Handle backspaces? xo-=add.x; }else{ add=putChar(xo,yo,s[i]); xo+=add.x; yo+=add.y; } }while(s[++i]); return xo; // i.e. the string width } float putStringCentered(const float x,const float y,const char *s){ unsigned int i = 0; float width = 0; do{ if(s[i]=='\n'){ // Handle newlines // TODO }else if(s[i]==' '){ // Handle spaces width+=fontSize/2; }else if(s[i]=='\b'){ // Handle backspaces? // Why? // Cuz }else{ width+=ftexwh[i].x+fontSize*.1; } }while(s[++i]); putString(x-width/2,y,s); return width; } /* * Draw a string in a typewriter-esque fashion. Each letter is rendered as calls are made * to this function. Passing a different string to the function will reset the counters. */ static char *ret = NULL; char *typeOut(char *str){ static unsigned int sinc, // Acts as a delayer for the space between each character. linc=0, // Contains the number of letters that should be drawn. size=0; // Contains the full size of the current string. //static char *ret = NULL; /* * Create a well-sized buffer if we haven't yet. */ if(!ret){ ret = new char[512]; //(char *)calloc(512,sizeof(char)); memset(ret,0,512*sizeof(char)); } /* * Reset values if a new string is being passed. */ if(strncmp(ret,str,linc-1)){ memset(ret,0,512); // Zero the buffer size=strlen(str); // Set the new target string size linc=0; // Reset the incrementers sinc=1; typeOutDone = false; } /* * Draw the next letter if necessary. */ if(typeOutDone) return str; else if(++sinc==2){ sinc=0; strncpy(ret+linc,str+linc,1); // Get next character if(linc<size) linc++; else typeOutDone = true; } return ret; // The buffered string. } /* * Draw a formatted string to the specified coordinates. */ float putText(const float x,const float y,const char *str,...){ va_list args; char *buf; float width; /* * Create a wimpy buffer. */ buf = new char[512]; //(char *)calloc(128,sizeof(char)); memset(buf,0,512*sizeof(char)); /* * Handle the formatted string, printing it to the buffer. */ va_start(args,str); vsnprintf(buf,512,str,args); va_end(args); /* * Draw the string, free resources, return the width of the string. */ width=putString(x,y,buf); delete[] buf; //free(buf); return width; } void dialogBox(const char *name,const char *opt,bool passive,const char *text,...){ va_list dialogArgs; unsigned int len; char *sopt,*soptbuf; dialogPassive = passive; /* * Set up the text buffer. */ memset(dialogBoxText,0,512); /* * Get the text ready for rendering. */ len=strlen(name); strcpy(dialogBoxText ,name); strcpy(dialogBoxText+len,": "); len+=2; va_start(dialogArgs,text); vsnprintf(dialogBoxText+len,512-len,text,dialogArgs); va_end(dialogArgs); /* * Set up option text. */ while(dialogOptCount){ if(dialogOptText[dialogOptCount]){ delete[] dialogOptText[dialogOptCount]; //free(dialogOptText[dialogOptCount]); dialogOptText[dialogOptCount] = NULL; } dialogOptCount--; }; dialogOptCount = 0; dialogOptChosen = 0; memset(&dialogOptLoc,0,sizeof(float)*12); if(opt != NULL){ soptbuf = new char[strlen(opt)+1]; strcpy(soptbuf,opt); sopt=strtok(soptbuf,":"); while(sopt != NULL){ dialogOptText[dialogOptCount] = new char[strlen(sopt)+1]; //(char *)malloc(strlen(sopt)); strcpy(dialogOptText[dialogOptCount++],sopt); sopt=strtok(NULL,":"); } delete[] soptbuf; } /* * Tell draw() that the box is ready. */ dialogBoxExists = true; dialogImportant = false; if(ret) ret[0] = '\0'; } void waitForDialog(void){ do{ mainLoop(); }while(ui::dialogBoxExists); } void waitForCover(void){ do{ mainLoop(); }while(fadeIntensity < 255); fadeIntensity = 255; } void waitForNothing(unsigned int ms){ unsigned int target = millis() + ms; do{ mainLoop(); }while(millis() < target); } void importantText(const char *text,...){ va_list textArgs; //if(!player->ground)return; memset(dialogBoxText,0,512); va_start(textArgs,text); vsnprintf(dialogBoxText,512,text,textArgs); va_end(textArgs); dialogBoxExists = true; dialogImportant = true; toggleBlack(); } void draw(void){ unsigned char i; float x,y,tmp; char *rtext; if(dialogBoxExists){ rtext=typeOut(dialogBoxText); if(dialogImportant){ setFontColor(255,255,255); if(fadeIntensity == 255){ setFontSize(24); putStringCentered(offset.x,offset.y,rtext); } }else{ x=offset.x-SCREEN_WIDTH/2+HLINE*8; y=(offset.y+SCREEN_HEIGHT/2)-HLINE*8; glColor3ub(255,255,255); glBegin(GL_LINE_STRIP); glVertex2f(x-1 ,y+1); glVertex2f(x+1+SCREEN_WIDTH-HLINE*16,y+1); glVertex2f(x+1+SCREEN_WIDTH-HLINE*16,y-1-SCREEN_HEIGHT/4); glVertex2f(x-1 ,y-1-SCREEN_HEIGHT/4); glVertex2f(x ,y+1); glEnd(); glColor3ub(0,0,0); glRectf(x,y,x+SCREEN_WIDTH-HLINE*16,y-SCREEN_HEIGHT/4); rtext=typeOut(dialogBoxText); putString(x+HLINE,y-fontSize-HLINE,rtext); for(i=0;i<dialogOptCount;i++){ setFontColor(255,255,255); tmp = putStringCentered(offset.x,dialogOptLoc[i][1],dialogOptText[i]); dialogOptLoc[i][2] = offset.x + tmp; dialogOptLoc[i][0] = offset.x - tmp; dialogOptLoc[i][1] = y - SCREEN_HEIGHT / 4 + (fontSize + HLINE) * (i + 1); if(mouse.x > dialogOptLoc[i][0] && mouse.x < dialogOptLoc[i][2] && mouse.y > dialogOptLoc[i][1] && mouse.y < dialogOptLoc[i][1] + 16 ){ // fontSize setFontColor(255,255,0); putStringCentered(offset.x,dialogOptLoc[i][1],dialogOptText[i]); } } setFontColor(255,255,255); } if(strcmp(rtext,dialogBoxText)){ Mix_PlayChannel(1,dialogClick,0); } }else if(!dialogImportant && !fadeIntensity){ vec2 hub = { (SCREEN_WIDTH/2+offset.x)-fontSize*10, (offset.y+SCREEN_HEIGHT/2)-fontSize }; putText(hub.x,hub.y,"Health: %u/%u",player->health>0?(unsigned)player->health:0, (unsigned)player->maxHealth ); if(player->alive){ glColor3ub(150,0,0); hub.y-=fontSize*1.15; glRectf(hub.x, hub.y, hub.x+150, hub.y+12); glColor3ub(255,0,0); glRectf(hub.x, hub.y, hub.x+(player->health/player->maxHealth * 150), hub.y+12); } /* * Lists all of the quests the player is currently taking. */ if(player->inv->invOpen){ hub.y = player->loc.y + fontSize * 8; hub.x = player->loc.x; putStringCentered(hub.x,hub.y,"Current Quests:"); for(auto &c : player->qh.current){ hub.y -= fontSize * 1.15; putString(hub.x,hub.y,c->title); } } } } void quitGame(){ gameRunning = false; updateConfig(); } void quitMenu(){ currentMenu = NULL; } menuItem createButton(vec2 l, dim2 d, Color c, const char* t, menuFunc f){ menuItem temp; temp.member = 0; temp.button.loc = l; temp.button.dim = d; temp.button.color = c; temp.button.text = t; temp.button.func = f; return temp; } menuItem createChildButton(vec2 l, dim2 d, Color c, const char* t){ menuItem temp; temp.member = -1; temp.button.loc = l; temp.button.dim = d; temp.button.color = c; temp.button.text = t; temp.button.func = NULL; return temp; } menuItem createParentButton(vec2 l, dim2 d, Color c, const char* t){ menuItem temp; temp.member = -2; temp.button.loc = l; temp.button.dim = d; temp.button.color = c; temp.button.text = t; temp.button.func = NULL; return temp; } menuItem createSlider(vec2 l, dim2 d, Color c, float min, float max, const char* t, float* v){ menuItem temp; temp.member = 1; temp.slider.loc = l; temp.slider.dim = d; temp.slider.color = c; temp.slider.minValue = min; temp.slider.maxValue = max; temp.slider.text = t; temp.slider.var = v; temp.slider.sliderLoc = *v; return temp; } char* stradd(const char* a, const char* b){ size_t len = strlen(a) + strlen(b); char *ret = (char*)malloc(len * sizeof(char) + 1); *ret = '\0'; return strcat(strcat(ret,a),b); } /* * Draws the menu */ void drawMenu(Menu *menu){ SDL_Event e; mouse.x=premouse.x+offset.x-(SCREEN_WIDTH/2); mouse.y=(offset.y+SCREEN_HEIGHT/2)-premouse.y; //custom event polling for menu's so all other events are disregarded while(SDL_PollEvent(&e)){ switch(e.type){ case SDL_QUIT: gameRunning=false; return; break; case SDL_MOUSEMOTION: premouse.x=e.motion.x; premouse.y=e.motion.y; break; case SDL_KEYUP: if(SDL_KEY == SDLK_ESCAPE){ menu->gotoParent(); return; } break; default:break; } } //draw the dark transparent background glColor4f(0.0f, 0.0f, 0.0f, .8f); glRectf(offset.x-SCREEN_WIDTH/2,0,offset.x+SCREEN_WIDTH/2,SCREEN_HEIGHT); //loop through all elements of the menu for(auto &m : menu->items){ //if the menu is any type of button if(m.member == 0 || m.member == -1 || m.member == -2){ //draw the button background glColor3f(m.button.color.red,m.button.color.green,m.button.color.blue); glRectf(offset.x+m.button.loc.x, offset.y+m.button.loc.y, offset.x+m.button.loc.x + m.button.dim.x, offset.y+m.button.loc.y + m.button.dim.y); //draw the button text putStringCentered(offset.x + m.button.loc.x + (m.button.dim.x/2), (offset.y + m.button.loc.y + (m.button.dim.y/2)) - ui::fontSize/2, m.button.text); //tests if the mouse is over the button if(mouse.x >= offset.x+m.button.loc.x && mouse.x <= offset.x+m.button.loc.x + m.button.dim.x){ if(mouse.y >= offset.y+m.button.loc.y && mouse.y <= offset.y+m.button.loc.y + m.button.dim.y){ //if the mouse if over the button, it draws this white outline glColor3f(1.0f,1.0f,1.0f); glBegin(GL_LINE_STRIP); glVertex2f(offset.x+m.button.loc.x, offset.y+m.button.loc.y); glVertex2f(offset.x+m.button.loc.x+m.button.dim.x, offset.y+m.button.loc.y); glVertex2f(offset.x+m.button.loc.x+m.button.dim.x, offset.y+m.button.loc.y+m.button.dim.y); glVertex2f(offset.x+m.button.loc.x, offset.y+m.button.loc.y+m.button.dim.y); glVertex2f(offset.x+m.button.loc.x, offset.y+m.button.loc.y); glEnd(); //if the mouse is over the button and clicks if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)){ switch(m.member){ case 0: //normal button m.button.func(); break; case -1: menu->gotoChild(); //goto child menu break; case -2: menu->gotoParent(); //goto parent menu default:break; } } } } //if element is a slider }else if(m.member == 1){ //combining slider text with variable amount char outSV[32]; sprintf(outSV, "%s: %.1f",m.slider.text, *m.slider.var); //width of the slider handle float sliderW = m.slider.dim.x * .05; //location of the slider handle m.slider.sliderLoc = m.slider.minValue + (*m.slider.var/m.slider.maxValue)*(m.slider.dim.x-sliderW); //draw the background of the slider glColor4f(m.slider.color.red,m.slider.color.green,m.slider.color.blue, .5f); glRectf(offset.x+m.slider.loc.x, offset.y+m.slider.loc.y, offset.x+m.slider.loc.x + m.slider.dim.x, offset.y+m.slider.loc.y + m.slider.dim.y); //draw the slider handle glColor4f(m.slider.color.red,m.slider.color.green,m.slider.color.blue, 1.0f); glRectf(offset.x+m.slider.loc.x+m.slider.sliderLoc, offset.y+m.slider.loc.y, offset.x+m.slider.loc.x + m.slider.sliderLoc + (m.slider.dim.x*.05), offset.y+m.slider.loc.y + m.slider.dim.y); //draw the now combined slider text putStringCentered(offset.x + m.slider.loc.x + (m.slider.dim.x/2), (offset.y + m.slider.loc.y + (m.slider.dim.y/2)) - ui::fontSize/2, outSV); //test if mouse is inside of the slider's borders if(mouse.x >= offset.x+m.slider.loc.x && mouse.x <= offset.x+m.slider.loc.x + m.slider.dim.x){ if(mouse.y >= offset.y+m.slider.loc.y && mouse.y <= offset.y+m.slider.loc.y + m.slider.dim.y){ //if it is we draw a white border around it glColor3f(1.0f,1.0f,1.0f); glBegin(GL_LINE_STRIP); glVertex2f(offset.x+m.slider.loc.x, offset.y+m.slider.loc.y); glVertex2f(offset.x+m.slider.loc.x+m.slider.dim.x, offset.y+m.slider.loc.y); glVertex2f(offset.x+m.slider.loc.x+m.slider.dim.x, offset.y+m.slider.loc.y+m.slider.dim.y); glVertex2f(offset.x+m.slider.loc.x, offset.y+m.slider.loc.y+m.slider.dim.y); glVertex2f(offset.x+m.slider.loc.x, offset.y+m.slider.loc.y); //and a border around the slider handle glVertex2f(offset.x+m.slider.loc.x + m.slider.sliderLoc, offset.y+m.slider.loc.y); glVertex2f(offset.x+m.slider.loc.x + (m.slider.sliderLoc + sliderW), offset.y+m.slider.loc.y); glVertex2f(offset.x+m.slider.loc.x + (m.slider.sliderLoc + sliderW), offset.y+m.slider.loc.y+m.slider.dim.y); glVertex2f(offset.x+m.slider.loc.x + m.slider.sliderLoc, offset.y+m.slider.loc.y+m.slider.dim.y); glVertex2f(offset.x+m.slider.loc.x + m.slider.sliderLoc, offset.y+m.slider.loc.y); glEnd(); //if we are inside the slider and click it will set the slider to that point if(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)){ //change handle location *m.slider.var = (((mouse.x-offset.x) - m.slider.loc.x)/m.slider.dim.x)*100; //draw a white box over the handle glColor3f(1.0f,1.0f,1.0f); glRectf(offset.x+m.slider.loc.x + m.slider.sliderLoc, offset.y+m.slider.loc.y, offset.x+m.slider.loc.x + (m.slider.sliderLoc + sliderW), offset.y+m.slider.loc.y + m.slider.dim.y); } //makes sure handle can't go below or above min and max values if(*m.slider.var >= m.slider.maxValue)*m.slider.var = m.slider.maxValue; else if(*m.slider.var <= m.slider.minValue)*m.slider.var = m.slider.minValue; } } } } } void dialogAdvance(void){ unsigned char i; if(!typeOutDone){ typeOutDone = true; return; } for(i=0;i<dialogOptCount;i++){ if(mouse.x > dialogOptLoc[i][0] && mouse.x < dialogOptLoc[i][2] && mouse.y > dialogOptLoc[i][1] && mouse.y < dialogOptLoc[i][1] + 16 ){ // fontSize dialogOptChosen = i + 1; goto DONE; } } DONE: if(dialogImportant){ dialogImportant = false; setFontSize(16); toggleBlack(); } dialogBoxExists = false; } void handleEvents(void){ static bool left=true,right=false; static int heyOhLetsGo = 0; World *tmp; vec2 oldpos,tmppos; SDL_Event e; mouse.x=premouse.x+offset.x-(SCREEN_WIDTH/2); mouse.y=(offset.y+SCREEN_HEIGHT/2)-premouse.y; while(SDL_PollEvent(&e)){ switch(e.type){ case SDL_QUIT: gameRunning=false; break; case SDL_MOUSEMOTION: premouse.x=e.motion.x; premouse.y=e.motion.y; break; case SDL_MOUSEBUTTONDOWN: if((e.button.button & SDL_BUTTON_RIGHT) && dialogBoxExists) dialogAdvance(); if((e.button.button & SDL_BUTTON_LEFT) && !dialogBoxExists) player->inv->usingi = true; break; /* KEYDOWN */ case SDL_KEYDOWN: /*if(SDL_KEY == SDLK_ESCAPE){ //gameRunning = false; pMenu = true; return; }else */if(SDL_KEY == SDLK_SPACE){ /*if(dialogBoxExists) dialogAdvance(); else */if(player->ground){ player->vel.y=.4; player->loc.y+=HLINE*2; player->ground=false; } break; }else if(!dialogBoxExists || dialogPassive){ tmp = currentWorld; switch(SDL_KEY){ case SDLK_a: if(fadeEnable)break; player->vel.x=-.15; player->left = true; player->right = false; left = true; right = false; if(currentWorld->toLeft){ oldpos = player->loc; if((tmp = currentWorld->goWorldLeft(player)) != currentWorld){ tmppos = player->loc; player->loc = oldpos; toggleBlackFast(); waitForCover(); player->loc = tmppos; currentWorld = tmp; toggleBlackFast(); } } break; case SDLK_d: if(fadeEnable)break; player->vel.x=.15; player->right = true; player->left = false; left = false; right = true; if(currentWorld->toRight){ oldpos = player->loc; if((tmp = currentWorld->goWorldRight(player)) != currentWorld){ tmppos = player->loc; player->loc = oldpos; toggleBlackFast(); waitForCover(); player->loc = tmppos; currentWorld = tmp; toggleBlackFast(); } } break; case SDLK_s: break; case SDLK_w: if(inBattle){ tmp = currentWorld; currentWorld = ((Arena *)currentWorld)->exitArena(player); if(tmp != currentWorld){ //delete &tmp; toggleBlackFast(); } }else{ if((tmp = currentWorld->goInsideStructure(player)) != currentWorld) currentWorld = tmp; } break; case SDLK_i: /*currentWorld=currentWorld->goWorldBack(player); // Go back a layer if possible if(tmp!=currentWorld){ currentWorld->detect(player); player->vel.y=.2; player->loc.y+=HLINE*5; player->ground=false; }*/ player->health -= 5; break; case SDLK_k: /*currentWorld=currentWorld->goWorldFront(player); // Go forward a layer if possible if(tmp!=currentWorld){ currentWorld->behind->detect(player); player->vel.y=.2; player->loc.y+=HLINE*5; player->ground=false; }*/ break; case SDLK_LSHIFT: if(debug){ Mix_PlayChannel(1,sanic,-1); player->speed = 4.0f; }else player->speed = 2.0f; break; case SDLK_LCTRL: player->speed = .5; break; case SDLK_F3: debug ^= true; break; case SDLK_b: if(debug)posFlag ^= true; break; case SDLK_e: edown=true; if(!heyOhLetsGo){ heyOhLetsGo = loops; player->inv->mouseSel = false; } if(loops - heyOhLetsGo >= 2 && !(player->inv->invOpen) && !(player->inv->selected)) player->inv->invHover=true; break; default: break; } if(tmp != currentWorld){ std::swap(tmp,currentWorld); toggleBlackFast(); waitForCover(); std::swap(tmp,currentWorld); toggleBlackFast(); } } break; /* * KEYUP */ case SDL_KEYUP: if(SDL_KEY == SDLK_ESCAPE){ //gameRunning = false; currentMenu = &pauseMenu; return; } switch(SDL_KEY){ case SDLK_a: left = false; break; case SDLK_d: right = false; break; case SDLK_LSHIFT: if(player->speed == 4){ Mix_FadeOutChannel(1,2000); } player->speed = 1; break; case SDLK_LCTRL: player->speed = 1; break; case SDLK_e: edown=false; if(player->inv->invHover){ player->inv->invHover = false; }else{ if(!player->inv->selected)player->inv->invOpening ^= true; else player->inv->selected = false; player->inv->mouseSel = false; } heyOhLetsGo = 0; break; case SDLK_LEFT: if(player->inv->sel)player->inv->sel--; break; case SDLK_RIGHT: player->inv->sel++; break; case SDLK_l: player->light^=true; break; case SDLK_f: currentWorld->addLight({player->loc.x + SCREEN_WIDTH/2, player->loc.y},{1.0f,1.0f,1.0f}); break; case SDLK_g: //currentWorld->addStructure(LAMP_POST, player->loc.x, player->loc.y, NULL); break; case SDLK_h: //currentWorld->addStructure(TOWN_HALL, player->loc.x, player->loc.y, NULL); break; case SDLK_j: //currentWorld->addStructure(FOUNTAIN, player->loc.x, player->loc.y, NULL); break; case SDLK_v: //currentWorld->addVillage(player->loc.x, player->loc.y, 5, 10, 100, NULL); break; case SDLK_b: currentWorld->addStructure(FIRE_PIT, player->loc.x, player->loc.y, NULL); currentWorld->addLight({player->loc.x + SCREEN_WIDTH/2, player->loc.y},{1.0f,1.0f,1.0f}); break; case SDLK_F12: std::cout << "Took screenshot" << std::endl; // Make the BYTE array, factor of 3 because it's RBG. static GLubyte* pixels = new GLubyte[ 3 * SCREEN_WIDTH * SCREEN_HEIGHT]; glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels); break; default: break; } if(!left&&!right) player->vel.x=0; break; default: break; } } if(!dialogBoxExists&&AIpreaddr.size()){ // Flush preloaded AI functions if necessary while(!AIpreaddr.empty()){ AIpreaddr.front()->addAIFunc(AIpreload.front(),false); AIpreaddr.erase(AIpreaddr.begin()); AIpreload.erase(AIpreload.begin()); } } } void toggleBlack(void){ fadeEnable ^= true; fadeWhite = false; fadeFast = false; } void toggleBlackFast(void){ fadeEnable ^= true; fadeWhite = false; fadeFast = true; } void toggleWhite(void){ fadeEnable ^= true; fadeWhite = true; fadeFast = false; } void toggleWhiteFast(void){ fadeEnable ^= true; fadeWhite = true; fadeFast = true; Mix_PlayChannel(1,battleStart,0); } }