Copy Link
Add to Bookmark
Report

HighScores

eZine's profile picture
Published in 
Techtutor
 · 29 Jul 2024

 ======================================================================== 
Just4Fun Productions presents:

Part 3 of: the Techtutor
(Topics never covered)


HighScores
========================================================================

Introduction

Welcome to part 3 of the Techtutor, this one is mainly for SuperFX users, because it explains how to read a string using the keyboard. It does however contains some information for beginners interested in putting a great highscore table in their game...

For an example of a very stylish high-score, read TECH03.PAS

---------------------------------------------------------------- 
For contacting Just4Fun or me (PeeBee) use the following ways:

Internet : http://people.zeelandnet.nl/rpb
Email : just4fun@zeelandnet.nl

SnailMail: P.Bestebroer
Anthony Edenlaan 28
4463 JC Goes (Zld.)
Holland

ICQ : 2309110 (probably fastest way to contact me)
----------------------------------------------------------------

Need more input...

First of all we'll need to get the name of the player, and the best way would be to let him/her type it. One problem occurs when using the engine, because we don't have the normal keyboard interrupt...

We could of course switch back to the old one, but it can be done different. The Engine contains an array which has the "names" of all the keys, and we are going to use that array... For the example, take a look at the GETINPUT procedure (tech03.pas) This procedure will get the input of the player, and return it. Note that this procedure could still use some work, like checking on ESCAPE to exit the input, and it has a few bugs in it. But the most important thing is shown, the checking on the correct key-pressed.

HighScore typecasting

Before we code anything, we'll have to define a HIGHSCORE type like this:

     TYPE  TScore = record 
name : string[8];
score : longint;
level : word;
date : Longint;
end;

VAR HiScore : array[1..15] of Tscore;

The example will record the following things about the new high-score:

  • Name of player, the most important item
  • Score of player, very nice to know...
  • Level reached, the level the player reached.
  • Date of game, this is to show when the game was played...

Of course not all these are needed, but just use what you want in you'r game, and simply erase the rest. Now that we have the type, we made an array of 1..15, so we can record 15 players..again this can be changed for you'r own desires.

Who makes the list...

The next thing we should do is checking if the player has a new highscore. To do this, we'll have to walk thru the existing list, and see if the score is larger then the lowest...if it is we need to know if it's higher then the next, and the next, and the next, etc...

{=-=-= Example =-=-=-=} 
FUNCTION SeeHIScore(Nscore:longint;Nlevel:word):boolean;
VAR i,j : byte;
done : boolean;
dow,hs : word;
tempD : DateTime;

BEGIN
SeeHiscore:=false;
if Nscore<HiScore[15].score then exit;{ if score is lower than last
one,exit}
i:=15;
done:=false;
repeat
if Nscore>HiScore[i].score then dec(i) else Done:=true;
until (i=0) or (done);
inc(i);
SeeHiScore:=true;
for j:=14 downto i do HiScore[j+1]:=HiScore[j];
with HiScore[i] do begin { add new highscore }
Name:=GetName; { get the name }

score := Nscore; { add score }
level := NLevel; { add level }
GetDate(TempD.year,TempD.month,TempD.day,dow);
GetTime(TempD.hour,TempD.min,TempD.sec,hs);
PackTime(TempD,date); { add date }
end;
END;
{=-=-= End of Example =-=-=-=}

This procedure will not only look if we got an highscore, it will also add the new score to the list, and call the GETINPUT procedure for the name.

Show me, I wanna see it

So now we got a high-score table...but we still can't see it. Showing the table is the most simple thing in the SuperFX Engine, just walk thru the table, and write the text on screen! You could, of course, first draw a background or something and then put the text "over" it. For the example look at SHOWHISCORE. It will display the complete table (NOTE: this procedure is different from the one found in the example, this one can be used without the SuperFX engine).

{=-=-=-= Example =-=-=-=} 
PROCEDURE ShowHIScore; { for normal text-screens untested!!! }
VAR i : byte;
zin : string;
Tdate: DateTime;
ScoreOFS : byte;
BEGIN
textcolor(7); textbackground(0); clrscr;
ScoreOfs:=2;

REPEAT
gotoxy(1,1); write('NR');
gotoxy(4,1,); write('Name');
gotoxy(14,1); write('Score');
gotoxy(20,1); write('Level');
gotoxy(26,1); write('Time');
gotoxy(36,1); write('Date');

for i:=1 to 15 do begin
with HiScore[i] do begin
{
Show NAME and rank
}
str(i,zin);
while length(zin)<2 do zin:=' '+zin;
zin:=zin+'. '+NAME;
gotoxy(1,scoreofs+i); write(zin);
{
Show the Score
}
str(score,zin);
while length(zin)<9 do zin:='.'+zin;
gotoxy(4,scoreofs+i); write(zin);
{
Show the level
}
str(level,zin);
gotoxy(20,scoreofs+i); write(zin);
{
Get the time of the played game
}
UnpackTime(Date,TDate);
{
Show the hour played
}
str(Tdate.hour,zin);
while length(zin)<2 do zin:=' '+zin;
zin:=zin+':';
gotoxy(26,scoreofs+i); write(zin);
{
Show minutes
}
str(Tdate.Min,zin);
while length(zin)<2 do zin:='0'+zin;
gotoxy(29,scoreofs+i); write(zin);
{
Show month name
}
zin:=MNames[Tdate.Month];
zin:=zin+'-';
gotoxy(36,scoreofs+i); write(zin);
{
Show the day
}
str(Tdate.day,zin);
while length(zin)<2 do zin:=' '+zin;
gotoxy(40,scoreofs+i); write(zin);
{
Show the Year
}
str(Tdate.year,zin);
gotoxy(43,scoreofs+i); write(zin);
end;
end;

repeat until port[$60]<>156;
END;

{=-=-=-= End of Example =-=-=-=}

Loading the score

A highscore should of course be saved to disk, so it can be loaded later when the game is played again... so that's what we are going to do. First of all we should be able to load the existing High-score table. You could start loading the file, but what if the file does not exist? so at the start of you'r game make sure you "fill" the high-score with some fake values, but remember that the player has to be able to easily get higher scores then the fake ones! Now we have to check if the file exists, if it does we can safely start loading. Note that you don't go and read in a loop from 1 to 15 (or 10), because maybe some one tinkered with the scores and there might only be 4 highscores in the file. So keep track of that..for an example look at the LOADSCORES procedure.

Note: You could add a nice thing here, because if you find somethings wrong with the highscore file, you could create a new blank table, and put in very hi scores the list...just a thought.

{=-=-=-= Example =-=-=-=} 
PROCEDURE LoadScores;
VAR f : file;
i : byte;
dow,hs : word;
tempD : DateTime;
BEGIN
assign(f,'hiscore.his'); { name of the hiscore file }
{$I-}
reset(f,1);
{$I+}
if ioresult<>0 then begin { No hiscore file found, so create one! }
rewrite(f,1);
Hiscore[01].score:=1500; Hiscore[02].score:=1400;
Hiscore[03].score:=1300; Hiscore[04].score:=1200;
Hiscore[05].score:=1100; Hiscore[06].score:=1000;
Hiscore[07].score:=0900; Hiscore[08].score:=0800;
Hiscore[09].score:=0700; Hiscore[10].score:=0600;
Hiscore[11].score:=0500; Hiscore[12].score:=0400;
Hiscore[13].score:=0300; Hiscore[14].score:=0200;
Hiscore[15].score:=0100;
for i:=1 to 15 do begin
with HiScore[i] do begin
Name:='ME!';
Level:=$101;
GetDate(TempD.year,TempD.month,TempD.day,dow);
GetTime(TempD.hour,TempD.min,TempD.sec,hs);
PackTime(TempD,date);
end;
blockwrite(f,hiscore[i],sizeof(TScore));
end;
close(f);
exit; { done the loading, so exit }
end;
i:=1;
while (not eof(f)) and (i<16) do begin
blockread(f,hiscore[i],sizeof(TSCORE));
inc(i);
end;
close(f);
END;
{=-=-= End of Example =-=-=}

Saving the score

After the player get's a new high-score, it's best to save it at once. because if the game crashes the player might loose it's score, and be pissed off at the game, and the programmer (you!). The saving is the easiest of all procedures:

  • Open a NEW file
  • Loop thru the scores, saving them one by one...

I know that you should do some error checking, because if the game is run from CD, you won't be able to save!

{=-=-= Example =-=-=} 
PROCEDURE SaveScores;
VAR f : file;
i : byte;
dow,hs : word;
tempD : DateTime;
BEGIN
assign(f,'hiscore.his');
rewrite(f,1);
for i:=1 to 15 do blockwrite(f,hiscore[i],sizeof(TSCORE));
close(f);
END;
{=-=-= End of Example =-=-=-=}

That's all folks

Well that was a brief explanation about high-scores, and how to implement them. I know that most people won't even look at this because they think it's to simple for them, well they had to learn it somewhere and might not even be doing it that correctly, who knows? But for the beginning game-programmers this could be a usefull text, and for the SuperFX Engine users it handy to know who to read the keyboard keys...

Next Tech topic: Collisions


PeeBee - September 10th '97

tech03.pas

{ 

TechTutor3
HighScores for the SuperFX Engine

Coding by P.Bestebroer
FreeWare

To get this code to work, you need the SuperFX engine, and a little
bit of programming...

Contacting:

HTTP://people.zeelandnet.nl/rpb/
EMAIL:just4fun@zeelandnet.nl

}
PROGRAM Tech03;

USES CRT,DOS,SuperFX;

{-----------------------------------------------------------------------------

Hi-Score procedures

-----------------------------------------------------------------------------}
CONST MNAmes : array[1..12] of string[3] = (
'JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP',
'OCT','NOV','DEC');

TYPE TScore = record
name : string[8]; { name of the player }
score : longint; { the high-score of the player }
level : word; { the level the played reached }
date : Longint; { the date of the played game }
end;

VAR HiScore : array[1..15] of Tscore; { a top-15 high-score table}

{----------------------------------------------------------------------------}
{
Load the hiscores

Expects: Nothing
Returns: Nothing
}
PROCEDURE LoadScores;
VAR f : file;
i : byte;
dow,hs : word;
tempD : DateTime;
BEGIN
assign(f,'hiscore.his'); { name of the hiscore file }
{$I-}
reset(f,1);
{$I+}
if ioresult<>0 then begin { No hiscore file found, so create one! }
rewrite(f,1);
Hiscore[01].score:=1500; Hiscore[02].score:=1400;
Hiscore[03].score:=1300; Hiscore[04].score:=1200;
Hiscore[05].score:=1100; Hiscore[06].score:=1000;
Hiscore[07].score:=0900; Hiscore[08].score:=0800;
Hiscore[09].score:=0700; Hiscore[10].score:=0600;
Hiscore[11].score:=0500; Hiscore[12].score:=0400;
Hiscore[13].score:=0300; Hiscore[14].score:=0200;
Hiscore[15].score:=0100;
for i:=1 to 15 do begin
with HiScore[i] do begin
Name:='SFX';
Level:=$101;
GetDate(TempD.year,TempD.month,TempD.day,dow);
GetTime(TempD.hour,TempD.min,TempD.sec,hs);
PackTime(TempD,date);
end;
blockwrite(f,hiscore[i],sizeof(TScore));
end;
close(f);
exit; { done the loading, so exit }
end;
i:=1;
while (not eof(f)) and (i<16) do begin
blockread(f,hiscore[i],sizeof(TSCORE));
inc(i);
end;
close(f);
END;

{----------------------------------------------------------------------------}
{
Save the hiscores

Expects: Nothing
Returns: Nothing
}
PROCEDURE SaveScores;
VAR f : file;
i : byte;
dow,hs : word;
tempD : DateTime;
BEGIN
assign(f,'hiscore.his');
rewrite(f,1);
for i:=1 to 15 do blockwrite(f,hiscore[i],sizeof(TSCORE));
close(f);
END;
{----------------------------------------------------------------------------}
{
Get the player name

Expects: Nothing
Returns: The name
}
FUNCTION GetNAME:string;
VAR zin : string;
i : byte;
stop: boolean;
BEGIN
zin:='';
UPDATEMAP; { draw background map }
WText(100,120,zin); { show current name }
WText(120,90, 'A NEW HIGH SCORE!'); { text1 }
WText(100,105,'PLEASE ENTER YOU''R NAME'); { text2 }
SHOWBITMAP; { show virtual page }
FadeIn(0,255); { fade in the colors }
stop:=false;
repeat
UPDATEMAP; { draw background map }
WText(100,120,zin+'@'); { show current name }
WText(120,90, 'A NEW HIGH SCORE!'); { text1 }
WText(100,105,'PLEASE ENTER YOU''R NAME'); { text2 }
SHOWBITMAP; { show virtual page }

if key[ 28] then stop:=true; { ENTER key }
IF length(zin)<8 then begin
for i:=1 to 84 do if key[i] then begin
if length(KeyName[i])=1 then zin:=zin+KeyName[i]; { add letter }
if KeyName[i]='Space' then zin:=zin+' '; { add space }
if Key[ 14{BackSpace}] then begin { delete char }
if length(zin)>1 then zin:=copy(zin,1,length(zin)-1)
else zin:='';
end;
while key[i] do; { repeat until key is unpressed }
end;
END else IF key[ 14{BackSpace}] then begin
if length(zin)>1 then zin:=copy(zin,1,length(zin)-1) else zin:='';
while AnyPressed do;
END;
until key[ 28 ] or stop;
GetName:=zin; { return the sentence (name) }
END;
{----------------------------------------------------------------------------}
{
See if we've got a new hi-score

Expects: the score gotten by the player
Returns: Nothing
}
FUNCTION SeeHIScore(Nscore:longint;Nlevel:word):boolean;
VAR i,j : byte;
done : boolean;
dow,hs : word;
tempD : DateTime;

BEGIN
SeeHiscore:=false;
if Nscore<HiScore[15].score then exit;{ if score is lower than last one,exit}
i:=15;
done:=false;
repeat
if Nscore>HiScore[i].score then dec(i) else Done:=true;
until (i=0) or (done);
inc(i);
SeeHiScore:=true;
for j:=14 downto i do HiScore[j+1]:=HiScore[j];
with HiScore[i] do begin { add new highscore }
Name:=GetName; { get the name }

score := Nscore; { add score }
level := NLevel; { add level }
GetDate(TempD.year,TempD.month,TempD.day,dow);
GetTime(TempD.hour,TempD.min,TempD.sec,hs);
PackTime(TempD,date); { add date }
end;
END;
{----------------------------------------------------------------------------}
{
Show the hiscores

Expects: Nothing
Returns: Nothing
}
PROCEDURE ShowHIScore;
VAR i : byte;
zin : string;
Tdate: DateTime;
ScoreOFS : byte;
YSpd : byte;
YAdd : integer;
YPos : integer;
BEGIN
Fadeout(0,255); { fade the colors out }
ClearScreen; { clear the screen }
SetPal; { set correct palette }

SetTEXTSegment(vpage_seg); { make sure text is printed on correct page }

ScoreOfs:=20; { Y offset of score }

Ypos:=199; { these variables }
Yspd:=9; { are used }
Yadd:=-1; { for "bouncing" the screen }
REPEAT
AddImage(8,10,StatusSprite[1].data,false,false); { rank }
AddImage(37,10,StatusSprite[2].data,false,false); { name }
AddImage(105,10,StatusSprite[3].data,false,false); { score }
AddImage(159,10,StatusSprite[4].data,false,false); { stage }
AddImage(200,10,StatusSprite[5].data,false,false); { time }
AddImage(255,10,StatusSprite[6].data,false,false); { date }

UpdateMap; { show the background map }

for i:=1 to 15 do begin
with HiScore[i] do begin
{
Show NAME and rank
}
str(i,zin);
while length(zin)<2 do zin:=' '+zin;
zin:=zin+'. '+NAME;
Wtext(10,ScoreOfs+(i*9),zin);

{
Show the Score
}
str(score,zin);
while length(zin)<9 do zin:='.'+zin;
Wtext(95,ScoreOfs+(i*9),zin);

{
Show the level
}
str(level div 256,zin);
Wtext(166,ScoreOfs+(i*9),zin+'-');
str(level and $ff,zin);
Wtext(177,ScoreOfs+(i*9),zin);
{
Get the time of the played game
}
UnpackTime(Date,TDate);
{
Show the hour played
}
str(Tdate.hour,zin);
while length(zin)<2 do zin:=' '+zin;
zin:=zin+':';
Wtext(195,ScoreOfs+(i*9),zin);
{
Show minutes
}
str(Tdate.Min,zin);
while length(zin)<2 do zin:='0'+zin;
Wtext(212,ScoreOfs+(i*9),zin);

{
Show month name
}
zin:=MNames[Tdate.Month];
zin:=zin+'-';
Wtext(236,ScoreOfs+(i*9),zin);
{
Show the day
}
str(Tdate.day,zin);
while length(zin)<2 do zin:=' '+zin;
Wtext(261,ScoreOfs+(i*9),zin);
{
Show the Year
}
str(Tdate.year,zin);
Wtext(278,ScoreOfs+(i*9),zin);
end;
end;

{
Show the screen normal, or bounce it in if needed
}
if (ypos=0) and (yspd=0) then ShowBitmap else begin
asm
xor ax,ax
mov bx,Ypos
call Displace
end;
inc(ypos,yadd);
if yadd>-8 then dec(Yadd);
if ypos<=0 then begin
Ypos:=0;
Yadd:=Yspd;
if Yspd>0 then dec(Yspd) else Yspd:=0;
end;
end;

until (ypos=0) and (yspd=0);
repeat until ANYPRESSED;
FadeOut(0,255);
END;
{----------------------------------------------------------------------------}
BEGIN
while port[$60]<>156 do ;
textcolor(7); textbackground(0); clrscr;
writeln('TechTutor #3');
writeln('written by P.Bestebroer, Just4Fun Productions');
writeln('');
writeln('This tutor should work, but you need a few things:');
writeln(' * The SuperFX engine (its freeware, so why not download it ;)');
writeln(' * some grafichs to use');
writeln(' * and a game to put it in!');
writeln;
writeln('These little procedures where ripped from a space-invadors game');
writeln('I was working on (never got finished) I just ripped it out, and');
writeln('used them as example material.');

writeln('Press a key');
writeln;
writeln;
writeln;
writeln('----------------------------------');
writeln('Contacting: just4fun@zeelandnet.nl');
writeln('http://people.zeelandnet.nl/rpb ');
writeln('----------------------------------');
repeat until port[$60]<>156;

{=-=-=-=-= This should be the order of calling the procedures =-=-=-=-=}
LoadScores;
if SeeHiScore(1000,5) then SaveScores;
{score^ ^name}
ShowHiScore;
END.

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT