3 * @brief The main source file for gljewel.
5 * Copyright 2001, 2008 David Ashley <dashxdr@gmail.com>
6 * Copyright 2008 Stephen M. Webb <stephen.webb@bregmasoft.ca>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of Version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #if defined(_WIN32) && !defined(__CYGWIN__)
23 # define WIN32_LEAN_AND_MEAN 1
40 #include <SDL/SDL_main.h>
54 typedef unsigned int uint32
;
58 #define HIGHSCOREFILENAME ".gljewelscores"
73 static GLint objectlists
;
75 char clearing
=1,clearonce
=0;
78 int stage
,score
,level
;
82 int cumulativebuildup
;
87 #define STARTLIFE 1000.0f
88 #define ALARMLEVEL 10.0f // seconds before death
90 #define INITIALDECAY 0.4f
91 #define DECAYADD 0.02f
94 #define LIFEVISIBLE (STARTLIFE*2.0f)
96 // position/scaling settings
97 #define SCALE 0.88f // size of each jewel
98 #define SPACING 1.76f // how much to move for each row/column
99 #define SHIFTX 3.0f // shift the jewels sideways so they're not centered
103 #define SCOREX -8.0f // coords for upper left
106 #define FONTSIZE 0.015f
107 #define LINESPACE (FONTSIZE*70)
108 #define SCORETAB 4.3f // move to right for even spacing
113 #define HIGHXNUMBER 0.0f
114 #define HIGHXNAME 1.3f
115 #define HIGHXSCORE 5.0f
116 #define HIGHXLEVEL 2.5f
117 #define HIGHYSPACE (-FONTSIZE*60)
119 #define HIGHLEFT -3.5f
120 #define HIGHRIGHT 8.2f
122 #define HIGHBOTTOM (-HIGHTOP)
124 #define MAXHIGHSCORES 100
126 #define MAXNAMELENGTH 12
128 char name
[MAXNAMELENGTH
];
131 } highscores
[MAXHIGHSCORES
];
133 char lastentered
[MAXNAMELENGTH
]={0};
141 static GLfloat lightpos
[4] = {-2.0f
, 4.0f
, 4.0f
, 0.0f
};
142 static GLfloat light1pos
[4] = {22.0f
, 2.0f
, 4.0f
, 0.0f
};
143 static GLfloat light2pos
[4] = {0.0f
, 0.0f
, 4.0f
, 0.0f
};
144 static GLfloat red
[4] = {0.8f
, 0.1f
, 0.0f
, 1.0f
};
145 static GLfloat green
[4] = {0.0f
, 0.8f
, 0.2f
, 1.0f
};
146 static GLfloat yellow
[4] = {1.0f
, 1.0f
, 0.0f
, 1.0f
};
147 static GLfloat blue
[4] = {0.2f
, 0.2f
, 1.0f
, 1.0f
};
148 static GLfloat white
[4] = {1.0f
, 1.0f
, 1.0f
, 1.0f
};
149 static GLfloat magenta
[4] = {1.0f
, 0.0f
, 1.0f
, 1.0f
};
151 static GLfloat white2
[4] = {WH2
, WH2
, WH2
, 1.0f
};
152 static GLfloat orange
[4] = {1.0f
, 0.5f
, 0.0f
, 1.0f
};
154 static GLfloat grey
[4] = {GV
,GV
,GV
,1.0f
};
156 static GLfloat grey2
[4] = {GV2
,GV2
,GV2
,1.0f
};
158 static GLfloat
*colormaps
[]={blue
,orange
,yellow
,magenta
,green
,red
,white
};
159 static GLfloat dimmer
[4]={0.0f
, 0.0f
, 0.0f
, 0.5f
};
176 #define MAXSCORESPRITES 12
181 } scoresprites
[MAXSCORESPRITES
];
183 int mousex
,mousey
,sizex
,sizey
;
187 uint32
torgba(unsigned int r
,unsigned int g
,unsigned int b
,unsigned int a
)
193 return (a
<<24) | (r
<<0) | (g
<<8) | (b
<<16);
200 matrix unprojectmatrix
;
202 void initunproject(void)
204 matrix projection
,model
;
207 glGetFloatv(GL_PROJECTION_MATRIX
,(void *)projection
);
208 glGetFloatv(GL_MODELVIEW_MATRIX
,(void *)model
);
209 matrixXmatrix(&temp
,&projection
,&model
);
210 invertmatrix(&unprojectmatrix
,&temp
);
213 SDL_Surface
*setvideomode(int w
, int h
)
216 screen
= SDL_SetVideoMode(w
, h
, 24, SDL_OPENGL
|SDL_RESIZABLE
);
219 fprintf(stderr
, "Couldn't set %dx%d GL video mode: %s\n",
220 sizex
, sizey
, SDL_GetError());
227 static void resize( unsigned int width
, unsigned int height
)
234 setvideomode(width
, height
);
236 glViewport(0, 0, (GLint
) width
, (GLint
) height
);
237 glMatrixMode(GL_PROJECTION
);
241 h
=(float)height
/(float)width
;
242 glFrustum(-1.0, 1.0, -h
, h
, 5.0, 60.0);
245 h
=(float)width
/(float)height
;
246 glFrustum(-h
,h
,-1.0,1.0,5.0,60.0);
248 glMatrixMode(GL_MODELVIEW
);
250 glTranslatef(0.0, 0.0, -40.0);
257 static Window
make_rgb_db_window( Display
*dpy
,
258 unsigned int width
, unsigned int height
)
260 int attrib
[] = { GLX_RGBA
,
268 XSetWindowAttributes attr
;
273 XVisualInfo
*visinfo
;
275 scrnum
= DefaultScreen( dpy
);
276 root
= RootWindow( dpy
, scrnum
);
278 visinfo
= glXChooseVisual( dpy
, scrnum
, attrib
);
280 printf("Error: couldn't get an RGB, Double-buffered visual\n");
284 /* window attributes */
285 attr
.background_pixel
= 0;
286 attr
.border_pixel
= 0;
287 attr
.colormap
= XCreateColormap( dpy
, root
, visinfo
->visual
, AllocNone
);
288 attr
.event_mask
= StructureNotifyMask
| ExposureMask
;
289 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
291 win
= XCreateWindow( dpy
, root
, 0, 0, width
, height
,
292 0, visinfo
->depth
, InputOutput
,
293 visinfo
->visual
, mask
, &attr
);
295 ctx
= glXCreateContext( dpy
, visinfo
, NULL
, True
);
297 glXMakeCurrent( dpy
, win
, ctx
);
304 void setmaterial(GLfloat
*color
)
307 glMaterialfv(GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, color
);
308 glMaterialfv(GL_FRONT
, GL_SPECULAR
, white
);
309 glMaterialfv(GL_FRONT
, GL_SHININESS
, &shiny
);
312 void makedots(float size
)
318 glDisable(GL_LIGHTING
);
330 glEnable(GL_LIGHTING
);
334 void norm2(float *p1
,float *p2
,float *p3
)
351 glNormal3f(nx
,ny
,nz
);
355 void makespiky(GLfloat
*color
,float scale
)
360 float x1
[SPIKES
],y1
[SPIKES
];
361 float x2
[SPIKES
],y2
[SPIKES
];
364 float p0
[3],p1
[3],p2
[3];
368 for(i
=0;i
<SPIKES
;++i
)
371 x1
[i
]=cosf(a
)*scale
*SPIKEIN
;
372 y1
[i
]=sinf(a
)*scale
*SPIKEIN
;
373 x2
[i
]=cosf(a
+b2
)*scale
;
374 y2
[i
]=sinf(a
+b2
)*scale
;
377 glDisable(GL_TEXTURE_2D
);
378 glEnable(GL_NORMALIZE
);
381 glBegin(GL_TRIANGLE_FAN
);
390 for(i
=0;i
<SPIKES
;++i
)
393 if(j
>=SPIKES
) j
-=SPIKES
;
426 #define LIFESIZE 2.0f
427 #define LIFENORMAL 0.7f
429 #define SECTIONYELLOW 4
434 glTranslatef(LIFEX
,LIFEY
,LIFEZ2
);
435 glRotatef(11.0f
, 0.0f
, 1.0f
, 0.0f
);
440 glNormal3f(0.0f
, 0.0f
, 1.0f
);
441 glBegin(GL_LINE_LOOP
);
442 for(i
=0;i
<SECTIONS
;++i
)
444 glVertex3f(sinf(a
)*LIFESIZE
,cosf(a
)*LIFESIZE
, 0.0);
449 glBegin(GL_TRIANGLE_FAN
);
450 glEnable(GL_NORMALIZE
);
451 glVertex3f(0.0, 0.0, LIFEZ1
-LIFEZ2
);
455 a
=PI
*2.0f
*life
/LIFEVISIBLE
;
458 glNormal3f(x
,y
,LIFENORMAL
);
459 glVertex3f(x
,y
,0.0f
);
460 i
=(int)(life
*(float)SECTIONS
/LIFEVISIBLE
);
464 else if(i
>SECTIONRED
)
466 else setmaterial(red
);
470 if(i
==SECTIONYELLOW
) setmaterial(yellow
);
471 else if(i
==SECTIONRED
) setmaterial(red
);
473 glNormal3f(sinf(a
), cosf(a
), LIFENORMAL
);
476 glVertex3f(sinf(a
)*LIFESIZE
,cosf(a
)*LIFESIZE
,0.0);
480 glTranslatef(0.0f
, -3.0f
, 0.0f
);
481 glRotatef(timeindicator
,0.0f
, 0.0f
, 1.0f
);
482 glCallList(objectlists
+8);
487 void setgrey(float v
)
489 float col
[4]={v
,v
,v
,v
};
490 glMaterialfv(GL_FRONT
,GL_AMBIENT_AND_DIFFUSE
, col
);
494 void f2(float angle
, GLfloat
*color
, int orient
)
505 // glDisable(GL_DEPTH_TEST);
510 glRotatef(angle
, 0.1f
, 1.0f
, 0.0f
);
516 if(i
==1 && j
>=1 && j
<4) continue;
541 glTranslatef(nx
-xt
,ny
-yt
,nz
-zt
);
546 // glRotatef(e->angle,e->ax,e->ay,e->az);
548 glCallList(objectlists
+1);
558 static float angle
=0.0;
560 glTranslatef(-5.5, -3.0, 10.0);
561 glScalef(FDOWN
, FDOWN
, FDOWN
);
573 static void draw(void)
577 float xt
,yt
,zt
,x
,y
,t
;
582 if(clearing
|| clearonce
)
584 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
585 if(clearonce
) clearonce
=0;
588 glLightfv(GL_LIGHT0
, GL_POSITION
, lightpos
);
589 glLightfv(GL_LIGHT1
, GL_POSITION
, light1pos
);
590 glLightfv(GL_LIGHT2
, GL_POSITION
, light2pos
);
593 if(gamestate
==PLAYING
) showlife();
603 glDisable(GL_DEPTH_TEST
);
614 nz
+=(1.0f
-e
->vanish
)*50.0f
;
618 a
=e
->swapping
*PI
/2.0f
/SWAPTIME
;
627 glTranslatef(nx
-xt
,ny
-yt
,nz
-zt
);
631 if(gamestate
==PLAYING
&& cposx
==i
&& cposy
==j
)
633 if(e
->swapping
) {glDisable(GL_BLEND
);glEnable(GL_DEPTH_TEST
);}
635 glRotatef(e
->angle
,e
->ax
,e
->ay
,e
->az
);
636 // glScalef(e->vanish,e->vanish,e->vanish);
637 setmaterial(colormaps
[e
->type
]);
641 glCallList(objectlists
+e
->type
);
643 if(e
->swapping
) {glEnable(GL_BLEND
);glDisable(GL_DEPTH_TEST
);}
644 if(gamestate
==PLAYING
&& cposx
==i
&& cposy
==j
)
645 glDisable(GL_LIGHT2
);
651 glEnable(GL_DEPTH_TEST
);
652 if(0 && cposx
>=0 && cposy
>=0 && cposx
<EX
&& cposy
<EY
)
654 nx
=-SPACING
*(-cposx
+EY
/2.0f
-0.5f
);
655 ny
= SPACING
*(-cposy
+EY
/2.0f
-0.5f
);
656 glTranslatef(nx
-xt
,ny
-yt
,nz
-zt
);
658 // glRotatef(cursorrot,.70710,-.70710,0.0);
660 // glCallList(objectlists+7);
663 glRotatef(cursorrot
,1.0f
,0.0f
,0.0f
);
664 glCallList(objectlists
+7);
670 #define SCORESPRITEFADE 0.01f
672 for(i
=0;i
<MAXSCORESPRITES
;++i
)
675 struct scoresprite
*ss
=scoresprites
+i
;
676 if(ss
->fade
==0.0) continue;
677 col
[0]=col
[1]=col
[2]=ss
->fade
;
679 glMaterialfv(GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, col
);
681 glTranslatef(ss
->x
,ss
->y
-(1.0f
-ss
->fade
),ss
->z
);
682 drawstring(1,"+%d",ss
->value
);
686 glMaterialfv(GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, red
);
689 glTranslatef(SCOREX
+SCORETAB
,SCOREY
,SCOREZ
);
690 drawstring(2,"%d",score
);
691 glTranslatef(0.0, -LINESPACE
, 0.0);
692 drawstring(2,"%d",level
);
693 glTranslatef(0.0, -LINESPACE
, 0.0);
694 drawstring(2,"%d",nummoves
);
695 glTranslatef(0.0, -LINESPACE
, 0.0);
699 glTranslatef(SCOREX
,SCOREY
,SCOREZ
);
700 drawstring(0,"Score");
701 glTranslatef(0.0, -LINESPACE
, 0.0);
702 drawstring(0,"Level");
703 glTranslatef(0.0, -LINESPACE
, 0.0);
704 drawstring(0,"Moves");
705 if(gamestate
!=PLAYING
)
707 glTranslatef(0.0f
, -3.5f
*LINESPACE
, 0.0f
);
708 drawstring(0,"Game Over");
710 else if(cumulativefade
>0.0)
712 setgrey(cumulativefade
);
714 glTranslatef(SCORETAB
/2.0, -LINESPACE
, 0.0);
715 drawstring(1,"+%d",cumulative
);
720 if(gamestate
!=PLAYING
)
722 struct highscore
*h
=highscores
+baseshow
;
725 glMaterialfv(GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, dimmer
);
726 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
727 glDisable(GL_LIGHT0
);
728 glDisable(GL_LIGHT1
);
730 glVertex3f(HIGHLEFT
,HIGHTOP
,HIGHZ
);
731 glVertex3f(HIGHLEFT
,HIGHBOTTOM
,HIGHZ
);
732 glVertex3f(HIGHRIGHT
,HIGHBOTTOM
,HIGHZ
);
733 glVertex3f(HIGHRIGHT
,HIGHTOP
,HIGHZ
);
737 glBlendFunc(GL_ONE
,GL_ONE
);
741 glTranslatef(HIGHX
,HIGHY
,HIGHZ
);
742 glMaterialfv(GL_FRONT
, GL_AMBIENT_AND_DIFFUSE
, grey
);
745 drawstring(1,"Rank");
746 glTranslatef(HIGHXNAME
, 0.0, 0.0);
747 drawstring(0,"Name");
748 glTranslatef(HIGHXSCORE
, 0.0, 0.0);
749 drawstring(1,"Score");
750 glTranslatef(HIGHXLEVEL
, 0.0, 0.0);
751 drawstring(1,"Level");
753 glTranslatef(0.0, HIGHYSPACE
, 0.0);
755 for(i
=0;i
<10;++i
,++h
)
757 char nametemp
[MAXNAMELENGTH
];
758 strcpy(nametemp
,h
->name
);
759 if(enteringline
==i
+baseshow
)
761 glMaterialfv(GL_FRONT
,GL_AMBIENT_AND_DIFFUSE
, red
);
762 if(gamestate
==ENTERHIGH
)
763 strcat(nametemp
,">");
766 drawstring(1,"%d.",i
+baseshow
+1);
767 glTranslatef(HIGHXNAME
, 0.0, 0.0);
768 drawstring(0,"%s",nametemp
);
769 glTranslatef(HIGHXSCORE
, 0.0, 0.0);
770 drawstring(1,"%d",h
->score
);
771 glTranslatef(HIGHXLEVEL
, 0.0, 0.0);
772 drawstring(1,"%d",h
->level
);
774 glTranslatef(0.0, HIGHYSPACE
, 0.0);
775 if(enteringline
==i
+baseshow
)
776 glMaterialfv(GL_FRONT
,GL_AMBIENT_AND_DIFFUSE
, grey
);
782 SDL_GL_SwapBuffers();
787 void showmatrix(float *f
)
789 printf("%f %f %f %f\n",f
[0],f
[4],f
[8],f
[12]);
790 printf("%f %f %f %f\n",f
[1],f
[5],f
[9],f
[13]);
791 printf("%f %f %f %f\n",f
[2],f
[6],f
[10],f
[14]);
792 printf("%f %f %f %f\n",f
[3],f
[7],f
[11],f
[15]);
795 void getpos(int *px
,int *py
,int mx
,int my
)
800 glGetIntegerv(GL_VIEWPORT
,viewport
);
801 screen
[0]=(mx
-viewport
[0])*2.0f
/viewport
[2]-1.0f
;
802 screen
[1]=(my
-viewport
[1])*2.0f
/viewport
[3]-1.0f
;
803 screen
[2]=0.27272727f
;
805 matrixXvector(&world
,&unprojectmatrix
,&screen
);
809 float z
=world
[2]/world
[3];
810 x
=(z
*world
[0]/world
[3]-SHIFTX
)/SPACING
+EX
/2;
811 y
=(z
*world
[1]/world
[3]-SHIFTY
)/SPACING
+EY
/2;
812 *px
=(int)(x
+1000)-1000;
813 *py
=(int)(y
+1000)-1000;
843 unsigned char temp
[EY
+4][EX
+4];
847 memset(temp
,0xff,sizeof(temp
));
851 temp
[j
+2][i
+2]=e
++ -> type
;
859 if(t
!=temp
[j
+wins
[k
][1]][i
+wins
[k
][0]]) continue;
860 if(t
!=temp
[j
+wins
[k
][3]][i
+wins
[k
][2]]) continue;
863 return nummoves
=moves
;
872 while(j
--) e
++ -> vanish
=0.999f
;
873 playsound(BIGDROPSOUND
);
876 void randomvector(float *x
,float *y
,float *z
)
883 ix
=(rand()&1023)-512;
884 iy
=(rand()&1023)-512;
885 iz
=(rand()&1023)-512;
886 } while(ix
==0 && iy
==0 && iz
==0);
887 d
=1.0f
/sqrtf((float)(ix
*ix
+iy
*iy
+iz
*iz
));
894 void initelement(struct element
*e
)
897 memset(e
,0,sizeof(*e
));
898 e
->type
=(rand()&0xffff)%7;
899 e
->angle
=(rand()&1023)*360.0f
/1024.0f
;
902 randomvector(&e
->ax
,&e
->ay
,&e
->az
);
905 void initelements(void)
918 struct element
*e
,*e2
;
928 if(e
->vanish
!=0.0) continue;
933 if(e2
->vanish
!=0.0) break;
943 e
->fall
=j
+falls
[i
]++;
949 void addlife(int chain
,int len
,float x
,float y
)
953 struct scoresprite
*ss
;
955 cumulative
=cumulativebuildup
+=value
;
957 for(ss
=scoresprites
,i
=0;i
<MAXSCORESPRITES
;++i
,++ss
)
959 if(ss
->fade
!=0.0f
) continue;
960 ss
->x
=(x
-EX
/2.0f
+0.5f
)*SPACING
+SHIFTX
;
961 ss
->y
=-(y
-EY
/2.0f
)*SPACING
+SHIFTY
;
969 life
+=(value
)*CREDIT
;
983 h
=highscores
+MAXHIGHSCORES
;
984 while(h
>highscores
&& h
[-1].score
<score
) --h
;
985 enteringline
=h
-highscores
;
986 baseshow
=enteringline
-5;
987 if(baseshow
<0) baseshow
=0;
988 if(baseshow
>MAXHIGHSCORES
-10) baseshow
=MAXHIGHSCORES
-10;
989 if(enteringline
==MAXHIGHSCORES
) return;
990 memmove(h
+1,h
,(MAXHIGHSCORES
-enteringline
)*sizeof(struct highscore
));
991 strcpy(h
->name
,lastentered
);
998 timeindicator
-=decay
*5.0f
;
1003 if(gamestate
!=GAMEOVER
)
1006 playsound(GAMEOVERSOUND
);
1011 int findwins(int justchecking
)
1024 if(i
<EX
&& e
->type
==e
[-1].type
) ++k
;
1032 addlife(chainreaction
,k
-1,x
,y
);
1035 while(k
) e
[-k
--].vanish
=0.999f
;
1047 if(i
<EY
&& e
->type
==e
[-EX
].type
) ++k
;
1055 addlife(chainreaction
,k
-1,x
,y
);
1058 while(k
) e
[-EX
*k
--].vanish
=0.999f
;
1067 playsound(ROWSOUND
);
1069 } else chainreaction
=0,cumulativebuildup
=0;
1075 char swapfifo
[SWAPMAX
][4];
1076 int swapput
=0,swaptake
=0;
1077 void addswap(int px
,int py
,int dx
,int dy
)
1080 if(((swapput
+1) & (SWAPMAX
-1)) == swaptake
) return;
1081 p
=swapfifo
[swapput
++];
1092 struct element
*e1
,*e2
;
1095 if(swapput
==swaptake
) return 0;
1097 playsound(SWAPSOUND
);
1098 p
=swapfifo
[swaptake
++];
1099 swaptake
&=SWAPMAX
-1;
1105 e2
=elements
[py
+dy
]+px
+dx
;
1119 #define FALLRATE 0.02f
1120 #define VANISHRATE 0.05f
1124 void illegal(struct element
*e1
,struct element
*e2
)
1153 struct element
*e
,*le
,*e1
=0,*e2
=0;
1156 struct scoresprite
*ss
;
1158 if(gamestate
==PLAYING
&& life
<ALARMLEVEL
*50*decay
)
1163 playsound(ALERTSOUND
);
1168 for(i
=0,ss
=scoresprites
;i
<MAXSCORESPRITES
;++i
,++ss
)
1170 ss
->fade
-=SCORESPRITEFADE
;
1171 if(ss
->fade
<0.0) ss
->fade
=0.0;
1174 cumulativefade
-=SCORESPRITEFADE
;
1175 if(cumulativefade
<0.0) cumulativefade
=0.0;
1179 while(e
<le
) e
++ ->angle
+=3.0;
1183 case ACTION_LOOKING
:
1185 actionmode
=ACTION_REMOVING
;
1188 actionmode
=ACTION_WAITING
;
1190 {tossall();actionmode
=ACTION_REMOVING
;}
1192 case ACTION_WAITING
:
1193 if(gamestate
!=PLAYING
) break;
1195 if(tryswap()) actionmode
=ACTION_SWAPPING
;
1197 case ACTION_UNSWAPPING
:
1199 case ACTION_SWAPPING
:
1208 if(e
->swapping
==SWAPTIME
)
1221 actionmode
=ACTION_REMOVING
;
1222 else if(actionmode
==ACTION_SWAPPING
)
1224 playsound(ILLEGALSOUND
);
1226 actionmode
=ACTION_UNSWAPPING
;
1228 actionmode
=ACTION_WAITING
;
1231 case ACTION_REMOVING
:
1238 e
->vanish
-=VANISHRATE
;
1251 actionmode
=ACTION_DROPPING
;
1254 case ACTION_DROPPING
:
1266 e
->fall
=e
->speed
=0.0;
1269 playsound(DROPSOUND
);
1276 if(!hadsome
) actionmode
=ACTION_LOOKING
;
1282 static int downcodes
[MAXCODES
];
1283 static int pressedcodes
[MAXCODES
];
1284 static int numcodes
=0,numpressed
=0;
1286 void processkey(int key
,int state
)
1291 if(numpressed
<MAXCODES
) pressedcodes
[numpressed
++]=key
;
1292 for(i
=0;i
<numcodes
;++i
)
1293 if(downcodes
[i
]==key
) return;
1294 if(numcodes
<MAXCODES
)
1295 downcodes
[numcodes
++]=key
;
1298 for(i
=0;i
<numcodes
;)
1300 if(downcodes
[i
]==key
)
1301 downcodes
[i
]=downcodes
[--numcodes
];
1311 for(i
=0;i
<numcodes
;++i
)
1312 if(downcodes
[i
]==key
) return 1;
1316 int WasPressed(int key
)
1319 for(i
=0;i
<numpressed
;++i
)
1320 if(pressedcodes
[i
]==key
) return 1;
1324 void writehighscores();
1326 void typedkey(int key
)
1329 if(key
<0 || key
>0x7f) return;
1330 p
=highscores
[enteringline
].name
;
1331 if(key
==10 || key
==13)
1338 if(*p
) p
[strlen(p
)-1]=0;
1340 if(strlen(p
)<MAXNAMELENGTH
-1)
1346 strcpy(lastentered
,highscores
[enteringline
].name
);
1352 void down(int x
,int y
)
1360 #define ABS(x) (((x)<0) ? (-(x)) : (x))
1361 void moved(int x
,int y
)
1366 getpos(&cposx
,&cposy
,x
,y
);
1370 if(dx
*dx
+dy
*dy
<DIST
*DIST
) return;
1383 getpos(&px
,&py
,downx
,downy
);
1386 px=(EX>>1)+((float)downx/sizex-0.5)*FIX;
1387 py=(EY>>1)+((float)downy/sizey-0.5)*FIX;
1390 if(px
<0 || px
>=EX
|| py
<0 || py
>=EY
) return;
1391 if(px
+dx
<0 || px
+dx
>=EX
|| py
+dy
<0 || py
+dy
>=EY
) return;
1392 addswap(px
,py
,dx
,dy
);
1396 void up(int x
,int y
)
1407 do initelements(); while(findwins(1));
1408 chainreaction
=swapput
=swaptake
=0;
1414 cumulativebuildup
=0;
1419 for(i
=0;i
<MAXSCORESPRITES
;++i
) scoresprites
[i
].fade
=0.0;
1420 actionmode
=ACTION_LOOKING
;
1427 void thandler(int val
)
1429 signal(SIGALRM
,thandler
);
1434 static void event_loop( void )
1443 Uint32 ticks
= SDL_GetTicks();
1447 Uint32 new_ticks
= SDL_GetTicks();
1448 Uint32 delta
= new_ticks
- ticks
;
1449 if (delta
> (1000/44))
1458 if(WasPressed(SDLK_F1
)) initgame();
1459 if(WasPressed(SDLK_F2
)) playsound(BIGDROPSOUND
);
1460 if(WasPressed(SDLK_F3
)) playsound(GAMEOVERSOUND
);
1461 if(WasPressed(SDLK_F4
)) playsound(ROWSOUND
);
1462 if(WasPressed(SDLK_F5
)) playsound(ILLEGALSOUND
);
1463 if(WasPressed(SDLK_F6
)) playsound(ALERTSOUND
);
1466 if(gamestate
==PLAYING
&& WasPressed(XK_p
)) freeze
=!freeze
;
1468 if(gamestate
==GAMEOVER
&& WasPressed(SDLK_SPACE
)) initgame();
1469 // if(WasPressed(XK_p)) freeze=!freeze;
1473 while(SDL_PollEvent(&event
))
1477 case SDL_MOUSEMOTION
:
1478 mousex
=event
.motion
.x
;
1479 mousey
=event
.motion
.y
;
1480 moved(mousex
, mousey
);
1482 case SDL_MOUSEBUTTONDOWN
:
1483 mousex
=event
.button
.x
;
1484 mousey
=event
.button
.y
;
1485 down(mousex
, mousey
);
1487 case SDL_MOUSEBUTTONUP
:
1488 mousex
=event
.button
.x
;
1489 mousey
=event
.button
.y
;
1493 code
=event
.key
.keysym
.sym
;
1494 if(code
==SDLK_ESCAPE
) exitflag
=1;
1495 processkey(code
, 1);
1496 if(gamestate
==ENTERHIGH
) typedkey(code
);
1499 code
=event
.key
.keysym
.sym
;
1500 processkey(code
, 0);
1502 case SDL_VIDEORESIZE
:
1503 resize(event
.resize
.w
, event
.resize
.h
);
1514 void makehighname(char *p
)
1516 char *homedir
= getenv("HOME");
1518 sprintf(p
,"%s/%s",homedir
,HIGHSCOREFILENAME
);
1520 sprintf(p
,"%s",HIGHSCOREFILENAME
);
1523 void readhighscores()
1529 struct highscore
*h
;
1531 memset(highscores
,0,sizeof(highscores
));
1532 makehighname(tempname
);
1533 f
=fopen(tempname
,"r");
1535 for(h
=highscores
,i
=0;i
<MAXHIGHSCORES
;++i
,++h
)
1537 n
=fscanf(f
,"%s %d %d",tempname
,&score
,&level
);
1540 tempname
[MAXNAMELENGTH
-1]=0;
1541 if(*tempname
=='.') *tempname
=0;
1542 strcpy(h
->name
,tempname
);
1548 void writehighscores()
1553 struct highscore
*h
;
1555 makehighname(tempname
);
1556 f
=fopen(tempname
,"w");
1559 for(h
=highscores
,i
=0;i
<MAXHIGHSCORES
;++i
,++h
)
1561 fprintf(f
,"%s %d %d\n",h
->name
[0] ? h
->name
: ".",h
->score
,h
->level
);
1567 int main( int argc
, char *argv
[] )
1569 SDL_Surface
*screen
;
1571 // if(fork()) return;
1584 SDL_Init(SDL_INIT_VIDEO
);
1588 screen
= setvideomode(sizex
, sizey
);
1589 SDL_WM_SetCaption("glJewel", "gljewel");
1591 resize(sizex
, sizey
);
1593 // glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
1594 glEnable(GL_CULL_FACE
);
1595 glEnable(GL_LIGHTING
);
1596 glEnable(GL_LIGHT0
);
1597 glEnable(GL_LIGHT1
);
1598 glLightfv(GL_LIGHT0
,GL_SPECULAR
,white
);
1599 glLightfv(GL_LIGHT0
,GL_DIFFUSE
,grey
);
1600 glLightfv(GL_LIGHT1
,GL_SPECULAR
,white2
);
1601 glLightfv(GL_LIGHT1
,GL_DIFFUSE
,grey2
);
1602 glLightfv(GL_LIGHT2
,GL_SPECULAR
,white
);
1603 glLightfv(GL_LIGHT2
,GL_DIFFUSE
,grey
);
1604 glEnable(GL_DEPTH_TEST
);
1606 glShadeModel( GL_FLAT
);
1607 glClearColor( 0.0, 0.0, 0.0, 1.0 );
1608 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
1610 glDisable(GL_BLEND
);
1611 // glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1612 glBlendFunc(GL_ONE
, GL_ONE
);
1614 #ifndef HAVE_GL_VERTEX_BUFFERS
1615 initGlVboExtension();
1619 glDisable(GL_LINE_SMOOTH
);
1623 objectlists
= glGenLists(9);
1624 glNewList(objectlists
+0, GL_COMPILE
);
1625 makebucky(0.9*SCALE
); // blue
1628 glNewList(objectlists
+1, GL_COMPILE
);
1629 makebcube(SCALE
); // orange
1632 glNewList(objectlists
+2, GL_COMPILE
);
1633 makepyramid(0.7*SCALE
); // yellow
1635 create_pyramid(&shapes
[2]);
1636 shapes
[2].create(0.7f
*SCALE
);
1638 glNewList(objectlists
+3, GL_COMPILE
);
1639 makeicosahedron(0,SCALE
); // magenta
1642 glNewList(objectlists
+4, GL_COMPILE
);
1643 makecylinder(0.8f
*SCALE
); // green
1646 glNewList(objectlists
+5, GL_COMPILE
);
1647 makediamond(0.9f
*SCALE
); // red
1650 glNewList(objectlists
+6, GL_COMPILE
);
1651 makeuvsphere(0.9f
*SCALE
); // white
1654 glNewList(objectlists
+7, GL_COMPILE
);
1655 makedots(0.95f
*SCALE
);
1658 glNewList(objectlists
+8, GL_COMPILE
);
1659 makespiky(blue
, 1.0);