Graphical version

This commit is contained in:
marco 1999-12-31 17:04:22 +00:00
parent 3f1c1e087b
commit ddbb4377dd

View File

@ -6,10 +6,12 @@
SameGame is a standard game in GNOME and KDE. I liked it, and I
automatically brainstormed how I would implement it.
It turned out to be really easy, and is basically only 100 lines or so.
It turned out to be really easy, and is basically only 100 lines or so,
the rest is scorekeeping, helptext, menu etc.
The game demonstrates some features of the MSMOUSE unit, and some of
the Crt unit.
the Crt and Graph units. (depending whether it is compiled with
UseGraphics or not)
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
@ -20,19 +22,66 @@
**********************************************************************}
PROGRAM SameGame;
Uses Crt,GameUnit;
CONST FieldX = 10; {Top left playfield coordinates}
Uses Crt,Dos,
{$IFDEF UseGraphics}
Graph,
{$ENDIF}
GameUnit;
CONST
GrFieldX = 10; {X topleft of playfield}
GrFieldY = 70; {Y topleft of playfield}
ScalerX = 22; {ScalerX x Scaler y dots
must be approx a square}
ScalerY = 20;
FieldX = 10; {Top left playfield
coordinates in squares(textmode)}
FieldY = 3; {Top left playfield coordinates}
PlayFieldXDimension = 20; {Dimensions of playfield}
PlayFieldYDimension = 15;
RowDispl = 15;
MenuX = 480;
MenuY = 120;
grNewGameLine = 'NEW GAME';
grHelpLine = 'HELP';
grEndGame = 'END GAME';
{Used colors. Colors[0..2] are the colors used on the playfield, Colors[3]
is the background and Colors[4] is the color used to mark the pieces}
Colors : ARRAY [0..4] OF LONGINT = (White,Blue,Red,Black,LightMagenta);
TYPE PlayFieldType=ARRAY[0..PlayFieldXDimension-1,0..PlayFieldYDimension-1] OF BYTE;
{$IFDEF UseGraphics}
PROCEDURE DisplayPlayField(CONST PlayField:PlayFieldType);
{Screen routine, simply puts the array Playfield on screen.
Both used for displaying the normal grid as the grid with a certain area marked}
VAR X,Y : LONGINT;
LastOne,
NumbLast : LONGINT;
BEGIN
HideMouse;
FOR Y:=0 TO PlayFieldYDimension-1 DO
BEGIN
X:=0;
REPEAT
LastOne:=PlayField[X,Y];
NumbLast:=X;
WHILE (PlayField[X,Y]=LastOne) AND (X<(PlayFieldXDimension-1))DO
INC(X);
SetFillStyle(SolidFill,Colors[LastOne]);
Bar(GrFieldX+NumbLast*ScalerX,GrFieldY+Y*ScalerY,GrFieldX+X*ScalerX-1,GrFieldY+(Y+1)*ScalerY-1);
UNTIL X>=(PlayFieldXDimension-1);
END;
ShowMouse;
END;
{$ELSE}
PROCEDURE DisplayPlayField(CONST PlayField:PlayFieldType);
{Screen routine, simply puts the array Playfield on screen.
Both used for displaying the normal grid as the grid with a certain area marked}
@ -50,6 +99,7 @@ BEGIN
END;
END;
END;
{$ENDIF}
PROCEDURE ShowHelp;
{Shows some explanation of the game and waits for a key}
@ -57,34 +107,59 @@ PROCEDURE ShowHelp;
VAR I : LONGINT;
BEGIN
FOR I:=2 TO 24 DO
BEGIN
GotoXY(1,I);
ClrEol;
END;
GotoXY(1,3); TextColor(White);
Write('SAMEGAME');
SetDefaultColor;
WriteLn(' is a small game, with a principle copied from some KDE game');
WriteLn;
WriteLn('I tried to implement it under Go32V2 to demonstrate the MsMouse unit');
Writeln('When it worked, I tried to get it running under Linux. I succeeded,');
Writeln('but the mouse unit of the API doesn'#39't work with GPM 1.17');
Writeln;
WriteLn('If you move over the playfield, aggregates of one color will be marked');
Writeln('in purple. If you then press the left mouse button, that aggregate will');
Writeln('disappear, and the playfield will collapse to the bottom-left. Please');
Writeln('keep in mind that only an aggregate of two blocks or more will disappear.');
Writeln;
Writeln('For every aggregate you let disappear you get points, but the score is');
Writeln('quadratic proportional to the number of blocks killed. So 4 times killing');
Writeln(' a 4 block aggregate scores 4 points, and one time 16 blocks will score 64');
Writeln('blocks. The purpose of the game is obtaining the highscore');
Writeln;
Writeln('If you manage to kill the entire playfield, you'#39'll get a bonus');
Writeln;
WriteLn('Press any key to get back to the game');
GetKey;
{$IFDEF UseGraphics}
HideMouse;
SetbkColor(black);
SetViewPort(0,0,getmaxx,getmaxy,clipoff);
ClearViewPort;
SetTextStyle(0,Horizdir,2);
OutTextXY(220,10,'SAMEGAME');
SetTextStyle(0,Horizdir,1);
OutTextXY(5,40+1*LineDistY,' is a small game, with a principle copied from some KDE game');
OutTextXY(5,40+3*LineDistY,'I tried to implement it under Go32V2 to demonstrate the MsMouse unit');
OutTextXY(5,40+4*LineDistY,'When it worked, I tried to get it running under Linux. I succeeded,');
OutTextXY(5,40+5*LineDistY,'but the mouse unit of the API doesn'#39't work with GPM 1.17');
OutTextXY(5,40+7*LineDistY,'If you move over the playfield, aggregates of one color will be marked');
OutTextXY(5,40+8*LineDistY,'in purple. If you then press the left mouse button, that aggregate will');
OutTextXY(5,40+9*LineDistY,'disappear, and the playfield will collapse to the bottom-left. Please');
OutTextXY(5,40+10*LineDistY,'keep in mind that only an aggregate of two blocks or more will disappear.');
OutTextXY(5,40+12*LineDistY,'For every aggregate you let disappear you get points, but the score is');
OutTextXY(5,40+13*LineDistY,'quadratic proportional to the number of blocks killed. So 4 times killing');
OutTextXY(5,40+14*LineDistY,' a 4 block aggregate scores 4 points, and one time 16 blocks will score 64');
OutTextXY(5,40+15*LineDistY,'blocks. The purpose of the game is obtaining the highscore');
OutTextXY(5,40+17*LineDistY,'If you manage to empty the entire playfield, you'#39'll get a bonus');
OutTextXY(5,40+19*LineDistY,'Press any key to get back to the game');
ShowMouse;
{$ELSE}
FOR I:=2 TO 24 DO
BEGIN
GotoXY(1,I);
ClrEol;
END;
GotoXY(1,3); TextColor(White);
Write('SAMEGAME');
SetDefaultColor;
WriteLn(' is a small game, with a principle copied from some KDE game');
WriteLn;
WriteLn('I tried to implement it under Go32V2 to demonstrate the MsMouse unit');
Writeln('When it worked, I tried to get it running under Linux. I succeeded,');
Writeln('but the mouse unit of the API doesn'#39't work with GPM 1.17');
Writeln;
WriteLn('If you move over the playfield, aggregates of one color will be marked');
Writeln('in purple. If you then press the left mouse button, that aggregate will');
Writeln('disappear, and the playfield will collapse to the bottom-left. Please');
Writeln('keep in mind that only an aggregate of two blocks or more will disappear.');
Writeln;
Writeln('For every aggregate you let disappear you get points, but the score is');
Writeln('quadratic proportional to the number of blocks killed. So 4 times killing');
Writeln(' a 4 block aggregate scores 4 points, and one time 16 blocks will score 64');
Writeln('blocks. The purpose of the game is obtaining the highscore');
Writeln;
Writeln('If you manage to empty the entire playfield, you'#39'll get a bonus');
Writeln;
WriteLn('Press any key to get back to the game');
{$ENDIF}
GetKey;
END;
VAR MarkField,PlayField : PlayFieldType; {The playfield, and the marked form}
@ -96,6 +171,7 @@ PROCEDURE ShowButtons;
{Shows the clickable buttons}
BEGIN
{$IFNDEF UseGraphics}
TextColor(Yellow); TextBackGround(Blue);
GotoXY(60,5); Write('NEW game');
GotoXY(60,6); Write('HELP');
@ -103,7 +179,14 @@ BEGIN
{$IFDEF Linux}
GotoXY(60,8); Write('Force IBM charset');
{$ENDIF}
SetDefaultColor;
SetDefaultColor;
{$ELSE}
SetTextStyle(0,Horizdir,1);
OutTextXY(MenuX,MenuY,grNewGameLine);
OutTextXY(MenuX,MenuY+RowDispl,grHelpLine);
OutTextXY(MenuX,MenuY+2*RowDispl,grEndGame);
{$ENDIF}
END;
FUNCTION PlayFieldPiecesLeft:LONGINT;
@ -123,11 +206,20 @@ END;
PROCEDURE ShowScore;
{Simply procedure to update the score}
VAR S : String;
BEGIN
{$IFDEF UseGraphics}
Str(Score:5,S);
SetFillStyle(SolidFill,0);
Bar(300,440,450,458);
OutTextXY(300,440,'Score :'+S);
{$ELSE}
TextColor(White);
GotoXY(20,23); Write(' ':20);
GotoXY(20,23); Write('Score : ',Score);
SetDefaultColor;
{$ENDIF}
END;
FUNCTION CubesToScore : LONGINT;
@ -237,11 +329,25 @@ PROCEDURE BuildScreen;
{Some procedures that build the screen}
BEGIN
ClrScr; Score:=0;
{$IFDEF UseGraphics}
setbkcolor(black);
setviewport(0,0,getmaxx,getmaxy,clipoff);
clearviewport;
{$ELSE}
ClrScr;
{$ENDIF}
Score:=0;
ShowScore;
ShowButtons;
ShowHighScore;
ShowMouse;
{$IFDEF UseGraphics}
SetTextStyle(0,Horizdir,2);
OuttextXY(10,10,'SameGame v0.03, (C) by Marco v/d Voort. ');
SetTextStyle(0,Horizdir,1);
OuttextXY(50,40,'A demo for the FPC RTL and API units Crt,(MS)Mouse and Graph');
{$ELSE}
GotoXY(1,1);
TextColor(Yellow);
Write('SameGame v0.02');
@ -250,6 +356,7 @@ BEGIN
TextColor(Yellow); Write('FPC');
TextColor(White); Write(' API or MsMouse unit. By Marco van de Voort');
SetDefaultColor;
{$ENDIF}
IF LastScore<>0 THEN
BEGIN
GotoXY(10,20);
@ -267,6 +374,7 @@ VAR X,Y,
MX,MY,MState,Dummy : LONGINT;
EndOfGame : LONGINT;
S : String;
DoneSomething : BOOLEAN;
BEGIN
RANDOMIZE;
@ -276,8 +384,14 @@ BEGIN
EndOfGame:=0;
REPEAT
GetMouseState(MX,MY,MState);
X:=MX SHR 3;
Y:=MY SHR 3;
{$IFDEF UseGraphics}
X:=2*((MX-GrFieldX) DIV ScalerX) +FieldX;
Y:=((MY-GrFieldY) DIV ScalerY) +FieldY-1;
{$ELSE}
X:=MX SHR 3;
Y:=MY SHR 3;
{$ENDIF}
DoneSomething:=FALSE;
IF PlayFieldPiecesLeft=0 THEN
BEGIN
INC(Score,1000);
@ -285,10 +399,21 @@ BEGIN
END
ELSE
BEGIN
{$IFDEF UseGraphics}
IF (MX>=MenuX) AND (MX<(MenuX+16*Length(GrNewGameLine))) THEN
BEGIN {X in clickable area}
IF (MY>=MenuY) AND (MY<(MenuY+RowDispl*3+2)) THEN
BEGIN
X:=65; {X doesn't matter as long as it is 60..69}
Y:=((MY-MenuY) DIV RowDispl)+4;
END;
END;
{$ENDIF}
IF (X>=60) AND (X<=69) THEN
BEGIN
IF (MState AND LButton) <>0 THEN {If leftbutton pressed,}
BEGIN
DoneSomething:=TRUE;
IF Y=4 THEN
EndOfGame:=1;
IF Y=6 THEN
@ -311,12 +436,15 @@ BEGIN
END;
IF (X>=(FieldX-2)) AND (Y>=(FieldY-2)) THEN
BEGIN
DEC(X,FieldX-1); DEC(Y,FieldY-1);
DEC(X,FieldX-1);
DEC(Y,FieldY-1);
X:=X SHR 1;
IF (X<PlayFieldXDimension) AND (Y<PlayFieldYDimension) THEN
BEGIN
IF MarkField[X,Y]<>4 THEN
BEGIN
DoneSomething:=TRUE;
MarkField:=PlayField;
MarkAfield(X,Y);
DisplayPlayField(MarkField);
@ -326,8 +454,10 @@ BEGIN
GotoXY(20,22);
Write('Marked :',CubesToScore);
END;
IF (MState AND LButton) <>0 THEN {If leftbutton pressed,}
IF (MarkField[X,Y]=4) AND ((MState AND LButton) <>0) THEN
{If leftbutton pressed,}
BEGIN
DoneSomething:=TRUE;
REPEAT {wait untill it's released.
The moment of pressing counts}
GetMouseState(X,Y,Dummy);
@ -335,13 +465,13 @@ BEGIN
Colapse;
MarkField:=PlayField;
DisplayPlayField(MarkField);
END;
END;
END
END
END;
IF KeyPressed THEN
BEGIN
X:=GetKey;
IF (X=ORD('X')) OR (X=ORD('x')) THEN
IF (CHR(X) IN ['X','x','Q','q']) OR (X=27) THEN
EndOfGame:=2;
END;
END;
@ -350,9 +480,17 @@ BEGIN
X:=SlipInScore(Score);
IF X<>0 THEN
BEGIN
HideMouse;
ShowHighScore;
InputStr(S,HighX,HighY+12-X,10,FALSE,AlfaBeta);
{$IFDEF UseGraphics}
Str(Score:5,S);
OutTextXY(HighX+150,HighY+LineDistY*(10-X),S);
GrInputStr(S,HighX,HighY+LineDistY*(10-X),16,12,10,FALSE,AlfaBeta);
{$ELSE}
InputStr(S,HighX,HighY+12-X,10,FALSE,AlfaBeta);
{$ENDIF}
HighScore[X-1].Name:=S;
ShowMouse;
END;
LastScore:=Score;
UNTIL EndOFGame=2;
@ -361,8 +499,26 @@ END;
CONST FileName='samegame.scr';
VAR I : LONGINT;
Error : LONGINT;
{$IFDEF UseGraphics}
gd,gm : INTEGER;
Pal : PaletteType;
{$ENDIF}
BEGIN
{$IFDEF UseGraphics}
gm:=vgahi;
gd:=vga;
InitGraph(gd,gm,'');
if GraphResult <> grOk then
begin
Writeln('Graph driver ',gd,' graph mode ',gm,' not supported');
Halt(1);
end;
SetFillStyle(SolidFill,1);
GetDefaultPalette(Pal);
SetAllPalette(Pal);
{$ENDIF}
IF NOT MousePresent THEN
BEGIN
Writeln('No mouse found. A mouse is required!');
@ -373,7 +529,11 @@ BEGIN
LoadHighScore(FileName);
InitMouse;
CursorOff;
HighX:=52; HighY:=10; {the position of the highscore table}
{$IFDEF UseGraphics}
HighX:=450; HighY:=220; {the position of the highscore table}
{$else}
HighX:=52; HighY:=10; {the position of the highscore table}
{$endif}
DoMainLoopMouse;
@ -381,13 +541,21 @@ BEGIN
DoneMouse;
CursorOn;
SaveHighScore;
{$IFDEF UseGraphics}
CloseGraph;
{$ENDIF}
ClrScr;
Writeln;
Writeln('Last games'#39' score was : ',Score);
END.
{
$Log$
Revision 1.2 1999-06-01 19:24:33 peter
Revision 1.3 1999-12-31 17:04:22 marco
Graphical version
Revision 1.2 1999/06/01 19:24:33 peter
* updates from marco
Revision 1.1 1999/05/27 21:36:34 peter