680 lines
14 KiB
C
680 lines
14 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#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/charriot.ttf", 10);
|
|
|
|
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, 0,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, 0,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
|
|
|
|
}
|