From 92419b025aa5d82bb7592281af5505ff931c2e58 Mon Sep 17 00:00:00 2001 From: andyq Date: Mon, 20 Jan 2003 23:11:56 +0000 Subject: Initial Revision --- (limited to 'noncore/games/sfcave-sdl') diff --git a/noncore/games/sfcave-sdl/animatedimage.cpp b/noncore/games/sfcave-sdl/animatedimage.cpp new file mode 100644 index 0000000..d9d6ff6 --- a/dev/null +++ b/noncore/games/sfcave-sdl/animatedimage.cpp @@ -0,0 +1,68 @@ +#include "SDL.h" +#include "SDL_image.h" + +#include "constants.h" +#include "animatedimage.h" + +AnimatedImage :: AnimatedImage( QString file, int nFrames ) +{ + nrFrames = nFrames; + currentFrame = 0; + + // Load image + image = IMG_Load( (const char *)file.c_str() ); + if ( !image ) + { + nrFrames = 0; + image = 0; + return; + } + + SDL_SetColorKey(image, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB( image->format, 0, 0, 0 ) ); +// image = SDL_DisplayFormat( tmp ); + +// SDL_FreeSurface( tmp ); + frameWidth = image->w/nrFrames; + frameHeight = image->h; +} + +AnimatedImage :: ~AnimatedImage() +{ + if ( image != 0 ) + SDL_FreeSurface( image ); +} + +bool AnimatedImage :: nextFrame() +{ + bool rc = true; + currentFrame ++; + if ( currentFrame >= nrFrames ) + { + currentFrame --; + rc = false; + } + + return rc; +} + +void AnimatedImage :: draw( SDL_Surface *screen, int x, int y ) +{ + SDL_Rect dst; + dst.x = currentFrame * frameWidth; + dst.y = 0; + dst.w = frameWidth; + dst.h = frameHeight; + + SDL_Rect dst2; + dst2.x = x - (frameWidth/2); + dst2.y = y - (frameHeight/2);; + SDL_BlitSurface( image, &dst, screen, &dst2 ); +} + +bool AnimatedImage :: AtEnd() +{ + if ( currentFrame +1 >= nrFrames || image == 0 ) + return true; + return false; +} + diff --git a/noncore/games/sfcave-sdl/animatedimage.h b/noncore/games/sfcave-sdl/animatedimage.h new file mode 100644 index 0000000..1b38e6d --- a/dev/null +++ b/noncore/games/sfcave-sdl/animatedimage.h @@ -0,0 +1,25 @@ +#ifndef __ANIMATED_IMAGE_H +#define __ANIMATED_IMAGE_H + +#include "SDL.h" + +class AnimatedImage +{ +public: + AnimatedImage( QString file, int nFrames ); + ~AnimatedImage(); + + bool nextFrame(); + void draw( SDL_Surface *screen, int x, int y ); + bool AtEnd(); + void reset() { currentFrame = 0; } +private: + + SDL_Surface *image; + int nrFrames; + int currentFrame; + + int frameWidth; + int frameHeight; +}; +#endif diff --git a/noncore/games/sfcave-sdl/bfont.cpp b/noncore/games/sfcave-sdl/bfont.cpp new file mode 100644 index 0000000..0f29104 --- a/dev/null +++ b/noncore/games/sfcave-sdl/bfont.cpp @@ -0,0 +1,443 @@ +/***********************************************************/ +/* */ +/* BFONT.c v. 1.0.2 - Billi Font Library by Diego Billi */ +/* BFONT++ C++ port by Gianluigi Davassi */ +/***********************************************************/ +#include "iostream" +using namespace std; +#include "string.h" +#include "stdlib.h" +#include "stdarg.h" + +#include "SDL_image.h" +#include "bfont.h" + +void BFont::InitFont() +{ + int x = 0, i = '!'; + Uint32 sentry = GetPixel(0,0); + + if (SDL_MUSTLOCK(Surface)) + SDL_LockSurface(Surface); + + while ( x < (Surface->w-1)) + { + if(GetPixel(x,0) != sentry) + { + Chars[i].x = x; + Chars[i].y = 1; + Chars[i].h = Surface->h; + for (; GetPixel(x, 0) != sentry && x < (Surface->w); ++x) ; + Chars[i].w = (x - Chars[i].x); + i++; + } else + { x++; } + } + Chars[' '].x = 0; + Chars[' '].y = 0; + Chars[' '].h = Surface->h; + Chars[' '].w = Chars['!'].w; + + if (SDL_MUSTLOCK(Surface)) + SDL_UnlockSurface(Surface); + + h = Surface->h; + + SDL_SetColorKey(Surface, SDL_SRCCOLORKEY, GetPixel(0, Surface->h-1)); +} + + +/* Load the font and stores it in the BFont_Info structure */ +void BFont::LoadFont (const char *filename) +{ + SDL_Surface *surface(NULL); + int x; + // tutta roba inutile in C++.... :-) + /* BFont_Info *Font=NULL; + Font = (BFont_Info *) malloc(sizeof(BFont_Info));*/ + + if ((filename != NULL ) && (this != NULL)) + { + surface = IMG_Load( filename ); + + if (surface != NULL) + { + Surface = surface; + for (x=0; x<256; x++) + { + Chars[x].x = 0; + Chars[x].y = 0; + Chars[x].h = 0; + Chars[x].w = 0; + } + InitFont(); // Init the font + } + } + else + { + cerr << "Error! The font has not been loaded!" << endl; + } +} + +BFont * BFont :: SetFontColor(Uint8 r, Uint8 g, Uint8 b) +{ + int x,y; + + BFont *newfont; + SDL_Surface *surface = NULL; + + Uint32 pixel; + Uint8 old_r, old_g, old_b; + Uint8 new_r, new_g, new_b; + Uint32 color_key; + + newfont = new BFont(NULL); + + if (newfont != NULL) { + + newfont->h = h; + + for (x=0; x<256; x++) { + newfont->Chars[x].x = Chars[x].x; + newfont->Chars[x].y = Chars[x].y; + newfont->Chars[x].h = Chars[x].h; + newfont->Chars[x].w = Chars[x].w; + } + + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, Surface->w, Surface->h, 32, + 0x000000ff,0x0000ff00, 0x00ff0000, 0xff000000); + if (surface != NULL) { + + if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface); + if (SDL_MUSTLOCK(Surface)) SDL_LockSurface(Surface); + + color_key = xGetPixel(Surface, 0, Surface->h-1); + + printf("looking...\n"); + for( x=0; x < Surface->w; x++) { + for( y=0; y < Surface->h; y++) { + old_r = old_g = old_b = 0; + pixel = xGetPixel(Surface,x,y); + + if (pixel != color_key) { + SDL_GetRGB(pixel, Surface->format, &old_r,&old_g,&old_b); + + new_r = (Uint8) ((old_r * r) / 255); + new_g = (Uint8) ((old_g * g) / 255); + new_b = (Uint8) ((old_b * b) / 255); + + pixel = SDL_MapRGB(surface->format,new_r,new_g,new_b); + } + PutPixel(surface,x,y,pixel); + } + } + printf("unlooking...\n"); + if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); + if (SDL_MUSTLOCK(Surface)) SDL_UnlockSurface(Surface); + + SDL_SetColorKey(surface, SDL_SRCCOLORKEY, color_key); + } + + newfont->Surface = surface; + } + return newfont; +} + + +/* Puts a single char on the surface with the specified font */ +int BFont::PutChar(SDL_Surface *screen, int x, int y, char c) +{ + int r=0; + SDL_Rect dest; + + dest.w = CharWidth(' '); + dest.h = FontHeight(); + dest.x = x; + dest.y = y; + + if (c != ' ') + SDL_BlitSurface( Surface, &Chars[c], screen, &dest); + + r = dest.w; + return r; +} + + +void BFont::PutString(SDL_Surface *screen, int x, int y, const char *text) +{ + int i(0); + while (text[i]!='\0') + { + x += PutChar(screen,x,y,text[i]); + i++; + } +} + +int BFont::TextWidth(const char *text) +{ + int i(0),x(0); + + while (text[i]!='\0') + { + x += CharWidth(text[i]); + i++; + } + return x; +} + + +/* counts the spaces of the strings */ +int BFont::count (const char *text) +{ + char *p(NULL); + int pos(-1),i(0); + + /* Calculate the space occupied by the text without spaces */ + while ((p=strchr(&text[pos+1],' ')) != NULL) + { + i++; + pos = p - text; + } + return i; +} + + +void BFont::JustifiedPutString( SDL_Surface *screen, int y, const char *text) +{ + int spaces(0),gap,single_gap,dif; + char *strtmp,*p; + int pos(-1),xpos(0); + + + if (strchr(text,' ') == NULL) + { + PutString(screen, 0, y, text); + } + else { + gap = (screen->w-1) - TextWidth(text); + + if (gap <= 0) { + PutString(screen, 0,y,text); + } else { + spaces = count(text); + dif = gap % spaces; + single_gap = (gap - dif) / spaces; + xpos=0; + pos = -1; + while ( spaces > 0 ) + { + p = strstr(&text[pos+1]," "); + strtmp = NULL; + strtmp = (char *) calloc ( (p - &text[pos+1]) + 1,sizeof(char)); + if (strtmp != NULL) + { + strncpy (strtmp, &text[pos+1], (p - &text[pos+1])); + PutString(screen, xpos, y, strtmp); + xpos = xpos + TextWidth(strtmp) + single_gap + CharWidth(' '); + if (dif >= 0) + { + xpos ++; + dif--; + } + pos = p - text; + spaces--; + free(strtmp); + } + } + strtmp = NULL; + strtmp = (char *) calloc ( strlen( &text[pos+1]) + 1,sizeof(char)); + + if (strtmp != NULL) { + strncpy (strtmp, &text[pos+1], strlen( &text[pos+1])); + PutString(screen, xpos, y, strtmp); + free(strtmp); + } + } + } +} + + +void BFont::CenteredPutString(SDL_Surface *screen, int y, const char *text) +{ + printf( "xpos - %d, %d <%s>\n", screen->w/2-TextWidth(text)/2, TextWidth(text), text ); + PutString( screen, screen->w/2-TextWidth(text)/2, y, text); +} + + +void BFont::RightPutString(SDL_Surface *screen, int y, const char *text) +{ + PutString( screen, screen->w - TextWidth(text) - 1, y, text); +} + +void BFont::LeftPutString(SDL_Surface *screen, int y, const char *text) +{ + PutString( screen, 0, y, text); +} + +/******/ + +void BFont::PrintString (SDL_Surface *screen, int x, int y, char *fmt, ...) +{ + va_list args; + char *temp; + va_start (args,fmt); + + if ( (temp = (char *) malloc(1000+1)) != NULL) { + vsprintf(temp,fmt,args); + PutString(screen, x, y, temp); + free (temp); + } + va_end(args); +} + +void BFont::CenteredPrintString(SDL_Surface *screen, int y, char *fmt, ...) +{ + va_list args; + char *temp; + va_start (args,fmt); + + if ( (temp = (char *) malloc(1000+1)) != NULL) { + vsprintf(temp,fmt,args); + CenteredPutString(screen, y, temp); + free (temp); + } + va_end(args); +} + +void BFont::RightPrintString(SDL_Surface *screen, int y, char *fmt, ...) +{ + va_list args; + char *temp; + va_start (args,fmt); + + if ( (temp = (char *) malloc(1000+1)) != NULL) { + vsprintf(temp,fmt,args); + RightPutString(screen, y, temp); + free (temp); + } + va_end(args); +} + +void BFont::LeftPrintString( SDL_Surface *screen, int y, char *fmt, ...) +{ + va_list args; + char *temp; + va_start (args,fmt); + + if ( (temp = (char *) malloc(1000+1)) != NULL) { + vsprintf(temp,fmt,args); + LeftPutString(screen, y, temp); + free (temp); + } + va_end(args); +} + +void BFont::JustifiedPrintString( SDL_Surface *screen, int y, char *fmt, ...) +{ + va_list args; + char *temp; + va_start (args,fmt); + + if ( (temp = (char *) malloc(1000+1)) != NULL) { + vsprintf(temp,fmt,args); + JustifiedPutString( screen, y,temp); + free (temp); + } + va_end(args); +} + + +void BFont::PutPixel(SDL_Surface *surface, int x, int y, Uint32 pixel) +{ + int bpp = surface->format->BytesPerPixel; + /* Here p is the address to the pixel we want to set */ + Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; + + switch(bpp) { + case 1: + *p = pixel; + break; + + case 2: + *(Uint16 *)p = pixel; + break; + + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { + p[0] = (pixel >> 16) & 0xff; + p[1] = (pixel >> 8) & 0xff; + p[2] = pixel & 0xff; + } else { + p[0] = pixel & 0xff; + p[1] = (pixel >> 8) & 0xff; + p[2] = (pixel >> 16) & 0xff; + } + break; + + case 4: + *(Uint32 *)p = pixel; + break; + } +} + +Uint32 BFont :: xGetPixel(SDL_Surface *surface, int x, int y) +{ + int bpp = surface->format->BytesPerPixel; + /* Here p is the address to the pixel we want to retrieve */ + Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; + + switch(bpp) { + case 1: + return *p; + + case 2: + return *(Uint16 *)p; + + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) + return p[0] << 16 | p[1] << 8 | p[2]; + else + return p[0] | p[1] << 8 | p[2] << 16; + + case 4: + return *(Uint32 *)p; + + default: + return 0; /* shouldn't happen, but avoids warnings */ + } +} + +Uint32 BFont::GetPixel( Sint32 X, Sint32 Y) +{ + + Uint8 *bits; + Uint32 Bpp; + + if (X<0) puts("x too small in GetPixel!"); + if (X>=Surface->w) puts("x too big in GetPixel!"); + + Bpp = Surface->format->BytesPerPixel; + + bits = ((Uint8 *)Surface->pixels)+Y*Surface->pitch+X*Bpp; + + // Get the pixel + switch(Bpp) { + case 1: + return *((Uint8 *)Surface->pixels + Y * Surface->pitch + X); + break; + case 2: + return *((Uint16 *)Surface->pixels + Y * Surface->pitch/2 + X); + break; + case 3: { // Format/endian independent + Uint8 r, g, b; + r = *((bits)+Surface->format->Rshift/8); + g = *((bits)+Surface->format->Gshift/8); + b = *((bits)+Surface->format->Bshift/8); + return SDL_MapRGB(Surface->format, r, g, b); + } + break; + case 4: + return *((Uint32 *)Surface->pixels + Y * Surface->pitch/4 + X); + break; + } +} diff --git a/noncore/games/sfcave-sdl/bfont.h b/noncore/games/sfcave-sdl/bfont.h new file mode 100644 index 0000000..dee97f1 --- a/dev/null +++ b/noncore/games/sfcave-sdl/bfont.h @@ -0,0 +1,70 @@ + +/************************************************************ + + BFONT v. 1.0.2 - Billi Font Library by Diego Billi + BFONT++ C++ port by Gianluigi Davassi +************************************************************/ + +#ifndef __BFONT_HEADER_H__ +#define __BFONT_HEADER_H__ + +#include +#include "SDL.h" + +class BFont +{ + int h; // font height + SDL_Surface *Surface; // font surface + SDL_Rect Chars[256]; // characters width + const char* name; // font name + + BFont(const BFont&); + + void InitFont(); + int count(const char *text); +public: + + BFont(const char *__filename) // generator bill + : name(__filename) + { LoadFont(__filename); } + + ~BFont() + { SDL_FreeSurface(Surface); } // screen must be free by application + + int FontHeight () // Returns the font height + { return h; } + + void SetFontHeight (int height) // Change the font height + { h = height ; } + + int CharWidth (char c) // Returns the character width of the specified font + { return Chars[c].w; } + + void LoadFont (const char *filename); // Load and store le font in the BFont structure + int PutChar (SDL_Surface *screen, int x, int y, char c); // Write a single character on the "Surface" with the current font + int TextWidth (const char *text ); // Returns the width, in pixels, of the text calculated with the current font + + BFont *SetFontColor(Uint8 r, Uint8 g, Uint8 b); // Returns a new font colored with the color (r,g,b) + + void PutString ( SDL_Surface *screen, int x, int y, const char *text); // Write a string on the "Surface" with the specified font + void LeftPutString ( SDL_Surface *screen, int y, const char *text); // Write a left-aligned string on the "Surface" with the specified font + void CenteredPutString ( SDL_Surface *screen, int y, const char *text); // Write a center-aligned string on the "Surface" with the specified font + void RightPutString ( SDL_Surface *screen, int y, const char *text); // Write a right-aligned string on the "Surface" with the specified font + void JustifiedPutString ( SDL_Surface *screen, int y, const char *text); // Write a justify-aligned string on the "Surface" with the specified font + + // The following functions do the same task but have the classic "printf" sintax + void PrintString ( SDL_Surface *screen, int x, int y, char *fmt, ...); + void CenteredPrintString ( SDL_Surface *screen, int y, char *fmt, ...); + void RightPrintString ( SDL_Surface *screen, int y, char *fmt, ...); + void LeftPrintString ( SDL_Surface *screen, int y, char *fmt, ...); + void JustifiedPrintString ( SDL_Surface *screen, int y, char *fmt, ...); + +private: + Uint32 GetPixel( Sint32 X, Sint32 Y); + Uint32 xGetPixel(SDL_Surface *surface, int x, int y); + void PutPixel( SDL_Surface *,int x, int y, Uint32 pixel); + +}; + +#endif // __BFONT_HEADER_H__ + diff --git a/noncore/games/sfcave-sdl/config.in b/noncore/games/sfcave-sdl/config.in new file mode 100644 index 0000000..9d56c0c --- a/dev/null +++ b/noncore/games/sfcave-sdl/config.in @@ -0,0 +1,5 @@ + config SFCAVE-SDL + boolean "sfcave-sdl" + default "y" + depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE + string "sfcave-sdl (warning: requires libsdl)" diff --git a/noncore/games/sfcave-sdl/constants.h b/noncore/games/sfcave-sdl/constants.h new file mode 100644 index 0000000..8fadae4 --- a/dev/null +++ b/noncore/games/sfcave-sdl/constants.h @@ -0,0 +1,67 @@ +#ifndef __CONSTANTS_H +#define __CONSTANTS_H + +#include +using namespace std; +#define QString string + +#ifdef QWS +#define IMAGES_PATH "/opt/QtPalmtop/pics/sfcave/data/" +#define SOUND_PATH "/opt/QtPalmtop/sounds/sfcave/" +#else +#define IMAGES_PATH "./images/" +#define SOUND_PATH "./sounds/" +#endif + +// Width and height of app +#define WIDTH 240 +#define HEIGHT 320 + +//Number of map segments +#define MAPSIZE 51 + +// Maximum number of blocks visible on screen at any one time +#define BLOCKSIZE 6 + +// length of players trail +#define TRAILSIZE 60 + +// Game States +#define STATE_QUIT -1 +#define STATE_PLAYING 0 +#define STATE_CRASHING 1 +#define STATE_CRASHED 2 +#define STATE_NEWGAME 3 +#define STATE_MENU 4 +#define STATE_REPLAY 5 +#define STATE_HELP 6 + +// Menu Options +#define MENU_STARTGAME 1 +#define MENU_REPLAYS 2 +#define MENU_OPTIONS 3 +#define MENU_HELP 4 +#define MENU_QUIT 5 +#define MENU_PLAY_REPLAY 6 +#define MENU_LOAD_REPLAY 7 +#define MENU_SAVE_REPLAY 8 +#define MENU_BACK 9 +#define MENU_GAME_TYPE 10 +#define MENU_DIFFICULTY 11 +#define MENU_CLEAR_SCORES 12 +#define MENU_GAME_SFCAVE 13 +#define MENU_GAME_GATES 14 +#define MENU_GAME_FLY 15 +#define MENU_DIFFICULTY_EASY 16 +#define MENU_DIFFICULTY_NORMAL 17 +#define MENU_DIFFICULTY_HARD 18 +#define MENU_SOUNDS 19 +#define MENU_SOUND_ON 20 +#define MENU_SOUND_OFF 21 +#define MENU_MUSIC_ON 22 +#define MENU_MUSIC_OFF 23 + +// Sounds +#define SND_EXPLOSION 0 +#define SND_THRUST 1 +#endif diff --git a/noncore/games/sfcave-sdl/fly_game.cpp b/noncore/games/sfcave-sdl/fly_game.cpp new file mode 100644 index 0000000..f5ab401 --- a/dev/null +++ b/noncore/games/sfcave-sdl/fly_game.cpp @@ -0,0 +1,103 @@ +#include "SDL_gfxPrimitives.h" + +#include "constants.h" +#include "fly_game.h" +#include "random.h" + +FlyGame :: FlyGame( SFCave *p, int w, int h, int diff ) + : Game( p, w, h, diff ) +{ + gameName = "Fly"; + difficulty = MENU_DIFFICULTY_EASY; + + terrain = new FlyTerrain( w, h ); + player = new Player( w, h ); + highScore = 0; +} + +FlyGame :: ~FlyGame() +{ +} + +void FlyGame :: init() +{ + Game :: init(); + + switch( difficulty ) + { + case MENU_DIFFICULTY_EASY: + player->setMovementInfo( 0.3, 0.2, 1.5, 1.5 ); + break; + case MENU_DIFFICULTY_NORMAL: + player->setMovementInfo( 0.35, 0.4, 2.5, 3 ); + break; + case MENU_DIFFICULTY_HARD: + player->setMovementInfo( 0.4, 0.6, 4, 5 ); + break; + } + + startScoring = false; +} + +void FlyGame :: update( int state ) +{ + Game::update( state ); + + if ( state == STATE_PLAYING ) + { + + if ( nrFrames % 3 == 0 ) + { + int diff = terrain->getMapBottom( 10 ) - player->getY(); + int tmpScore = ((FlyTerrain *)terrain)->getScore( 1, diff ); +// printf( "diff - %d score - %d\n", diff, tmpScore ); + if ( !startScoring ) + { + if ( tmpScore > 0 ) + startScoring = true; + } + + if ( startScoring ) + { + // Update score + // get distance between landscape and ship + + // the closer the difference is to 0 means more points + score += tmpScore; + } + } + + if ( checkCollisions() ) + { +// printf( "Crashed!\n" ); + parent->changeState( STATE_CRASHING ); + return; + } + + // Game logic goes here + terrain->moveTerrain( 5 ); + player->move( press ); + } +} + +void FlyGame :: draw( SDL_Surface *screen ) +{ + Game::preDraw( screen ); + + // Screen drawing goes here + terrain->drawTerrain( screen ); + + player->draw( screen ); + + Game::draw( screen ); +} + + +bool FlyGame :: checkCollisions() +{ + bool ret = false; + + // Check collision with landscape + + return terrain->checkCollision( player->getX(), player->getY(), player->getHeight() ); +} diff --git a/noncore/games/sfcave-sdl/fly_game.h b/noncore/games/sfcave-sdl/fly_game.h new file mode 100644 index 0000000..1ab081a --- a/dev/null +++ b/noncore/games/sfcave-sdl/fly_game.h @@ -0,0 +1,28 @@ +#ifndef __FLY_GAME_H +#define __FLY_GAME_H + +#include "sfcave.h" +#include "flyterrain.h" +#include "player.h" +#include "game.h" +#include "SDL.h" + +class FlyGame : public Game +{ +public: + FlyGame( SFCave *p, int w, int h, int diff ); + ~FlyGame(); + + void init(); + void update( int state ); + void draw( SDL_Surface *screen ); + +private: + +// int movePlayer; + bool startScoring; + + bool checkCollisions(); +}; + +#endif diff --git a/noncore/games/sfcave-sdl/flyterrain.cpp b/noncore/games/sfcave-sdl/flyterrain.cpp new file mode 100644 index 0000000..b1b8db5 --- a/dev/null +++ b/noncore/games/sfcave-sdl/flyterrain.cpp @@ -0,0 +1,103 @@ + +#include "SDL_gfxPrimitives.h" + +#include "constants.h" +#include "flyterrain.h" +#include "random.h" + + +int FlyTerrain :: flyScoreZones[][3] = { { 0, 20, 5 }, + { 20, 30, 2 }, + { 30, 40, 0 }, + { 40, 100, -1 }, + { 100, 300, -2 }, + { -1, -1, -1 } }; + +FlyTerrain :: FlyTerrain( int w, int h ) + : Terrain( w, h, false, true ) +{ + showScoreZones = true; +} + +FlyTerrain :: ~FlyTerrain() +{ +} + +void FlyTerrain :: setPoint( int point ) +{ + static int fly_difficulty_levels[] = { 5, 10, 15 }; + if ( nextInt(100) >= 75 ) + dir *= -1; + + int prevPoint = mapBottom[point-1]; + + int nextPoint = prevPoint + (dir * nextInt( fly_difficulty_levels[0] ) ); + + if ( nextPoint > sHeight ) + { + nextPoint = sHeight; + dir *= -1; + } + else if ( nextPoint < maxHeight ) + { + nextPoint = maxHeight; + dir *= 1; + } + + mapBottom[point] = nextPoint; +} + +void FlyTerrain :: drawTerrain( SDL_Surface *screen ) +{ + Terrain::drawTerrain( screen ); + int tmpOffset = offset + speed*segSize; + + for ( int i = 0 ; i < MAPSIZE -1; ++i ) + { + + if ( showScoreZones ) + { + int r = 0; + int g = 0; + int b = 0; + for ( int j = 1 ; flyScoreZones[j][0] != -1 ; ++j ) + { + if ( flyScoreZones[j][2] == 0 ) + { + g = 255; + b = r = 0; + } + else if ( flyScoreZones[j][2] < 0 ) + { + r = 255; + b = g = 0; + } + else + { + b = 255; + r = g = 0; + } + + lineRGBA( screen, (i*segSize) - tmpOffset, mapBottom[i]-flyScoreZones[j][0], ((i+1)*segSize)-tmpOffset, mapBottom[i+1]-flyScoreZones[j][0], r, g, b, 255 ); + + } + + } + } +} + +int FlyTerrain :: getScore( int difficulty, int dist ) +{ + int score = 0; + for ( int i = 0 ; flyScoreZones[i][0] != -1 ; ++i ) + { + if ( flyScoreZones[i][0] <= dist && flyScoreZones[i][1] > dist ) + { + score = flyScoreZones[i][2]; + break; + } + } + + return score; +} + diff --git a/noncore/games/sfcave-sdl/flyterrain.h b/noncore/games/sfcave-sdl/flyterrain.h new file mode 100644 index 0000000..63b5731 --- a/dev/null +++ b/noncore/games/sfcave-sdl/flyterrain.h @@ -0,0 +1,29 @@ +#ifndef __FLYTERRAIN_H +#define __FLYTERRAIN_H + +#include + +#include "terrain.h" + +class FlyTerrain : public Terrain +{ +public: + FlyTerrain( int w, int h ); + ~FlyTerrain(); + + void drawTerrain( SDL_Surface *screen ); + int getScore( int difficulty, int dist ); + + void displayScoreZones( bool val ) { showScoreZones = val; } + +protected: + bool showScoreZones; + + static int flyScoreZones[][3]; + + void setPoint( int point ); +}; + + +#endif + diff --git a/noncore/games/sfcave-sdl/font.cpp b/noncore/games/sfcave-sdl/font.cpp new file mode 100644 index 0000000..2976d48 --- a/dev/null +++ b/noncore/games/sfcave-sdl/font.cpp @@ -0,0 +1,72 @@ +#include "font.h" + +#include "constants.h" + +BFont *FontHandler :: menuSelFont; +BFont *FontHandler :: menuUnSelFont; +BFont *FontHandler :: whiteFont; +BFont *FontHandler :: colouredFont; +BFont *FontHandler :: helpFont; + +void FontHandler :: init() +{ + // Load font images + // Convert to fonts + menuSelFont = new BFont( IMAGES_PATH "sel_menu_font.bmp" ); + menuUnSelFont = new BFont( IMAGES_PATH "unsel_menu_font.bmp" ); + whiteFont = new BFont( IMAGES_PATH "score_font.bmp" ); + helpFont = new BFont( IMAGES_PATH "help_font.bmp" ); + colouredFont = 0; +} + +void FontHandler :: cleanUp() +{ + delete menuSelFont; + delete menuUnSelFont; + delete whiteFont; + delete helpFont; + + if ( colouredFont ) + delete colouredFont; +} + +int FontHandler :: TextWidth( int font, const char *text ) +{ + return getFont( font )->TextWidth( text ); +} + +int FontHandler :: FontHeight( int font ) +{ + return getFont( font )->FontHeight(); +} + +void FontHandler :: draw( SDL_Surface *screen, int font, const char *text, int x, int y ) +{ + if ( x == -1 ) + getFont( font )->CenteredPutString( screen, y, text ); + else + getFont( font )->PutString( screen, x, y, text ); +} + +void FontHandler :: changeColor( int font, int r, int g, int b ) +{ + if ( colouredFont ) + delete colouredFont; + + colouredFont = getFont( font )->SetFontColor( r, g, b ); +} + + +BFont *FontHandler :: getFont( int font ) +{ + if ( font == FONT_MENU_HIGHLIGHTED ) + return menuSelFont; + else if ( font == FONT_MENU_UNHIGHLIGHTED ) + return menuUnSelFont; + else if ( font == FONT_COLOURED_TEXT ) + return colouredFont; + else if ( font == FONT_HELP_FONT ) + return helpFont; + else + return whiteFont; +} diff --git a/noncore/games/sfcave-sdl/font.h b/noncore/games/sfcave-sdl/font.h new file mode 100644 index 0000000..e5bb707 --- a/dev/null +++ b/noncore/games/sfcave-sdl/font.h @@ -0,0 +1,33 @@ +#ifndef __FONT_H +#define __FONT_H + +#include "SDL.h" +#include "bfont.h" + +#define FONT_MENU_HIGHLIGHTED 1 +#define FONT_MENU_UNHIGHLIGHTED 2 +#define FONT_WHITE_TEXT 3 +#define FONT_COLOURED_TEXT 4 +#define FONT_HELP_FONT 5 + +class FontHandler +{ +public: + static void init(); + static void cleanUp(); + + static int TextWidth( int font, const char *text ); + static int FontHeight( int font ); + static void draw( SDL_Surface *screen, int font, const char *text, int x, int y ); + static void changeColor( int font, int r, int g, int b ); + + static BFont *getFont( int font ); +private: + static BFont *menuSelFont; + static BFont *menuUnSelFont; + static BFont *whiteFont; + static BFont *colouredFont; + static BFont *helpFont; +}; + +#endif diff --git a/noncore/games/sfcave-sdl/game.cpp b/noncore/games/sfcave-sdl/game.cpp new file mode 100644 index 0000000..a644696 --- a/dev/null +++ b/noncore/games/sfcave-sdl/game.cpp @@ -0,0 +1,332 @@ +#include +#include + +#include +#include + +#include "font.h" + +#include "constants.h" +#include "game.h" +#include "player.h" +#include "random.h" +#include "sound.h" +#include "stringtokenizer.h" + +#include "sfcave_game.h" +#include "gates_game.h" +#include "fly_game.h" +#include "starfield.h" + +Game :: Game( SFCave *p, int w, int h, int diff ) +{ + parent = p; + sHeight = h; + sWidth = w; + difficulty = diff; + replayIt = 0; + replay = false; + terrain = 0; + player = 0; + thrustChannel = -1; +} + +Game :: ~Game() +{ + if ( terrain ) + delete terrain; + + if ( player ) + delete player; + + replayList.clear(); +} + +void Game :: init() +{ + if ( replay ) + { + setSeed( currentSeed ); + replayIt = replayList.begin(); + } + else + { + setSeed( -1 ); + replayList.clear(); + } + + score = 0; + nrFrames = 0; + press = false; + + // Load highscore + string key = getGameName() + "_" + getGameDifficultyText() + "_highscore"; + highScore = atoi( parent->loadSetting( key, "0" ).c_str() ); + + terrain->initTerrain(); + player->init(); +} + +void Game :: handleKeys( SDL_KeyboardEvent &key ) +{ + if ( !replay && key.keysym.sym == SDLK_SPACE ) + { + if ( key.type == SDL_KEYDOWN ) + { + if ( !press ) + replayList.push_back( nrFrames ); + press = true; + +// if ( thrustChannel == -1 && parent->getState() == STATE_PLAYING ) +// thrustChannel = SoundHandler :: playSound( SND_THRUST, -1, -1, false ); + } + else + { + if ( press ) + replayList.push_back( nrFrames ); + press = false; + + if ( thrustChannel != -1 ) + { +// SoundHandler :: stopSound( thrustChannel, true, 300 ); +// thrustChannel = -1; + } + } + } +} + + + +QString Game :: getGameDifficultyText() +{ + QString ret; + + if ( difficulty == MENU_DIFFICULTY_EASY ) + ret = "Easy"; + else if ( difficulty == MENU_DIFFICULTY_NORMAL ) + ret = "Medium"; + else if ( difficulty == MENU_DIFFICULTY_HARD ) + ret = "Hard"; + + return ret; +} + +void Game :: setDifficulty( string diff ) +{ + if ( diff == "Easy" ) + difficulty = MENU_DIFFICULTY_EASY; + else if ( diff == "Medium" ) + difficulty = MENU_DIFFICULTY_NORMAL; + else if ( diff == "Hard" ) + difficulty = MENU_DIFFICULTY_HARD; +} + +void Game :: update( int state ) +{ + nrFrames ++; + + if ( score > highScore ) + highScore = score; + + + if ( state == STATE_PLAYING ) + { + if ( replay ) + { + while( replayIt != replayList.end() && (*replayIt) == nrFrames-1 ) + { + press = !press; + replayIt ++; + } + } + + if ( press && thrustChannel == -1 ) + thrustChannel = SoundHandler :: playSound( SND_THRUST, -1, -1, false ); + + if ( !press &&thrustChannel != -1 ) + { + SoundHandler :: stopSound( thrustChannel, true, 300 ); + thrustChannel = -1; + } + } + + if ( state == STATE_CRASHING || state == STATE_CRASHED ) + { + // fade out any trail marks remainin + if ( player->updateCrashing() ) + parent->changeState( STATE_CRASHED ); + + } +} + +void Game :: preDraw( SDL_Surface *screen ) +{ +} + +void Game :: draw( SDL_Surface *screen ) +{ + char tmp[100]; + QString scoreText; + sprintf( tmp, "Score: %06ld High Score: %06ld", score, highScore ); +// printf( "%s\n", (const char *)scoreText ); + FontHandler::draw( screen, FONT_WHITE_TEXT, tmp, 3, 10 ); + + if ( parent->getState() == STATE_CRASHED ) + { + QString crashText; + crashText = "Game Over"; + int x = (240 - FontHandler::TextWidth( FONT_WHITE_TEXT, (const char *)crashText.c_str() )) / 2; + FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)crashText.c_str(), x, 150 ); + + int fontHeight = FontHandler::FontHeight( FONT_WHITE_TEXT ); + crashText = "Press Middle Button to play again"; + x = (240 - FontHandler::TextWidth( FONT_WHITE_TEXT, (const char *)crashText.c_str() )) / 2; + FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)crashText.c_str(), x, 150 + fontHeight ); + + crashText = "or OK for menu"; + x = (240 - FontHandler::TextWidth( FONT_WHITE_TEXT, (const char *)crashText.c_str() )) / 2; + FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)crashText.c_str(), x, 150 + 2*fontHeight ); + } + + if ( parent->showFPS() ) + { + sprintf( tmp, "FPS : %d", parent->getFPS() ); + FontHandler::draw( screen, FONT_WHITE_TEXT, tmp, 20, 300 ); + } +} + +void Game :: stateChanged( int from, int to ) +{ + if ( from != STATE_CRASHING && to == STATE_CRASHING ) + { + // play explosion sound + SoundHandler :: stopSound( -1, false ); + SoundHandler :: playSound( SND_EXPLOSION ); + + // Check and save highscore + printf( "Got Highscore = %d\n", gotHighScore() ); + if ( gotHighScore() ) + { + string key = getGameName() + "_" + getGameDifficultyText() + "_highscore"; + parent->saveSetting( key, getHighScore() ); + } + + } +} + +void Game :: setSeed( int seed ) +{ + if ( seed == -1 ) + currentSeed = ((unsigned long) time((time_t *) NULL)); + else + currentSeed = seed; + PutSeed( currentSeed ); +} + +void Game :: saveReplay( QString file ) +{ + FILE *out; + out = fopen( file.c_str(), "w" ); + if ( !out ) + { + printf( "Couldn't write to /home/root/%s\n", file.c_str() ); + parent->setMenuStatusText( "Couldn't save replay file" ); + return; + } + + // Build up string of values + // Format is:: ....... + QString val; + char tmp[20]; + sprintf( tmp, "%d %d ", currentSeed, difficulty ); + val = tmp; + + list::iterator it = replayList.begin(); + while( it != replayList.end() ) + { + sprintf( tmp, "%d ", *it ); + val += tmp; + + it++; + } + val += "\n"; + + QString line; + sprintf( tmp, "%d\n", val.length() ); + line = tmp; + fwrite( line.c_str(), 1, line.length(), out ); + + fwrite( val.c_str(), 1, val.length(), out ); + + fclose( out ); + + printf( "Replay saved to %s\n", (const char *)file.c_str() ); + +} + +void Game :: loadReplay( QString file ) +{ + + FILE *in = fopen( (const char *)file.c_str(), "r" ); + + if ( in == 0 ) + { + printf( "Couldn't load replay file %s!\n", (const char *)file.c_str() ); + parent->setMenuStatusText( "Couldn't load replay file" ); + return; + } + + // Read next line - contains the size of the options + char line[10+1]; + fgets( line, 10, in ); + + int length = -1; + sscanf( line, "%d", &length ); + char *data = new char[length+1]; + + fread( data, 1, length, in ); +// printf( "data - %s", data ); + + QString sep = " "; + + StringTokenizer st( data, sep ); + + // print it out + vector::iterator it = st.begin(); + currentSeed = atoi( (*it).c_str() ); + ++it; + difficulty = atoi( (*it).c_str() ); + ++it; + + replayList.clear(); + for ( ; it != st.end(); ++it ) + { + int v = atoi( (*it).c_str() ); + replayList.push_back( v ); + } + + delete data; + + fclose( in ); + + printf( "Replay loaded from %s\n", (const char *)file.c_str() ); + +} + + +Game *Game :: createGame( SFCave *p, int w, int h, string game, string difficulty ) +{ + Game *g; + + if ( game == "SFCave" ) + g = new SFCaveGame( p, w, h, 0 ); + else if ( game == "Gates" ) + g = new GatesGame( p, w, h, 0 ); + else if ( game == "Fly" ) + g = new FlyGame( p, w, h, 0 ); + + if ( g ) + g->setDifficulty( difficulty ); + + return g; +} diff --git a/noncore/games/sfcave-sdl/game.h b/noncore/games/sfcave-sdl/game.h new file mode 100644 index 0000000..56fa6a1 --- a/dev/null +++ b/noncore/games/sfcave-sdl/game.h @@ -0,0 +1,82 @@ +#ifndef __GAME_H +#define __GAME_H + +#include +using namespace std; + +#include "sfcave.h" + +class Terrain; +class Player; + +class Game +{ +public: + Game( SFCave *p, int w, int h, int diff ); + virtual ~Game(); + + virtual void init( ); + virtual void update( int state ); + virtual void preDraw( SDL_Surface * ); + virtual void draw( SDL_Surface * ); + + virtual void stateChanged( int from, int to ); + + void setReplay( bool val ) { replay = val; } + + void handleKeys( SDL_KeyboardEvent &key ); + QString getGameName() { return gameName; } + int getDifficulty() { return difficulty; } + QString getGameDifficultyText(); + void setDifficulty( int diff ) { difficulty = diff; } + void setDifficulty( string diff ); + + long getScore() { return score; } + long getHighScore() { return highScore; } + void increaseScore( long val ) { score += val; } + void clearScore() { score = 0; } + bool gotHighScore() { return (score >= highScore); } + bool isReplayAvailable() { return replayList.size() > 0; } + + Terrain *getTerrain() { return terrain; } + + void setSeed( int seed ); + void loadReplay( QString file ); + void saveReplay( QString file ); + + static Game *createGame( SFCave *p, int w, int h, string game, string difficulty ); + +protected: + QString gameName; + + int thrustChannel; + + int difficulty; + + SFCave *parent; + Terrain *terrain; + Player *player; + + int nrFrames; + + bool press; + + int sHeight; + int sWidth; + long score; + long highScore; + + // Stuff for the replays + int currentSeed; + +// QListIterator *replayIt; + list replayList; + list::iterator replayIt; +// QList replayList; + bool replay; + QString replayFile; + +private: +}; + +#endif diff --git a/noncore/games/sfcave-sdl/gates_game.cpp b/noncore/games/sfcave-sdl/gates_game.cpp new file mode 100644 index 0000000..1a9bc89 --- a/dev/null +++ b/noncore/games/sfcave-sdl/gates_game.cpp @@ -0,0 +1,188 @@ +#include "SDL_gfxPrimitives.h" + +#include "constants.h" +#include "gates_game.h" +#include "random.h" + +GatesGame :: GatesGame( SFCave *p, int w, int h, int diff ) + : Game( p, w, h, diff ) +{ + gameName = "Gates"; + difficulty = MENU_DIFFICULTY_EASY; + blockUpdateRate = 200; + + terrain = new Terrain( w, h ); + player = new Player( w, h ); + highScore = 0; +} + +GatesGame :: ~GatesGame() +{ +} + +void GatesGame :: init() +{ + Game :: init(); + + blockHeight = 80; + blockWidth = 20; + lastGateBottomY = 0; + + gateDistance = 75; + nextGate = nextInt( 50 ) + gateDistance; + gapHeight = 75; + + switch( difficulty ) + { + case MENU_DIFFICULTY_EASY: + gapHeight = 75; + player->setMovementInfo( 0.4, 0.6, 4, 5 ); + break; + case MENU_DIFFICULTY_NORMAL: + gapHeight = 50; + player->setMovementInfo( 0.4, 0.6, 4, 5 ); + break; + case MENU_DIFFICULTY_HARD: + gapHeight = 25; + player->setMovementInfo( 0.6, 0.8, 6, 7 ); + break; + } + + for ( int i = 0 ; i < BLOCKSIZE ; ++i ) + blocks[i].y( -1 ); +} + +void GatesGame :: update( int state ) +{ + Game::update( state ); + + // Game logic goes here + if ( state == STATE_PLAYING ) + { + if ( nrFrames % 3 == 0 ) + score ++; + + if ( nrFrames % 500 == 0 ) + { + if ( gapHeight > 75 ) + gapHeight -= 5; + } + + // Slightly random gap distance + if ( nrFrames >= nextGate ) + { + nextGate = nrFrames + nextInt( 50 ) + gateDistance; + addGate(); + } + + if ( checkCollisions() ) + { +// printf( "Crashed!\n" ); + parent->changeState( STATE_CRASHING ); + return; + } + + terrain->moveTerrain( 5 ); + moveBlocks( 5 ); + player->move( press ); + } +} + +void GatesGame :: draw( SDL_Surface *screen ) +{ + Game::preDraw( screen ); + + if ( parent->getState() == STATE_PLAYING ) + { + // Screen drawing goes here + terrain->drawTerrain( screen ); + + player->draw( screen ); + + drawBlocks( screen ); + } + else + { + // Screen drawing goes here + terrain->drawTerrain( screen ); + + drawBlocks( screen ); + + player->draw( screen ); + } + + Game::draw( screen ); +} + + +void GatesGame :: addGate() +{ + printf( "gapHeight = %d\n", gapHeight ); + for ( int i = 0 ; i < BLOCKSIZE ; ++i ) + { + if ( blocks[i].y() == -1 ) + { + int x1 = sWidth; + int y1 = terrain->getMapTop(50); + int b1Height = nextInt(terrain->getMapBottom( 50 ) - terrain->getMapTop(50) - gapHeight); + + // See if height between last gate and this one is too big + if ( b1Height - 100 > lastGateBottomY ) + b1Height -= 25; + else if ( b1Height + 100 < lastGateBottomY ) + b1Height += 25; + lastGateBottomY = b1Height; + + + int x2 = sWidth; + int y2 = y1 + b1Height + gapHeight; + int b2Height = terrain->getMapBottom( 50 ) - y2; + + + blocks[i].setRect( x1, y1, blockWidth, b1Height ); + blocks[i+1].setRect( x2, y2, blockWidth, b2Height ); + + break; + } + } +} + +void GatesGame :: moveBlocks( int amountToMove ) +{ + for ( int i = 0 ; i < BLOCKSIZE ; ++i ) + { + if ( blocks[i].y() != -1 ) + { + blocks[i].moveBy( -amountToMove, 0 ); + if ( blocks[i].x() + blocks[i].y() < 0 ) + blocks[i].y( -1 ); + } + } +} + +void GatesGame :: drawBlocks( SDL_Surface *screen ) +{ + for ( int i = 0 ; i < BLOCKSIZE ; ++i ) + { + if ( blocks[i].y() != -1 ) + { + SDL_Rect r = blocks[i].getRect(); + SDL_FillRect( screen, &r, SDL_MapRGB( screen->format, 100, 100, 255 ) ); + } + } +} + +bool GatesGame :: checkCollisions() +{ + // Check collisions with blocks + for ( int i = 0 ; i < BLOCKSIZE ; ++i ) + { + if ( blocks[i].y() != -1 ) + { + if ( blocks[i].intersects( player->getPos() ) ) + return true; + } + } + // Check collision with landscape + return terrain->checkCollision( player->getX(), player->getY(), player->getHeight() ); +} diff --git a/noncore/games/sfcave-sdl/gates_game.h b/noncore/games/sfcave-sdl/gates_game.h new file mode 100644 index 0000000..8499ff9 --- a/dev/null +++ b/noncore/games/sfcave-sdl/gates_game.h @@ -0,0 +1,45 @@ +#ifndef __GATES_GAME_H +#define __GATES_GAME_H + +#include "SDL.h" + +#include "rect.h" + +#include "sfcave.h" +#include "terrain.h" +#include "player.h" +#include "game.h" + +class GatesGame : public Game +{ +public: + GatesGame( SFCave *p, int w, int h, int diff ); + ~GatesGame(); + + void init(); + void update( int state ); + void draw( SDL_Surface *screen ); + +private: + + int gapHeight; + + int gateDistance; + int nextGate; + int lastGateBottomY; + + int blockDistance; + int blockHeight; + int blockWidth; + int blockUpdateRate; + + Rect blocks[BLOCKSIZE]; + + void addGate(); + void moveBlocks( int amountToMove ); + void drawBlocks( SDL_Surface *screen ); + bool checkCollisions(); + +}; + +#endif diff --git a/noncore/games/sfcave-sdl/help.cpp b/noncore/games/sfcave-sdl/help.cpp new file mode 100644 index 0000000..91c62da --- a/dev/null +++ b/noncore/games/sfcave-sdl/help.cpp @@ -0,0 +1,237 @@ +#include "SDL.h" +#include "constants.h" + +#include "font.h" +#include "help.h" +#include "sfcave.h" +#include "starfield.h" + +Help :: Help( SFCave *p ) +{ + parent = p; + stars = new StarField( false, 200 ); + + loadText(); + + init(); +} + +Help :: ~Help() +{ + delete stars; +} + +void Help :: handleKeys( SDL_KeyboardEvent &key ) +{ + if ( key.type == SDL_KEYDOWN ) + { + if ( key.keysym.sym == SDLK_SPACE ) + parent->changeState( STATE_MENU ); + else if ( key.keysym.sym == SDLK_DOWN ) + textSpeed = 5; + else if ( key.keysym.sym == SDLK_UP ) + { + if ( textSpeed > 0 ) + textSpeed = 0; + else textSpeed = 1; + } + + } + else if ( key.type == SDL_KEYUP ) + { + if ( key.keysym.sym == SDLK_DOWN ) + textSpeed = 1; + } +} +void Help :: init() +{ + startPos = 320; + currLine = 0; + textSpeed = 1; + + // Create our coloured font + FontHandler :: changeColor( FONT_HELP_FONT, 0, 0, 255 ); +} + +void Help :: draw( SDL_Surface *screen ) +{ + stars->draw( screen ); + + + list::iterator it = textList.begin(); + + // Move to start of text + for ( int i = 0 ; i < currLine && it != textList.end() ; ++i ) + it++; + + int pos = startPos; + while ( pos < 320 && it != textList.end() ) + { + // get next line + string text = *it; + + // draw text + FontHandler::draw( screen, FONT_COLOURED_TEXT, text.c_str(), -1, pos ); + pos += FontHandler::FontHeight( FONT_COLOURED_TEXT ); + it ++; + } + +} + +void Help :: update() +{ + stars->move(); + + startPos -= textSpeed; + if ( startPos <= -FontHandler::FontHeight( FONT_COLOURED_TEXT ) ) + { + startPos = 0; + currLine ++; + + if ( currLine > textList.size() ) + { + startPos = 320; + currLine = 0; + } + } + +} + +void Help :: loadText() +{ + textList.push_back( "SFCave" ); + textList.push_back( "Written By AndyQ" ); + textList.push_back( "" ); + textList.push_back( "Instructions" ); + textList.push_back( "To return to the menu" ); + textList.push_back( "press the space or " ); + textList.push_back( "middle button." ); + textList.push_back( "" ); + textList.push_back( "To speed up the text" ); + textList.push_back( "hold the down button" ); + textList.push_back( "(releasing will return" ); + textList.push_back( "to normal speed)" ); + textList.push_back( "" ); + textList.push_back( "" ); + textList.push_back( "SFCave is a flying game" ); + textList.push_back( "writtin originally for the" ); + textList.push_back( "Sharp Zaurus." ); + textList.push_back( "" ); + textList.push_back( "The aim is to stay alive" ); + textList.push_back( "for as long as possible," ); + textList.push_back( "and get the highest score" ); + textList.push_back( "you can." ); + textList.push_back( "" ); + textList.push_back( "There are currently three" ); + textList.push_back( "game types - SFCave," ); + textList.push_back( "Gates, and Fly." ); + textList.push_back( "" ); + textList.push_back( "SFCave is a remake of" ); + textList.push_back( "the classic SFCave game." ); + textList.push_back( "Fly through the cavern" ); + textList.push_back( "avoiding all the blocks" ); + textList.push_back( "that just happen to be" ); + textList.push_back( "hanging in mid-air" ); + textList.push_back( "" ); + textList.push_back( "Gates is similar to" ); + textList.push_back( "SFCave but instead of" ); + textList.push_back( "avoiding blocks you must" ); + textList.push_back( "fly through gates without" ); + textList.push_back( "crashing." ); + textList.push_back( "" ); + textList.push_back( "Fly is a different kettle of" ); + textList.push_back( "fish altogether. Instead," ); + textList.push_back( "you are flying in the " ); + textList.push_back( "open air above a" ); + textList.push_back( "scrolling landscape and" ); + textList.push_back( "the aim is to fly as close" ); + textList.push_back( "to the land as possible." ); + textList.push_back( "The closer to the land" ); + textList.push_back( "you fly the more points" ); + textList.push_back( "you score. But beware," ); + textList.push_back( "fly too high above the" ); + textList.push_back( "land and points get" ); + textList.push_back( "deducted." ); + textList.push_back( "" ); + textList.push_back( "How to play" ); + textList.push_back( "Press the space or middle" ); + textList.push_back( "button (Zaurus only) to " ); + textList.push_back( "apply thrust (makes you" ); + textList.push_back( "go up) and release it" ); + textList.push_back( "to go down." ); + textList.push_back( "" ); + textList.push_back( "Have fun" ); + textList.push_back( "AndyQ" ); +} + +// Test +#ifdef DEBUG_HELP +SDL_Surface *screen; +Help *help; + +void go() +{ + FontHandler :: init(); + + /* Initialize SDL */ + if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) + { + fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + + int videoflags = SDL_SWSURFACE ; + + if ( (screen=SDL_SetVideoMode(240, 320,32,videoflags)) == NULL ) + { + fprintf(stderr, "Couldn't set %ix%i video mode: %s\n",240,320,SDL_GetError()); + exit(2); + } + + help = new Help(); + + bool done = false; + while ( !done ) + { + SDL_FillRect( screen, 0, 0 ); + help->draw( screen ); + help->update( ); + + SDL_Flip( screen ); + + SDL_Delay( 10 ); + + SDL_Event event; + while ( SDL_PollEvent(&event) ) + { + switch (event.type) + { + case SDL_KEYDOWN: + // Escape keypress quits the app + if ( event.key.keysym.sym != SDLK_ESCAPE ) + { + break; + } + case SDL_QUIT: + done = 1; + break; + default: + break; + } + } + } + } + + + + +#ifdef __cplusplus +extern "C" +#endif +int main( int argc, char *argv[] ) +{ + go(); +} + +#endif diff --git a/noncore/games/sfcave-sdl/help.h b/noncore/games/sfcave-sdl/help.h new file mode 100644 index 0000000..dc9e80e --- a/dev/null +++ b/noncore/games/sfcave-sdl/help.h @@ -0,0 +1,35 @@ + +#ifndef __HELP_H +#define __help_h + +#include +#include +using namespace std; + +class SFCave; +class StarField; + +class Help +{ +public: + Help( SFCave *p ); + ~Help(); + + void init(); + void handleKeys( SDL_KeyboardEvent &key ); + void draw( SDL_Surface *screen ); + void update(); +private: + + SFCave *parent; + StarField *stars; + + int textSpeed; + list textList; + int startPos; + int currLine; + + void loadText(); +}; + +#endif diff --git a/noncore/games/sfcave-sdl/menu.cpp b/noncore/games/sfcave-sdl/menu.cpp new file mode 100644 index 0000000..0a7366f --- a/dev/null +++ b/noncore/games/sfcave-sdl/menu.cpp @@ -0,0 +1,337 @@ +#include +#include "SDL_rotozoom.h" + +#include "constants.h" +#include "sfcave.h" +#include "game.h" +#include "menu.h" +#include "font.h" +#include "starfield.h" + +MenuOption :: MenuOption( QString text, int id ) +{ + menuText = text; + menuId = id; + nextMenu = 0; + highlighted = false; +} + +MenuOption :: ~MenuOption() +{ +} + + +int MenuOption :: draw( SDL_Surface *screen, int y ) +{ + if ( highlighted ) + { + int x = (240 - FontHandler::TextWidth( FONT_MENU_HIGHLIGHTED, (const char *)menuText.c_str() ))/2; + FontHandler::draw( screen, FONT_MENU_HIGHLIGHTED, (const char *)menuText.c_str(), x, y ); + return FontHandler::FontHeight( FONT_MENU_HIGHLIGHTED ); + } + else + { + int x = (240 - FontHandler::TextWidth( FONT_MENU_UNHIGHLIGHTED, (const char *)menuText.c_str() ))/2; + FontHandler::draw( screen, FONT_MENU_UNHIGHLIGHTED, (const char *)menuText.c_str(), x, y ); + return FontHandler::FontHeight( FONT_MENU_UNHIGHLIGHTED ); + } +} + +void MenuOption :: setNextMenu( Menu *item, bool down ) +{ + nextMenu = item; + downMenuTree = down; +} + + + +//----------------- Menu Class ------------- + +SDL_Surface * Menu :: sfcaveTextImage; +Menu *Menu :: mainMenu; +Menu *Menu :: currentMenu; + +// This is the Master Menu constructor +Menu :: Menu( SFCave *p ) +{ + parent = p; + parentMenu = 0; + statusText = ""; + +// listItems.setAutoDelete( TRUE ); + + SDL_Surface *tmp = IMG_Load( IMAGES_PATH "sfcave_text.bmp" ); + sfcaveTextImage = SDL_CreateRGBSurface(SDL_SWSURFACE, tmp->w, tmp->h, 32, + 0x000000ff,0x0000ff00, 0x00ff0000, 0xff000000); + SDL_BlitSurface(tmp, NULL, sfcaveTextImage, NULL); + SDL_FreeSurface(tmp); + + // Create menu structure + // Top level menu has 5 items - Start Game, Replays, Options, Help, and Quit + // Replays, Option menu items hav submenus + MenuOption *replayMenu = 0; + MenuOption *optionsMenu = 0; + MenuOption *item = 0; + addMenuOption( "Start Game", MENU_STARTGAME ); + replayMenu = addMenuOption( "Replays", MENU_REPLAYS ); + optionsMenu = addMenuOption( "Options", MENU_OPTIONS ); + addMenuOption( "Help", MENU_HELP ); + addMenuOption( "Quit", MENU_QUIT ); + + // Now deal with the Replays Menu + Menu *replay = new Menu( this ); + replay->addMenuOption( "Play Replay", MENU_PLAY_REPLAY ); + replay->addMenuOption( "Load Replay", MENU_LOAD_REPLAY ); + replay->addMenuOption( "Save Replay", MENU_SAVE_REPLAY ); + item = replay->addMenuOption( "Back", MENU_BACK ); + item->setNextMenu( this, false ); + replayMenu->setNextMenu( replay ); + + // Now deal with the Options Menu currentMenu->currentMenuOption->setHighlighted( false ); + listItems.front()->highlight( true ); + + Menu *options = new Menu( this ); + MenuOption *typeMenu = 0; + MenuOption *difficultyMenu = 0; + MenuOption *soundsMenu = 0; + typeMenu = options->addMenuOption( "Game Type", MENU_GAME_TYPE ); + difficultyMenu = options->addMenuOption( "Difficulty", MENU_DIFFICULTY ); + soundsMenu = options->addMenuOption( "Sound", MENU_SOUNDS ); + options->addMenuOption( "Clear Scores", MENU_CLEAR_SCORES ); + item = options->addMenuOption( "Back", MENU_BACK ); + item->setNextMenu( this, false ); + optionsMenu->setNextMenu( options ); + + // Game Type menu + Menu *gameType = new Menu( options ); + item = gameType->addMenuOption( "SFCave", MENU_GAME_SFCAVE ); + item->setNextMenu( options ); + item = gameType->addMenuOption( "Gates", MENU_GAME_GATES ); + item->setNextMenu( options ); + item = gameType->addMenuOption( "Fly", MENU_GAME_FLY ); + item->setNextMenu( options ); + item = gameType->addMenuOption( "Back", MENU_BACK ); + item->setNextMenu( options ); + typeMenu->setNextMenu( gameType ); + + // Game Difficulty menu + Menu *gameDifficulty = new Menu( options ); + item = gameDifficulty->addMenuOption( "Easy", MENU_DIFFICULTY_EASY ); + item->setNextMenu( options, false ); + item = gameDifficulty->addMenuOption( "Normal", MENU_DIFFICULTY_NORMAL ); + item->setNextMenu( options, false ); + item = gameDifficulty->addMenuOption( "Hard", MENU_DIFFICULTY_HARD ); + item->setNextMenu( options, false ); + item = gameDifficulty->addMenuOption( "Back", MENU_BACK ); + item->setNextMenu( options, false ); + difficultyMenu->setNextMenu( gameDifficulty ); + + // Sounds Menu + Menu *sounds = new Menu( options ); + sounds->addMenuOption( "Sound On", MENU_SOUND_ON ); + sounds->addMenuOption( "Sound Off", MENU_SOUND_OFF ); + sounds->addMenuOption( "Music On", MENU_MUSIC_ON ); + sounds->addMenuOption( "Music Off", MENU_MUSIC_OFF ); + item = sounds->addMenuOption( "Back", MENU_BACK ); + item->setNextMenu( options, false ); + soundsMenu->setNextMenu( sounds ); + + // Set static variables for menu selection up + mainMenu = this; + currentMenuOption = 0; + + resetToTopMenu(); + + angle = 0; + + stars = new StarField; +} + +// This is a private constructor used for creating sub menus - only called by the Master Menu +Menu :: Menu( Menu *p ) +{ + parentMenu = p; +// listItems.setAutoDelete( TRUE ); + currentMenuOption = 0; +} + +Menu :: ~Menu() +{ + if ( this == mainMenu ) + { + SDL_FreeSurface( sfcaveTextImage ); + delete stars; + } +} + +void Menu :: draw( SDL_Surface *screen ) +{ + // draw stafield + stars->draw( screen ); + stars->move( ); + + // Draw the spinning SFCave logo + SDL_Surface *rotozoom_pic; + SDL_Rect dest; + + angle += 2; + if ( angle > 359 ) + angle = 0; + if ((rotozoom_pic=rotozoomSurface (sfcaveTextImage, angle*1, 1, SMOOTHING_ON))!=NULL) + { + dest.x = (screen->w - rotozoom_pic->w)/2; + dest.y = 10; + dest.w = rotozoom_pic->w; + dest.h = rotozoom_pic->h; + SDL_BlitSurface( rotozoom_pic, NULL, screen, &dest ); + SDL_FreeSurface(rotozoom_pic); + } + + // Draw what game is selected + char text[100]; + sprintf( text, "Current Game: %s", (const char *)parent->getCurrentGame()->getGameName().c_str() ); +// Menu::scoreFont.PutString( screen, (240 - Menu::scoreFont.TextWidth( (const char *)text ))/2, 120, (const char *)text ); + FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)text, (240 - FontHandler::TextWidth( FONT_WHITE_TEXT,(const char *)text ))/2, 120 ); + sprintf( text, "Difficulty: %s", (const char *)parent->getCurrentGame()->getGameDifficultyText().c_str() ); +// Menu::scoreFont.PutString( screen, (240 - Menu::scoreFont.TextWidth( (const char *)text ))/2, 120 + Menu::scoreFont.FontHeight()+2, (const char *)text ); + FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)text, (240 - FontHandler::TextWidth( FONT_WHITE_TEXT,(const char *)text ))/2, 120 + FontHandler::FontHeight( FONT_WHITE_TEXT ) ); + + if ( statusText != "" ) + FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)statusText.c_str(), (240 - FontHandler::TextWidth( FONT_WHITE_TEXT,(const char *)statusText.c_str() ))/2, 120 + (2*FontHandler::FontHeight( FONT_WHITE_TEXT ))+6 ); +// Menu::scoreFont.PutString( screen, (240 - Menu::scoreFont.TextWidth( (const char *)statusText ))/2, 120 + (Menu::scoreFont.FontHeight()*2)+6, (const char *)statusText ); + + + // Loop round each menu option and draw it + int y = 155; + list::iterator it; + for ( it = currentMenu->listItems.begin(); it != currentMenu->listItems.end() ; ++it ) + { + y += (*it)->draw( screen, y ) + 2; + } +} + +int Menu :: handleKeys( SDL_KeyboardEvent &key ) +{ + if ( key.type != SDL_KEYDOWN ) + return -1; + + statusText = ""; + switch( key.keysym.sym ) + { + case SDLK_DOWN: + { + // Move to next menu item + currentMenu->currentMenuOption->highlight( false ); + + list::iterator it; + for ( it = currentMenu->listItems.begin(); it != currentMenu->listItems.end() ; ++it ) + { + if ( (*it) == currentMenu->currentMenuOption ) + { + it++; + break; + } + } + + if ( it == currentMenu->listItems.end() ) + it = currentMenu->listItems.begin(); + + currentMenu->currentMenuOption = *it; + currentMenu->currentMenuOption->highlight( true ); + + break; + } + case SDLK_UP: + { + // Move to previous menu item + currentMenu->currentMenuOption->highlight( false ); + list::iterator it; + bool reachedBeginning = false; + for ( it = (currentMenu->listItems).end()--; ; --it ) + { + if ( (*it) == currentMenu->currentMenuOption ) + { + + if ( it == currentMenu->listItems.begin( ) ) + { + reachedBeginning = true; + break; + } + else + it--; + break; + } + + } + + if ( reachedBeginning ) + currentMenu->currentMenuOption = currentMenu->listItems.back(); + else + currentMenu->currentMenuOption = *it; + + currentMenu->currentMenuOption->highlight( true ); + + break; + } + case SDLK_LEFT: + if ( currentMenu->parentMenu != 0 ) + { + currentMenu = currentMenu->parentMenu; + printf( "HERE\n" ); + + return -1; + } + break; + + case SDLK_RETURN: + case SDLK_SPACE: + { + // select menu item + int id = currentMenu->currentMenuOption->getMenuId(); +// // if the current item has a child menu then move to that menu + Menu *next = currentMenu->currentMenuOption->getNextMenu(); + if ( next != 0 ) + { + bool down = currentMenu->currentMenuOption->isDownMenuTree(); + currentMenu = next; + if ( down ) + initCurrentMenu(); +// return -1; + } +// else + { + return id; + } + + break; + } + + default: + break; + } + + return -1; +} + +MenuOption *Menu :: addMenuOption( QString text, int id ) +{ + MenuOption *item = new MenuOption( text, id ); + + listItems.push_back( item ); + + return item; +} + +void Menu :: resetToTopMenu() +{ + currentMenu = mainMenu; + initCurrentMenu(); +} + +void Menu :: initCurrentMenu() +{ + if ( currentMenu->currentMenuOption != 0 ) + currentMenu->currentMenuOption->highlight( false ); + currentMenu->currentMenuOption = currentMenu->listItems.front(); + currentMenu->currentMenuOption->highlight( true ); +} diff --git a/noncore/games/sfcave-sdl/menu.h b/noncore/games/sfcave-sdl/menu.h new file mode 100644 index 0000000..08f7528 --- a/dev/null +++ b/noncore/games/sfcave-sdl/menu.h @@ -0,0 +1,71 @@ +#ifndef __MENU_H +#define __MENU_H + +#include +using namespace std; + +#include + +class SFCave; +class StarField; +class Menu; + +class MenuOption +{ +public: + MenuOption( QString text, int id ); + ~MenuOption(); + + void highlight( bool val ) { highlighted = val; } + int draw( SDL_Surface *screen, int y ); + void setNextMenu( Menu *item, bool down = true ); + Menu *getNextMenu() { return nextMenu; } + int getMenuId() { return menuId; } + bool isDownMenuTree() { return downMenuTree; } + +private: + int menuId; + QString menuText; + bool highlighted; + bool downMenuTree; + + Menu *nextMenu; +}; + +class Menu +{ +public: + Menu( SFCave *p ); + ~Menu(); + + void draw( SDL_Surface *screen ); + int handleKeys( SDL_KeyboardEvent & ); + MenuOption *addMenuOption( QString text, int id ); + void resetToTopMenu(); + void initCurrentMenu(); + + void setStatusText( QString text ) { statusText = text; } + +protected: + +private: + static SDL_Surface * sfcaveTextImage; + int angle; + + static Menu *mainMenu; + static Menu *currentMenu; + Menu *parentMenu; + + StarField *stars; + + QString statusText; + + SFCave *parent; + list listItems; + MenuOption *currentMenuOption; + + Menu( Menu* p ); +}; + + +#endif diff --git a/noncore/games/sfcave-sdl/player.cpp b/noncore/games/sfcave-sdl/player.cpp new file mode 100644 index 0000000..830ee78 --- a/dev/null +++ b/noncore/games/sfcave-sdl/player.cpp @@ -0,0 +1,162 @@ +#include +#include "SDL_gfxPrimitives.h" + +#include "constants.h" +#include "player.h" +#include "random.h" +#include "animatedimage.h" + +Player :: Player( int w, int h ) +{ + sWidth = w; + sHeight = h; + + thrustUp = 0.4; + thrustDown = 0.6; + maxUpSpeed = 4.0; + maxDownSpeed = 5.0; + + explosion = new AnimatedImage( IMAGES_PATH "explosion.bmp", 15 ); + init(); +} + +Player :: ~Player() +{ + if ( explosion ) + delete explosion; +} + +void Player :: init() +{ + // Set player position + pos.x( 50 ); + pos.y( sWidth/2 ); + pos.h( 2 ); + pos.w( 4 ); + thrust = 0; + crashing = false; + crashLineLength = 0; + crashed = false; + explosion->reset(); + allFaded = false; + expNextFrame = false; + + // Reset Trail + for ( int i = 0 ; i < TRAILSIZE ; ++i ) + { + trail[i].x( -1 ); + trail[i].y( 0 ); + trail[i].w( 2 ); + trail[i].h( 2 ); + } +} + +void Player :: draw( SDL_Surface *screen ) +{ + if ( !crashing ) + { + // Draw Player +// ellipseRGBA( screen, pos.x(), pos.y(), pos.x()+ pos.width(), pos.y()+pos.height(), 0, 255, 255, 255 ); + filledEllipseRGBA( screen, pos.x() + pos.w(), pos.y(), pos.w(), pos.h(), 0, 255, 255, 255 ); + + // Draw Trail + drawTrails( screen ); + } + else + { + drawTrails( screen ); + + if ( !crashed ) + explosion->draw( screen, pos.x(), pos.y() ); + } +} + +void Player :: drawTrails( SDL_Surface *screen ) +{ + if ( allFaded && crashing ) + return; + + for ( int i = 0 ; i < TRAILSIZE ; ++i ) + { + if ( trail[i].x() >= 0 ) + { +// int r = (int) ((255.0/pos.x()) * (trail[i].x)); +// int g = (int) ((150.0/pos.x()) * (trail[i].x)); + int c = (int)((150.0/50) * (50.0 - (pos.x() - trail[i].x() ) )); +// SDL_FillRect( screen, &trail[i], SDL_MapRGBA( screen->format, r, g, 0, 0 ) ); //(int)(1.5*c), 0, 255 ) ); + boxRGBA( screen, trail[i].x(), trail[i].y(), trail[i].x() + 2, trail[i].y() + 2, 255, (int)(1.5*c), 0, c ); + } + } +} + +void Player :: move( bool up ) +{ + // Find enpty trail and move others + moveTrails(); + + if ( up ) + thrust -= thrustUp; + else + thrust += thrustDown; + + if ( thrust > maxDownSpeed ) + thrust = maxDownSpeed; + else if ( thrust < -maxUpSpeed ) + thrust = -maxUpSpeed; + + pos.moveBy( 0, (int)(thrust) ); +} + +void Player :: moveTrails() +{ + bool done = false; + bool stillVisible = false; + + // Dont do anything here if all faded when were crashing + if ( allFaded && crashing ) + return; + + for ( int i = 0 ; i < TRAILSIZE ; ++i ) + { + if ( trail[i].x() < 0 ) + { + stillVisible = true; + if ( !crashing && !done ) + { + trail[i].x( pos.x() - 5 ); + trail[i].y( pos.y() ); + done = true; + } + } + else + trail[i].x( trail[i].x() - 1 ); + } + + if ( !stillVisible ) + allFaded = true; +} + +bool Player :: updateCrashing() +{ + crashing = true; + + moveTrails(); + if ( expNextFrame ) + { + expNextFrame = false; + crashed = !explosion->nextFrame(); + } + else + expNextFrame = true; + + return crashed; +} + +void Player :: setMovementInfo( double up, double down, double maxUp, double maxDown ) +{ + thrustUp = up; + thrustDown = down; + maxUpSpeed = maxUp; + maxDownSpeed = maxDown; +} + diff --git a/noncore/games/sfcave-sdl/player.h b/noncore/games/sfcave-sdl/player.h new file mode 100644 index 0000000..e4c904a --- a/dev/null +++ b/noncore/games/sfcave-sdl/player.h @@ -0,0 +1,50 @@ +#ifndef __PLAYER_H +#define __PLAYER_H + +#include "rect.h" + +class SDL_Surface; +class AnimatedImage; + +class Player +{ +public: + Player( int w, int h ); + ~Player(); + + void init(); + void draw( SDL_Surface *screen ); + void drawTrails( SDL_Surface *screen ); + void move( bool up ); + void moveTrails(); + Rect getPos() { return pos; } + int getX() { return pos.x(); } + int getY() { return pos.y(); } + int getHeight() { return pos.h(); } + bool updateCrashing(); + void setMovementInfo( double up, double down, double maxUp, double maxDown ); + +private: + AnimatedImage *explosion; + + int sWidth; + int sHeight; + + bool expNextFrame; + bool allFaded; + bool crashing; + bool crashed; + int crashLineLength; + Rect pos; + double thrust; + + double thrustUp; + double thrustDown; + double maxUpSpeed; + double maxDownSpeed; + + Rect trail[TRAILSIZE]; + +}; + +#endif diff --git a/noncore/games/sfcave-sdl/random.cpp b/noncore/games/sfcave-sdl/random.cpp new file mode 100644 index 0000000..9f716f2 --- a/dev/null +++ b/noncore/games/sfcave-sdl/random.cpp @@ -0,0 +1,189 @@ +/* ------------------------------------------------------------------------- + * This is an ANSI C library for multi-stream random number generation. + * The use of this library is recommended as a replacement for the ANSI C + * rand() and srand() functions, particularly in simulation applications + * where the statistical 'goodness' of the random number generator is + * important. The library supplies 256 streams of random numbers; use + * SelectStream(s) to switch between streams indexed s = 0,1,...,255. + * + * The streams must be initialized. The recommended way to do this is by + * using the function PlantSeeds(x) with the value of x used to initialize + * the default stream and all other streams initialized automatically with + * values dependent on the value of x. The following convention is used + * to initialize the default stream: + * if x > 0 then x is the state + * if x < 0 then the state is obtained from the system clock + * if x = 0 then the state is to be supplied interactively. + * + * The generator used in this library is a so-called 'Lehmer random number + * generator' which returns a pseudo-random number uniformly distributed + * 0.0 and 1.0. The period is (m - 1) where m = 2,147,483,647 and the + * smallest and largest possible values are (1 / m) and 1 - (1 / m) + * respectively. For more details see: + * + * "Random Number Generators: Good Ones Are Hard To Find" + * Steve Park and Keith Miller + * Communications of the ACM, October 1988 + * + * Name : rngs.c (Random Number Generation - Multiple Streams) + * Authors : Steve Park & Dave Geyer + * Language : ANSI C + * Latest Revision : 09-22-98 + * ------------------------------------------------------------------------- + */ + +#include +#include + +#define __RANDOM_CPP +#include "random.h" + +#define MODULUS 2147483647 /* DON'T CHANGE THIS VALUE */ +#define MULTIPLIER 48271 /* DON'T CHANGE THIS VALUE */ +#define CHECK 399268537 /* DON'T CHANGE THIS VALUE */ +#define STREAMS 256 /* # of streams, DON'T CHANGE THIS VALUE */ +#define A256 22925 /* jump multiplier, DON'T CHANGE THIS VALUE */ +#define DEFAULT 123456789 /* initial seed, use 0 < DEFAULT < MODULUS */ + +static long seed[STREAMS] = {DEFAULT}; /* current state of each stream */ +static int stream = 0; /* stream index, 0 is the default */ +static int initialized = 0; /* test for stream initialization */ + + + double Random(void) +/* ---------------------------------------------------------------- + * Random returns a pseudo-random real number uniformly distributed + * between 0.0 and 1.0. + * ---------------------------------------------------------------- + */ +{ + const long Q = MODULUS / MULTIPLIER; + const long R = MODULUS % MULTIPLIER; + long t; + + t = MULTIPLIER * (seed[stream] % Q) - R * (seed[stream] / Q); + if (t > 0) + seed[stream] = t; + else + seed[stream] = t + MODULUS; + return ((double) seed[stream] / MODULUS); +} + + + void PlantSeeds(long x) +/* --------------------------------------------------------------------- + * Use this function to set the state of all the random number generator + * streams by "planting" a sequence of states (seeds), one per stream, + * with all states dictated by the state of the default stream. + * The sequence of planted states is separated one from the next by + * 8,367,782 calls to Random(). + * --------------------------------------------------------------------- + */ +{ + const long Q = MODULUS / A256; + const long R = MODULUS % A256; + int j; + int s; + + initialized = 1; + s = stream; /* remember the current stream */ + SelectStream(0); /* change to stream 0 */ + PutSeed(x); /* set seed[0] */ + stream = s; /* reset the current stream */ + for (j = 1; j < STREAMS; j++) { + x = A256 * (seed[j - 1] % Q) - R * (seed[j - 1] / Q); + if (x > 0) + seed[j] = x; + else + seed[j] = x + MODULUS; + } +} + + +int nextInteger( int range,const char *file, int line ) +{ + int val = (int)(Random( ) * range); +// printf( "nextInt() called from %s line %d - returning %d\n", file, line, val ); + + return val; + +} + void PutSeed(long x) +/* --------------------------------------------------------------- + * Use this function to set the state of the current random number + * generator stream according to the following conventions: + * if x > 0 then x is the state (unless too large) + * if x < 0 then the state is obtained from the system clock + * if x = 0 then the state is to be supplied interactively + * --------------------------------------------------------------- + */ +{ + char ok = 0; + + if (x > 0) + x = x % MODULUS; /* correct if x is too large */ + if (x < 0) + x = ((unsigned long) time((time_t *) NULL)) % MODULUS; + if (x == 0) + while (!ok) { + printf("\nEnter a positive integer seed (9 digits or less) >> "); + scanf("%ld", &x); + ok = (0 < x) && (x < MODULUS); + if (!ok) + printf("\nInput out of range ... try again\n"); + } + seed[stream] = x; +} + + + void GetSeed(long *x) +/* --------------------------------------------------------------- + * Use this function to get the state of the current random number + * generator stream. + * --------------------------------------------------------------- + */ +{ + *x = seed[stream]; +} + + + void SelectStream(int index) +/* ------------------------------------------------------------------ + * Use this function to set the current random number generator + * stream -- that stream from which the next random number will come. + * ------------------------------------------------------------------ + */ +{ + stream = ((unsigned int) index) % STREAMS; + if ((initialized == 0) && (stream != 0)) /* protect against */ + PlantSeeds(DEFAULT); /* un-initialized streams */ +} + + + void TestRandom(void) +/* ------------------------------------------------------------------ + * Use this (optional) function to test for a correct implementation. + * ------------------------------------------------------------------ + */ +{ + long i; + long x; + double u; + char ok = 0; + + SelectStream(0); /* select the default stream */ + PutSeed(1); /* and set the state to 1 */ + for(i = 0; i < 10000; i++) + u = Random(); + GetSeed(&x); /* get the new state value */ + ok = (x == CHECK); /* and check for correctness */ + + SelectStream(1); /* select stream 1 */ + PlantSeeds(1); /* set the state of all streams */ + GetSeed(&x); /* get the state of stream 1 */ + ok = ok && (x == A256); /* x should be the jump multiplier */ + if (ok) + printf("\n The implementation of rngs.c is correct.\n\n"); + else + printf("\n\a ERROR -- the implementation of rngs.c is not correct.\n\n"); +} diff --git a/noncore/games/sfcave-sdl/random.h b/noncore/games/sfcave-sdl/random.h new file mode 100644 index 0000000..d416b59 --- a/dev/null +++ b/noncore/games/sfcave-sdl/random.h @@ -0,0 +1,24 @@ +/* ----------------------------------------------------------------------- + * Name : rngs.h (header file for the library file rngs.c) + * Author : Steve Park & Dave Geyer + * Language : ANSI C + * Latest Revision : 09-22-98 + * ----------------------------------------------------------------------- + */ + +#if !defined( _RNGS_ ) +#define _RNGS_ + + +#define nextInt(x) nextInteger( (x),__FILE__, __LINE__ ) +//#define DEBUG_NEW new + +double Random(void); +int nextInteger( int range,const char *file, int line); +void PlantSeeds(long x); +void GetSeed(long *x); +void PutSeed(long x); +void SelectStream(int index); +void TestRandom(void); + +#endif diff --git a/noncore/games/sfcave-sdl/rect.h b/noncore/games/sfcave-sdl/rect.h new file mode 100644 index 0000000..dc9c9d5 --- a/dev/null +++ b/noncore/games/sfcave-sdl/rect.h @@ -0,0 +1,61 @@ +#ifndef __RECT_H +#define __RECT_H + +#include "SDL.h" + +class Rect +{ +public: + Rect() { r.x = r.y = r.w = r.h = 0; } + Rect( int x, int y, int w, int h ) { setRect( x, y, w, h ); } + ~Rect() {} + + void setRect( int x, int y, int w, int h ) { r.x = x; r.y = y; r.w = w; r.h = h; } + SDL_Rect getRect() { return r; } + int x() { return r.x; } + int y() { return r.y; } + int w() { return r.w; } + int h() { return r.h; } + + void x( int x) { r.x = x; } + void y( int y) { r.y = y; } + void w( int w) { r.w = w; } + void h( int h) { r.h = h; } + + void moveBy( int x, int y ) + { + r.x += x; + r.y += y; + } + + bool intersects( Rect r2 ) + { + int tw = r.w; + int th = r.h; + int rw = r2.w(); + int rh = r2.h(); + if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) { + return false; + } + int tx = r.x; + int ty = r.y; + int rx = r2.x(); + int ry = r2.y(); + rw += rx; + rh += ry; + tw += tx; + th += ty; + + // overflow || intersect + return ((rw < rx || rw > tx) && + (rh < ry || rh > ty) && + (tw < tx || tw > rx) && + (th < ty || th > ry)); + } + +private: + SDL_Rect r; +}; + +#endif + diff --git a/noncore/games/sfcave-sdl/settings.cpp b/noncore/games/sfcave-sdl/settings.cpp new file mode 100644 index 0000000..914c4ec --- a/dev/null +++ b/noncore/games/sfcave-sdl/settings.cpp @@ -0,0 +1,273 @@ +#include +#include +#include +#include + +#include "settings.h" + + +#define DEFAULT_DIR "." +#define DEFAULT_FILE "Settings.cfg" +#define MAX_LINE_SIZE 2048 + + +Settings::Settings( char * env_file, char * env_dir ) +{ + // Store the correct environment directory + if (env_dir == NULL) + { + char * homeDir = getenv( "HOME" );; + + if ( homeDir ) + { + envFile.append(homeDir); + envFile.append("/"); + } + else + printf( "Environment var HOME not set!\n" ); + + envFile.append(DEFAULT_DIR); + } + else + envFile.append(env_dir); + + envFile.append("/"); + + // Store the correct environment file + if (env_file == NULL) + envFile.append(DEFAULT_FILE); + else + envFile.append(env_file); +} + +Settings::Settings() +{ + char * homeDir = getenv("HOME"); + + if ( homeDir) + { + envFile.append(homeDir); + envFile.append("/"); + } + else + printf( "Environment var HOME not set!\n" ); + + envFile.append(DEFAULT_DIR); + envFile.append("/"); + + envFile.append(DEFAULT_FILE); +} + +Settings::~Settings() +{ +} + +bool Settings::readSetting(const string key_str,int& result) +{ + string Buffer; + if (readSetting(key_str,Buffer)) + { + result = atoi(Buffer.c_str()); + return true; + } + else + return false; +} + +bool Settings::readSetting(const string key_str,unsigned int& result) +{ + string Buffer; + if (readSetting(key_str,Buffer)) + { + result = atoi(Buffer.c_str()); + return true; + } + else + return false; +} + +bool Settings::readSetting(const string key_str,long int& result) +{ + string Buffer; + if (readSetting(key_str,Buffer)) + { + result = atol(Buffer.c_str()); + return true; + } + else + return false; +} + +bool Settings::readSetting(const string key_str,unsigned long& result) +{ + string Buffer; + if (readSetting(key_str,Buffer)) + { + result = atol(Buffer.c_str()); + return true; + } + else + return false; +} + +bool Settings::readSetting(const string key_str,bool& result) +{ + string Buffer; + if (readSetting(key_str,Buffer)) + { + result = (Buffer == "true"); + return true; + } + else + return false; +} + +bool Settings::readSetting(const string key_str,string& results) +{ + // This function will read a string from the env file that corresponds to the + // key key_str passed in. + FILE * fd = 0; + char buf[MAX_LINE_SIZE]; + bool ret_flag = false; + char* key; + char* value; + + // open file + fd = fopen(envFile.c_str(), "r"); + + if (fd) + { + while (fgets(buf, MAX_LINE_SIZE-1, fd)) + { + key = strtok(buf, "\t"); + value = strtok(NULL, "\n"); + // find key in file + if (!strcasecmp(key,key_str.c_str())) + { + results = value; + ret_flag = true; + } + } + fclose(fd); + } + + return(ret_flag); +} + +void Settings::writeSetting(const string key_str,const bool value) +{ + value ? writeSetting(key_str,string("true")) :writeSetting(key_str,string("false")); +} + +void Settings::writeSetting(const string key_str,const int value) +{ + char Buffer[30]; + + sprintf(Buffer,"%i",value); + writeSetting(key_str,string(Buffer)); +} + +void Settings::writeSetting(const string key_str,const unsigned int value) +{ + char Buffer[30]; + + sprintf(Buffer,"%i",value); + writeSetting(key_str,string(Buffer)); +} + +void Settings::writeSetting(const string key_str,const long int value) +{ + char Buffer[30]; + + sprintf(Buffer,"%li",value); + writeSetting(key_str,string(Buffer)); +} + +void Settings::writeSetting(const string key_str,const unsigned long value) +{ + char Buffer[30]; + + sprintf(Buffer,"%lu",value); + writeSetting(key_str,string(Buffer)); +} + +void Settings::writeSetting(const string key_str,const string value) +{ + // This function will write a value for the key key_str. If the key_str + // already exists then it will be overwritten. + + std::vector FileEntries; + FILE *fd=NULL,*ftemp=NULL; + char * dir_str; + char * dir_ptr; + char buf[MAX_LINE_SIZE]; + char tempname[12]; + + dir_str = strdup(envFile.c_str()); + printf( "dir = %s, file - %s\n", dir_str, envFile.c_str() ); + if (dir_str) + { + // remove file from the directory string + dir_ptr = strrchr(dir_str, (int)'/'); + if (dir_ptr) + { + *dir_ptr = 0; + + // make the directory path if it does not exist +// mkdir(dir_str, 777 ); + + // if file exists we need to save contents + if ((fd = fopen(envFile.c_str(), "r")) != NULL) + { + while (fgets(buf, MAX_LINE_SIZE-1, fd)) + FileEntries.push_back(string(buf)); + fclose(fd); + } + + char *home = getenv( "HOME" ); + string tmp; + if ( home ) + tmp = home + string( "/" ) + "tmpsfcave.dat"; + else + tmp = "./tmpsfcave.dat"; + strcpy(tempname,tmp.c_str() ); + printf( "tmp - %s\n", tempname ); + if ((ftemp = fopen(tempname,"w")) != NULL) + { + char *key1,*key2; + char buff1[80],buff2[80]; + + strncpy(buff1,key_str.c_str(),80); + key1 = strtok(buff1,"\t"); + for (std::vector::iterator iter = FileEntries.begin(); iter < FileEntries.end(); iter++) + { + strncpy(buff2,(*iter).c_str(),80); + key2 = strtok(buff2,"\t"); + // IF not the key string then write out to file + if (strcmp(key1,key2) != 0) + { + fprintf(ftemp,"%s",iter->c_str()); + fflush(ftemp); + } + } + + fprintf(ftemp, "%s\t%s\n", key_str.c_str(),value.c_str()); + fflush(ftemp); + fclose(ftemp); + + remove(envFile.c_str()); + + rename( tempname, envFile.c_str() ); + } + else + printf( "Can't open file %s\n", envFile.c_str() ); + } + + delete dir_str; + } +} + +void Settings::deleteFile(void) +{ + remove(envFile.c_str()); +} diff --git a/noncore/games/sfcave-sdl/settings.h b/noncore/games/sfcave-sdl/settings.h new file mode 100644 index 0000000..5e828ed --- a/dev/null +++ b/noncore/games/sfcave-sdl/settings.h @@ -0,0 +1,52 @@ +#ifndef __SETTINGS_H +#define __SETTINGS_H + +// This class will create a . directory in the users home directory or +// a directory for the users choice. It will then manage a set of key values +// that the programmer can search for. This allows programmers to save a users +// settings and then retrieve then at a latter time. It currently supports +// upto 1024 different settings. +// Two constructors are provided. They will dertermine what directory to look +// for the settings file and what the name of the file is. If the directory is +// not specified then a default directory of . will be created in +// the users home directory. A file will be created in this directory. The name +// will be the one specified by the caller. If none is specified then +// DEFAULT_FILE will be created. +// To retrieve and store strings into the file readSetting and writeSetting +// should be called. + +#include +using namespace std; + +class Settings +{ + +public: + + Settings( char * env_file = 0, char * env_dir = 0 ); + Settings(); + ~Settings(); + + bool readSetting(const string key_str,string& results); + bool readSetting(const string key_str,int& result); + bool readSetting(const string key_str,unsigned int& result); + bool readSetting(const string key_str,long int& result); + bool readSetting(const string key_str,unsigned long& result); + bool readSetting(const string key_str,bool& result); + + void writeSetting(const string key_str,const string value); + void writeSetting(const string key_str,const int value); + void writeSetting(const string key_str,const unsigned int result); + void writeSetting(const string key_str,const long int result); + void writeSetting(const string key_str,const unsigned long result); + void writeSetting(const string key_str,const bool value); + + void deleteFile(void); + +private: + + string envFile; +}; + + +#endif diff --git a/noncore/games/sfcave-sdl/sfcave-sdl.pro b/noncore/games/sfcave-sdl/sfcave-sdl.pro new file mode 100644 index 0000000..e874f0d --- a/dev/null +++ b/noncore/games/sfcave-sdl/sfcave-sdl.pro @@ -0,0 +1,55 @@ +TEMPLATE = app +CONFIG += qt warn_on release +DESTDIR = $(OPIEDIR)/bin +TARGET = sfcave-sdl + +DEFINES = _REENTRANT main=SDL_main + +INCLUDEPATH += $(OPIEDIR)/include +INCLUDEPATH += $(OPIEDIR)/include/SDL +DEPENDPATH += $(OPIEDIR)/include + +LIBS += -lqpe -L${SDLDIR}/lib -lSDL -lSDLmain -lSDL_gfx -lSDL_image -lSDL_mixer -lstdc++ + +SOURCES = animatedimage.cpp \ + bfont.cpp \ + font.cpp \ + game.cpp \ + menu.cpp \ + help.cpp \ + player.cpp \ + random.cpp \ + sfcave.cpp \ + sfcave_game.cpp \ + gates_game.cpp \ + fly_game.cpp \ + flyterrain.cpp \ + sound.cpp \ + terrain.cpp \ + settings.cpp \ + starfield.cpp \ + util.cpp + +HEADERS = animatedimage.h \ + bfont.h \ + constants.h \ + font.h \ + game.h \ + menu.h \ + player.h \ + random.h \ + rect.h \ + sfcave.h \ + help.h \ + sfcave_game.h \ + gates_game.h \ + fly_game.h \ + flyterrain.h \ + sound.h \ + terrain.h \ + stringtokenizer.h \ + settings.h \ + starfield.h \ + util.h + +include ( ../../../include.pro ) \ No newline at end of file diff --git a/noncore/games/sfcave-sdl/sfcave.cpp b/noncore/games/sfcave-sdl/sfcave.cpp new file mode 100644 index 0000000..8d376a1 --- a/dev/null +++ b/noncore/games/sfcave-sdl/sfcave.cpp @@ -0,0 +1,546 @@ +#include +#include + +#include +#include + +#include "SDL.h" +#include "SDL_gfxPrimitives.h" + +#include "constants.h" + +#include "sound.h" +#include "menu.h" +#include "help.h" +#include "game.h" +#include "terrain.h" +#include "random.h" +#include "sfcave.h" +#include "font.h" +#include "settings.h" +#include "util.h" + +#include "sfcave_game.h" +#include "gates_game.h" +#include "fly_game.h" + +void start( int argc, char *argv[] ) +{ + FontHandler::init(); + SFCave app( argc, argv ); + FontHandler::cleanUp(); +} + +#ifdef __cplusplus +extern "C" +#endif +int main(int argc, char *argv[]) +{ + start( argc, argv ); + return 0; +} + + +SFCave :: SFCave( int argc, char *argv[] ) +{ + string diff = loadSetting( "GameDifficulty", "Easy" ); + string game = loadSetting( "GameType", "SFCave" ); + musicPath = loadSetting( "MusicPath", SOUND_PATH ); + printf( "musicPath %s\n", musicPath.c_str() ); + musicType = loadSetting( "MusicType", "mod,ogg" ); + if ( musicPath[musicPath.size()-1] != '/' ) + musicPath += "/"; + + // Init main SDL Library + initSDL( argc, argv ); + + // Init SoundHandler + if ( !SoundHandler :: init() ) + printf("Unable to open audio!\n"); + + currentGame = Game::createGame( this, WIDTH, HEIGHT, game, diff ); + if ( !currentGame ) + currentGame = new SFCaveGame( this, WIDTH, HEIGHT, 0 ); + currentGame->setSeed(-1); + menu = new Menu( this ); + + help = new Help( this ); + + maxFPS = 50; + showFps = false; + mainEventLoop(); + + SoundHandler :: cleanUp(); + SDL_Quit(); +} + +SFCave :: ~SFCave() +{ + if ( currentGame ) + delete currentGame; + + if ( menu ) + delete menu; + + SDL_FreeSurface( screen ); +} + + +void SFCave :: drawGameScreen( ) +{ + //ClearScreen(screen, "Titletext"); + +} + +void SFCave :: initSDL( int argc, char *argv[] ) +{ + const SDL_VideoInfo *info; + Uint8 video_bpp; + Uint32 videoflags; + + + + /* Initialize SDL */ + if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0 ) { + fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + + /* Alpha blending doesn't work well at 8-bit color */ + video_bpp = 16; + + if ( !SDL_VideoModeOK(WIDTH, HEIGHT, 16, SDL_DOUBLEBUF) ) + printf( "No double buffering\n" ); + + videoflags = SDL_HWSURFACE | SDL_SRCALPHA;//|| SDL_DOUBLEBUF;// | SDL_SRCALPHA | SDL_RESIZABLE; + while ( argc > 1 ) { + --argc; + if ( strcmp(argv[argc-1], "-bpp") == 0 ) { + video_bpp = atoi(argv[argc]); + --argc; + } else + if ( strcmp(argv[argc], "-hw") == 0 ) { + videoflags |= SDL_HWSURFACE; + } else + if ( strcmp(argv[argc], "-warp") == 0 ) { + videoflags |= SDL_HWPALETTE; + } else + if ( strcmp(argv[argc], "-fullscreen") == 0 ) { + videoflags |= SDL_FULLSCREEN; + } else { + fprintf(stderr, + "Usage: %s [-bpp N] [-warp] [-hw] [-fullscreen]\n", + argv[0]); + exit(1); + } + } + + /* Set 240x320 video mode */ + if ( (screen=SDL_SetVideoMode(WIDTH,HEIGHT,video_bpp,videoflags)) == NULL ) { + fprintf(stderr, "Couldn't set %ix%i video mode: %s\n",WIDTH,HEIGHT,SDL_GetError()); + exit(2); + } + + /* Use alpha blending */ + SDL_SetAlpha(screen, SDL_RLEACCEL, 0); + + /* Set title for window */ + SDL_WM_SetCaption("SFCave","SFCave"); +} + +void SFCave :: mainEventLoop() +{ + SDL_Event event; + int done; + + /* Wait for a keystroke */ + done = 0; + state = 0; + state = STATE_CRASHED; + changeState( STATE_MENU ); + + int FPS = 0; + bool limitFPS = true; + actualFPS = 0; + long time1 = 0; + long start; + long end; +// long nrTimes = 0; + struct timeb tp; + while ( !done ) + { + // calc FPS + ftime( &tp ); + start =(tp.time%10000)*10000 + tp.millitm; +// printf( "start = %ld, time1 - %d, st-tm - %d, tp.time - %ld\n", start, time1, start-time1, (tp.time%1000)*1000 ); + if ( start - time1 >= 1000 ) + { + actualFPS = FPS; +// printf( "%d FPS = %d\n", nrTimes++, actualFPS ); + FPS = 0; + time1 = start; + } + else + FPS ++; + + SDL_FillRect( screen, 0, 0 ); + switch( state ) + { + case STATE_MENU: + SDL_FillRect( screen, 0, 0 ); + menu->draw( screen ); + break; + case STATE_HELP: + SDL_FillRect( screen, 0, 0 ); + help->update(); + help->draw( screen ); + break; + case STATE_NEWGAME: + printf( "STATE_NEWGAME\n" ); + currentGame->setReplay( false ); + currentGame->init(); + changeState( STATE_PLAYING ); + break; + + case STATE_REPLAY: + printf( "STATE_NEWGAME\n" ); + currentGame->setReplay( true ); + currentGame->init(); + changeState( STATE_PLAYING ); + break; + + case STATE_PLAYING: + case STATE_CRASHING: + currentGame->update( state ); + currentGame->draw( screen ); + break; + + case STATE_CRASHED: + currentGame->update( state ); + currentGame->draw( screen ); + + // Display Game Over message + break; + + case STATE_QUIT: + done = 1; + break; + } + + /* Show */ +// if ( state != STATE_CRASHED ) + SDL_Flip( screen ); +// SDL_UpdateRect(screen, 0, 0, 0, 0); + + if ( limitFPS ) + { + /* Slow down polling - limit to x FPS*/ + ftime( &tp ); + end = abs((tp.time%10000)*10000 + tp.millitm); + if ( end-start < (1000/maxFPS) ) + { +// printf( "end - %ld, timetaken for frame = %ld, sleeping for %ld %d\n", end, end-start, (1000/maxFPS)-(end-start), actualFPS ); + if ( (1000/maxFPS)-(end-start) > 500 ) + { + // Should never happen but in case it does sleep for 5 seconds + printf( "WARNING WILL ROBINSON! delay = %ld - start %ld, end %ld\n", (1000/maxFPS)-(end-start), start, end ); + SDL_Delay( 5 ); + } + else + SDL_Delay((1000/maxFPS)-(end-start) ); + } + } + else + SDL_Delay( 5 ); + + /* Check for events */ + while ( SDL_PollEvent(&event) ) + { + switch (event.type) + { + case SDL_KEYDOWN: + case SDL_KEYUP: + // Escape keypress quits the app + if ( event.key.keysym.sym != SDLK_ESCAPE ) + { +// printf( "Key Pressed was %d %s\n", event.key.keysym.sym, SDL_GetKeyName( event.key.keysym.sym ) ); + + if ( state == STATE_MENU ) + { + int rc = menu->handleKeys( event.key ); + if ( rc != -1 ) + handleMenuSelect( rc ); + } + else if ( state == STATE_HELP ) + { + help->handleKeys( event.key ); + } + else if ( state == STATE_CRASHED ) + { + if ( event.type == SDL_KEYDOWN ) + { + if ( event.key.keysym.sym == SDLK_UP || + event.key.keysym.sym == SDLK_DOWN || + event.key.keysym.sym == SDLK_SPACE ) + changeState( STATE_NEWGAME ); + else if ( event.key.keysym.sym == SDLK_RETURN || event.key.keysym.sym == 0 ) + { + changeState( STATE_MENU ); + menu->resetToTopMenu(); + } + else if ( event.key.keysym.sym == SDLK_r ) + { + changeState( STATE_REPLAY ); + } + else if ( event.key.keysym.sym == SDLK_s ) + { + SoundHandler :: playSound( SND_EXPLOSION ); + } + } + } + else + { + switch ( event.key.keysym.sym ) + { + case SDLK_f: + printf( "showFPS - %d\n", showFps ); + if ( event.type == SDL_KEYDOWN ) + showFps = !showFps; + break; + case SDLK_l: + if ( event.type == SDL_KEYDOWN ) + limitFPS = !limitFPS; + break; + + case SDLK_p: + if ( event.type == SDL_KEYDOWN ) + { + maxFPS ++; + printf( "maxFPS - %d\n", maxFPS ); + } + break; + + case SDLK_o: + if ( event.type == SDL_KEYDOWN ) + { + maxFPS --; + printf( "maxFPS - %d\n", maxFPS ); + } + break; + + case SDLK_n: + currentGame->getTerrain()->offset++; + break; + + default: + currentGame->handleKeys( event.key ); + break; + } + } + + break; + } + + + case SDL_QUIT: + done = 1; + break; + default: + break; + } + } + } +} + +void SFCave :: changeState( int s ) +{ + if ( state != s ) + currentGame->stateChanged( state, s ); + + if ( state == STATE_MENU && s == STATE_HELP ) + help->init(); + if ( state == STATE_CRASHED && s == STATE_MENU ) + { + SoundHandler :: stopMusic( true ); + + string musicFile = chooseRandomFile( musicPath, musicType ); + printf("playing music %s\n", musicFile.c_str() ); + SoundHandler :: setMusicVolume( 128 ); + SoundHandler :: playMusic( musicFile ); + } + else if ( state == STATE_MENU && (s == STATE_NEWGAME || s == STATE_REPLAY) ) + { + SoundHandler :: stopMusic( ); + + // Start the in game music + string musicFile = SOUND_PATH "ingame.mod"; + SoundHandler :: playMusic( musicFile ); + SoundHandler :: setMusicVolume( 25 ); + } + + state = s; +} + + +void SFCave :: handleMenuSelect( int menuId ) +{ + switch( menuId ) + { + case MENU_STARTGAME: + changeState( STATE_NEWGAME ); + break; + + case MENU_HELP: + changeState( STATE_HELP ); + break; + + case MENU_QUIT: + changeState( STATE_QUIT ); + break; + + case MENU_PLAY_REPLAY: + if ( currentGame->isReplayAvailable() ) + changeState( STATE_REPLAY ); + else + setMenuStatusText( "No replay available yet" ); + break; + + case MENU_LOAD_REPLAY: + { +#ifdef QWS + QString replayFile = getenv( "HOME" ); +#else + QString replayFile = "."; +#endif + replayFile += string( "/" ) + currentGame->getGameName() + ".replay"; + + currentGame->loadReplay( replayFile ); + + break; + } + + case MENU_SAVE_REPLAY: + { + + if ( currentGame->isReplayAvailable() ) + { +#ifdef QWS + QString replayFile = getenv( "HOME" ); +#else + QString replayFile = "."; +#endif + replayFile += string( "/" ) + currentGame->getGameName() + ".replay"; + + currentGame->saveReplay( replayFile ); + } + else + setMenuStatusText( "No replay available yet" ); + + break; + } + case MENU_CLEAR_SCORES: + break; + + case MENU_GAME_SFCAVE: + if ( currentGame->getGameName() != "SFCave" ) + { + int diff = currentGame->getDifficulty(); + delete currentGame; + currentGame = new SFCaveGame( this, WIDTH, HEIGHT, 0 ); + currentGame->setDifficulty( diff ); + + saveSetting( "GameType", "SFCave" ); + } + break; + + case MENU_GAME_GATES: + if ( currentGame->getGameName() != "Gates" ) + { + int diff = currentGame->getDifficulty(); + delete currentGame; + currentGame = new GatesGame( this, WIDTH, HEIGHT, 0 ); + currentGame->setDifficulty( diff ); + + saveSetting( "GameType", "Gates" ); + } + break; + break; + + case MENU_GAME_FLY: + if ( currentGame->getGameName() != "Fly" ) + { + int diff = currentGame->getDifficulty(); + delete currentGame; + currentGame = new FlyGame( this, WIDTH, HEIGHT, 0 ); + currentGame->setDifficulty( diff ); + + saveSetting( "GameType", "Fly" ); + } + break; + + case MENU_DIFFICULTY_EASY: + currentGame->setDifficulty( MENU_DIFFICULTY_EASY ); + saveSetting( "GameDifficulty", "Easy" ); + break; + + case MENU_DIFFICULTY_NORMAL: + currentGame->setDifficulty( MENU_DIFFICULTY_NORMAL ); + saveSetting( "GameDifficulty", "Medium" ); + break; + + case MENU_DIFFICULTY_HARD: + currentGame->setDifficulty( MENU_DIFFICULTY_HARD ); + saveSetting( "GameDifficulty", "Hard" ); + break; + + case MENU_SOUND_ON: + SoundHandler :: setSoundsOn( true ); + break; + + case MENU_SOUND_OFF: + SoundHandler :: setSoundsOn( false ); + break; + + case MENU_MUSIC_ON: + SoundHandler :: setMusicOn( true ); + break; + + case MENU_MUSIC_OFF: + SoundHandler :: setMusicOn( false ); + break; + + default: + break; + } +} + +void SFCave :: setMenuStatusText( string statusText ) +{ + menu->setStatusText( statusText ); +} + + +void SFCave :: saveSetting( string key, string val ) +{ + Settings cfg( "sfcave-sdl" ); + cfg.writeSetting( key, val ); +} + +void SFCave :: saveSetting( string key, int val ) +{ + Settings cfg( "sfcave-sdl" ); + cfg.writeSetting( key, val ); +} + +string SFCave :: loadSetting( string key, string defaultVal ) +{ + string val; + Settings cfg( "sfcave-sdl" ); + cfg.readSetting( key, val ); + + if ( val == "" ) + val = defaultVal; + + return val; +} diff --git a/noncore/games/sfcave-sdl/sfcave.h b/noncore/games/sfcave-sdl/sfcave.h new file mode 100644 index 0000000..96c2334 --- a/dev/null +++ b/noncore/games/sfcave-sdl/sfcave.h @@ -0,0 +1,50 @@ +#ifndef __SFCAVE_H +#define __SFCAVE_H + +#include "SDL.h" + +#include "terrain.h" + +class Game; +class Menu; +class Help; + +class SFCave +{ +public: + SFCave( int argc, char *argv[] ); + ~SFCave(); + + void drawGameScreen(); + void initSDL( int argc, char *argv[] ); + void mainEventLoop(); + + void setCrashed( bool val ); + void changeState( int s ); + int getState() { return state; } + Game *getCurrentGame() { return currentGame; } + int getFPS() { return actualFPS; } + bool showFPS() { return showFps; } + + void setMenuStatusText( string statusText ); + + void saveSetting( string key, string val ); + void saveSetting( string key, int val ); + string loadSetting( string key, string defaultVal = "" ); +private: + SDL_Surface *screen; + + Game *currentGame; + Menu *menu; + Help *help; + int state; + int maxFPS; + int actualFPS; + bool showFps; + string musicPath; + string musicType; + + void handleMenuSelect( int menuId ); +}; + +#endif diff --git a/noncore/games/sfcave-sdl/sfcave_game.cpp b/noncore/games/sfcave-sdl/sfcave_game.cpp new file mode 100644 index 0000000..72c5ce3 --- a/dev/null +++ b/noncore/games/sfcave-sdl/sfcave_game.cpp @@ -0,0 +1,167 @@ +#include "SDL_gfxPrimitives.h" + +#include "constants.h" +#include "sfcave_game.h" +#include "random.h" + +SFCaveGame :: SFCaveGame( SFCave *p, int w, int h, int diff ) + : Game( p, w, h, diff ) +{ + gameName = "SFCave"; + difficulty = MENU_DIFFICULTY_EASY; + blockUpdateRate = 200; + + terrain = new Terrain( w, h ); + player = new Player( w, h ); + highScore = 0; +} + +SFCaveGame :: ~SFCaveGame() +{ +} + +void SFCaveGame :: init() +{ + Game :: init(); + + blockDistance = 50; + blockHeight = 80; + blockWidth = 20; + + switch( difficulty ) + { + case MENU_DIFFICULTY_EASY: + blockDistance = 50; + break; + case MENU_DIFFICULTY_NORMAL: + blockDistance = 40; + break; + case MENU_DIFFICULTY_HARD: + blockDistance = 30; + break; + } + + for ( int i = 0 ; i < BLOCKSIZE ; ++i ) + blocks[i].y( -1 ); +} + +void SFCaveGame :: update( int state ) +{ + Game::update( state ); + + if ( state == STATE_PLAYING ) + { + if ( nrFrames % 3 == 0 ) + score ++; + + if ( nrFrames % 200 == 0 ) + { + if ( terrain->getMaxHeight() < sHeight - 100 ) + { + terrain->increaseMaxHeight( 10 ); + + // Reduce block height + if ( terrain->getMaxHeight() > sHeight - 150 ) + blockHeight -= 5; + } + } + + if ( checkCollisions() ) + { +// printf( "Crashed!\n" ); + parent->changeState( STATE_CRASHING ); + return; + } + + if ( nrFrames % blockDistance == 0 ) + addBlock(); + + // Game logic goes here + terrain->moveTerrain( 5 ); + moveBlocks( 5 ); + player->move( press ); + } +} + +void SFCaveGame :: draw( SDL_Surface *screen ) +{ + Game::preDraw( screen ); + + if ( parent->getState() == STATE_PLAYING ) + { + // Screen drawing goes here + terrain->drawTerrain( screen ); + + player->draw( screen ); + + drawBlocks( screen ); + } + else + { + // Screen drawing goes here + terrain->drawTerrain( screen ); + + drawBlocks( screen ); + + player->draw( screen ); + } + + Game::draw( screen ); +} + +void SFCaveGame :: addBlock() +{ + for ( int i = 0 ; i < BLOCKSIZE ; ++i ) + { + if ( blocks[i].y() == -1 ) + { + int x = sWidth; + + int y = terrain->getMapTop( MAPSIZE-1 ) + (int)(nextInt(terrain->getMapBottom( MAPSIZE-1 ) - terrain->getMapTop( MAPSIZE-1 ) - blockHeight)); + + blocks[i].setRect( x, y, blockWidth, blockHeight ); + + break; + } + } +} + +void SFCaveGame :: moveBlocks( int amountToMove ) +{ + for ( int i = 0 ; i < BLOCKSIZE ; ++i ) + { + if ( blocks[i].y() != -1 ) + { + blocks[i].moveBy( -amountToMove, 0 ); + if ( blocks[i].x() + blocks[i].y() < 0 ) + blocks[i].y( -1 ); + } + } +} + +void SFCaveGame :: drawBlocks( SDL_Surface *screen ) +{ + for ( int i = 0 ; i < BLOCKSIZE ; ++i ) + { + if ( blocks[i].y() != -1 ) + { + SDL_Rect r = blocks[i].getRect(); + SDL_FillRect( screen, &r, SDL_MapRGB( screen->format, 100, 100, 255 ) ); + } + } +} + +bool SFCaveGame :: checkCollisions() +{ + // Check collisions with blocks + for ( int i = 0 ; i < BLOCKSIZE ; ++i ) + { + if ( blocks[i].y() != -1 ) + { + if ( blocks[i].intersects( player->getPos() ) ) + return true; + } + } + // Check collision with landscape + return terrain->checkCollision( player->getX(), player->getY(), player->getHeight() ); +} diff --git a/noncore/games/sfcave-sdl/sfcave_game.h b/noncore/games/sfcave-sdl/sfcave_game.h new file mode 100644 index 0000000..92a0f5d --- a/dev/null +++ b/noncore/games/sfcave-sdl/sfcave_game.h @@ -0,0 +1,39 @@ +#ifndef __SFCAVE_GAME_H +#define __SFCAVE_GAME_H + +#include "SDL.h" + +#include "rect.h" + +#include "sfcave.h" +#include "terrain.h" +#include "player.h" +#include "game.h" + +class SFCaveGame : public Game +{ +public: + SFCaveGame( SFCave *p, int w, int h, int diff ); + ~SFCaveGame(); + + void init(); + void update( int state ); + void draw( SDL_Surface *screen ); + +private: + + int blockDistance; + int blockHeight; + int blockWidth; + int blockUpdateRate; + + Rect blocks[BLOCKSIZE]; + + void addBlock(); + void moveBlocks( int amountToMove ); + void drawBlocks( SDL_Surface *screen ); + bool checkCollisions(); + +}; + +#endif diff --git a/noncore/games/sfcave-sdl/sound.cpp b/noncore/games/sfcave-sdl/sound.cpp new file mode 100644 index 0000000..5fda859 --- a/dev/null +++ b/noncore/games/sfcave-sdl/sound.cpp @@ -0,0 +1,154 @@ +#include "constants.h" +#include "sound.h" + +Mix_Chunk *SoundHandler :: sounds[NR_SOUNDS]; +Mix_Music *SoundHandler :: music; +int SoundHandler :: soundChannels[NR_SOUNDS]; +bool SoundHandler :: soundOn; +bool SoundHandler :: musicOn; + +bool SoundHandler :: init( ) +{ + // We're going to be requesting certain things from our audio + // device, so we set them up beforehand + int audio_rate = 22050; + Uint16 audio_format = AUDIO_S16; //AUDIO_S16; /* 16-bit stereo */ + int audio_channels = 2; + int audio_buffers = 1024;//4096; + + // This is where we open up our audio device. Mix_OpenAudio takes + // as its parameters the audio format we'd /like/ to have. + if(Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers)) + { + printf("Unable to open audio!\n"); + return false; + } + + // We're going to pre-load the sound effects that we need right here + sounds[SND_EXPLOSION] = Mix_LoadWAV( SOUND_PATH "explosion.wav"); + sounds[SND_THRUST] = Mix_LoadWAV( SOUND_PATH "thrust.wav"); + + music = 0; + + soundOn = true; + + return true; +} + +void SoundHandler :: cleanUp() +{ + // Free audio sounds + Mix_FreeChunk( sounds[SND_EXPLOSION] ); + Mix_FreeChunk( sounds[SND_THRUST] ); + + if ( music ) + Mix_FreeMusic( music ); + + Mix_CloseAudio(); +} + +int SoundHandler :: playSound( int soundNr, int channel, int nrLoops, int playBeforeFinished ) +{ + if ( !soundOn ) + return -1; + + if ( soundNr >= NR_SOUNDS ) + return -1; + + Mix_Chunk *chunk = sounds[soundNr]; + if( channel == -1 || !Mix_Playing( channel ) ) + channel = Mix_PlayChannel(-1, sounds[soundNr], nrLoops); + + Mix_Volume( channel, MIX_MAX_VOLUME ); + return channel; +} + +void SoundHandler :: stopSound( int channel, bool fadeOut, int nrMilliSecs ) +{ + if ( !soundOn ) + return; + + if ( !fadeOut ) + Mix_HaltChannel( channel ); + else + { + Mix_FadeOutChannel( channel, nrMilliSecs ); + } +} + +void SoundHandler :: playMusic( string musicFile ) +{ + if ( !soundOn ) + return; + + // If music already exists - stop it playing if necessary and free it up + if ( music ) + { + stopMusic(); + Mix_FreeMusic( music ); + } + + // Load music + music = Mix_LoadMUS( musicFile.c_str() ); + if(!music) + { + printf("Mix_LoadMUS(%s): %s\n", musicFile.c_str(), Mix_GetError()); + // this might be a critical error... + } + + playMusic(); +} + +void SoundHandler :: playMusic( bool fade ) +{ + if ( !soundOn ) + return; + + if ( music ) + { + Mix_VolumeMusic( MIX_MAX_VOLUME ); + Mix_RewindMusic(); + + if ( fade ) + Mix_FadeInMusic( music, -1, 1000 ); + else + Mix_PlayMusic( music, -1 ); + + } +} + +void SoundHandler :: stopMusic( bool fadeOut ) +{ + if ( !music || !Mix_PlayingMusic() ) + return; + + if ( fadeOut && Mix_FadingMusic() == MIX_NO_FADING ) + { + Mix_FadeOutMusic( 1000 ); + } + else + { + Mix_HaltMusic(); + } + +} + +void SoundHandler :: setMusicVolume( int vol ) +{ + Mix_VolumeMusic( vol ); +} + +void SoundHandler :: setSoundsOn( bool val ) +{ + soundOn = val; +} + +void SoundHandler :: setMusicOn( bool val ) +{ + musicOn = val; + + if ( !musicOn ) + stopMusic(); + else + playMusic( true ); +} diff --git a/noncore/games/sfcave-sdl/sound.h b/noncore/games/sfcave-sdl/sound.h new file mode 100644 index 0000000..d46b5bc --- a/dev/null +++ b/noncore/games/sfcave-sdl/sound.h @@ -0,0 +1,35 @@ +#ifndef __SOUND_H +#define __SOUND_H + +#include +#include "SDL_mixer.h" + +#define NR_SOUNDS 3 + +class SoundHandler +{ +public: + static bool init(); + static void cleanUp(); + + static int playSound( int soundNr, int channel = -1, int nrLoops = 0, int playBeforeFinished = false ); + static void stopSound( int channel, bool fadeOut, int nrMilliSecs = 1000 ); + static void setSoundsOn( bool val ); + static void setMusicOn( bool val ); + static void playMusic( string musicFile ); + static void playMusic( bool fadeIn = false ); + static void stopMusic( bool fadeOut = false ); + static void setMusicVolume( int vol ); + + +private: + static Mix_Music *music; + static Mix_Chunk *sounds[NR_SOUNDS]; + static int soundChannels[NR_SOUNDS]; + static bool soundOn; + static bool musicOn; + + SoundHandler() {} +}; + +#endif diff --git a/noncore/games/sfcave-sdl/starfield.cpp b/noncore/games/sfcave-sdl/starfield.cpp new file mode 100644 index 0000000..c1f2d73 --- a/dev/null +++ b/noncore/games/sfcave-sdl/starfield.cpp @@ -0,0 +1,223 @@ +#include "SDL.h" +#include "SDL_gfxPrimitives.h" + +#include + +#include "starfield.h" +#include "random.h" +#include "util.h" + +#define VERTICAL_VELOCITY 0 + +StarField :: StarField( bool side, int nStars, int mx, int my, int minz, int maxz ) +{ + nrStars = nStars; + maxX = mx; + maxY = my; + minZ = minz; + maxZ = maxz; + + min_brightness = 50; + top_star_speed = 6; + + sideways = side; + + if ( !sideways ) + { + x = new int[nrStars]; + y = new int[nrStars]; + z = new int[nrStars]; + + star_color = 0; + vel_x = 0; + vel_y = 0; + pos_x = 0; + pos_y = 0; + } + else + { + star_color = new int[nrStars]; + vel_x = new int[nrStars]; + vel_y = new int[nrStars]; + pos_x = new int[nrStars]; + pos_y = new int[nrStars]; + + x = 0; + y = 0; + z = 0; + } + + init(); +} + +StarField :: ~StarField() +{ + if ( star_color ) + delete []star_color; + if ( vel_x ) + delete []vel_x; + if ( vel_y ) + delete []vel_y; + if ( pos_x ) + delete []pos_x; + if ( pos_y ) + delete []pos_y; + + if ( x ) + delete []x; + if ( y ) + delete []y; + if ( z ) + delete []z; +} + +void StarField :: init() +{ + if ( !sideways ) + { + for ( int i = 0 ; i < nrStars ; ++i ) + { + newStar( i ); + z[i] = (int)(Random() * (double)(maxZ - minZ)) + minZ ; + } + } + else + { + int brightness; + + //Initialise each star + for(int i = 0; i < nrStars ; i++) + { + //Inialise velocities + vel_x[i] = -(int)floor( (Random() * top_star_speed)+1 ); + vel_y[i] = VERTICAL_VELOCITY; + + //Initialise positions randomly + pos_x[i] = (int)floor((Random() * 240)); + pos_y[i] = (int)floor((Random() * 320)); + + //The Faster it goes, the Dimmer it is + if (vel_x[i] != 0) + { + brightness = (int)(255 / fabs(vel_x[i]) ); + if (brightness < min_brightness) + brightness = min_brightness; + } + else + brightness = 255; + + star_color[i] = brightness; + } + } +} + +void StarField :: newStar( int starNr ) +{ + if ( !sideways ) + { + x[starNr] = (int)(Random() * (double)maxX) + 1; + y[starNr] = (int)(Random() * (double)maxY) + 1; + z[starNr] = maxZ; + + int i = (int)(Random() * 4.0); + if(i < 2) + x[starNr] = -x[starNr]; + if(i == 0 || i == 2) + y[starNr] = -y[starNr]; + } +} + +void StarField :: move( ) +{ + if ( !sideways ) + { + int amountToMove = 16; + for(int i = 0; i < nrStars; i++) + { + // Rotate star + z[i] = z[i] - amountToMove; + if(z[i] < minZ) + newStar(i); + } + } + else + { + for(int i = 0; i < nrStars ; i++) + { + //Check speed limits x + if (vel_x[i] > top_star_speed) + vel_x[i] = top_star_speed; + else if (vel_x[i] < -top_star_speed) + vel_x[i] = -top_star_speed; + + //Check speed limits y + if (vel_y[i] > top_star_speed) + vel_y[i] = top_star_speed; + else if (vel_y[i] < -top_star_speed) + vel_y[i] = -top_star_speed; + + + + //Move Star + pos_x[i] += vel_x[i]; + pos_y[i] += vel_y[i]; + + if (pos_x[i] < 0) + pos_x[i] = pos_x[i] + 240; + + if (pos_x[i] > 240) + pos_x[i] = pos_x[i] - 240; + if (pos_y[i] < 0) + pos_y[i] = pos_y[i] + 320; + + if (pos_y[i] > 320) + pos_y[i] = pos_y[i] - 320; + } + } +} + +void StarField :: draw( SDL_Surface *screen, int w, int h ) +{ + if ( !sideways ) + { + int scrW = w / 2; + int scrH = h / 2; + for(int i = 0; i < nrStars; i++) + { + int sx = (x[i] * 256) / z[i] + scrW; + int sy = (y[i] * 256) / z[i] + scrH; + if(sx < 0 || sx > w || sy < 0 || sy > h) + { + newStar(i); + } + else + { + int size = (z[i] * 3) / maxZ; + + SDL_Rect r; + r.x = sx; + r.y = sy; + r.w = 3 - size; + r.h = 3 - size; + + SDL_FillRect( screen, &r, SDL_MapRGB( screen->format, 255, 255, 255 ) ); + } + } + } + else + { + SDL_LockSurface( screen ); + for(int i = 0; i < nrStars ; i++) + { + + Uint32 c = getpixel( screen, pos_x[i], pos_y[i] ); + + + if ( c == 0 ) + lineRGBA( screen, pos_x[i], pos_y[i], pos_x [i]+ vel_x[i], pos_y[i] + vel_y[i], star_color[i], star_color[i], star_color[i], 255 ); + + //*** NOTE : if the velocity of the stars never changes then the values such as 'pos_x[i] + vel_x[i]' could be precalculated for each star *** + } + SDL_UnlockSurface( screen ); + } +} diff --git a/noncore/games/sfcave-sdl/starfield.h b/noncore/games/sfcave-sdl/starfield.h new file mode 100644 index 0000000..ae9bd34 --- a/dev/null +++ b/noncore/games/sfcave-sdl/starfield.h @@ -0,0 +1,41 @@ +#ifndef __STARFIELD_H +#define __STARFIELD_H + +class StarField +{ +public: + StarField( bool side = false, int nrStars = 100, int mx = 240, int my = 320, int minz = 32, int maxz = 725 ); + ~StarField(); + + void init(); + void move( ); + void draw( SDL_Surface *screen, int w = 240, int h = 320 ); + +private: + // 3d effect + int *x; + int *y; + int *z; + + int maxX; + int maxY; + int minZ; + int maxZ; + + // Sideways + int *star_color; + int *vel_x; + int *vel_y; + int *pos_x; + int *pos_y; + int min_brightness; + int top_star_speed; + + bool sideways; + int nrStars; + + void newStar( int i ); +}; + + +#endif diff --git a/noncore/games/sfcave-sdl/stringtokenizer.h b/noncore/games/sfcave-sdl/stringtokenizer.h new file mode 100644 index 0000000..3f299a6 --- a/dev/null +++ b/noncore/games/sfcave-sdl/stringtokenizer.h @@ -0,0 +1,23 @@ +#ifndef __STRINGTOKENIZER_H +#define __STRINGTOKENIZER_H + +#include +using namespace std; + +class StringTokenizer : public vector +{ + public: + StringTokenizer(const string &rStr, const string &rDelimiters = " ,\n") + { + string::size_type lastPos(rStr.find_first_not_of(rDelimiters, 0)); + string::size_type pos(rStr.find_first_of(rDelimiters, lastPos)); + while (string::npos != pos || string::npos != lastPos) + { + push_back(rStr.substr(lastPos, pos - lastPos)); + lastPos = rStr.find_first_not_of(rDelimiters, pos); + pos = rStr.find_first_of(rDelimiters, lastPos); + } + } +}; + +#endif diff --git a/noncore/games/sfcave-sdl/terrain.cpp b/noncore/games/sfcave-sdl/terrain.cpp new file mode 100644 index 0000000..c001a56 --- a/dev/null +++ b/noncore/games/sfcave-sdl/terrain.cpp @@ -0,0 +1,313 @@ +#include "SDL.h" +#include "SDL_rotozoom.h" +#include "SDL_gfxPrimitives.h" + +#include "constants.h" +#include "terrain.h" +#include "random.h" +#include "util.h" +#include "starfield.h" + +Terrain :: Terrain( int w, int h, bool drawTop, bool drawBottom ) +{ + sWidth = w; + sHeight = h; + speed = 1; + segSize = sWidth/(MAPSIZE-2)+1; + this->drawTop = drawTop; + this->drawBottom = drawBottom; + + stars = new StarField( true ); + + SDL_Surface *tmp = SDL_CreateRGBSurface(SDL_SWSURFACE, sWidth + 20, sHeight, 32, + 0x000000ff,0x0000ff00, 0x00ff0000, 0xff000000); + terrainSurface = SDL_DisplayFormat( tmp ); + SDL_FreeSurface( tmp ); + + initTerrain(); + +} + +Terrain :: ~Terrain() +{ + SDL_FreeSurface( terrainSurface ); + delete stars; +} + +void Terrain :: initTerrain() +{ + dir = 1; + offset = 0; + + maxHeight = 50; + + mapTop[0] = (int)(nextInt(50)) + 5; + mapBottom[0] = sHeight - (maxHeight - mapTop[0]); + for ( int i = 1 ; i < MAPSIZE ; ++i ) + setPoint( i ); + + SDL_FillRect( terrainSurface, 0, 0 ); + // Draw Terrain into surface + Sint16 px[5]; + Sint16 py[5]; + + for ( int i = 0 ; i < MAPSIZE ; ++i ) + { + int left = (i*segSize); + int right = ((i+1)*segSize); + px[0] = left; + py[0] = mapTop[i]; + px[1] = right; + py[1] = mapTop[i+1]; + px[2] = right; + py[2] = 0; + px[3] = left; + py[3] = 0; + + if ( drawTop ) + { + // Only display top landscape if not running FLY_GAME + filledPolygonRGBA( terrainSurface, px, py, 4, 0, 190, 0, 255 ); + } + + if ( drawBottom ) + { + py[0] = mapBottom[i]; + py[1] = mapBottom[i+1]; + py[2] = sHeight; + py[3] = sHeight; + filledPolygonRGBA( terrainSurface, px, py, 4, 0, 190, 0, 255 ); + } + + } + + +} + +void Terrain :: moveTerrain( int amountToMove ) +{ + stars->move(); + + offset += amountToMove; + speed = offset/segSize; + +// printf( "offset - %d, speed - %d\n", offset, speed ); + if ( offset >= segSize ) + { + for ( int i = 0 ; i < (MAPSIZE)-speed ; ++i ) + { + mapTop[i] = mapTop[i+speed]; + mapBottom[i] = mapBottom[i+speed]; + } + + for ( int i = (MAPSIZE)-speed ; i < MAPSIZE ; ++i ) + { + setPoint( i ); + } + + SDL_Rect dst; + dst.x = offset; + dst.y = 0; + dst.w = sWidth; + dst.h = sHeight; + + SDL_Rect dst2; + dst2.x = 0; + dst2.y = 0; + + SDL_BlitSurface(terrainSurface, &dst, terrainSurface, &dst2 ); + + dst.x = sWidth-5; + dst.y = 0; + dst.w = offset; + dst.h = sHeight; + SDL_FillRect( terrainSurface, &dst, 0 ); + for ( int i = (MAPSIZE-1) - speed -1; i < MAPSIZE-1 ; ++i ) + { + Sint16 px[4]; + Sint16 py[5]; + int left = ((i-1)*segSize); + int right = ((i)*segSize); + // printf( "left = %d, right = %d\n", left, right ); + + px[0] = left; + py[0] = mapTop[i]; + px[1] = right; + py[1] = mapTop[i+1]; + px[2] = right; + py[2] = 0; + px[3] = left; + py[3] = 0; + + if ( drawTop ) + { + // Only display top landscape if not running FLY_GAME + filledPolygonRGBA( terrainSurface, px, py, 4, 0, 190, 0, 255 ); + } + + if ( drawBottom ) + { + py[0] = mapBottom[i]; + py[1] = mapBottom[i+1]; + py[2] = sHeight; + py[3] = sHeight; + filledPolygonRGBA( terrainSurface, px, py, 4, 0, 190, 0, 255 ); + } + } + + offset -= speed*segSize; + + } + +} + +void Terrain :: setPoint( int point ) +{ + if ( nextInt( 100 ) >= 80 ) + dir *= -1; + + mapTop[point] = mapTop[point-1] + (dir * nextInt( 5 )); + if ( mapTop[point] < 0 ) + { + mapTop[point] = 0; + dir *= -1; + } + else if ( mapTop[point] >= maxHeight ) + { + mapTop[point] = maxHeight; + dir *= -1; + } + + mapBottom[point] = sHeight - (maxHeight - mapTop[point]); +} + +void Terrain :: increaseMaxHeight( int amount ) +{ + maxHeight += amount; +} + +void Terrain :: drawTerrain( SDL_Surface *screen ) +{ + // Blit terrain surface onto screen + + SDL_Rect dst; + dst.x = offset; + dst.y = 0; + dst.w = sWidth; + dst.h = sHeight; +// dst.h = maxHeight; + + SDL_Rect dst2; + dst2.x = 0; + dst2.y = 0; + + SDL_BlitSurface(terrainSurface, &dst, screen, &dst2 ); + + stars->draw( screen ); + +// dst.y = sHeight - maxHeight; +// dst2.y = sHeight - maxHeight; +// SDL_BlitSurface(terrainSurface, &dst, screen, &dst2 ); + +/* + for ( int i = 0 ; i < MAPSIZE ; ++i ) + { + int x1 = (i*segSize) - (offset*speed); + int x2 = ((i+1)*segSize)-(offset*speed); + if ( x2 >= sWidth ) + x2 = sWidth-1; + aalineRGBA( screen, x1, mapTop[i], x2, mapTop[i+1], 0, 220, 0, 255 ); + aalineRGBA( screen, x1, mapBottom[i], x2, mapBottom[i+1], 0, 220, 0, 255 ); + } +*/ +} + +bool Terrain :: checkCollision( int x, int y, int h ) +{ + if ( y < 0 || y > sHeight ) + return true; + // First get segment that matches x + SDL_LockSurface( terrainSurface ); + + Uint32 c = getpixel( terrainSurface, x, y ); + + SDL_UnlockSurface( terrainSurface ); + + if ( c == 0 ) + return false; + else + return true; +} + + +// Test +#ifdef DEBUG_TERRAIN +SDL_Surface *screen; +Terrain *terrain; + +void go() +{ + /* Initialize SDL */ + if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) + { + fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + + int videoflags = SDL_SWSURFACE ; + + if ( (screen=SDL_SetVideoMode(280, 320,32,videoflags)) == NULL ) + { + fprintf(stderr, "Couldn't set %ix%i video mode: %s\n",WIDTH,HEIGHT,SDL_GetError()); + exit(2); + } + + terrain = new Terrain( 240, 320 ); + + bool done = false; + while ( !done ) + { + SDL_FillRect( screen, 0, 0 ); + terrain->drawTerrain( screen ); + terrain->moveTerrain( 5 ); + + SDL_Flip( screen ); + + SDL_Delay( 5 ); + + SDL_Event event; + while ( SDL_PollEvent(&event) ) + { + switch (event.type) + { + case SDL_KEYDOWN: + // Escape keypress quits the app + if ( event.key.keysym.sym != SDLK_ESCAPE ) + { + terrain->moveTerrain( 5 ); + break; + } + case SDL_QUIT: + done = 1; + break; + default: + break; + } + } + } + } + + + + +#ifdef __cplusplus +extern "C" +#endif +int main( int argc, char *argv[] ) +{ + go(); +} + +#endif + diff --git a/noncore/games/sfcave-sdl/terrain.h b/noncore/games/sfcave-sdl/terrain.h new file mode 100644 index 0000000..4070318 --- a/dev/null +++ b/noncore/games/sfcave-sdl/terrain.h @@ -0,0 +1,50 @@ +#ifndef __TERRAIN_H +#define __TERRAIN_H + +#include + +class StarField; +class Terrain +{ +public: + Terrain( int w, int h, bool drawTop = true, bool drawBottom = true ); + virtual ~Terrain(); + + virtual void initTerrain(); + virtual void moveTerrain( int amountToMove ); + virtual bool checkCollision( int x, int y, int h ); + virtual void drawTerrain( SDL_Surface *screen ); + + int getMapTop( int pos ) { return mapTop[pos]; } + int getMapBottom( int pos ) { return mapBottom[pos]; } + int getMaxHeight() { return maxHeight; } + void increaseMaxHeight( int amount ); + + int offset; +protected: + + int sWidth; + int sHeight; + + int drawTop; + int drawBottom; + + int mapTop[MAPSIZE]; + int mapBottom[MAPSIZE]; + int maxTop; + int maxBottom; + + int maxHeight; + int dir; + int speed; + int segSize; + + SDL_Surface *terrainSurface; + StarField *stars; + + void setPoint( int point ); +}; + + +#endif + diff --git a/noncore/games/sfcave-sdl/util.cpp b/noncore/games/sfcave-sdl/util.cpp new file mode 100644 index 0000000..86738ad --- a/dev/null +++ b/noncore/games/sfcave-sdl/util.cpp @@ -0,0 +1,64 @@ +#include "SDL.h" + +#include + +#include +using namespace std; + +#include "util.h" +#include "random.h" + +Uint32 getpixel(SDL_Surface *surface, int x, int y) +{ + int bpp = surface->format->BytesPerPixel; + /* Here p is the address to the pixel we want to retrieve */ + Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; + + switch(bpp) { + case 1: + return *p; + + case 2: + return *(Uint16 *)p; + + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) + return p[0] << 16 | p[1] << 8 | p[2]; + else + return p[0] | p[1] << 8 | p[2] << 16; + + case 4: + return *(Uint32 *)p; + + default: + return 0; /* shouldn't happen, but avoids warnings */ + } +} + +const char *chooseRandomFile( string path, string fileType ) +{ + vector files; + DIR *d = opendir( path.c_str() ); + if ( !d ) + return ""; + + struct dirent *item = readdir( d ); + while ( item ) + { + string file = string( path ) + item->d_name; + + // Rip extension from file + int pos = file.find( ".", 1 ) + 1; + string tmp = file.substr( pos ); + printf( "pos = %d, tmp =%s\n", pos, tmp.c_str() ); + if ( tmp.size() > 0 && fileType.find( tmp ) != -1 ) + { + printf( "Matching <%s> - %s with <%s>\n", file.substr( pos ).c_str(), file.c_str(), fileType.c_str() ); + files.push_back( file ); + } + item = readdir( d ); + } + + closedir( d ); + return files[nextInt( files.size() )].c_str(); +} diff --git a/noncore/games/sfcave-sdl/util.h b/noncore/games/sfcave-sdl/util.h new file mode 100644 index 0000000..fe3e9c0 --- a/dev/null +++ b/noncore/games/sfcave-sdl/util.h @@ -0,0 +1,10 @@ +#ifndef __UTIL_H +#define __UTIL_H + +#include +using namespace std; + +Uint32 getpixel(SDL_Surface *surface, int x, int y); +const char *chooseRandomFile( string path, string fileType ); + +#endif -- cgit v0.9.0.2