• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GML [SOLVED] Pseudo Room Problem - Space Game

L

Lennayy

Guest
Hello all, this is my first post so apologies if this is in the wrong place or badly formatted.

In my game, you fly a spaceship. This spaceship has multiple levels, but the ship as a whole stays in the same room (so your position in space and other objects in space don't change). I have sprites for the different levels of the ship and basic system for creating the various objects (wall blocks, doors, consoles, etc.) of each level, including their positions, using arrays:

Saucer.png Saucer 2.png

An array is created using two for loops to generate grid coordinates, then each array entry is assigned a value of an object (e.g. array[1,10] = obj_block). Another two for loops are run to create the objects in their respective positions. Using this system I can have any number of ships, of any shape and size, but only have to use one room (which is useful given how I would like there to be one 'Space' room!)

I can also create different layers of the ship by having the array change based on the level you are on (basement, floor 1, top deck, etc.)

What I cannot figure out is how to make the objects on layers that aren't currently in use persistent, as you can do with rooms. I would like to have AI objects (cleaning robots, rogues aliens, computer malfunctions) on different levels that still function when you aren't on that level.

I have toyed with ideas such as making the levels all exist at the same time jumping their position to outside of the room when not on that particular level (shifting all instances of that level) but I fear I will run into complications later when dealing with collision checks with other ships that will be outside of the room.

I'm not sure with the current method I have if there will be a solution to this problem, or at least not a simple, easy to work with one.

Many thanks in advance!
 

NightFrost

Member
Well, to give the ship's interior space persistence, you have to let all the levels exist at the same time. Meaning, all the level arrays need to exist and be usable at the same time. Changing the draw is the easiest part. You just need to have a variable which tells you which level player currently is, and have your draw routine pick and draw that level.

You could do entities that roam the ship as objects. Their draw part is also simple: they draw themselves only if they are on the same level as player. Movement will be more work. For random wandering, you can just do a grid collision system, basically you pick a direction for the entity and it checks directly in the array of its current level for anything that could block movement (and against positions of other entities if they block too). Seeking movement is a bigger problem. Multiple levels means the ship is a 3D grid, so mp_grid won't help you there as it is 2D only. You'd have to implement A* pathfinder if you want to seek shortest route from point A to point B across multiple ship levels. This cannot be reduced to 2D seek on each level separtely, because you need to know which inter-level connections exist and form the shortest route.
 
L

Lennayy

Guest
You've just helped me see my problem clearer, thank you!
I'm thinking about objects moving and colliding based on the standard position of objects, but if I base it on my array map instead (check array position instead of objects coordinates) then I can almost create a fake 3D collision checking (if that makes sense?)
I've not used an A* pathfinder before, but I've read up on them quite a bit. The game itself is grid based so I have an advantage there (no collision outside of this grid.)
The grid collision system does sound ideal, but I will have a play around implementing the array a bit more before I try that out.
But in it's simplest form, I could use a 2D array 'map' for each layer, and a 'level' variable to draw that particular level (as you said) and also check for collision.

Thanks for the help.

I understand what you're saying about the mp_grid not working on 3D. I think I may just cross that bridge when I come to it.
 

NightFrost

Member
Well if you can master A* on 2D then 3D is just as easy. This is because A* doesn't see space, it just sees a graph, which is a collection of points and connections between them. It doesn't matter which way the connection "points" because - where A* is concerned it is just a connection between two points. A 2D grid is just a special case of a graph where every connection is of equal length and neighbours can be ordered into neat rows and columns.
 
L

Lennayy

Guest
A* algorithm sounds a bit complex compared to what I have in my head, though what I have in my head may just be the same thing... I'm still basing it on a graph (or 2D array.)
Will have a little play around see where it leads.
Thanks again.
 
L

Lennayy

Guest
I have run into another issue.
When drawing a level (forgive me if I'm just being dumb here) I'm trying to work out how I would draw interactive objects.
What I'm thinking of doing is having each object interact with an array 'map' rather than having actual coordinates and objects. This is obviously slightly harder than moving... I would effectively be changing the array constantly based on an objects pseudo-position.
Am I overcomplicating things here?
 

NightFrost

Member
What do you mean by an interactive object? Things like switches? And what do you mean with having them interact with an array instead of being an object? You're probably overcomplicating things.
 
L

Lennayy

Guest
Good questions!

Yes like a switch. Objects that change themselves or other things (e.g. doors that open and can be locked by the player.) Things that will change the state of the ship's level.

I have built a better system (I hope.)

The ship's layout is built from multiple 2D arrays. The first array holds boolean values, and the player detects its value and if it's true, it can move there, otherwise it can't.

The second array places objects, such as doors and switches, which each have a level variable to say it only affects objects on that level.
That way, the arrays can be updated and changed without having to draw a single object (providing the persistence I need.)
I have also managed to create a dynamic way of creating these arrays without having to painstakingly alter every single array entry to things like 'obj_block' but will have to upload that later when I'm on my computer.
 
I would actually just store all of the objects stats in a data structure and when I create each instance I would pull it's stats from the DS, rather than trying to mess around with having everything exist at once. It's much cleaner and more efficient to only create what you need and store only the required data for each thing.
 

NightFrost

Member
I would actually just store all of the objects stats in a data structure and when I create each instance I would pull it's stats from the DS, rather than trying to mess around with having everything exist at once. It's much cleaner and more efficient to only create what you need and store only the required data for each thing.
Isn't that what OP is now doing, saying there's a second array for those interactive objects? But if not, yeah, saving data into separately modeled structure would be the way to go. Using enumerators then makes it easy to retrieve data you need. For a simple example that would just store the type and position of various interactive objects around the ship:
Code:
// Define object data enum
enum Item_Data {
    type,
    level,
    x
    y
}

// Define object types enum
enum Item_Type {
    door,
    switch,
    light
}

// Define objects
global.Items[0, Item_Data.type] = Item_Type.door;
global.Items[0, Item_Data.level] = 1;
global.Items[0, Item_Data.x] = 8;
global.Items[0, Item_Data.y] = 12
global.Items[1, Item_Data.type] = Item_Type.light;
// ...and so on.
You then just extend the data enum and array to store more data about each.
 
L

Lennayy

Guest
I haven't actually used enumerators before, but essentially the principle's the same. I've been using arrays but that will be easy to convert to something like data structures. Everything shouldn't need to exist at once (or at least be present in the room) but things will need to update whilst they aren't present. Well, I would like them to anyhow.
 
L

Lennayy

Guest
Here's my solution so far;

I have a (parent) shuttle object, which has a sprite of a shuttle (the very same as in my first post) and generates an array based on the sprite's width and height, but divided by cell_size (16) to create basic xy coordinates of the shuttle's current level:
Code:
///Create Script

//Set shuttle variables

shuttle = sprite_index;

level_create = 1;

shuttle_width  = sprite_get_width(shuttle);
shuttle_height = sprite_get_height(shuttle);

if ( shuttle_width / 16 ) % 2 == 1 {
   
    shuttle_x = ( room_width  / 2 ) - ( shuttle_width  / 2 ) + 8;
    shuttle_y = ( room_height / 2 ) - ( shuttle_height / 2 ) + 8;
   
    } else {
   
    shuttle_x = ( room_width  / 2 ) - ( shuttle_width  / 2 );
    shuttle_y = ( room_height / 2 ) - ( shuttle_height / 2 );
   
    }

//Populate shuttle array.

for ( i = 0 ; i <= ( shuttle_height / cell_size ) ; i++ ) {
for ( j = 0 ; j <= ( shuttle_width  / cell_size ) ; j++ ) {

    shuttle_wall_map[j,i] = true;

    }}
The shuttle sprite is drawn in the draw event so the ship's center aligns with the room's center (the actual object is placed in the top left corner of the room.)

In the draw GUI event, if the level has not been generated (ie level_create = 1) then a map sprite of the ship (see here: Shuttle Map.png ) is drawn in at coordinates 0,0 (top left corner of the view) and the array is run through again. If the pixel value (using draw_getpixel()) is equal to 0 (is == black) then set the value of that aray point to false, otherwise set it to true. Once run, set level_create to 0:

Code:
///Create shuttle objects

if level_create = 1 {
    
    for ( i = 0 ; i <= ( shuttle_height / cell_size ) ; i++ ) {
    for ( j = 0 ; j <= ( shuttle_width  / cell_size ) ; j++ ) {
        
        draw_sprite(spr_saucermap, 0, 0, 0);
        if draw_getpixel(j,i) == 0 { shuttle_wall_map[j,i] = false; } else { shuttle_wall_map[j,i] = true; }}
    
    level_create = 0;
    
    }}
The player's grid movement is no longer based on blocks being in positions. It converts it's room coordinates to the array coordinates of the shuttle, and detects the value of the array (true = can move, false = can't move):

Code:
///Handle movement.

depth = -y;

if keyboard_check(vk_shift) { move_speed = 4; } else { move_speed = 2; }

if place_snapped(cell_size, cell_size) {

    speed = 0;
    is_moving = 0;

    }

if keyboard_jacked = false {
    
    for ( i = 0 ; i < array_length_1d(movement_inputs) ; i++ ) {
        
        var this_key = movement_inputs[i];
        
        if (keyboard_check(this_key) && is_moving = 0) {
    
            var map = obj_shuttleparent.shuttle_wall_map;
    
            pax = ceil( ( ( x + lengthdir_x( cell_size, i * 90 ) ) - obj_shuttleparent.shuttle_x ) / cell_size );
            pay = ceil( ( ( y + lengthdir_y( cell_size, i * 90 ) ) - obj_shuttleparent.shuttle_y ) / cell_size );
                    
            if !(map[pax,pay] = false) {
                
                direction = i*90;
                speed = move_speed;
                is_moving = 1;
                
                }}}}
The movement is based on 'Buttery Smooth Tech Tips' (https://www.yoyogames.com/blog/432/buttery-smooth-tech-tips-movement) but converted to work in grid movement, then converted to the array check instead of position check.

It works perfectly! So far... I just need to check it works for different levels. The principle of using draw_getpixel() to map the array saves a lot of manual labour (shuttle_wall_map[0,0] = obj_block.... repeat ad nauseum) and can use multiple colours to create a colour map that can place doors, panels, switches, toilets, old food, anything! What I cannot work out at the moment is if I can still create objects or if I should just have scripts that control various aspects, like doors.

I am feeling like arrays may be a better approach for now. I may need to use enumerators for actual object qualities in places.

I'm not sure data structures will be as effective, I have read that arrays can run quicker but that may not be true. I don't need particularly complicated structures so far as I can tell.
 

TheouAegis

Member
Code:
///Create shuttle objects

if level_create = 1 {

for ( i = 0 ; i <= ( shuttle_height / cell_size ) ; i++ ) {
for ( j = 0 ; j <= ( shuttle_width / cell_size ) ; j++ ) {

draw_sprite(spr_saucermap, 0, 0, 0);
if draw_getpixel(j,i) == 0 { shuttle_wall_map[j,i] = false; } else { shuttle_wall_map[j,i] = true; }}

level_create = 0;

}}
Draw the sprite and clear level_create BEFORE the for loops.
 
L

Lennayy

Guest
Good spot!
Although I'm now trying to convert the process to use surface_getpixel() instead, but will do that now.
Thank you.
 

TheouAegis

Member
If you're going to draw to a surface, atthat point you could just make an array of buffers and use buffer_get_surface() to store all the shuttle layers. Just an idea.
 
L

Lennayy

Guest
That may be worthwhile! But for now I still haven't solved the persistence issue. I can destroy and recreate instances, I can deactivate and activate the instances, but keeping them active when not around is proving tricky...

I think I might have to work on a system that only allows interaction with instances based on level. Have a variable called 'level' and have all instances only react based on a level variable check. This sounds annoyingly simple. This could lead to lots of instances at once :/ apologies if this was already suggested I am very tired This morning haha.
 
L

Lennayy

Guest
I am also running into a problem regarding dynamically creating levels (I want one shuttle parent object to build my shuttles from). I dynamically create the arrays, but to then dynamically create the levels becomes 3D array territory... Of which the only solution I have is to off set on array dimension (array[xx, yy + (levels * Cell_size)]) so they all exist on the same level, but that's a bit harder to organise.

EDIT: array[xx, yy + ( shuttle height * levels )]
 
Well, if you need things to 'happen' to the instances when they are deactivated/not existing, that's why you should be storing the data that you need to create them. Instead of worrying about instances, worry about the data.

For instance, in my game I have a garden where you grow crops and an overworld where you fight enemies. They are separate rooms, meaning that when you are on the overworld no crop instances exist. But I still have all the crop data that I use to recreate the crop instances when you enter the garden again. If I need something to happen to the crops while you're on the overworld, I change this data. If I need my crops to grow, I change the growth data that I've stored, I don't worry about the instances not existing (because when I recreate them, I recreate them using the data I am manipulating). I think this is a better way to think about storing and loading levels that need to have changes happening.

To give an example, if a switch is on Level 2 that needs to open a door on Level 1, you -should- be storing some data relating to the door (and everything else that could potentially change) for use whenever you load Level 1. This means that when the switch on Level 2 is triggered, you should be able to access the stored data for Level 1 and change the doors status to open. Then when you go back to Level 1 and you create all the instances, the door instance should be pulling it's status from the stored data and it should then know that it has been activated.

I'm hoping that I understand what you are trying to do, lol.
 

NightFrost

Member
Yeah that's why we've been talking about separate data structure for your interactive objects. Because all the relevant state information is in the data, not on the instances, they can be destroyed and recreated whenever without losing any information. I failed to mention this earlier but this is why in my code example above the data is on a global: it makes it persistent and accessible from everywhere.
 
L

Lennayy

Guest
Hit the nail on the head!
Yes that's it. I think my brain was too muddled with other mechanics (I hadn't built enough of the system before sorting this but I knew I would run into this issue!)
Just need to work out the best method for this. I haven't played around with this yet.
I guess my issue now (apart from building this) is the difference in how the data is changed. I effectively need to manipulate the data exactly the same whether it is active or not, so surely I may as well treat all objects as just changing data, rather than both changing data and instances.

To explain a little better:

The player interacts with objects, like a door, and treats it like an object.

A rogue alien on a different level breaks into the computer room and chews through the wires, but this is just data that changes as it isn't happening on the player's level

A janitorial robot on the same level as the player, whilst is interacting with the objects, should only change data. The reason being is that if it were to happen on a different level to the player, the process and effect would be the same, but it would seem pointless having two different systems to do the same job at the same time.

I am looking into enumerators as I think that may be the best approach for saving and loading, but I may need to use data structures instead. I've only just been able to sit down now and work through this method, and having not worked with either yet may be a bit chewy...
 
Instead of piling arrays into arrays into arrays (as well as having a million enumerators) don't be afraid to create a ds_map for each instance that you need and store it in a ds_list. That way you can have things like:
Code:
// Creating the instances data properties
var inst_map = ds_map_create();
inst_map[? "activate script"] = open_door; // open_door being the name of a script you have made here that you want to run when someone "uses" the instance
inst_map[? "name"] = "Door";
inst_map[? "description"] = "Opens when you find the right switch";
inst_map[? "locked"] = true;
inst_map[? "type"] = "door";
inst_map[? "sprite"] = spr_door;
inst_map[? "object"] = obj_door;
inst_map[? "level"] = 1;
inst_map[? "pos"] = [250,500]; // X and Y coords
inst_map[? "list pos"] = 0;
// Etc, etc
global.level1_instance_list[| 0] = inst_map; // Create a pointer to the above map inside your ds_list
ds_list_mark_as_map(global.level1_instance_list,0); // Mark the list position as a map (read the manual for an explanation of why you should do this)
You can store as many properties as you like in the map, and then use that when recreating the instance, for example:
Code:
var _inst_map = global.level1_instance_list[| 0]; // Get the inst_map at position 0
var pos_array = _inst_map[? "pos"]; // Pull out the array storing the position in the room
var xx = pos_array[0]; // Get the values out of the array, i'm just doing this for understanding, you could just as easily use pos_array[0] for x and pos_array[1] for y
var yy = post_array[1];
var inst = instance_create_layer(xx,yy,_inst_map[? "object"]); // Create an instance at the stored position of the stored object type from the inst_map
inst.inst_map = _inst_map; // Create a pointer within the object itself that will allow you to manipulate it's inst_map without having to pull it from the list everytime (as long as you are accessing the variable inst_map from inside the obj_door instance itself)
inst.sprite_index = _inst_map[? "sprite"]; // Set the sprite of the created instance to the sprite stored in the map
Now you might wanna store things a little differently and there might be challenges that this specific setup creates for how you have setup things, but this'll give you just a taste of the power of a ds_map. Ds_lists are also super useful (and grids, and prio lists and...who am I kidding, they're all useful). You can do things like loop through all the "instances" in a level by looping through the whole ds_list and pulling out the map for each position, you can delete positions in the list to entirely delete "instances", etc. You can also easily save and load list > map systems using JSON encoding, and they'll be saved in a human readable format (be wary of storing arrays in the lists or maps though as when JSON encodes them, they will be automatically converted into a ds_list and so when you load the JSON back in, any array references you have will cause an error as they will now be ds_lists...better to create a ds_list each time you would make an array if you are intending to save load like this).

You can also very easily see if something has a certain property by using:
Code:
if (ds_map_exists(inst_map,"locked")) {
  // Code here will only run if the particular inst_map you are accessing has the "locked" key setup
}
On a side note: Don't be too scared of having like 1000 maps or whatever. It's unlikely that you'll run into performance issues with this, as long as you are not trying to ACCESS the 1000 maps every step or something silly like that. Plan your code properly and you'll never run into any performance problems from anything like this (and even if you do, THAT'S when you start worrying about it, not before when you're only thinking of a hypothetical performance hit).

And this is only one way of achieving the results you're looking for. It's the way that has worked best for me and has given me a lot of flexibility when doing stuff like data manipulation, but other people will have other methods with reasons why their methods work for them. The important thing is to get into the mindset of stepping out of GM's object based system and into a more systemic, data flow system.
 
L

Lennayy

Guest
Perfect! Now to try and get my head around it all haha. I am trying to use instance activation/deactivation for my levels but can't figure out how to only activate instances if their 'level' variable is == to the level the player is on. It works perfectly fine with destroying the instances and recreating them but I was seeing if there may be a smoother method (I'm trying to avoid writing a line of code to destroy each instance needed.)

In the meantime, I will try using the ds_map, but if there's any advice you can give on where to go should I get stuck (have read through the manuals on this already) that'd be greatly appreciated!
 
Create a parent object, maybe called obj_destroy_parent, and then set that to be that to be the parent of every object you want to be cleared when you move out of a level, then simply use:
Code:
with (obj_destroy_parent) {
  instance_destroy();
}
Instance activation/deactivation is -doable- but I honestly think it'd be easier to just destroy and recreate. Maybe try a "top level" ds_list, called room_list and store a new list in each slot for the rooms, so room_list[| 0] will hold a list that holds all the inst_maps for level 1 (because lists start at 0, not 1), room_list[| 1] will store the list that holds all the inst_maps for level 2, etc:
Code:
global.room_list = ds_list_create(); // Create the top level room list, each slot in this list holds another list, which holds all the inst_maps for each instance in that room
var room1 = ds_list_create(); // Create the list for room 1
global.room_list[| 0] = room1; // Store room 1 list in the first slot of the top level room list
ds_list_mark_as_list(global.room_list,0); // Mark that position as a list

var inst_map = ds_map_create(); // Create the first ds_map for instances
inst_map[? "name"] = "Door";
// Etc for all the values for this specific door
room1[| 0] = inst_map; // Store that map in position 0 of the room 1 list
ds_list_mark_as_map(room1,0);  // Mark position 0 in the room 1 list as a map

var inst_map = ds_map_create(); // Create the second instance and do as above
inst_map[? "name"] = "Enemy";
// Etc
room1[| 1] = inst_map;
ds_list_mark_as_map(room1,0);

// When you are finished with this, room_list[| 0] will hold the list called room1. Each slot in the room1 list will hold a ds_map that has the values for an instance in room 1. When you go back to room 1, you would do something like:
[code]
var enter_room_list = global.room_list[| room_no]; // Room_no should be 0 or 1 or 2, etc, just remember that it starts at 0 not 1
var list_size = ds_list_size(enter_room_list);
for (var i=0;i<list_size;i++) {
  var inst_map = enter_room_list[| i];
  // Use the same code to create the instances as in my previous post here
}
You would also repeat the process for room_list[| 1] (with that holding another list that has inst_maps in it), room_list[| 2], etc.

Something along those lines should work and be fairly modular, though remember, none of us will be able to carry you all the way there, it's going to be up to you to use the info you get here and adapt it to suit your specific needs within your project.
 
L

Lennayy

Guest
I actually already had a parent object built for all instances on the ship (or at least instances that are part of the ship), so I have no idea why I didn't just think of destroying that... brain fart.

Thank you. I am cracking on with ds_maps/lists for this now to see if I can get it to work. I briefly thought if it may just be better to stick with my arrays, and use data structures for the variables of the objects, but I realise now I can effectively dynamically create the equivalent of a 3D (or even 4D?) array but in ds_lists/maps, which is incredibly helpful!

If this works out (or more correctly, if I can get it to work, I'm sure it does work I just need to get my head around it!) that'll be my problem solved! :)
 
L

Lennayy

Guest
I have got all my data structures, and I have had quite a lot of success with this! I have now, however, hit another brick wall, and I can't figure out if I'm just having a dumb moment or if I don't understand DS as much as I thought...

I have been creating ds_lists and ds_grids dynamically, and everything now runs smoothly (albeit after a lot of trial and error) and works excactly how I'd like it to bar one thing.

All my data structures are made in the shuttle's create event. I have a 'shuttle_create' boolean which will fill in the data structures dynamically (using for loops) in the draw GUI event (it uses draw_pixelget() so has to be here, for now at least). This basically builds the entire ship in data structures using my pixel maps.

I then use a 'level_create' boolean to load each level as the player enters them:
Code:
if level_create = 1 {

    level_create = 0;

    //Grab level layout
    var this_level = ds_list_find_value(shuttle_layout, level);

    for ( yy = 0 ; yy < ( shuttle_height / cell_size ) ; yy++ ) {
    for ( xx = 0 ; xx < ( shuttle_width  / cell_size ) ; xx++ ) {

        //Grab cell information
        var this_cell = ds_grid_get(this_level, xx, yy);

        var sox = shuttle_x + ( xx * cell_size );
        var soy = shuttle_y + ( yy * cell_size );

        instance_create(sox, soy, ds_list_find_value(this_cell, 1));
      
        }}}

I would have thought (as these data structures were populated with information in the room_create process) that the data would be stored and I could pull the information from it here... but that doesn't appear to be the case. It doesn't create an instance because it thinks the instance isn't there. The game runs but no instances are created from this process. The 'instance_create' line works perfectly when put in the room_create process, but not in the level_create process and I can't figure out why :/ Have I gotten something wrong about data structures?

EDIT: I used temporary variables, but forgot to then assign the new information to the original data structures, and referenced the original data structures which did not have the updated information! I haven't fixed this but I believe this to be the problem!
 
Last edited by a moderator:
L

Lennayy

Guest
I can't seem to set the original data structures to have the new information. My code for changing the data structures is as follows:

Code:
if shuttle_create = 1 {
  
    shuttle_create = 0;
  
    for ( l = 0; l <= levels ; l++ ) {

        var this_level = ds_list_find_value(shuttle_layout, l);
      
        for ( yy = 0 ; yy < ( shuttle_height / cell_size ) ; yy++ ) {
        for ( xx = 0 ; xx < ( shuttle_width  / cell_size ) ; xx++ ) {
          
            var this_cell = ds_grid_get(this_level, xx, yy);
          
            //Define walls;
            draw_sprite(shuttle_map, l, 0, 0);
            if draw_getpixel(xx,yy) == 0 { ds_list_replace(this_cell, 0, false); } else { ds_list_replace(this_cell, 0, true); }
          
            var sox = shuttle_x + ( xx * cell_size );
            var soy = shuttle_y + ( yy * cell_size );
          
            //Define objects;
            draw_sprite(shuttle_obj, l, 0, 0);
          
            for ( n = 0 ; n < array_height_2d(color_map) ; n++ ) {
              
                if draw_getpixel(xx,yy) == color_map[n,0] {
                  
                    ds_list_replace(this_cell, 1, color_map[n,1]);
                  
                    } else {
                  
                    ds_list_replace(this_cell, 1, obj_null);
                  
                    }}
          
                //Transfer new data to original structures;
              
                var new_cell_list  = this_cell;
                ds_grid_set(this_level, xx, yy, this_cell);

                }
              
                var new_grid_list  = this_level;
                ds_list_replace(shuttle_layout, l, this_level);
              
                }}}
I then have this process for loading each level:

Code:
if level_create = 1 {
   
    level_create = 0;
   
    with(obj_shuttleobparent) instance_destroy();
   
    //Grab level layout
    var this_level = ds_list_find_value(shuttle_layout, level);
   
    for ( yy = 0 ; yy < ( shuttle_height / cell_size ) ; yy++ ) {
    for ( xx = 0 ; xx < ( shuttle_width  / cell_size ) ; xx++ ) {
       
        //Grab cell information
        var this_cell = ds_grid_get(this_level, xx, yy);
       
        var sox = shuttle_x + ( xx * cell_size );
        var soy = shuttle_y + ( yy * cell_size );
       
       
       
        for ( n = 0 ; n < array_height_2d(color_map) ; n++ ) {
       
        draw_sprite(shuttle_obj, level, 0, 0);
        if draw_getpixel(xx,yy) == 0 { ds_list_replace(this_cell, 1, obj_block); }
        else if draw_getpixel(xx,yy) == color_map[n,0] { ds_list_replace(this_cell, 1, color_map[n,1]); } else { ds_list_replace(this_cell, 1, obj_null); }
       
       
        var inst = ds_list_find_value(this_cell, 1);
        instance_create(sox, soy, inst);
       
        }}}}
But it doesn't load the things I have placed in the previous process, it just loads what was entered in the creation event (a load of basically blank variables but there as a back up should something have gone wrong.)

I've spent about 10 hours straight trying to sort this and still haven't had any resolve :S

EDIT: My second code was wrong, should be this:

Code:
if level_create = 1 {
    
    level_create = 0;
    
    with(obj_shuttleobparent) instance_destroy();
    
    //Grab level layout
    var this_level = ds_list_find_value(shuttle_layout, level);
    
    for ( yy = 0 ; yy < ( shuttle_height / cell_size ) ; yy++ ) {
    for ( xx = 0 ; xx < ( shuttle_width  / cell_size ) ; xx++ ) {
        
        //Grab cell information
        var this_cell = ds_grid_get(this_level, xx, yy);
        
        var sox = shuttle_x + ( xx * cell_size );
        var soy = shuttle_y + ( yy * cell_size );
     
        var inst = ds_list_find_value(this_cell, 1);
        instance_create(sox, soy, inst);
        
        }}}}
The bit I removed just now causes it to work, but it not by referencing the original DS as I would need it to.
 
Last edited by a moderator:
L

Lennayy

Guest
SOLVED:

I have gone back to arrays (I am pretty much using my original solution for creating/destroying objects and setting the walls) but I am using data structure maps to store each instances values needed! I used this tutorial here and adjusted the bits as necessary!


Thank you to everyone who helped. This has been utterly deflating trying to sort it out, but now I have I have regained that sense of triumph to continue!

My Solution is to use arrays for my walls and objects, but to have a ds_map to store the values needed. The link explains it so much better so I shan't waste time trying here, I suggest you watch that. Using data structures for the whole lot became overly complex and far too hard for me to keep on top of (or even fully understand) but using it just for instance variables works perfectly! At least for now, I may need to tweak it for more complex objects but it works just fine for keeping doors locked!

Thank you to all who replied and especially @RefresherTowel, I don't think I would have learned so much about DS (or even bothered to be honest) if it wasn't for you.
 
Top