Referencing object created after using Create Object (by name)

0 favourites
From the Asset Store
With this template you will learn how to use the GooglePlay Games native plugin
  • Greetings once again,

    I am using a JSON file to feed the name of an object (a sprite) into my script. I am then using Create object (by name) to instantiate that object in my application.

    I do not, however, know how to then reference that instance of that sprite. Can anyone help?

    More details:

    I have many different sprites with image points on them. The goal of my application is to dynamically draw a schematic showing how one device (referenced by a sprite) connects to another (referenced by another sprite) by drawing a line from image point on the first sprite to a different image point on the second sprite.

    All of the information is stored in a JSON file. (The sprite names, the referenced image points for the respective sprite, etc.)

    I query the JSON file, use the Create Object (by name) function to instantiate the sprite and then I am stuck.

    I need to be able to reference [the image I just created's] image point, however I do not know how to reference the [image I just created].

    Normally, when using the fixed Create Object function where we choose the object to create, the subsequent reference would simply be [that known object].imagePoint or whatever, of course, but in this case I can't do that.

    I know there is the "pick last created," but that too, requires the manual selection of the object type.

    One thought is to put all my sprites into a family and then trying pick last created [family] and seeing if that works, but I don't know if families work that way, or if Construct will be looking for the *last family* that was created. (I am about to try this.)

    If anyone has experience with this, I would greatly appreciate the help.

    Thank you.

  • Try your family idea, it could work. If it doesn't another idea is to use js scripting, but I haven't looked into it. Another ideas is to just use the normal create action, just do one per type. You could also change it to use one object type with different animations for the different images.

    When it comes to picking two separate objects to make a line between them it helps to simplify as much as possible, that's why I suggest to make one object type with animations to distinguish between them. Then having a family with that single type allows you to pick two separate instances at the same time.

    However with the picking system of events it is a bit more complicated to connect two different objects just created since only the latest will be picked in that event. One solution is to create all the objects and then in a second top level event (when they can be picked as normal) do the picking.

    Anyways, here's one way to do it. The data has a list of objects to create and links to make between them. It utilizes a 1d array to keep track of the new object uids and a family to be able to pick them.

    dropbox.com/s/3ke0ef3zlndyqyb/createNconnect.capx

  • Thanks for your reply.

    So far it seems that my family idea is not going to work. I created a family called "devices" and put 10 device sprites into it.

    I am loading 8 of those sprites onto the layout using the Create Object (by name) from my JSON file which is working perfectly well.

    When I try to run a For each on the "devices" family, I am not getting any actions to work despite adding family members to the layout.

    Until a few minutes ago, I had all of the sprites I've created sitting on the layer, outside the layout area. When I was running the for each

    For each "devices": devices.ObjectTypeName = "ccehd":

    ("ccehd" is the name of one of my sprites that I was testing with)

    For testing, I was appending some text and "devices.ObjectTypeName" to a text box.

    It was iterating 8 times (the number of sprite family members in "devices" that were created on the layout). Which almost made sense, execpt it meant that my second condition, "devices.ObjectTypeName = "ccehd", was not evaluating true.

    For another test, I toggled the second condition off and my test text iterated 10-times. The total number of family members; not just the number currently on the layout.

    It then occurred to me that technically I DID have all 10 sprites on the layout, they were just off screen, so I removed them, but after I removed them, the loop stopped iterating altogether. So despite dynamically creating 8 family-member instances, the "for each devices" loop was not seeing those sprites as family members.

    Doesn't look like this is going to work as I hoped.

    Further, the second part - figuring out a way to reference them is still unclear... I can incorporate "devices.ImagePointX(0)" in an action, but that is not the reference point I am looking for. There does not seem to be a way to drill down to the specific family member. (I tried "devices.ObjectTypeName" - which does print the sprite name in text - but there is no ".ImagePointX()" that I can append to it.

    I am thinking I may have to build an array that links references that I will use in my JSON file to objects in the array. I am guessing this may be what is in the capx you posted, but I haven't had a chance to look at that, yet. That's for tomorrow morning.

  • So I think I confirmed that running a forEach on a family just counts the number of instances of that family, not the members of that family. I'm still working on how to properly reference its children.

    I tried doing a for loop from 0 to family.AllChildCount but this only returned a single iteration of the loop. It is not properly counting (or detecting) the family's children. Perhaps I am not understanding how families are supposed to work.

  • Families are so you can treat multiple object types as one type. You’re probably after hierarchies. I haven’t used it but it lets you have child objects to others.

  • One thought is to put all my sprites into a family and then trying pick last created [family]

    This is the right method, I use it all the time.

    I tried doing a for loop from 0 to family.AllChildCount but this only returned a single iteration of the loop. It is not properly counting (or detecting) the family's children.

    AllChildCount expression is related to hierarchies. Family "children" are usually called members, and unfortunately there is no way to get a list of all family members in events. You can make your own list of members, for example with an array.

  • rojohound & dop2000 Thanks again for your input. My day didn't go as planned (took my car in for a new tire this morning and ended up waiting around 3 more hours than I had expected) so I didn't have time to work more on this project today. I will roll your suggestions into my trials and errors tomorrow.

    Earlier today I conceived the idea of using a 3D array to store all of the image points (X and Y locations) for all of my device sprites upon starting the layout (there are a lot of them, some of my "devices" have 80 image points) and then cross-referencing them in the array for the devices I need to draw on, but then it occurred to me that if that array is filled before the sprites are positioned on the page, the X and Y locations in the array will not match the "new" x and y positions of the placed sprites. :-(

    Just as there is "Create Object (by name)", it would be so simple if there were only a "Pick Object (by name).ImagePointX(0)"

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • I don't understand the problem. You can still pick family instances by object name. And use Family.ImagepointX/Y

  • I've tried doing that but it didn't seem to give me the correct image point location..

    I instantiated my sprites like this:

    This places the sprites named in my JSON test file from left to right on screen, calculating their position from a variable devImageWidth = 1200.

    (8 sprites load, each one is given a space of 1200px w to sit in and all 9600px worth of images are centered on the layout. I'm using scrollX to slide left to right.)

    For testing, I then tried to place another sprite at the same X location as the desired imagePoint (I haven't started scripting the connecting lines I ultimately wish to make).

    When I do this with no conditions, it places 8 "statusLed" sprites in line with the very center of all 8 sprites directly on top of each other (I can see the 8 of them in debug.)

    When I add either of the commented out "devices.ObjectTypeName = " conditions (both are same condition, tested one from JSON reference and the other typed just in case I was having a JSON issue) the "statusLed" sprites do not get created.

    I have also tried changing the ImagePoint() number but that does not change anything.

    When I append ImagePointX() to my testing text area, it shows as "0" which is where the center of all 8 sprites is. If I mess with my placement math so the images skew left or right of center, devices.ImagePointX(0) remains at 0px for all 8 instances.

    I thought I might have to do a "for each devices" and then have the "if ObjectTypeName =" condition, however that does not seem to generate the desired result either.

    Am I making some other glaring mistake?

    Thanks again.

  • It's hard to troubleshoot without the project file. "For each devices" with the condition where you check for ObjectTypeName should work.

    Where and when do you run this event? Instances in C3 are not created immediately, sometimes you need to wait until the end of the tick to be able to access them from other events. If this is the case, add "Wait 0" before running that event.

    I suggest debugging such issues using Browser Log action. For example:

    For each devices : Browse Log "Iterating devices UID=" & devices.UID
    
    .. devices.ObjectTypeName="foo" : "Picked device:"&devices.ObjectTypeName
    
    etc.
    

    Open the browser console and check the messages there.

  • dop2000

    So I've made some progress. Adding the Wait 0.0 made a world of difference in terms of getting output that I was looking for, but I found that I have to add indexes to the devices family in order to reference its members.

    I added the lines you suggested for logging. Nothing in the log would appear until I added wait after creating the objects.

    My order is:

    For each entry in ".path" (from my JSON file) Create object (sprite name from JSON file) Create textbox Set textbox to (title from JSON file) Wait: 0.0

    My x position calculation stopped working which takes place after all of the inner-loop actions so I found that moving to above the Wait function solved that issue. (I keep having to reorganize my thinking around the concept that Construct executes everything more or less simultaneously and not sequentially - I suppose each iteration of the outer "For Each Entry Loop" executes before the subsequent "For Each devices" sub-event actions. (Hence adding the Wait in the first place, yes?)

    But what I also found through trial and error is that I have to add "indexes" to the "devices" family whenever I am referencing it ("devices(1)").

    So devices.ImagePointX(0) will only reference the very first object created from the family, but devices(7).ImagePointX(0) will reference the 8th object created from the family.

    I have not seen this anywhere in the documentation, but it does seem to be working.

    I also had to create my own index (deviceIndex) as the "For each entry in ".path" does not seem to create a loopindex. (it always evaluates to 0). So I have a variable, "deviceIndex" which advances by 1 for each object created.

    So now, after adding the Wait 0.0 and then changing my subsequent loop to:

    For Each devices: if devices(loopIndex).ObjectTypeName="ccehd": { //DO STUFF - place my test image, output the imagePoint coordinates, etc }

    It looks like I will be able to reference the image points that I need to reference.

  • EDITED

    I wrote a whole long post, but I've been trying different things for a while and think I have a better assessment of what is going on so I deleted what I wrote earlier.

    What I think IS happening is exactly what you said earlier about the instantiation of sprites taking some time...

    My sub-event (inner ForLoop) is executing before the devices family members are finished being created so the references to the "last object created" (eg. familyName.ImagePoint(0)) don't work because they probably don't exist yet.

    The problem is that if I add the "Wait 0" anywhere, it causes my inner loop to fire after the outer loop is finished repeating so my loops end up not being nested. This means loop indices don't flow form outer to inner and variable auto-incrementation falls out of order.

    Ideally I would like to do things sequentially:

    Create an instance of a device -> Draw something at an image point belonging to that device -> repeat for next device. But it looks like that can't happen.

    It looks like I will have to do things in two separate (un-nested) loops.

    1) Instantiate all of the devices that are in my JSON file and place them on screen.

    2) Iterate over all of the newly created devices... compare each one to each of the devices in my JSON file... when there is a match, draw the appropriate object at the appropriate image point for that object.

    Does this sound like I am understanding things correctly?

    Thanks.

  • Update: I have it working.

    I had a ForLoop searching the JSON file for a specific entry... within that loop, I had a ForLoop generating the objects found on a schematic... within that loop, I was trying to overlay a test graphic (eventually to be a connecting line) at a specific ImagePoint on the schematic objects.

    As I said I would do in my previous post, I separated the nested ForLoop (for the test graphic) from the outer loop and placed it on the script outside of the outermost ForLoop. This is working!

    I was also able to go back to using "ForEach" loops for all of my loops and built-in references like "device.ImagePoint(0)" are working without the need for adding loop names and indexes.

    I removed all "Wait"s.

    (See screenshots below).

    I am still wondering why I have to do it this way. There really does not seem to be a way to effectively "pause" the script long-enough to instantiate the objects before their properties became available to the next part of the script. Is that not possible, or, again, was I doing something wrong? No matter where I placed a "WAIT", it would "un-order" my subsequent actions.

    What I have now should work for my purposes, but I would be interested in knowing if there is a better way or if I am misunderstanding something. (I produce small applications - some games, others utilities or front-end GUIs in Construct - as I am doing here - often, so I'm trying to get better and better at using the program.)

    Thank you all, for your assistance and input!

  • You just need to keep in mind that newly created instances may not be immediately available in other events. Example:

  • I do (now) understand this, however what I experienced seems like the opposite of what you are showing here... The new instances were NOT available to my sub-event right away, but they WERE available to other events.

    In actuality, it may just be the new instances' properties that were not available (I could position a new instance immediately in the same event, but I couldn't read that position in the same or a sub-event.)

    I have an on-screen button that kicks off the loops creating objects... If I clicked it once they would be created, but the sub-events didn't "work." If I clicked it a second time, even though the very first thing I had it do was "destroy" any existing objects before re-creating them, the sub-event would work. I believe this happened "coincidentally" because the sub-event was able to read the properties of the existing instances before they were destroyed (I'm guessing because it probably takes a short amount of time to destroy instances as well)

    dop2000, Thanks again for your help!

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)