hyperkaos/Engine.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:
thisChunk = LEVEL1;
nextChunk = LEVEL1;
savestate = eventState;
bufferData(LEVEL1);
pushBufferData();
warpto(mapData[0]);
hero->point.x = 160;
hero->point.y = 90;
playing = 1;
fclose(saveData);
break;
case 1:
if (saveData)
{
fscanf(saveData, "%d %d %d %d %lld", &level, &roomNo, &xPos, &yPos, &eventState);
}
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]);
playing = 1;
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
}