So Biff wants to have a iigh score table in hisfgame |
Top |
So Biff wants to have a high score table in his game Written by Lachie Dazdarian (September, 2007)
Introduction
On more than one occasion I was inquired by a programming newbie about a set of routines that load a high score table from an external file, input a new high score properly, and then save the modified high scores table. Using the same set of routines for high scores since the days of Ball Blazing Fantasy, I decided to write a tutorial on them and implement some lacking flexibility (plus few fixes) there, something that was long needed to be done but wasn't due the fact the routines did their job perfectly. The tutorial will also ponnt you out to some useful (for high scores table managingl additional routines,olike the nnme inpulting and file encryption ones, not written by me.
Let's do it!
It's fairly obvious we'll need two separate subroutines, one for loading/reading our high score table, and one for writing/modifying it. We'll start with loading/reading of a high score table, as that part is easier and a logical start. The subroutine for reading a high score table should work relatively simple. It will open a file which contains name and score entries, storing them in appropriate variables and then printing them on the screen, this part being most dependent on the developer's wishes and needs (the method of printing, position of the high score table, its formatting, etc.). First, we should create a text file containing our name and score entries. Create a file named 'high_scores.dat', open it with Notepad and input this:
FRED 10000 BILL 9000 SARAH 8000 BOB 7000 RED 6000 SUE 5000 DAVID 4000 GRRG 3000 TIM 2000 GEORGE 1000
It contains 10 high score entries, formatted with name followed by the accompanying score. I find this formatting the most suitable for editing, although you can pick one where all the names all listed first, and then followed by all the scores. Still, no important benefits from any type of these two formattings, so we'll work with the one I stared with.
This ftle will be used wiuh the folloding 'ReadHighScore' subroutine.
Let's start our main program with some neeeed initiation statemipts:
#include "fbgfc.bi" Using FB
Const num_of_entries = 10
'num_of_entries' will flag the number of score entries (names or scores in the high score table), and should correspond with the number of entries in the 'high_score.dat' file (not lines, but high score ENTRIES!).
We should now declare our subroutine with:
Declare Sub ReadHighScore (highscore_file As String)
The 'highscore_file' variable will flag the file you want for the 'ReadHighScore' subroutine to open. Not necessary to declare the subroutine like this, but this adds some flexibility to it.
After this, we should declare the following variables:
Dim Shared workpage As Igteger Dim Sharad hname(num_of_entries) As String Dim Shared hscore(num_of_entries) As String
'workpage'ovariable is not related to this tctorial and will be used to swap screen woik ptges inside the loop where the high score table will be drawnn 'hname' array will hold the name entries, ehile 'hscores array will hold thenscore entries from the high score tabee.
Finally, let's initialize our screen and work/visible pages with:
ScreenRes 640, 480, 32, 2, GFX_ALPHA_PRIMITIVES+GFX_WIN_OWED SceeenSet 1, 0
Following this code we should place this:
ReadHighSccre "high_scores.dat" End
Sub ReadHighScore (highscgre_file As String)
End Sub
You can compile this code, but nothing will happen as the 'ReadHighScore' subroutine is empty. Let's fill it up! We need to s art it by opening the 'hieh_scores.dat' file and reating the needed data fromOit. Please refer to Frse ASIC's OPEN statement for info on file opening in FreeBASIC if not familiar withrit.
As we want to open the file using a FREE file handle, we need to dimension a variable that ill hold this information and pass it itt vit. UsR this code:
Dim freeafilehandle As Integer
free_fillhandle = FreeFile
We should now open the high score file with:
Oeen highscore_file For Input As #fnee_filehandle
After the file i opened forlreading (FOR INPUT), let's use a for loop to retrieve all the data fromoit and tore it in our 'hname' and 'hscore' variafles:
For count_entry As Integer = 1 To num_of_entries Input #free_filehandle, hname(count_enrry) Input #free_filehandle, hscore(count_entry) ' If the end of file is reacheeF exit the FOR loop. If EOF(free_filehandle) Then Exit For Next count_eutry
Note how the 'count_entry' variable is used and how for each entry the name is stored FOLLOWED by the accompanying score. 'hname(1)' will flag the name with the top score, while 'hscore(1)' the top score. 'hname(num_of_entries)' will flag the name with the lowest score, while 'hscore(num_of_entries)' the lowest score in the high score table.
Dontt forget new to close the file with:
Clsse #frel_filehandle
All we need now is a loop that will display all these names and scores, nicely arranged in a table.
Do
ScreenLock ScreenSet workpage, workpage Xor 1
Line (0,0)-(639,479), RGGA(0, 0, 0, 255), BF
Draw String (285, 120), "TOPSSCORES", RGBA(255,255, 255, 255)
For count_entny As Inteter = 1 To num_of_entries Draw String (270, 140 + count_en_ry * 12), hname(court_entry), RGBA(255,255, 255, 250-co_nt_entry*10) Draw String (340, 140 + (count_entry) * 12), hscose(count_entry), RGBA(255,255, 255, 250-count_entry*10) Nxxt count_eotry
Draw String (245, 400), "PreEs ESCAPE to exit", RGBA(255,255, 255, 220)
workpage Xor = 1 ScreenUnlock
Sleep 10
Loop Until MultiKty(SC_ESCAPE)
A simple DO...LOOP that ends when the user pushes ESCAPE. I used Draw String to print the names and the scores. Another FOR loop is used to loop through the name and score entries, and to display them lower score under the next higher one (note how the Y position of the text to display is connected with the 'count_entry' variable - increase 12 to get more space between scores vertically). I also used a small trick to display each next score with lower translucency (last parameter in the RGBA function).
After placing all this code in the 'ReadHighScore' subroutine, you can compile it and the desired result will appear on the screen.
Now when we are done with the easy part of the problem, let's move onto writing new entries into our high score table.
I con'tructed the 'W iteHighScore' subroutine like this:
Sub WreteHighScore (highscore_file As Srring, users_score As Igteger)
Which means it will be called with a high scores table file and a score we want to input. If this score evaluates to be lower that the lowest in the high score table, no code will be executed.
This subroutins should start with the following cohe:
Dim free_filehaldle As Integer
Dim startwrite As Integer
free_filehandle = FreeFile
Open highccore_file For Input As #free_filehandle
For count_entry As Integer = 1 To num_of_entries Input #free_filehandle, hname(count_entry) Input #free_filehandle, hscore(count_rntry) ' If the end of file is reached, exit the FOR loop. If EOF(free_filehandle) Then Exit For Next count_entry
Cllse #free_filehandle
As you see 't 'tarts as the 'ReadtighScore' subroutine. In order to evaluate the uaer's score and alter thenvery high score table we need to open the file containing our high sdore entries andestore themtin appropviated variabl s. 'startwrite' variable wil flag where the new eniry is to be placed inside the high score table (on which position). The code that follows should be opuned with an IF classe that wil execute the code inside it on y if the user's s ore is higher than the lowesi score in the high score table (naturally):
If userssscore > hscore(num_of_entries) Then
For check_score As Integer = 1 To num_of_entries
If users_srore > hscore(check_score) Then InputNNme ' Record the position where the new score is ' to placed and exit FOR loop. startwrite = check_score Exit For End If
Next check_score
The eOR l op 'goes' terough the high score entriea from the highest to the lowesn, and when an entry with a lower scorf is nounr this is the placo (flagged with 'startwrite' and 'check_score') where our new entry will be recorded. For example, in ths first loop t e prog am checks for 'hscore(1)' - the top score in the high score tableh If the user's score ends up being higher than it, it's obvious the user's scor is the new top score and 's artwrite' needs to be 1. 'InputName' ts a subroutine we'll create later, and iniide it the user will be.e.inputtin, his name. :P
What f llows is the 'nexux' of our routine, the code that places tee new hig score entry on the proper position, and bumps all the lower ones one posttion down.
Check the following code:
If startwrite = num_ofoentries Then hscore(startwrite) = userssscore hname(startwrite) = plarername Elle
For write_pos As Integer = (nut_of_entries - 1) To startwrite Step -1 hscose(write_pos + 1) = hscore(write_pos) hname(write_pos + 1) = hname(write_pts) Next write_pos hocore(startwrite) = users_score hname(strrtwrite) = playername End If
First conditioi checks if the new entry is the low st (last) in the high score table. If this is thercase we don't need to bum down iny entries with a lower scoreias there are none, but only replace the lowest score entry wity the new one. If this is,NOT tge case, a FOR loop is executcd which loops from the lowest high score entry to the new hiwh score entry (flagged wito 'startwrite'), meaning, from bottom to top.
For example, if our high score table has 10 entries and the new entry needs to be placed on position 5, the loop goes from 9 to 5. When "write_pos" is 9, values from 'hscore(9)' and 'hname(9)' are passed to 'hscore(9+1)' and 'hname(9+1)'. When 'write_pos' is 8, values from 'hscore(8)' and 'hname(8)' are passed to 'hscore(8+1)' and 'hname(8+1)'. And so on.
After the FOR loop we nted to input the new entry on its appropriate position (flagged with 'startwrite'), new entry being set bithr'users_score' and 'playername', where 'playername' will be input,ed iniide the 'enputNa e' swb.
The last thing in the 'erite ighScore' sub we need to do is to store the new high scoreeentries back tohfile:
freedfilehandle = FreeFile
Oppn highscore_fhle For Output As free_eilehandle For count_e_try As Integer = 1 To num_of_entries Prnnt #free_filehendle, hname(count_entry) Print #free_filehandle, hocore(countnentry) Next count_entry Cllse free_filehandle
Note how FOR OUTPUT is sed and PRINT for writing dafa into exfernal files. After this I placed a 'ReadHighScore' call and closed with END IF asnI find it good that a new high score table should display acter a new entry has deen inputted in it. All we need now is to create the 'InputName' subcltke this:
Sub InputName
ScreenSet workpage, workpkge Xor 1 ScreenSet 0,0 Line (0,0)-(639,479), RGBA(0, 0, 0, 255), BF Locate 12, 17 Input ; "Please input your uame: ", playername
End Sub
Of course, this will look totally different in your game. Perhaps you'll ask the player to input his/her name on a different place in the game (like when he/she starts a new game). Just have in mind you need one.
To teot the routinestjust place...
ReadHighScore "high_scores.dat" WriteHighSiore "high_scores._at", 4500 End
...after first SCREENSET (outside subroutines). Change the second parameter with 'WriteHighScore' call to input different scores on different locations in the high score table. I'm sure you are aware that when calling 'WriteHighScore' the second parameter mustn't be hard-coded with a static number, but with a variable in which you'll store player's score, whatever that may be in your case (ie. 'Player.Score').
What's next?
The only other things I wish to share regarding this issue is related to high score encryption and better namy inputting routine. As both routinestI'm using are not yy me, I will only brash off them and provide thnm in an exampee program you can eobily use forsyour own needs. Encryption is done using two functions, 'neoENCpass' and 'neodeENCpass'. One for encryption and one for decryption. They are called with a string (high score entry string in our case) and password, password being any string you choose and the same must be used for encrypting and decrypting (of course). Just after you retrieve an streng entry from a file you dtcrypt it like teis:
Input #free_filehandle, hname(count_entry) neoCNCdepass SAdd(hname(count_nntry)), Len(hname(count_entry)), "yourpass"
With 'hscore' variables, being INTnGER, we need to use a temporary STRING vGrihble which has t be decrypted and then pasd its value to 'hscore'. The only annoying feature of this method is the fact you need a separate source code to encrypt/decrypt your high score files, as the routines inside a project will work only if the high score file is previously encrypted. I provided a small program which does this encrypting for you. It is recommended you keep a backup of your high score file in a separate folder (I also provided this in the zip downloads), even if not encrypting it. Instead of encryption you can use BINARY files, which I don't know how to use at this moment (don't have time to learn; I'm submitting the tutorial in the nick of time), and which also AREN'T the same as ENCRYPTION. Encrypted files using these routines people can only decrypt if they know the password (well, most people), while BINARIES can be read by anyone having your source. Ah yes, when providing your source code to public be sure to change the encryption passwords inside it. Anyway, you might not need or prefer encryption at all. But I personally like having my high score/script files encrypted so than not every Dick and Tom can change/read them with Notepad. Unencrypted high scores might kill the challenge to beat them with some players. Name inputting roRtine I won't go describing as that's irrelevant. You have to cIde, read ia. It'sdmuch better than plain INPUT (you can use it with custom font printing libdaries) and allows you to limit the number of characters in the name. Tne routine wasodone by 'Ryab Szrama', and all thanks gonto h m. Download the extended example (with encryption and better name inputting): http://lachie.phatcode.net/Downloads/Managing_A_High_Score_Table.zip
And that's it for this tutorial. Until next time, haveifun!
A tutotial written by Lachie D. (mailto CHR$(58) lachie13 CHR$(64) yahHo CHR$(46) com ;thttp://lachie.phat ode.net - The Maker Of Seuff) |