⌂ YolkfolkThe Dizzy Fansite
Community discussion

DizzyAGE General Coding Queries

Started by delta on 9 February 2008 • 258,915 views

721 posts
#63365
alex, if i'm playing a game, and changing the map as i play (but not re-loading the map in the game), then i try to save the game, am i correct that it will produce a file error message when trying to save the static brushes?

cause it is doing.
👍 0
#63423
Forgive my stupidity here, but are global variables that I define in the "gamedef" file supposed to reload upon restarting from the menu? Cause they aren't.

I can easily get around this by setting them in the "start" file, but I would have thought that choosing 'restart' would reread all the variables from "gamedef".

Is this not the case? Am I just doing something dumb and putting things in the wrong place?

As I said, it's an easy workaround, it's just that I'm pretty sure I'm doing something wrong that is causing the error in the first place.


ETA:
Actually, even worse, it doesn't seem to be saving my variables in the 'save game' function at all...

A little help here? (This will absolutely kill my game dead - unless I disable the 'save/load' feature entirely, which I don't want to do...)
👍 0
#63425
if you're setting them as game variables (or even player variables) such as:

#def G_TEST 101
#def G_TESTER 102

etc, then it will reload them, save them, etc. automatically.

if however you're just using:

int test
int tester

etc, then you will have to manually reload then, and save/load then when loading the save game files. I'll post how to do this when i get back home tonight. It's not too difficult.
👍 0
#63426
Not sure of the answer to your first part but I always reset them manually as that is what I have had to do in other languages.

You have to save and load global variables yourself. In game.gs look for SaveUserData(file) and LoadUserData(file). Here you list the variables to be saved and loaded. The syntax is shown in the comments. Make sure you include the '&' in LoadUserData or it won't work. I missed it in my first game and it took me hours to discover why it wouldn't work.
👍 0
#63427

Thanks guys - crisis averted! I was panicking because it was an entirely unexpected issue that I stumbled across (I had one of those very early on too that nearly made me drop the whole thing, until I figured out what that one was).

I still reckon I'm doing something wrong somewhere that's giving me some of these issues, but I got the variables to load back in properly now. Phew!

Sorry to have to ask for help on such a basic issue! Doesn't bode well for my new game, does it? {yolkfolk}:tongue:

Make sure you include the '&' in LoadUserData or it won't work. I missed it in my first game and it took me hours to discover why it wouldn't work.

I spent ages last night (I was tired and overdue for bed) agonizing over why a simple UseObject function wasn't working - I tried everything and simply couldn't get it to work. I was tearing my hair out.

Anyway, turns out I had accidentally typed a lower-case "u", i.e. "useObject". D'oh!

👍 0
#63429

right, here we go. I now try to set everything as game (or player) variables, so that i don't have to change stuff in the load/save function of files.gs

you can put them in either def.gs or gamedef.gs, but the latter is recommended so that as few files are altered from the default as possible (makes it easier for new developers to understand what's been done). this is a sample of my custom variables from IID:

#def G_ENTERX 101 // room entry pos X
#def G_ENTERY 102 // room entry pos Y
#def G_ENTERPREVX 103 // Save the players previous roomX pos when entering a room
#def G_ENTERPREVY 104 // Save the players previous roomY pos when entering a room
#def G_WATERX 105 // water entry pos X
#def G_WATERY 106 // water entry pos Y
#def G_FADE 107 // fade 0..100
#def G_SIGN 108 // sets the sign style for messages

#def P_LIFEBAR 64 // new lifebar
#def P_LIFEBARDEDUCT 65 // new lifebar
#def P_DLAY 66 // frame delay

using the above method, you don't have to reset them on game restarts (the game will auto set them all to 0 value), and they will automatically be saved and loaded in the files.gs file.

however the other way to set variables is as follows. you define them as follows in the def.gs or gamedef.gs file (the following is from RRD, with little notes to remind me of stuff):

int p_lifebar
int p_lifebardeduct
int g_timer_lasttick //don't save on savegame.
int g_sign //don't save on savegame.
int lp
int ls
int trsp
int whsp
int t1sp
int t2sp
int t3sp
int t4sp
int t5sp
int c1sp
int c2sp
int c3sp
int c4sp
int c5sp
int whro
int plsp
int truckspeed
int speeddelay
int truck

if you do it this way, you will have to insert the following code into the load game code (highlighted in red):

func LoadGame( file )
{
f = gs_fileopen(file,0); if(!f) goto fileerrorrecover;

val=0;
sz="";

// load id
if(!gs_filereadtext(&sz,f)) goto fileerrorrecover;
if(sz!="DIZZYAGE") goto fileerrorrecover;

// load game id
if(!gs_filereadtext(&sz,f)) goto fileerrorrecover;
if(sz!=GAME_ID) goto fileerrorrecover;

// load game data
for(i=0;i < G_MAX;i++) { if(!gs_filereadint(&val, f)) goto fileerror; GameSet(i,val); } // load objects data for(o=0;o < ObjCount();o++) { for(i=0;i < O_MAX;i++) { if(!gs_filereadint(&val, f)) goto fileerror; ObjSet(o,i,val); } } // load player data for(i=0;i < P_MAX;i++) { if(!gs_filereadint(&val, f)) goto fileerror; PlayerSet(i,val); } // load static brushes with valid ids if(!LoadStaticBrushes(f)) goto fileerror; // load music music = -1; musicpos = -1; if(!gs_filereadint(&music,f)) goto fileerror; if(!gs_filereadint(&musicpos,f)) goto fileerror; // load user data if(!LoadUserData(f)) goto fileerror; [color="Red"] // load lifebar data if(!gs_filereadint(&val, f)) goto fileerror; p_lifebar = val; if(!gs_filereadint(&val, f)) goto fileerror; p_lifebardeduct = val; // load other variables if(!gs_filereadint(&val, f)) goto fileerror; lp = val; if(!gs_filereadint(&val, f)) goto fileerror; ls = val; if(!gs_filereadint(&val, f)) goto fileerror; trsp = val; if(!gs_filereadint(&val, f)) goto fileerror; whsp = val; if(!gs_filereadint(&val, f)) goto fileerror; t1sp = val; if(!gs_filereadint(&val, f)) goto fileerror; t2sp = val; if(!gs_filereadint(&val, f)) goto fileerror; t3sp = val; if(!gs_filereadint(&val, f)) goto fileerror; t4sp = val; if(!gs_filereadint(&val, f)) goto fileerror; t5sp = val; if(!gs_filereadint(&val, f)) goto fileerror; c1sp = val; if(!gs_filereadint(&val, f)) goto fileerror; c2sp = val; if(!gs_filereadint(&val, f)) goto fileerror; c3sp = val; if(!gs_filereadint(&val, f)) goto fileerror; c4sp = val; if(!gs_filereadint(&val, f)) goto fileerror; c5sp = val; if(!gs_filereadint(&val, f)) goto fileerror; whro = val; if(!gs_filereadint(&val, f)) goto fileerror; plsp = val; if(!gs_filereadint(&val, f)) goto fileerror; truckspeed = val; if(!gs_filereadint(&val, f)) goto fileerror; speeddelay = val; if(!gs_filereadint(&val, f)) goto fileerror; truck = val;

gs_fileclose(f);

// reload room
MusicStop();
MusicFade(0,3);
MusicPlay(music,musicpos);
TimerOnLoad();
GameCommand(CMD_REFRESH);
ObjPresentGather(); // refresh present list
SamplePlay(FX_RESPAWN);

OpenDialogMessage( "LOAD SUCCESSFUL!", COLOR_YELLOW );
return 1;

fileerror:
OpenDialogMessage( "FILE ERROR!", COLOR_RED );
gs_fileclose(f);
GameCommand(CMD_EXIT);
return 0;

fileerrorrecover:
OpenDialogMessage( "FILE ERROR!", COLOR_RED );
gs_fileclose(f);
return 0;
}

and the following into the savegame code (note these HAVE to be loaded and saved in the same order):

func SaveGame( file )
{
f = gs_fileopen(file,1); if(!f) goto fileerror;

// save id
if(!gs_filewritetext( "DIZZYAGE", f )) goto fileerror;

// save game id
if(!gs_filewritetext( GAME_ID, f )) goto fileerror;

// save game data
for(i=0;i < G_MAX;i++) { if(!gs_filewriteint(GameGet(i), f)) goto fileerror; } // save objects data for(o=0;o < ObjCount();o++) { for(i=0;i < O_MAX;i++) { if(!gs_filewriteint(ObjGet(o,i), f)) goto fileerror; } } // save player data for(i=0;i < P_MAX;i++) { if(!gs_filewriteint(PlayerGet(i), f)) goto fileerror; } // save static brushes with valid ids if(!SaveStaticBrushes(f)) goto fileerror; // save music if(!gs_filewriteint(MusicPlaying(),f)) goto fileerror; if(!gs_filewriteint(MusicPosition(),f)) goto fileerror; // save user data if(!SaveUserData(f)) goto fileerror; [color="#ff0000"] //save lifebar data if(!gs_filewriteint(p_lifebar, f)) goto fileerror; if(!gs_filewriteint(p_lifebardeduct, f)) goto fileerror; // save other variables if(!gs_filewriteint(lp, f)) goto fileerror; if(!gs_filewriteint(ls, f)) goto fileerror; if(!gs_filewriteint(trsp, f)) goto fileerror; if(!gs_filewriteint(whsp, f)) goto fileerror; if(!gs_filewriteint(t1sp, f)) goto fileerror; if(!gs_filewriteint(t2sp, f)) goto fileerror; if(!gs_filewriteint(t3sp, f)) goto fileerror; if(!gs_filewriteint(t4sp, f)) goto fileerror; if(!gs_filewriteint(t5sp, f)) goto fileerror; if(!gs_filewriteint(c1sp, f)) goto fileerror; if(!gs_filewriteint(c2sp, f)) goto fileerror; if(!gs_filewriteint(c3sp, f)) goto fileerror; if(!gs_filewriteint(c4sp, f)) goto fileerror; if(!gs_filewriteint(c5sp, f)) goto fileerror; if(!gs_filewriteint(whro, f)) goto fileerror; if(!gs_filewriteint(plsp, f)) goto fileerror; if(!gs_filewriteint(truckspeed, f)) goto fileerror; if(!gs_filewriteint(speeddelay, f)) goto fileerror; if(!gs_filewriteint(truck, f)) goto fileerror;

gs_fileclose(f);

SamplePlay(FX_COIN);
OpenDialogMessage( "SAVE SUCCESSFUL!", COLOR_YELLOW );
return 1;

fileerror:
OpenDialogMessage( "FILE ERROR!", COLOR_RED );
gs_fileclose(f);
return 0;
}

now there may be an easier way of doing this in v2.2 of DizzyAGE, but this is the code i used in v1.31, and it still works, so i carried on using it.

That deals with the save/load functions, and the last thing is to reset all the variables when restarting. For this, i make a function called ResetVar(), in which i include all the variables that need resetting on game restart, as follows:

func ResetVar()
{
lp = 0;
ls = 0;
trsp = 0;
whsp = 0;
t1sp = 0;
t2sp = 0;
t3sp = 0;
t4sp = 0;
t5sp = 0;
c1sp = 0;
c2sp = 0;
c3sp = 0;
c4sp = 0;
c5sp = 0;
whro = 0;
plsp = 0;

truckspeed = 0;
speeddelay = 0;
truck = 0;
}

then i call it using ResetVar(); somewhere in the BeginNewGame() function, as every new game has to go through this function to start.

I hope this is of some help.

👍 0
#63439
TO Humbert:
Yes, the game saves and loads global game variables (those accessed through GameGet, GameSet and using the mentioned defines for clarity), player's variables and dynamic objects' variables. What you declare as global script variables you must save (and load) yourself in the SaveUserData callback - see the docs:
https://www.yolkfolk.com/dizzyage/books/dizzyage/ref03_template.html#SaveUserData()
However, not all script variables must be saved and reloaded. Some of them could just be reseted to default values in the LoadUserData() callback (when the game is loaded). Depends on what you do with them.
The SaveUserData and LoadUserData callbacks are in game.gs to avoid chances to the default template - as Jamie said, they are called from SaveGame and LoadGame.

TO Jamie.
I'm not sure about the error you have when saving a modified map. If you change static brushes' normal properties (like material, visibility, etc) it should be fine. You shouldn't change their positions or sizes, especially placing them outside the room they're in (that's why they are called static). As for the error, I don't know what could cause it exactly - I have to see a log or an example.
👍 0
#63447
Alex i think it was just because i was changing the map brushes file while i was playing the game. I think it references it or something when saving, which was then throwing up an error because i'd changed it from what it was expecting.

whatever, i've had no problems since. Thanks!
👍 0
#63449
Oh, I get it! You were changing the brushes file, not the brushes properties from ingame. Yeah, of course it doesn't like that :smile:
👍 0
#65167

Yikes! :sad:

Sometimes just looking at delta's questions makes my head hurt.

Cannot wait till I am as good as he is!

👍 0
#65168

Oh,
while we are referring to "coding quieries", I have a few questions.
1) How would you make an dynamic brush follow the player? This is the code I have:

px = PlayerGet(P_X );
x = ObjGet(idx, O_X );
if( px < x) x-=4;
if( px > x) x+= 4;
ObjSet(idx, O_X, x );

Now I am not an advanced scripter yet, so if you would please keep the answers simple. Thanks. :smile:

👍 0
#65172
Yes, that is the idea.
However there are a few more details.

For example if you do as you said, and x is not multiple of 4, it will jump each frame around player's position. So I would use a proximity range, like: if(px < x-4) x-=4

You can use a smaller move step if you want it to move slowler than the player.
Also consider that the player is not updated every frame which also helps you adjust speeds. If you need to match player's updates, there is a "IsPlayerUpdate" function (see it in the default template).

For a more advanced way of "following player" you can check the implementation of Daisy following Dizzy in act 3 of "Dizzy and The Other Side". She considers the material map so she can walk on solid materials in the same way the player does.

Or you can have a look at the bird in act 1. It flies around on spline paths and attack player if in a special area.

Alex
👍 0
#65177

personally i'd just find the players position, and set the dynamic objects position as the same! (you can also offset it if you wish)

thus:

func UpdateRoom_01_01()
{
px = PlayerGet(P_ X) ;
py = PlayerGet(P_Y);

idx = ObjFind(2000);
ObjSet(idx,O_X,px);
ObjSet(idx,O_Y,py);
ObjPresent(idx);
}

that's basically the way i've done it in IID and MSD.

👍 0
#65178
the bit of code alex meant is: if(px < x-4) x-=4 it was cut off by the forum as it contained a < in the middle of text.
👍 0
#65182
Yes, you can do as Jamie said if you want to "link" the object to the player.
The other case was more of a "following", especially if player can move faster.

To Jamie:
I saw your signature and I instantly heard the Iron Maiden's song "The Rime of the Ancient Mariner". I know it's based on a known english poem but now I have to find my Powerslave disk :smile:
👍 0
#65186
yes i pulled it straight from the poem 'The Rime of the Ancient Mariner' by Samuel Taylor Coleridge. I've been looking through things trying to get puzzle ideas for CoTM, and although i doubt i'll use anything from that poem (have you SEEN the length of it?), i do quite like those verses, so i thought i'd put them as my signature. :smile:
👍 0
#65196
Thanks for the help, but I think I'll have to fiddle around with it.

To Delta:
If your looking for ideas for your game in literature, here are some good titles:
1 Alfred, Lord Tennyson's "Idyll's of the King"
2 William Shakespear's "MacBeth"
3 Sir Walter Scott's "Ivanhoe"
👍 0
#65199
OK,
I tried what Mr. Simion said, but the thing still won't move! :sad:
Not sure what is wrong.
👍 0
#65209

You can always use the "println" command to show debug info in log and in console (open console with ` key). Use [ins] key in console to write script commands. For example:

println( ObjGet(ObjFind(ID),O_ X) );

You can also use this command to debug your code and find out if it gets executed as expected.

👍 0
#65222

Wow! Did not know about that interesting tool! Thanks! :smile:

Maybe I can set the player's P_COINS on IID using this method...
( no way! don't want to ruin a perfect game)

👍 0