The Daily Click ::. Forums ::. Klik Coding Help ::. Saving and loading 'Duplicate' objects
 

Post Reply  Post Oekaki 
 

Posted By Message

Dave S.



Registered
  26/09/2003
Points
  924
14th January, 2015 at 14/01/2015 18:16:34 -

I am working on a simple grid level editor and want to save the positions of all the detectors (the same active object that has been duplicated many times). If I save and load using the 'ini' extension, only one detector shows up. Should I be using an array?

 
n/a

The_Antisony

At least I'm not Circy

Registered
  01/07/2002
Points
  1341

VIP MemberStarSnow
15th January, 2015 at 15/01/2015 01:40:20 -

Sure this isn't an instance issue? If these are all copies of the same active object, INI is probably only pulling the X,Y from the last created instance of the object. If you make a new alterable value then have that value increment by one every time the object is recreated, then you should be able to use a fastloop that tests the value and records each active's X and Y positions independently?

 
ChrisD> Employer: Say, wanna see a magic trick?
ChrisD> Employee: Uhh… sure, boss.
ChrisD> Employer: Your job! It just disappeared! Pack your things and leave! Pretty good trick, huh?

The_Antisony

At least I'm not Circy

Registered
  01/07/2002
Points
  1341

VIP MemberStarSnow
15th January, 2015 at 15/01/2015 01:55:14 -

If you're not talking about spawned objects at runtime, but rather several of the same active copied around the level editor, you should still be able to apply a spread-value at runtime and then deal with the little bastards independently.

http://www.create-games.com/article.asp?id=1082

Edited by The_Antisony

 
ChrisD> Employer: Say, wanna see a magic trick?
ChrisD> Employee: Uhh… sure, boss.
ChrisD> Employer: Your job! It just disappeared! Pack your things and leave! Pretty good trick, huh?

Dave S.



Registered
  26/09/2003
Points
  924
15th January, 2015 at 15/01/2015 09:13:25 -

Thanks for the tips. The article link looks interesting (may take a few reads). I also found this one... http://www.create-games.com/article.asp?id=1129 - it's ancient but caters for spawned objects at runtime though not all of it made sense (to me).

 
n/a

UrbanMonk

BRING BACK MITCH

Registered
  07/07/2008
Points
  49567

Has Donated, Thank You!Little Pirate!ARGH SignKliktober Special Award TagPicture Me This Round 33 Winner!The Outlaw!VIP MemberHasslevania 2!I am an April FoolKitty
Picture Me This Round 32 Winner!Picture Me This Round 42 Winner!Picture Me This Round 44 Winner!Picture Me This Round 53 Winner!
15th January, 2015 at 15/01/2015 18:07:18 -

You can use the ini object for this.

If you're using MMF 2 you'll have to use spread value on the object and then loop through them one at a time and save their positions.
If you're using CF 2.5 you can use the new For Each action on the object and again save their positions to the ini.

To load them again you loop through the data in the ini and create them one by one again.

That's really all there is to it.

 
n/a

The_Antisony

At least I'm not Circy

Registered
  01/07/2002
Points
  1341

VIP MemberStarSnow
15th January, 2015 at 15/01/2015 22:21:02 -

This may need correction, but I always thought "Pick one at random" only selected from objects active within the viewable playfield at runtime. That kinda bursts your bubble if you're working on any sort of scrolling game. I'd suggest sticking to the tried and true method of using a spread value. There's no skipping copies of your active or accidentally selecting the wrong one when two or more exist on the screen at the same time with that "Pick one at random" deal.

Applying spread values and differentiating between active duplicates are sort-of confusing and vague concepts, but they're worth learning. You could probably find some way of adapting the process to other projects to save on resource use and project size. I'm sure Nivram has a tutorial or two pertaining to spread values, but they're likely all in MMF and MMF2 formats, and I'm not aware of any for F2.5.

I'ma try a shot at a quick and basic tutorial.

In the level editor, select your active. Add an alterable value called "ID".
Also, add a counter object.
In the event editor:

Start of Level:
Active -> Spread Value 0 in alterable value ID(Active).
Set Counter to alterable value ID(Active)+1
**Spread Value 0 will locate the first instance of Active, set its ID to 0, find the next instance - set it to 1; next instance = 2, etc. If there are 15 actives, each individual Active will be assigned an individual ID of 0 to 14. For the sake of making spread value work, this is the only event you'll need, but we should probably test this out. The counter will update to the latest ID assigned + 1. Reason for this is that later, when you're manually adding detectors in the level editor, they will need an ID too. We have to remember where the spread value left off so the next few detectors are assigned IDs in the same sequence.

To test, you could just add your active to the debugger and check the ID in each instance that way. You could also make a visual counter in the level editor and set it to Active's ID alterable value when you click on each Active.

If you need to test for collisions, it might be a good idea to create a new alterable value named "triggered" or something which tests for object overlap, negated object overlap, overlap with obstacle backdrops, and negated overlap with obstacle backdrops. That would probably look a little something like this:

Active is Overlapping Active
OR (filtered)
Active is Overlapping Backdrop:
Active -> Set triggered to 1

(negated) Active is Overlapping Active +
(negated) Active is Overlapping Backdrop:
Active -> Set triggered to 0
**So basically, to test collisions, if Active's alterable value "trigger" = 1 then pull the active's ID. That's the detector or set of detectors which are colliding. It's best to use an alterable value for this instead of a flag because down the road you may need to differentiate between the two types of collisions and test for 2 or 3 for example.

I haven't said a damn thing about INIs yet. Guess I should get to that. Once all your actives have an independent ID, its pretty easy fast-looping through them to save all the values to an ini. Time to jump back into the event editor.
OnLoop "saveXY"+
ID of ("Active") = LoopIndex ("saveXY"):
INI++ -> Set Current Group to "Active".
INI++ -> Save Position (0,0) from ("Active") to item Str$(LoopIndex("saveXY")+"Active"
**See that "Str$()" expression? That's turning the index of the loop into a string so it can be glued together with the name of the object. I don't know if it's necessary, but this should allow you to later use other string modding expressions to single-out entry types by name and individual entries by number. Otherwise the only recourse is selecting by group and ordered entry via the INI++ object.

I should explain the rest, too. This save system does depend on each active having an independent ID. That's all fine and dandy since we're unable to add these Actives to the level ourselves and all of the Active IDs get accounted for at the beginning of the level, but adding in more Actives throws a wrench into the cogs because as they're placed, they won't receive a new ID. Remember that counter we created at the start? It should contain the last assigned spread value +1, meaning that when the user drops a new detector into the level editor at runtime, assign its ID to the counter value, then increase the counter by 1.

Now all we need is a trigger event.
Upon Pressing Space bar:
Special Conditions -> Start loop "saveXY" NObjects( "Active" ) times.

...and another trigger event. So far, the INI is just sitting in memory, so just for testing purposes, it might make sense just to use another keypress event.
Upon Pressing Control:
INI++ -> Save INI as AppPath$+"xy.ini"

Done.
If you open the created INI, it should list several #Active entries, each with a separate X and Y value.
Each entry has a number preceding it so they can be individually tested and loaded with Val% and Left$ expressions.

 
ChrisD> Employer: Say, wanna see a magic trick?
ChrisD> Employee: Uhh… sure, boss.
ChrisD> Employer: Your job! It just disappeared! Pack your things and leave! Pretty good trick, huh?

Dave S.



Registered
  26/09/2003
Points
  924
15th January, 2015 at 15/01/2015 22:28:13 -

Ant, you have gone to a lot of trouble - very much appreciated.

Give me a day or so to try it out. Think I'll print it off.

Get back to you soon - thanks again.

 
n/a

The_Antisony

At least I'm not Circy

Registered
  01/07/2002
Points
  1341

VIP MemberStarSnow
15th January, 2015 at 15/01/2015 23:02:54 -

Hold up; just discovered a little logic bug and it's fowling up the whole shebang. When dropping new detector Actives into the level editor during runtime, setting the newly created Active's ID to the counter value will actually overwrite all the IDs in all of the Actives. They'll all be the same. See how this gets tricky?

The easy fix ix simply running another spread value on all the Active's just before saving position data to the INI, but that will completely reassign all IDs, not just update objects that don't have an ID value.

If you need IDs to persist per-object between saves, jump back to the level editor, select the active, and manually set it's ID to 0.

Then you'll need to mod a couple of events:

Start of Level:
Active -> Spread Value 1 in alterable value ID(Active).
Set Counter to alterable value ID(Active)+1
**I'm changing the spread value to start at 1 so that newly created detectors are defaultely left with an ID of 0. Now, if you've got 15 detectors in the level editor, they'll be assigned a value of 1 to 15.

This event, too:

OnLoop "saveXY"+
ID of ("Active") = LoopIndex ("saveXY")+1:
INI++ -> Set Current Group to "Active".
INI++ -> Save Position (0,0) from ("Active") to item Str$(id( "Active" ))+"Active"
**I changed the LoopIndex ("saveXY") to LoopIndex ("saveXY")+1 to reflect the fact that the spread value now skips 0. I also changed the LoopIndex reference in the INI filename to the ID of the active object.

Now, instead of having to assign a spread value to all of the Actives before a save, you can test if the Active's ID = 0. If it does, spread value in those actives beginning at the Counter value. Now, older values aren't at risk of getting overwritten by new Active detectors in close vicinity and every detector still has an independent ID.

 
ChrisD> Employer: Say, wanna see a magic trick?
ChrisD> Employee: Uhh… sure, boss.
ChrisD> Employer: Your job! It just disappeared! Pack your things and leave! Pretty good trick, huh?

Dave S.



Registered
  26/09/2003
Points
  924
18th January, 2015 at 18/01/2015 19:43:08 -

Saving worked a treat (I checked the INI file) but I found loading was an issue. I resorted to JonWog's 'pick blob at random' way in the end, sorry. However, spreading alterable values is useful to know (I set up an event to check it was all working at the time).

It's a pity that the 'Save Object'/Load Object in the INI file doesn't work with duplicates as I find it much more straightforward. Grouping actives as qualifiers ends up as just one chunk (and one group).

Thanks again for your input. Maybe you have benefited in some way?

 
n/a
   

Post Reply



 



Advertisement

Worth A Click