I have found that I have a large set of interesting and maybe sometimes useful applications. I have been programming for 14 years, I started from Pascal and tried Delphi, C++, Java, Perl, Clipper, FoxPro, Lua , JavaScript, C#, Octave, Python, Scala, R, F# (and may be something else that I currently do not remember). Through the years I created set of programs that may be interesting for someone else. These programs may look simple for experts, but I hope that they can be useful for beginners. So, I would like to add a new rubric to my blog, called “Apps”, where I will try to collect and share as much as I can find)
This post is about second version of the small maze game that called SuperSDG2, which was created in 2005 using C++, OpenGL(glut32) and a bit of passion. In the game, you are a lonely red ball in the large terrible maze. Your only wish is to find an exit from the random-generated maze. It is strange, but exit is a yellow ball ;). The source code and binaries of this application are available on GitHub.
Control keys:
- Left/Right/Up/Down – move actions
- A/S – rotate camera
- Z/X – up/down camera
- R – reset camera position
- Esc/Q – exit
Feel free to download binaries, play and modify the source code.
/******************************** * SuperSDG v2.2 release * Copyright (c) 2002-2008 Ravent * All rights reserved *********************************/ #pragma comment (lib,"glut32.lib") #pragma comment (lib,"glaux.lib") #include "glaux.h" #include "glut.h" #include <stdio.h> #include <stdlib.h> #include <conio.h> #define _USE_MATH_DEFINES #include <math.h> #include <time.h> const int sMax=6, m=40, mm=m+1, direction_parts=36; int cur_direction=0; double distance=4.; unsigned textureId = -1, texFloor = -1; AUX_RGBImageRec *localTexture = NULL, *localFloor = NULL; int glWin,pathLen,myLen=0; struct Tpos {char x,y;}; struct Player { int x,y,z; int dx,dz; bool isGo; }player,ex; struct Maps {int x,z;} map; char data[m+2][m+2], cp[m+2][m+2]; float lightAmb [] = { 0.03, 0.03, 0.03 }; float lightDif [] = { 0.95, 0.95, 0.95 }; float lightPos [] = { (int)m/2, 7, (int)m/2 }; void display(void); void halt(bool f=false); void drawFloor(GLfloat x1, GLfloat x2, GLfloat z1, GLfloat z2, unsigned texture=texFloor) { glBindTexture ( GL_TEXTURE_2D, texture ); glBegin(GL_POLYGON); glNormal3f( 0.0, 1.0, 0.0); glTexCoord2f(0,0); glVertex3f( x1, 0, z2 ); glTexCoord2f(1,0); glVertex3f( x2, 0, z2 ); glTexCoord2f(1,1); glVertex3f( x2, 0, z1 ); glTexCoord2f(0,1); glVertex3f( x1, 0, z1 ); glEnd(); } void drawBox (GLint j, GLint i, unsigned texture=textureId) { GLfloat x1=i, x2=i+1, y1=0, y2=1, z1=j, z2=j+1; glBindTexture ( GL_TEXTURE_2D, texture ); if ((j==map.z+1)||(data[j-1][i]!='x')) { glBegin(GL_POLYGON); // Back glNormal3f( 0.0, 0.0, -1.0); glTexCoord2f(0,0); glVertex3f( x2, y1, z1 ); glTexCoord2f(1,0); glVertex3f( x1, y1, z1 ); glTexCoord2f(1,1); glVertex3f( x1, y2, z1 ); glTexCoord2f(0,1); glVertex3f( x2, y2, z1 ); glEnd(); } if ((j==map.z-1)||(data[j+1][i]!='x')) { glBegin(GL_POLYGON); // Front glNormal3f( 0.0, 0.0, 1.0); glTexCoord2f(0,0); glVertex3f( x1, y1, z2 ); glTexCoord2f(1,0); glVertex3f( x2, y1, z2 ); glTexCoord2f(1,1); glVertex3f( x2, y2, z2 ); glTexCoord2f(0,1); glVertex3f( x1, y2, z2 ); glEnd(); } if ((i>0)&&(data[j][i-1]!='x')) { glBegin(GL_POLYGON); // Left glNormal3f( -1.0, 0.0, 0.0); glTexCoord2f(0,0); glVertex3f( x1, y1, z1 ); glTexCoord2f(1,0); glVertex3f( x1, y1, z2 ); glTexCoord2f(1,1); glVertex3f( x1, y2, z2 ); glTexCoord2f(0,1); glVertex3f( x1, y2, z1 ); glEnd(); } if ((i<map.x)&&(data[j][i+1]!='x')) { glBegin(GL_POLYGON); // Right glNormal3f( 1.0, 0.0, 0.0); glTexCoord2f(0,0); glVertex3f( x2, y1, z2 ); glTexCoord2f(1,0); glVertex3f( x2, y1, z1 ); glTexCoord2f(1,1); glVertex3f( x2, y2, z1 ); glTexCoord2f(0,1); glVertex3f( x2, y2, z2 ); glEnd(); } glBegin(GL_POLYGON); // Top glNormal3f( 0.0, 1.0, 0.0); glTexCoord2f(0,0); glVertex3f( x1, y2, z2 ); glTexCoord2f(1,0); glVertex3f( x2, y2, z2 ); glTexCoord2f(1,1); glVertex3f( x2, y2, z1 ); glTexCoord2f(0,1); glVertex3f( x1, y2, z1 ); glEnd(); } void animate() { if ((player.x == ex.x)&&(player.z==ex.z)) { halt(true); }; if (player.isGo==true) { if (player.dx>0) player.dx+=1; else if (player.dz>0) player.dz+=1; else if (player.dx<0) player.dx-=1; else if (player.dz<0) player.dz-=1; if ((player.dx>=sMax)||(player.dz>=sMax)) { player.isGo=false; if (player.dx>0) player.x+=1; if (player.dz>0) player.z+=1; player.dx=0; player.dz=0; }else if ((player.dx<=-sMax)||(player.dz<=-sMax)) { player.isGo=false; if (player.dx<0) player.x-=1; if (player.dz<0) player.z-=1; player.dx=0; player.dz=0; } } glutPostRedisplay(); } void init() { glClearColor( 0.0, 0.0, 0.0, 1.0 ); glEnable( GL_DEPTH_TEST ); glEnable( GL_TEXTURE_2D ); glEnable( GL_CULL_FACE ); glPixelStorei ( GL_PACK_ALIGNMENT, 1 ); glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); glShadeModel (GL_SMOOTH); glLightfv ( GL_LIGHT0, GL_AMBIENT, lightAmb ); glLightfv ( GL_LIGHT0, GL_DIFFUSE, lightDif ); //glLightfv ( GL_LIGHT0, GL_POSITION, lightPos ); glEnable ( GL_LIGHT0 ); glEnable ( GL_LIGHTING ); player.dx=0; player.dz=0; player.isGo=false; glEnable(GL_COLOR_MATERIAL); } void display() { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); gluLookAt(player.x+(1.0*player.dx/sMax)+0.5f+3*cos(M_PI_2+cur_direction/double(direction_parts)*2.*M_PI),player.y+distance,player.z+(1.0*player.dz/sMax)+0.5f+3*sin(M_PI_2+cur_direction/double(direction_parts)*2.*M_PI), player.x+(1.0*player.dx/sMax)+0.5f,player.y+0.5f,player.z+(1.0*player.dz/sMax)+0.5f, 0,1,0); for (int i=0;i<map.x;i++) for (int j=0;j<map.z;j++) if (data[j][i] == 'x') { drawBox(j,i); } else { drawFloor(i,i+1,j,j+1); } glPushMatrix(); glTranslatef ( player.x+(1.0*player.dx/sMax)+0.5f, player.y+0.5f, player.z+(1.0*player.dz/sMax)+0.5f); glColor3d(1,0,0); glutSolidSphere(0.5,100,100); glColor3d(1,1,1); glPopMatrix(); glPushMatrix(); glTranslatef ( ex.x +0.5f, ex.y+0.5f, ex.z+0.5f); glColor4d(1,1,0.,0.4); glutSolidSphere(0.5,100,100); glColor3d(1,1,1); glPopMatrix(); glutSwapBuffers(); } void reshape ( int w, int h ) { glViewport( 0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 60.0, (GLfloat)w/(GLfloat)h, 1.0, 60.0); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); gluLookAt(0,0,25,0,0,0,0,1,0); } void key( unsigned char key, int x, int y) { if ( key=='q' || key=='Q' || key == 27) halt(false); if ( key=='a' || key=='A' ) { cur_direction--; if (cur_direction<0) cur_direction+=direction_parts;} if ( key=='s' || key=='S' ) { cur_direction++; if (cur_direction==direction_parts) cur_direction=0;} if ((key=='z' || key=='Z') && (distance<58.) ) distance+=0.25; if ((key=='x' || key=='X') && (distance>3.) ) distance-=0.25; if ( key=='r' || key=='R' ) { cur_direction=0; distance=4.;} } const int move[4][2]={{-1,0},{0,-1},{1,0},{0,1}}; const int move_key[4] = {GLUT_KEY_UP, GLUT_KEY_LEFT, GLUT_KEY_DOWN, GLUT_KEY_RIGHT }; bool good_move(int z, int x){ return (0<=z && 0<=x && z<map.z && x<map.x && data[z][x]!='x'); } void keys( int key, int x, int y) { if (player.isGo) return; int dir=int(((direction_parts-cur_direction-1)/double(direction_parts))*4.+0.5); for (int i=0; i<4; i++) if ( key == move_key[i] ) { int newz=player.z+move[(dir+i)%4][0]; int newx=player.x+move[(dir+i)%4][1]; if (good_move(newz,newx)) { player.isGo=true; player.dz+=move[(dir+i)%4][0]; player.dx+=move[(dir+i)%4][1]; myLen++; } } } void genMap(void); int main (int argc, char** argv) { genMap(); glutInit(&argc,argv); glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ); glutInitWindowSize(1024,768); glWin = glutCreateWindow("SuperSDG 2"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(key); glutSpecialFunc(keys); glutIdleFunc(animate); localTexture = auxDIBImageLoad(L"1.bmp"); glGenTextures (1,&textureId); glBindTexture (GL_TEXTURE_2D,textureId); glPixelStorei (GL_UNPACK_ALIGNMENT,1); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT); gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, localTexture->sizeX, localTexture->sizeY, GL_RGB, GL_UNSIGNED_BYTE, localTexture->data); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); localFloor = auxDIBImageLoad(L"2.bmp"); glGenTextures (1,&texFloor); glBindTexture (GL_TEXTURE_2D,texFloor); glPixelStorei (GL_UNPACK_ALIGNMENT,1); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT); gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, localFloor->sizeX, localFloor->sizeY, GL_RGB, GL_UNSIGNED_BYTE, localFloor->data); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glutFullScreen(); glutMainLoop(); return 0; } int step(int y, int x) { int res=0; if ((data[y][x]=='x')) res++; if ((y<mm)&&(data[y+1][x]=='x')) res++; if ((y>0 )&&(data[y-1][x]=='x')) res++; if ((x<mm)&&(data[y][x+1]=='x')) res++; if ((x>0 )&&(data[y][x-1]=='x')) res++; return res; } int stepC(int y, int x) { int res=0; if ((cp[y][x]=='x')) res++; if ((y<mm)&&(cp[y+1][x]=='x')) res++; if ((y>0 )&&(cp[y-1][x]=='x')) res++; if ((x<mm)&&(cp[y][x+1]=='x')) res++; if ((x>0 )&&(cp[y][x-1]=='x')) res++; return res; } void DataToCp(void) { for(int j=1;j<=mm;j++) for (int i=1;i<=mm;i++) cp[j][i]=data[j][i]; } void fill (int y,int x,Tpos *v, int *l) { int st=1,en=0; int G[mm*mm],Ll[mm*mm]; G[0]=y*mm+x; Ll[0]=0; cp[y][x]='x'; while (st!=en) { if ((G[en]%mm+1<mm)&&(cp[(int)G[en]/mm][G[en]%mm+1]=='.')) { G[st]=G[en]+1; Ll[st]=Ll[en]+1; cp[(int)G[st]/mm][G[st]%mm]='x'; st++; } if ((G[en]%mm-1>0)&&(cp[(int)G[en]/mm][G[en]%mm-1]=='.')) { G[st]=G[en]-1; Ll[st]=Ll[en]+1; cp[(int)G[st]/mm][G[st]%mm]='x'; st++; } if ((((int)G[en]/mm)+1<mm)&&(cp[((int)G[en]/mm)+1][G[en]%mm]=='.')) { G[st]=G[en]+mm; Ll[st]=Ll[en]+1; cp[(int)G[st]/mm][G[st]%mm]='x'; st++; } if ((((int)G[en]/mm)-1>0)&&(cp[((int)G[en]/mm)-1][G[en]%mm]=='.')) { G[st]=G[en]-mm; Ll[st]=Ll[en]+1; cp[(int)G[st]/mm][G[st]%mm]='x'; st++; } en++; } int rnd=rand()%5+1; (*v).x =(int) G[en-rnd] % mm; (*v).y =(int) G[en-rnd] / mm; *l=Ll[en-rnd]; } bool isGood(Tpos a) { DataToCp(); int k=0,i,j,lt; Tpos temp; cp[a.y][a.x]='x'; if ((step(a.y,a.x)>3)||(step(a.y+1,a.x)>3)||(step(a.y-1,a.x)>3)||(step(a.y,a.x+1)>3)||(step(a.y,a.x-1)>3)) return false; for(j=1;j<=m;j++) for(i=1;i<=m;i++) if (cp[j][i]=='.') { if (k>0) return false; fill(j,i,&temp,<); k++; } return true; } void genMap() { int i,j; map.x=m+2; map.z=m+2; printf("Loading... Please Wait.\n"); srand( (unsigned)time( NULL ) ); for (j=0;j<map.z;j++) for (i=0;i<map.x;i++) { if ((i==0)||(j==0)||(i==map.x-1)||(j==map.z-1)) data[j][i]='x'; else data[j][i]='.'; } int k=0; Tpos t; while (k<(int)m*m/2.5) { t.x = rand()%mm+1; t.y = rand()%mm+1; if ((data[t.y][t.x]=='.')&&(isGood(t))) { data[t.y][t.x]='x'; k++; } } for (j=1;j<=m;j++) for (i=1;i<=m;i++) if ((data[j][i]=='x')&&(step(j,i)>3)) { data[j][i]='.'; } for (j=1;j<=m;j++) for (i=1;i<=m;i++) if ((data[j][i]=='.')&&(step(j,i)<2)) { t.x = i; t.y=j; if (isGood(t)) data[j][i]='x'; } Tpos ps[11]; k=0; while (k<=10) { t.x = rand()%mm+1; t.y = rand()%mm+1; if (data[t.y][t.x]=='.') { ps[k]=t; k++; } } k=rand()%11; player.x=ps[k].x; player.z=ps[k].y; DataToCp(); fill(ps[k].y,ps[k].x,&t,&pathLen); ex.x=t.x; ex.z=t.y; printf("Loading complete.\n"); } void halt(bool f) { glutDestroyWindow(glWin); printf("-----------------------------------------------------\n"); printf("# SuperSDG 2.2 #\n"); if (f==true) { printf("-----------------------------------------------------\n"); printf("# The shortest path %d. #\n",pathLen); printf("# Your path %d. #\n",myLen); printf("# Congratulate you passed the game. #\n"); if ( 1.2*pathLen >= myLen ) { printf("-----------------------------------------------------\n"); printf("# YOU ONE OF THE BEST PLAYER OF THE WORLD. #\n"); } } printf("-----------------------------------------------------\n"); printf("# Developers: #\n"); printf("# Ravent - programmer. #\n"); printf("# Series found: #\n"); printf("# Ravent - Sergey Tihon #\n"); printf("# MasterZerg - Dima Rudol #\n"); printf("-----------------------------------------------------\n"); printf("# Copyright (c) Ravent 2002-2008. #\n"); printf("# All rights reserved #\n"); printf("-----------------------------------------------------\n"); getch(); exit(0); }
while compiling the program, i’m getting the error “Failed to open DIB file 1.bmp”, please help..
All images are near the source code in GitHub repo https://github.com/sergey-tihon/Ravent-App-Store/tree/master/SuperSDG2/src
Thank you for replying.
I’m using ms visual c++, i’ve place .bmp files in the source files, but still i’m getting the same error.
Please help..
Download source code from GitHub, where files added to project and copy to build target directory
Hi can you please tell me how did you calculate the parameters for the gluLookAt func. ??
This is the most clear explanation http://profs.sci.univr.it/~colombar/html_openGL_tutorial/en/08viewing_005.html
Thank you.. it really helped…
I have enjoyed the trial version of this game and look forward to buying and playing it.
Hello
Someone plz tell me how to run this program on Visual studios. also where to add the files and images. Please reply ASAP because i have an assignment on it to submit next week. the link for this is https://github.com/sergey-tihon/Ravent-App-Store/tree/master/SuperSDG2/src
what are the algorithm used for finding the shortest path and also the placing of balls…?
I did not search shortest path, for balls I used one of longest pathes
how you are find out shortest path…?..Is their any more details available..?
hi I would like to get the full explanation of the code …….
or at least those functions that are used to create the map, place the player and the target, calculation of players path……. please do help…….
Sorry, I have no more detailed explanation than source code.
Hi i decided to make a random generator maze with sdl2 can you this that is possible with Krushkal algorithm ?
Try it and you will see
how i run this in linux, pls help me with commands
How can I make a square shape instead of a round one?