/* * glpuzzle, an OpenGL jigsaw game * * version 0.2 * * http://www.resorama.com/glpuzzle/ * * Copyright (C) 2005 Maarten de Boer * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * */ float BG_R = 0.6; float BG_G = 0.0; float BG_B = 0.0; #include #include #include #include #include #include #include #include #include #include "version.hxx" #ifdef WIN32 #include #else // mkdir, dirent #include #include #endif #include #include "Screen.hxx" #include "Sprite.hxx" #include #ifdef WIN32 #define ENABLE_SOUND #endif #ifdef ENABLE_SOUND #include Mix_Chunk *mixChunkConnect = NULL; Mix_Chunk *mixChunkFinish = NULL; #endif #include "Loader.hxx" void Assign(Texture& texture,RGBA& rgba,GLint param) { texture.Bind(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rgba.Width(), rgba.Height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba.Data()); texture.rect = Rect(0,0,rgba.Width(),rgba.Height()); } using namespace std; string puzzlename; Uint32 fadestart = 0; Uint32 fotofade = 0; bool fadein = 0; enum Mode { start_intro, intro, end_intro, start_browse, browse, end_browse, start_play, play, end_play, end }; Mode mode,next_mode,next_next_mode; Sprite *image = 0; Sprite *arrow = 0; Sprite *leave= 0; Sprite *chars[128]; int mouseX = 0,mouseY = 0; class PuzzlePieceSprite **grid = 0; int ncolumns = 0; int nrows = 0; GLuint global_gl_texture; typedef std::list < class PreviewSprite * >PreviewSpriteList; typedef std::list < class PuzzlePieceSprite * >PuzzlePieceSpriteList; PreviewSpriteList previews; PuzzlePieceSpriteList puzzlePieces; PuzzlePieceSpriteList drawOrder; PuzzlePieceSprite *grab = 0; int grabdx,grabdy; int lastSingleGroup = 0; int nextGroup = 0; int aw, ah; Texture *texture; bool drawFoto = 0; Uint32 prevticks = 0; float fade = 0.; void FadeIn(void) { fadestart = SDL_GetTicks(); fadein = true; } void FadeOutTo(Mode _next_mode,Mode _next_next_mode) { fadestart = SDL_GetTicks(); fadein = false; next_mode = _next_mode; next_next_mode = _next_next_mode; } class PreviewSprite:public Sprite { public: string name; int npieces; // used for sorting PreviewSprite(const string & _name):Sprite(), name(_name) {} }; class PuzzlePieceSprite:public Sprite { public: int id; int group; int cx, cy; int tx, ty; Uint32 fadestart; PuzzlePieceSprite(int _id):Sprite(), id(_id) { group = 0; fadestart = 0; } }; void GrabToFront(void) { std::list < PuzzlePieceSprite * >::iterator it, end; for (it = drawOrder.begin(); it != drawOrder.end();) { PuzzlePieceSprite *piece = *it; it++; if (grab != 0 && piece->group == grab->group) { if (piece->fadestart==0) piece->fadestart = SDL_GetTicks(); } } } int NextGroup(void) { return nextGroup++; } bool Finished(void) { std::list < PuzzlePieceSprite * >::iterator it; int g = -1; for (it = puzzlePieces.begin(); it != puzzlePieces.end(); it++) { if (g == -1) g = (*it)->group; if ((*it)->group != g) return false; } return true; } void JoinGroups(int idA, int idB) { std::list < PuzzlePieceSprite * >::iterator it; for (it = puzzlePieces.begin(); it != puzzlePieces.end(); it++) { if ((*it)->group == idB) (*it)->group = idA; } if (idA <= lastSingleGroup) { int idC = NextGroup(); for (it = puzzlePieces.begin(); it != puzzlePieces.end(); it++) { if ((*it)->group == idA) (*it)->group = idC; } } } bool GroupNeighbours(int a, int b) { std::list < PuzzlePieceSprite * >::iterator it; for (int j = 0; j < nrows; j++) { for (int i = 0; i < ncolumns; i++) { if (grid[i + j * ncolumns]->group == a) { if (i != 0 && grid[i - 1 + j * ncolumns]->group == b) return 1; if (i != ncolumns - 1 && grid[i + 1 + j * ncolumns]->group == b) return 1; if (j != 0 && grid[i + (j - 1) * ncolumns]->group == b) return 1; if (j != nrows - 1 && grid[i + (j + 1) * ncolumns]->group == b) return 1; } } } return 0; } void FreePreviews(void) { std::list < PreviewSprite * >::iterator it; for (it = previews.begin(); it != previews.end(); it++) { PreviewSprite* preview = *it; delete preview; } previews.clear(); delete arrow; arrow = 0; delete leave; leave = 0; delete texture; texture = 0; } void FreeChars(void) { for (int i = 0; i < 128; i++) { if (chars[i]) { delete chars[i]; chars[i] = 0; } chars[i] = 0; } std::list < PuzzlePieceSprite * >::iterator it; for (it = puzzlePieces.begin(); it != puzzlePieces.end(); it++) { PuzzlePieceSprite* crop = *it; delete crop; } puzzlePieces.clear(); drawOrder.clear(); delete texture; texture = 0; delete arrow; delete leave; } void FreePuzzle(void) { std::list < PuzzlePieceSprite * >::iterator it; for (it = puzzlePieces.begin(); it != puzzlePieces.end(); it++) { PuzzlePieceSprite* crop = *it; delete crop; } puzzlePieces.clear(); drawOrder.clear(); delete image; image = 0; delete arrow; arrow = 0; delete leave; leave = 0; delete [] grid; grid = 0; delete texture; texture = 0; } class TmpDir { public: string _path; TmpDir() { stringstream ss; #ifdef WIN32 ss << "tmpfiles/"; _path = ss.str(); mkdir(_path.c_str()); #else ss << "/tmp/glpuzzle." << getpid() << "/"; _path = ss.str(); mkdir(_path.c_str(),0755); #endif } ~TmpDir() { DIR* dir = opendir(_path.c_str()); struct dirent* dirent; while ((dirent = readdir(dir))) { string n(dirent->d_name); if (n!="." && n!="..") { n = _path+n; remove(n.c_str()); } } remove(_path.c_str()); closedir(dir); } const string& Path() { return _path; } }; class PuzzleFile { public: TmpDir tmpdir; string jpg; string png; string thumbJpg; string map; const string& Jpg(void) { return jpg; } const string& Png(void) { return png; } const string& ThumbJpg(void) { return thumbJpg; } const string& Map(void) { return map; } PuzzleFile(const string& pzl) { std::ifstream f(pzl.c_str(), std::ios::binary); char tmp[4096]; int chucklen; f.getline(tmp, 256 ,'\n'); // PzlF if (string(tmp)!="PzlF") { fprintf(stderr,"%s is not a valid file\n",pzl.c_str()); } f.getline(tmp, 256 ,'\n'); // version if (string(tmp)!="0.1") { fprintf(stderr,"%s is not the right version\n",pzl.c_str()); } f.getline(tmp, 256 ,'\n'); // name f.getline(tmp, 256 ,'\n'); // URL while (!f.eof()) { f.getline(tmp, 256, '\n'); // filename if (!f.eof()) { string filename(tmpdir.Path() + tmp); if (filename.substr(filename.length()-6)=="-t.jpg") thumbJpg = filename; else { string ext = filename.substr(filename.length()-4); if (ext==".png") png = filename; else if (ext==".jpg") jpg = filename; else if (ext==".map") map = filename; else throw "ERROR PARSING PUZZLE FILE"; } std::ofstream of(filename.c_str(), std::ios::binary); f.getline(tmp, 256); // length string s(tmp); stringstream ss(s); ss >> chucklen; int n = chucklen; while (n) { int m = n; if (m>4096) m = 4096; f.read(tmp,m); of.write(tmp,m); n -= m; } } } } }; void LoadImages(RGBA& rgba) { int offsetX = 0; int offsetY = 0; { PngLoader pngLoader; RGBA arrowRGBA; pngLoader.Load("/usr/X11R6/share/glpuzzle/image/arrow.png",arrowRGBA); rgba.Paste(arrowRGBA,rgba.Width()-arrowRGBA.Width(), rgba.Height()-arrowRGBA.Height()); arrow = new Sprite; arrow->CreateTextureMap(texture, Rect( rgba.Width()-arrowRGBA.Width(), rgba.Height()-arrowRGBA.Height(), arrowRGBA.Width(), arrowRGBA.Height())); arrow->Move(Point(mouseX, mouseY)); offsetX = arrowRGBA.Width(); } { PngLoader pngLoader; RGBA leaveRGBA; pngLoader.Load("/usr/X11R6/share/glpuzzle/image/leave.png",leaveRGBA); rgba.Paste(leaveRGBA,rgba.Width()-offsetX-leaveRGBA.Width(), rgba.Height()-offsetY-leaveRGBA.Height()); leave = new Sprite; leave->CreateTextureMap(texture, Rect( rgba.Width()-offsetX-leaveRGBA.Width(), rgba.Height()-offsetY-leaveRGBA.Height(), leaveRGBA.Width(), leaveRGBA.Height())); leave->Move(Point(1024-leave->GetRect().w,768-leave->GetRect().h)); } } struct sort_previews:public binary_function { bool operator()(PreviewSprite* a,PreviewSprite* b) { return a->npieces < b->npieces; } }; int CountPieces(const string& map) { int n = 0; std::fstream f(map.c_str(), std::ios::in); char tmp[256]; while (!f.eof()) { if (f.getline(tmp, 256)) { string s(tmp); if (s.substr(0, 4) == "crop") { n++; } } } return n; } void ReadPreviews(void) { texture = new Texture(global_gl_texture); RGBA rgba(1024,1024); JpgLoader jpgLoader; string dirname("/usr/X11R6/share/glpuzzle/puzzles/"); DIR* dir = opendir(dirname.c_str()); struct dirent* dirent; int x = 0,y = 0; while ((dirent = readdir(dir))) { string n(dirent->d_name); if (n!="." && n!="..") { PuzzleFile puzzlefile(dirname+n); jpgLoader.Load(puzzlefile.ThumbJpg(),rgba,x,y); PreviewSprite *preview; preview = new PreviewSprite(dirname+n); preview->npieces = CountPieces(puzzlefile.Map()); previews.push_back(preview); preview->CreateTextureMap(texture, Rect(x,y,jpgLoader.width,jpgLoader.height)); x += 256; if (x==1024) { x = 0; y += 240; } } } closedir(dir); previews.sort(sort_previews()); x = 0; y = 0; std::list < PreviewSprite * >::iterator it; for (it = previews.begin(); it != previews.end(); it++) { PreviewSprite* preview = *it; preview->pos = Point( x+(256-preview->GetRect().w)/2, y+(240-preview->GetRect().h)/2); x += 256; if (x==1024) { x = 0; y += 240; } } LoadImages(rgba); Assign(*texture,rgba,GL_NEAREST); } void ReadChars(void) { for (int i = 0; i < 128; i++) { chars[i] = 0; } string mapDataFilename = "/usr/X11R6/share/glpuzzle/font/charmap.map"; texture = new Texture(global_gl_texture); RGBA rgba(1024,1024); PngLoader pngLoader; pngLoader.Load("/usr/X11R6/share/glpuzzle/font/charmap.png",rgba); JpgLoader jpgLoader; jpgLoader.Merge("/usr/X11R6/share/glpuzzle/font/charmap.jpg",rgba); Assign(*texture,rgba,GL_LINEAR); std::fstream f(mapDataFilename.c_str(), std::ios::in); if (!f.is_open()) { fprintf(stderr, "Failed to open %s\n", mapDataFilename.c_str()); exit(-1); } char tmp[256]; ncolumns = 0; nrows = 0; while (!f.eof()) { if (f.getline(tmp, 256) && tmp[0] != '#') { string s(tmp); stringstream ss(s); Sprite *p = 0; Rect rect; Point handle; string name; ss >> name; ss >> rect.x; ss >> rect.y; ss >> rect.w; ss >> rect.h; ss >> handle.x; ss >> handle.y; if (name.substr(0, 4) == "crop") { PuzzlePieceSprite *crop = 0; stringstream sn(name.substr(4)); int id; sn >> id; crop = new PuzzlePieceSprite(id); puzzlePieces.push_back(crop); drawOrder.push_back(crop); ss >> crop->cx; ss >> crop->cy; ss >> crop->tx; ss >> crop->ty; p = crop; } else { char c = strtol(name.c_str(), 0, 16); int i = c; chars[i] = new Sprite; p = chars[i]; } if (p) { p->handle = handle; p->CreateTextureMap(texture, rect); } } } std::list < PuzzlePieceSprite * >::iterator it; for (it = puzzlePieces.begin(); it != puzzlePieces.end(); it++) { PuzzlePieceSprite *pp = *it; pp->Move(Point(240 + pp->tx * 2, 220 + pp->ty * 2)); } LoadImages(rgba); Assign(*texture,rgba,GL_NEAREST); } void ReadPuzzle(const string & pzl) { PuzzleFile puzzlefile(pzl); texture = new Texture(global_gl_texture); RGBA rgba; PngLoader pngLoader; pngLoader.Load(puzzlefile.Png(),rgba); JpgLoader jpgLoader; jpgLoader.Merge(puzzlefile.Jpg(),rgba); Assign(*texture,rgba,GL_LINEAR); std::fstream f(puzzlefile.Map().c_str(), std::ios::in); char tmp[256]; ncolumns = 0; nrows = 0; while (!f.eof()) { if (f.getline(tmp, 256) && tmp[0] != '#') { string s(tmp); stringstream ss(s); Sprite *p = 0; Rect rect; Point handle; string name; ss >> name; ss >> rect.x; ss >> rect.y; ss >> rect.w; ss >> rect.h; ss >> handle.x; ss >> handle.y; if (name == "image") { image = new Sprite; p = image; } else if (name.substr(0, 4) == "crop") { PuzzlePieceSprite *crop = 0; stringstream sn(name.substr(4)); int id; sn >> id; crop = new PuzzlePieceSprite(id); puzzlePieces.push_back(crop); drawOrder.push_back(crop); ss >> crop->cx; ss >> crop->cy; ss >> crop->tx; ss >> crop->ty; crop->group = NextGroup(); lastSingleGroup = crop->group; if (crop->cx >= ncolumns) ncolumns = crop->cx + 1; if (crop->cy >= nrows) nrows = crop->cy + 1; p = crop; } if (p) { p->handle = handle; p->CreateTextureMap(texture, rect); } } } { std::list < PuzzlePieceSprite * >::iterator it; grid = new PuzzlePieceSprite *[ncolumns * nrows]; for (it = puzzlePieces.begin(); it != puzzlePieces.end(); it++) { PuzzlePieceSprite *piece = *it; grid[piece->cx + piece->cy * ncolumns] = piece; } } aw = grid[0]->GetRect().w; ah = grid[0]->GetRect().h; LoadImages(rgba); Assign(*texture,rgba,GL_NEAREST); } void DrawString(int x, int y, char *str, int scale) { char *ptr = str; int tw = 0; while (*ptr) { Sprite *s = chars[int (*ptr++)]; if (s) { Rect r = s->GetRect(); r.w = (r.w * scale) >> 8; tw += r.w; } } x -= tw / 2; ptr = str; while (*ptr) { Sprite *s = chars[int (*ptr++)]; if (s) { Rect r = s->GetRect(); r.x = x; r.y = y - ((s->handle.y * scale) >> 8); r.w = (r.w * scale) >> 8; r.h = (r.h * scale) >> 8; s->Draw(r); x += r.w; } } } void Randomize(void) { std::list < PuzzlePieceSprite * >::iterator it; int n = nrows * ncolumns; std::vector < int >v(n); nextGroup = 0; for (int i = 0; i < n; i++) v[i] = i; for (it = puzzlePieces.begin(); it != puzzlePieces.end(); it++) { int r = rand() % n; int i = v[r]; v[r] = v[--n]; (*it)->pos = Point(4 + grid[i]->tx + grid[i]->tx / 5, 4 + grid[i]->ty + grid[i]->ty / 5); (*it)->group = NextGroup(); } drawFoto = 0; } void DrawFade(void) { if (fadestart) { if (fadein) { fade = 1.-float(SDL_GetTicks() - fadestart) / 200.; if (fade < 0.) { fadestart = 0; fade=0.; } }else{ fade= float(SDL_GetTicks() - fadestart) / 200.; if (fade>1.) { fadestart = 0; fade=1.; mode = next_mode; next_mode = next_next_mode; } } } glDisable(GL_TEXTURE_2D); glColor4f(BG_R,BG_G,BG_B,fade); glRectf(0,0,1024,768); } void Display2(void) { /* if (mode==intro) { static float fr = 0, fg = 0, fb = 0; static int bgT = 0; if (bgT == 0) bgT = SDL_GetTicks(); fr += float (SDL_GetTicks() - bgT) / 2000.; fg += float (SDL_GetTicks() - bgT) / 2100.; fb += float (SDL_GetTicks() - bgT) / 2200.; bgT = SDL_GetTicks(); if (fr > 2. * M_PI) fr -= 2. * M_PI; if (fg > 2. * M_PI) fg -= 2. * M_PI; if (fb > 2. * M_PI) fb -= 2. * M_PI; BG_R = fabs(sin(fr)); BG_G = fabs(sin(fg)); BG_B = fabs(sin(fb)); } */ glClearColor(BG_R,BG_G,BG_B,0.0); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if (mode == start_intro) { ReadChars(); prevticks = 0; mode = intro; FadeIn(); return; } if (mode == end_intro) { FreeChars(); mode = next_mode; return; } if (mode == browse) { glColor3f(1,1 , 1); std::list < PreviewSprite * >::iterator it; for (it = previews.begin(); it != previews.end(); it++) { (*it)->Draw(); } leave->Draw(); arrow->Draw(); return; } if (mode == intro) { { glColor4f(0.7,1,1,0.7); std::list < PuzzlePieceSprite * >::iterator it; static float f = 0, f2 = 0; if (prevticks == 0) prevticks = SDL_GetTicks(); f += float (SDL_GetTicks() - prevticks) / 700.; f2 += float (SDL_GetTicks() - prevticks) / 800.; prevticks = SDL_GetTicks(); if (f > 2. * M_PI) f -= 2. * M_PI; if (f2 > 2. * M_PI) f2 -= 2. * M_PI; float x = sin(f); float y = sin(f2); x = 1.8 + x; y = 1.8 + y; if (x < 1.) x = 1.; if (y < 1.) y = 1.; for (it = puzzlePieces.begin(); it != puzzlePieces.end(); it++) { PuzzlePieceSprite *pp = *it; pp->Move(Point(1024 / 2 + int (float (pp->tx - 140) * x), 768 / 2 + 50 + int (float (pp->ty - 100) * y) )); } for (it = drawOrder.begin(); it != drawOrder.end(); it++) { (*it)->Draw(); } } static Uint32 mark = 0; static int frames = 0; static bool strinited = 0; static char str[256]; if (!strinited) { strinited =1 ; strcpy(str,"----"); } frames++; if (SDL_GetTicks()-mark>200) { sprintf(str,"%f",float(frames)/(float(SDL_GetTicks()-mark)/1000.)); mark = SDL_GetTicks(); frames = 0; } glColor3f(1, 0.8, 0.2); //DrawString(1024 / 2, 150, str, 256); DrawString(1024 / 2, 150, "glpuzzle", 256); DrawString(1024 / 2, 200, "v" VERSIONSTR, 96); glColor3f(0.9, 1, 1); DrawString(1024 / 2, 270, "programming & design:", 96); DrawString(1024 / 2, 320, "maarten de boer", 96); DrawString(1024 / 2, 370, "maarten@resorama.com", 96); glColor3f(0.1, 0.1, 0.7); DrawString(1024 / 2, 440, "http://www.resorama.com/glpuzzle/", 96); glColor3f(0.9, 1, 1); DrawString(1024 / 2, 510, "Press 'Esc' to quit", 96); DrawString(1024 / 2, 560, "During puzzle:",96); DrawString(1024 / 2, 610, "'f': bring bottom-piece to front",96); glColor3f(1, 0.8, 0.2); DrawString(1024 / 2, 700, "Press any key to continue", 128); glColor3f(1, 1, 1); leave->Draw(); arrow->Draw(); return; } if (mode == start_browse) { ReadPreviews(); mode = browse; FadeIn(); } if (mode == end_browse) { FreePreviews(); mode = next_mode; return; } if (mode == start_play) { ReadPuzzle(puzzlename); Randomize(); mode = play; FadeIn(); return; } if (mode == end_play) { FreePuzzle(); mode = next_mode; return; } if (mode == play) { std::list < PuzzlePieceSprite * >::iterator it; for (it = drawOrder.begin(); it != drawOrder.end(); it++) { glColor3f(1,1,1); (*it)->Draw(); } std::list < PuzzlePieceSprite * >tmp; for (it = drawOrder.begin(); it != drawOrder.end();) { PuzzlePieceSprite* piece = *it; it++; if (piece->fadestart!=0) { float f= float(SDL_GetTicks() - piece->fadestart) / 300.; if (f>1.) { f=1.; piece->fadestart = 0; drawOrder.remove(piece); tmp.push_back(piece); } glColor4f(1,1,1,f); piece->Draw(); } } for (it =tmp.begin(); it != tmp.end(); it++) { PuzzlePieceSprite *piece = *it; drawOrder.push_back(piece); } if (drawFoto) { image->pos = grid[0][0].pos; float f= float(SDL_GetTicks() - fotofade) / 1000.; if (f>1.) f=1.; glColor4f(1, 1, 1, f); image->Draw(); } glColor3f(1, 1, 1); leave->Draw(); arrow->Draw(); } } void Display(void) { Display2(); DrawFade(); } void MouseMove(int x, int y) { mouseX = x; mouseY = y; if (arrow) arrow->Move(Point(mouseX, mouseY)); if (mode == intro) { return; } if (mode == browse) return; if (grab) { grab->Move(Point(mouseX+grabdx, mouseY+grabdy)); std::list < PuzzlePieceSprite * >::iterator it; for (it = puzzlePieces.begin(); it != puzzlePieces.end(); it++) { PuzzlePieceSprite *piece = *it; if (piece->group != grab->group) { int dx = piece->pos.x + piece->handle.x - piece->tx - (grab->pos.x + grab->handle.x - grab->tx); int dy = piece->pos.y + piece->handle.y - piece->ty - (grab->pos.y + grab->handle.y - grab->ty); if (abs(dx) < 4 && abs(dy) < 4) { if (GroupNeighbours(grab->group, piece->group)) { JoinGroups(grab->group, piece->group); if (Finished()) { fotofade = SDL_GetTicks(); drawFoto = 1; #ifdef ENABLE_SOUND if (mixChunkFinish) Mix_PlayChannel(-1, mixChunkFinish, 0); #endif }else{ #ifdef ENABLE_SOUND if (mixChunkConnect) Mix_PlayChannel(-1, mixChunkConnect, 0); #endif } GrabToFront(); } } } if (piece != grab && piece->group == grab->group) { piece->pos.x = grab->pos.x + grab->handle.x - grab->tx - piece->handle.x + piece->tx; piece->pos.y = grab->pos.y + grab->handle.y - grab->ty - piece->handle.y + piece->ty; } } } } bool clickLeave = false; void MouseClick(void) { if (mode == browse) { std::list < PreviewSprite * >::iterator it; for (it = previews.begin(); it != previews.end(); it++) { PreviewSprite *s = *it; if (arrow->pos.x - arrow->handle.x >= s->pos.x && arrow->pos.y - arrow->handle.y >= s->pos.y && arrow->pos.x - arrow->handle.x <= s->pos.x + s->GetRect().w && arrow->pos.y - arrow->handle.y <= s->pos.y + s->GetRect().h) { puzzlename = s->name; FadeOutTo(end_browse,start_play); } } } if (mode == play) { std::list < PuzzlePieceSprite * >::iterator it; float min_d = 1000.; for (it = puzzlePieces.begin(); it != puzzlePieces.end(); it++) { PuzzlePieceSprite *piece = *it; int dx = piece->pos.x + piece->handle.x - arrow->pos.x - arrow->handle.x; int dy = piece->pos.y + piece->handle.y - arrow->pos.y - arrow->handle.y; float d = sqrt(dx*dx+dy*dy); if (dx > -aw / 2 && dx < aw / 2 && dy > -ah / 2 && dy < ah / 2) { if (dpos.x - arrow->handle.x >= s->pos.x && arrow->pos.y - arrow->handle.y >= s->pos.y && arrow->pos.x - arrow->handle.x <= s->pos.x + s->GetRect().w && arrow->pos.y - arrow->handle.y <= s->pos.y + s->GetRect().h) { clickLeave=true; } } } void usage(void) { printf("glpuzzle, an OpenGL jigsaw game\n\n"); printf("version " VERSIONSTR "\n\n"); printf("http://www.resorama.com/glpuzzle/\n\n"); printf ("Copyright (C) 2005 Maarten de Boer \n\n"); printf("Usage: glpuzzle [-h | -w]\n\n"); printf(" -h show this usage info\n"); printf(" -w window mode (default is fullscreen)\n"); printf("\n"); printf ("glpuzzle requires a OpenGL hardware accelaration and runs at 1024x768 only\n\n"); #ifndef ENABLE_SOUND printf("Sound support disabled at compilation\n\n"); #endif exit(0); } int main(int argc, char **argv) { try { bool fullscreen = true; mode = start_intro; string argv0(argv[0]); #ifdef WIN32 unsigned int slashpos = argv0.rfind("\\"); #else unsigned int slashpos = argv0.rfind("/"); #endif if (slashpos != string::npos) { string dir = argv0.substr(0, slashpos); chdir(dir.c_str()); } if (argc > 1) { if (argc > 2) usage(); if (string(argv[1]) == "-h") usage(); if (string(argv[1]) == "-w") fullscreen = false; } Screen s(1024, 768); s.DoubleBuffer(); if (fullscreen) s.FullScreen(); s.Init(); glGenTextures(1, &global_gl_texture); int audio_rate = 44100; Uint16 audio_format = AUDIO_S16; int audio_channels = 2; int audio_buffers = 512; SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); #ifdef ENABLE_SOUND if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers)) { printf("Unable to open audio... continuing without.\n"); }else{ mixChunkConnect= Mix_LoadWAV("/usr/X11R6/share/glpuzzle/sound/connect.wav"); mixChunkFinish= Mix_LoadWAV("/usr/X11R6/share/glpuzzle/sound/finish.wav"); } #endif FadeIn(); SDL_ShowCursor(0); int i; Uint8 *keys = SDL_GetKeyState(&i); SDL_Event event; while (mode!=end) { //static Uint32 mark = 0; SDL_Delay(10); while (SDL_PollEvent(&event)) { clickLeave = false; if (event.type == SDL_MOUSEBUTTONDOWN) { MouseClick(); if (!clickLeave) { if (mode == intro) { FadeOutTo(end_intro,start_browse); } } } if (event.type == SDL_MOUSEBUTTONUP) grab = 0; if (event.type == SDL_MOUSEMOTION) { MouseMove(event.motion.x, event.motion.y); } if (event.type == SDL_KEYDOWN) { if (keys[SDLK_ESCAPE] || keys['q']) { clickLeave = true; } else { if (mode == play ) { if (keys['f'] || keys[' ']) { if (drawOrder.front()->fadestart==0) { drawOrder.front()->fadestart=SDL_GetTicks(); } } } if (mode == intro) { FadeOutTo(end_intro,start_browse); } } } if (clickLeave) { if (mode == intro) FadeOutTo(end_intro,end); else if (mode == browse) { FadeOutTo(end_browse,start_intro); } else { FadeOutTo(end_play,start_browse); } } if (event.type == SDL_QUIT) { mode = end; break; } } s.Flip(); Display(); } s.Exit(); } catch (LoaderException& e) { fprintf(stderr,e.what()); } return 0; }