#include #include #include "config.h" #include "SDL/SDL.h" #include "SDL/SDL_image.h" #include "SDL/SDL_ttf.h" #ifdef SOUND_ON #include "SDL/SDL_mixer.h" #endif #include "enum.h" #include "Engine.h" #include "Timer.h" #include "Player.h" #include "Room.h" #include "WorldData.h" #include "TextBox.h" #include "Kaos.h" #include "HyperKaos.h" #include "Scene.h" #include "Synergy.h" #include "extern.h" // // graphics primitives // SDL_Surface* loadImage(char* filename) { SDL_Surface* loadedImage = NULL; SDL_Surface* optimizedImage = NULL; loadedImage = IMG_Load(filename); if (loadedImage != NULL) { optimizedImage = SDL_DisplayFormat(loadedImage); SDL_FreeSurface(loadedImage); } return optimizedImage; } void applySurface(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip) { SDL_Rect offset; offset.x = x; offset.y = y; SDL_BlitSurface(source, clip, destination, &offset); } Uint32 getPixel(SDL_Surface* surface, int x, int y) { Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel; return *(Uint32 *)p; } void scaleScreen() { Sint32 x, y; static SDL_Rect superPixel = {0,0, SCALE_FACTOR,SCALE_FACTOR}; switch (SCALE_FACTOR) { case 1: applySurface(0,0,screen,window,NULL); break; default: superPixel.y = 0; for (y = 0; y < SCREEN_HEIGHT; y++) { superPixel.x = 0; for (x = 0; x < SCREEN_WIDTH; x++) { SDL_FillRect(window, &superPixel, getPixel(screen, x, y)); superPixel.x += SCALE_FACTOR; } superPixel.y += SCALE_FACTOR; } break; } } // // sound // #ifdef SOUND_ON Mix_Music* loadBGM(char* filename) { Mix_Music* bgmTrack = Mix_LoadMUS(filename); hasMusic = 1; return bgmTrack; } Mix_Chunk* loadSFX(char* filename) { Mix_Chunk* sfxClip = Mix_LoadWAV(filename); return sfxClip; } #endif // // world // void renderBackground() { applySurface(0, 0, rightHere->spriteSheet, screen, &(rightHere->clip)); animate(rightHere); } void renderForeground() { drawFgObjects1(rightHere); drawPeople(rightHere); drawPlayer(hero); drawFgObjects2(rightHere); } void renderHUD() { SDL_Rect clip; clip.x = bookMark*16;; clip.y = 0; clip.w = 16; clip.h = 16; applySurface(300,160, spellGlyphs, screen, &clip); } void interact() { while(SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: switch (event.key.keysym.sym) { case DPAD_UP: hero->bearing.y = -2; break; case DPAD_LEFT: hero->bearing.x = -2; break; case DPAD_DOWN: hero->bearing.y = 2; break; case DPAD_RIGHT: hero->bearing.x = 2; break; case A_BUTTON: actionbutton = 1; break; case B_BUTTON: spellbutton = 1; break; case L_BUTTON: bookMark--; if (bookMark == -1) bookMark = 9; while (!spellKnowledge[bookMark]) { bookMark--; } break; case R_BUTTON: bookMark++; if (bookMark == 10) bookMark = 0; while (!spellKnowledge[bookMark]) { bookMark++; if (bookMark == 10) bookMark = 0; } break; case PAUSE_BUTTON: pausemenu(); break; case FS_BUTTON: toggleFullscreen(); break; default: break; } break; case SDL_KEYUP: switch( event.key.keysym.sym ) { case DPAD_UP: if (hero->bearing.y < 0) { hero->bearing.y = 0; } break; case DPAD_LEFT: if (hero->bearing.x < 0) { hero->bearing.x = 0 ; } break; case DPAD_DOWN: if (hero->bearing.y > 0) { hero->bearing.y = 0; } break; case DPAD_RIGHT: if (hero->bearing.x > 0) { hero->bearing.x = 0; } break; case A_BUTTON: actionbutton = 0; break; case B_BUTTON: spellbutton = 0; default: break; } break; case SDL_QUIT: quit = 1; playing = 0; break; } } } void kListen() { if (spellbutton) { spellFlag = bookMark; run(spellBook[spellFlag]); synergize(); spellFlag = -1; } if (kaosFlag >= 0) { run(rightHere->eventTriggers[kaosFlag]); kaosFlag = -1; } } // // system // int init(int argc, char* args[]) { printf("Initializing SDL\n"); #ifdef SOUND_ON if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO) == -1) return 0; printf("Initialized\nOpening soundsystem\n"); if (Mix_OpenAudio(22050,MIX_DEFAULT_FORMAT, 2, 4096) == -1) return 0; printf("Soundsystem open\nCreating window\n"); #else if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) == -1) return 0; printf("Initialized\nCreating window\n"); #endif if (argc >= 2) { if (strcmp(args[1], "-w")) { window = SDL_SetVideoMode( SCREEN_WIDTH*SCALE_FACTOR, SCREEN_HEIGHT*SCALE_FACTOR, 32, SDL_FULLSCREEN|SDL_HWSURFACE); fullscreen = 1; } else { window = SDL_SetVideoMode( SCREEN_WIDTH*SCALE_FACTOR, SCREEN_HEIGHT*SCALE_FACTOR, 32, SDL_HWSURFACE|SDL_RESIZABLE); } } else { window = SDL_SetVideoMode( SCREEN_WIDTH*SCALE_FACTOR, SCREEN_HEIGHT*SCALE_FACTOR, 32, SDL_FULLSCREEN|SDL_HWSURFACE); fullscreen = 1; } screen = loadImage("assets/img/rawscreen.png"); if (window == NULL || screen == NULL) return 0; SDL_ShowCursor(0); SDL_WM_SetCaption("Kaos Mage's Infinite Sidequest", NULL); printf("Window created\nInitializing fonts\n"); if (TTF_Init() == -1) return 0; printf("Fonts initialized\nInitializing data\n"); menuBG = newRoom("assets/img/backgrounds/mainmenu.png", 1); //font = TTF_OpenFont("assets/ocr-b.pxl8.ttf", 9); font = TTF_OpenFont("assets/mecha.ttf", 13); saveMenu = loadImage("assets/img/windows/saveMenu.gif"); textBoxBG = loadImage("assets/img/windows/textBox.gif"); choiceBox = loadImage("assets/img/windows/choiceBox.gif"); nextArrow = loadImage("assets/img/windows/nextButton.gif"); selectArrow = loadImage("assets/img/windows/selectArrow.gif"); loadingTxt = TTF_RenderText_Solid(font, "loading map data...", textColor); spellGlyphs = loadImage("assets/img/hud/spellbook.png"); SDL_SetAlpha(spellGlyphs, SDL_SRCALPHA|SDL_RLEACCEL, 156); hero = newPlayer("assets/img/characters/kmage.png", 160, 90); mapData = malloc(64*sizeof(Room*)); mapBuffer= malloc(64*sizeof(Room*)); dialogueData = malloc(124*sizeof(Room*)); #ifdef SOUND_ON bgmData = malloc(8*sizeof(Mix_Music*)); sfxData = malloc(24*sizeof(Mix_Chunk*)); #endif kaosData = malloc(124*sizeof(Kaos*)); theatre = malloc(8*sizeof(Scene*)); writeSpellBook(); printf("Init complete\n"); return 1; } void writeSpellBook() { HyperKaos* testSpell = newHyperKaos(1,0,0,0,0,0); Kaos* stopPlayer = newManip("hero, xSpd 0, ySpd 0"); Kaos* beam = newSpell_Beam(); addKaos(testSpell, stopPlayer); addKaos(testSpell, beam); spellBook = malloc(4*sizeof(HyperKaos**)); spellBook[0] = testSpell; testSpell = newHyperKaos(1,0,0,0,0,0); Kaos* stopPlayer2 = newManip("hero, xSpd 0, ySpd 0"); Kaos* flash = newSpell_Flash(); addKaos(testSpell, stopPlayer2); addKaos(testSpell, flash); spellBook[1] = testSpell; } void burnSpellBook() { cleanHyperKaos(spellBook[0]); deleteHyperKaos(spellBook[0]); cleanHyperKaos(spellBook[1]); deleteHyperKaos(spellBook[1]); free(spellBook); } void toggleFullscreen() { if (!fullscreen) { SDL_SetVideoMode(SCREEN_WIDTH*SCALE_FACTOR, SCREEN_HEIGHT*SCALE_FACTOR, 32, SDL_FULLSCREEN|SDL_HWSURFACE); fullscreen = 1; } else { SDL_SetVideoMode(SCREEN_WIDTH*SCALE_FACTOR, SCREEN_HEIGHT*SCALE_FACTOR, 32, SDL_HWSURFACE|SDL_RESIZABLE); fullscreen = 0; } } void timeDilation() { int i = getTicks(&fps); if (i < 1000 / 30) SDL_Delay(1000/30 - i); } void frameAdvance() { scaleScreen(); SDL_Flip(window); timeDilation(); } void cleanup() { if(fullscreen) toggleFullscreen(); unloadData(thisChunk); printf("Freeing global data\n"); killPlayer(hero); deleteRoom(menuBG); free(mapData); free(kaosData); free(dialogueData); #ifdef SOUND_ON free(bgmData); free(sfxData); #endif free(theatre); burnSpellBook(); SDL_FreeSurface(textBoxBG); SDL_FreeSurface(nextArrow); SDL_FreeSurface(saveMenu); SDL_FreeSurface(selectArrow); SDL_FreeSurface(loadingTxt); SDL_FreeSurface(screen); SDL_FreeSurface(window); printf("Closing SDL\n"); #ifdef SOUND_ON Mix_CloseAudio(); #endif TTF_CloseFont(font); TTF_Quit(); SDL_Quit(); printf("Cleanup complete\n"); } void intro() { SDL_Color black = {0,0,0}; SLayer* nebula = newSLayer(loadImage("assets/img/backgrounds/presents.png"), 0,0,0,0,255); SLayer* fogF = newSLayer(loadImage("assets/img/fx/fog.png"), 0,0,-1,0,128); SLayer* fogB = newSLayer(loadImage("assets/img/fx/plasma.png"), -320,0,1,0,56); SLayer* presents = newSLayer(TTF_RenderText_Solid(font, "nilFM presents", textColor), 120,84,0,0,128); SLayer* menuTransition = newSLayer(loadImage("assets/img/backgrounds/mainmenu.png"),0,0,0,0,255); Scene* intro = newScene(30,30, 200, black, black); Scene* transition = newScene(30,0,30, black, black); buildScene(intro, nebula); buildScene(intro, fogB); buildScene(intro, fogF); buildScene(intro, presents); buildScene(transition, menuTransition); playScene(intro); playScene(transition); deleteScene(intro); deleteScene(transition); } void mainmenu() { int menucounter = 0; int select = 0; FILE* saveData = fopen("sram", "r"); int level = 1; int roomNo = 0; int xPos = 180; int yPos = 90; long long int eventState = 2; warpto(menuBG); #ifdef SOUND_ON if (menuBGM == NULL) Mix_HaltMusic(); else Mix_PlayMusic(menuBGM, -1); #endif while (!select) { timeStart(&fps); renderBackground(); while(SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: switch (event.key.keysym.sym) { case DPAD_UP: menucounter--; break; case DPAD_DOWN: menucounter++; break; case A_BUTTON: select = 1; break; case FS_BUTTON: toggleFullscreen(); break; default: break; } break; case SDL_QUIT: quit = 1; playing = 0; select = 1; break; } if (menucounter == 3) menucounter = 0; if (menucounter == -1) menucounter = 2; } switch (menucounter) { case 0: applySurface(230, 61, selectArrow, screen, NULL); break; case 1: applySurface(230, 83, selectArrow, screen, NULL); break; case 2: applySurface(230, 105, selectArrow, screen, NULL); } frameAdvance(); } if (quit) return; switch (menucounter) { case 0: playing = 1; thisChunk = LEVEL1; nextChunk = LEVEL1; savestate = eventState; bufferData(LEVEL1); pushBufferData(); warpto(mapData[0]); hero->point.x = 160; hero->point.y = 90; fclose(saveData); break; case 1: if (saveData) { fscanf(saveData, "%d %d %d %d %lld", &level, &roomNo, &xPos, &yPos, &eventState); } playing = 1; thisChunk = (enum dataChunks)(level); nextChunk = (enum dataChunks)(level); savestate = eventState; bufferData((enum dataChunks)(level)); pushBufferData(); hero->point.x = xPos; hero->point.y = yPos; warpto(mapData[roomNo]); fclose(saveData); printf("Loaded save: level %d, room %d (%d,%d) state: %lld\n", level, roomNo, xPos, yPos, eventState); break; case 2: quit = 1; playing = 0; fclose(saveData); } } void pausemenu() { int paused = 1; int menucounter = 0; int select = 0; int roomNo; int i; FILE* saveData; hero->bearing.x = 0; hero->bearing.y = 0; #ifdef SOUND_ON Mix_VolumeMusic(MIX_MAX_VOLUME/3); #endif for (i = 0; i < 64; i++) { if (rightHere == mapData[i]) { roomNo = i; break; } } while (paused) { timeStart(&fps); applySurface(60, 45, saveMenu ,screen, NULL); while(SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: switch (event.key.keysym.sym) { case DPAD_UP: menucounter--; break; case DPAD_DOWN: menucounter++; break; case A_BUTTON: select = 1; break; case PAUSE_BUTTON: paused = 0; break; case FS_BUTTON: toggleFullscreen(); break; default: break; } break; case SDL_QUIT: quit = 1; paused = 0; playing = 0; break; } if (menucounter == 3) menucounter = 0; if (menucounter == -1) menucounter = 2; } switch (menucounter) { case 0: applySurface(93, 60, selectArrow, screen, NULL); break; case 1: applySurface(93, 82, selectArrow, screen, NULL); break; case 2: applySurface(93, 104, selectArrow, screen, NULL); } if (select) { switch (menucounter) { case 0: { printf("Saving data: level %d, room %d (%d,%d) state: %lld\n", thisChunk, roomNo, hero->point.x, hero->point.y, savestate); saveData = fopen("sram", "w"); fprintf(saveData, "%d %d %d %d %lld", (int)(thisChunk), roomNo, hero->point.x, hero->point.y, savestate); paused = 0; fclose(saveData); break; } case 1: { printf("Saving data: level %d, room %d (%d,%d) state: %lld\n", thisChunk, roomNo, hero->point.x, hero->point.y, savestate); saveData = fopen("sram", "w"); fprintf(saveData, "%d %d %d %d %lld", (int)(thisChunk), roomNo, hero->point.x, hero->point.y, savestate); paused = 0; playing = 0; fclose(saveData); break; } case 2: paused = 0; playing = 0; break; } } frameAdvance(); } #ifdef SOUND_ON Mix_VolumeMusic(MIX_MAX_VOLUME); #endif }