summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--noncore/games/sfcave-sdl/animatedimage.cpp68
-rw-r--r--noncore/games/sfcave-sdl/animatedimage.h25
-rw-r--r--noncore/games/sfcave-sdl/bfont.cpp443
-rw-r--r--noncore/games/sfcave-sdl/bfont.h70
-rw-r--r--noncore/games/sfcave-sdl/config.in5
-rw-r--r--noncore/games/sfcave-sdl/constants.h67
-rw-r--r--noncore/games/sfcave-sdl/fly_game.cpp103
-rw-r--r--noncore/games/sfcave-sdl/fly_game.h28
-rw-r--r--noncore/games/sfcave-sdl/flyterrain.cpp103
-rw-r--r--noncore/games/sfcave-sdl/flyterrain.h29
-rw-r--r--noncore/games/sfcave-sdl/font.cpp72
-rw-r--r--noncore/games/sfcave-sdl/font.h33
-rw-r--r--noncore/games/sfcave-sdl/game.cpp332
-rw-r--r--noncore/games/sfcave-sdl/game.h82
-rw-r--r--noncore/games/sfcave-sdl/gates_game.cpp188
-rw-r--r--noncore/games/sfcave-sdl/gates_game.h45
-rw-r--r--noncore/games/sfcave-sdl/help.cpp237
-rw-r--r--noncore/games/sfcave-sdl/help.h35
-rw-r--r--noncore/games/sfcave-sdl/menu.cpp337
-rw-r--r--noncore/games/sfcave-sdl/menu.h71
-rw-r--r--noncore/games/sfcave-sdl/player.cpp162
-rw-r--r--noncore/games/sfcave-sdl/player.h50
-rw-r--r--noncore/games/sfcave-sdl/random.cpp189
-rw-r--r--noncore/games/sfcave-sdl/random.h24
-rw-r--r--noncore/games/sfcave-sdl/rect.h61
-rw-r--r--noncore/games/sfcave-sdl/settings.cpp273
-rw-r--r--noncore/games/sfcave-sdl/settings.h52
-rw-r--r--noncore/games/sfcave-sdl/sfcave-sdl.pro55
-rw-r--r--noncore/games/sfcave-sdl/sfcave.cpp546
-rw-r--r--noncore/games/sfcave-sdl/sfcave.h50
-rw-r--r--noncore/games/sfcave-sdl/sfcave_game.cpp167
-rw-r--r--noncore/games/sfcave-sdl/sfcave_game.h39
-rw-r--r--noncore/games/sfcave-sdl/sound.cpp154
-rw-r--r--noncore/games/sfcave-sdl/sound.h35
-rw-r--r--noncore/games/sfcave-sdl/starfield.cpp223
-rw-r--r--noncore/games/sfcave-sdl/starfield.h41
-rw-r--r--noncore/games/sfcave-sdl/stringtokenizer.h23
-rw-r--r--noncore/games/sfcave-sdl/terrain.cpp313
-rw-r--r--noncore/games/sfcave-sdl/terrain.h50
-rw-r--r--noncore/games/sfcave-sdl/util.cpp64
-rw-r--r--noncore/games/sfcave-sdl/util.h10
41 files changed, 4954 insertions, 0 deletions
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 <iostream>
+#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 <string>
+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 <SDL.h>
+
+#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 <stdio.h>
+#include <time.h>
+
+#include <SDL.h>
+#include <SDL_image.h>
+
+#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:: <landscape seed> <game type> <difficulty> <framenr> <framenr>.......
+ QString val;
+ char tmp[20];
+ sprintf( tmp, "%d %d ", currentSeed, difficulty );
+ val = tmp;
+
+ list<int>::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<string>::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 <list>
+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<int> *replayIt;
+ list<int> replayList;
+ list<int>::iterator replayIt;
+// QList<int> 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<string>::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 <list>
+#include <string>
+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<string> 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 <SDL_image.h>
+#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<MenuOption *>::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<MenuOption *>::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<MenuOption *>::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 <list>
+using namespace std;
+
+#include <SDL.h>
+
+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<MenuOption *> 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 <SDL.h>
+#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 <stdio.h>
+#include <time.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <vector>
+
+#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<string> 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<string>::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 .<name> 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 .<DEFAULT_DIR> 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 <string>
+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 <stdio.h>
+#include <stdlib.h>
+
+#include <time.h>
+#include <sys/timeb.h>
+
+#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 <SDL.h>
+#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 <stdlib.h>
+
+#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 <vector>
+using namespace std;
+
+class StringTokenizer : public vector<string>
+{
+ 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 <SDL.h>
+
+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 <dirent.h>
+
+#include <vector>
+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<string> 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 <string>
+using namespace std;
+
+Uint32 getpixel(SDL_Surface *surface, int x, int y);
+const char *chooseRandomFile( string path, string fileType );
+
+#endif