Add children from array - arrays

I've been trying to learn swift for a few days now, and all tutorials I've found had had a specified number of SKNodes. I'm trying to programmatically add new instances to an array nodeList and add them to the scene, because I want each of them to execute some code periodically. This is my current version of code for adding more objects:
if (last_created < 0) {
//Some other code here
for i in 0...3 {
self.nodeList.append(self.backObject);
var x_current = CGFloat(Float(arc4random())/4294967296.0 * Float(x_range) + Float(x_min));
var y_current = CGFloat(Float(y_min) - Float(y_range));
self.nodeList[self.nodeList.count-1].position = CGPoint(x: x_current, y: y_current);
self.addChild(self.nodeList[self.nodeList.count-1]);
}
}
Attempt to execute this raises an exception:
Attemped to add a SKNode which already has a parent
I assume that every item in my nodeList array is seen as the same object, rather than separate instances. However, I don't know how to fix the problem. How should I have done this?
Thanks for your help.

You are adding self.backObject to the array multiple times, so it is being added to the scene more than once, causing the error. You should create a new instance of the node within the loop and add that to the array.

Related

IndexedDb dynamically populating existing ObjectStores

I have created many, let's say three ObjectStores inside a defined and versioned IndexedDB schema.
I need to populate all of them. To do so, I created an object which stores both name end endpoint (where it gets data to populate).
Also to avoid error when trying to fill objectstores already populated, I use the count() method to ... count key inside the objectstore and if there are 0 key, then populates, else reads.
It works perfect if I execute on a one by one basis, that is instead of using a loop, declare and execute each one of the three objectstores.
However when invoking the function to populate each storage inside a loop, I get the following error message for the last two objectstores to be populated:
Failed to read the 'result' property from 'IDBRequest': The request
has not finished. at IDBRequest.counts.(anonymous function).onsuccess
Here is the code:
// object contains oject stores and endpoints.
const stores = [
{osName:'user-1', osEndPoint:'/api/1,
{osName:'user-2', osEndPoint:'/api/2},
{osName:'user-3', osEndPoint:'/api/3}
];
// open db.
var request = indexedDB.open(DB_NAME, DB_VERSION);
// in order to dynamically create vars, instantiate two arrays.
var tx = [];
var counts = [];
var total = [];
// onsuccess callback.
request.onsuccess = function (e) {
db = this.result;
for(k in stores) {
tx[k] = db.transaction(stores[k].osName).objectStore(stores[k].osName);
counts[k] = tx[i].count();
counts[k].onsuccess = function(e) {
total[k] = e.target.result;
// if the counting result equals 0, then populate by calling a function that does so.
if (total[k] == 0) {
fetchGet2(stores[k].osEndPoint, popTable, stores[k].osName); //
} else {
readData(DB_NAME, DB_VERSION, stores[0].osName);
}
};
} // closes for loop
}; // closes request.onsuccess.
The fetchGet2 function works well inside a loop, for example the loop used to create the objectstores, and also has been tested on a one by one basis.
It looks like an async issue, however I cannot figure how to fix the problem which is to be able to populate existing objectstores dynamically, avoiding to populate filled objectsores and only filling empty ones.
Indeed testing without the count issue, but inside the loop works perfect, or with the count but without loop.
At the moment and when logging counts[k], It only logs data for the last member of the object.
Thanks in advance, I'm coding with vanilla js, and I'm not interested in using any framework at all.
Yes, this looks like an issue with async. For loops iterate synchronously. Try writing a loop that does not advance i until each request completes.

Unity2D: Spawn objects using array and deleting spawn object once exit out of camera view

Is there an easier way of controlling how many enemies I want to spawn in within the inspector, instead of me keep on copying and pasting the same method in my code but renaming it. Um I think using an array (example):
Should do the trick but I don't know how to implement it into my code. Please and thank you! :)
My code:
public GameObject enemy;
// Variable to know how fast we should create new enemies
public float spawnTime = 2;
void Start() {
// Call the 'addEnemy' function every 'spawnTime' seconds
InvokeRepeating ("addEnemy", spawnTime, spawnTime);
}
// New function to spawn an enemy
void addEnemy() {
// Variables to store the X position of the spawn object
// See image below
var x1 = transform.position.x - GetComponent<Renderer> ().bounds.size.x / 2;
var x2 = transform.position.x + GetComponent<Renderer> ().bounds.size.x / 2;
// Randomly pick a point within the spawn object
var spawnPoint = new Vector2 (Random.Range (x1, x2), transform.position.y);
// Create an enemy at the 'spawnPoint' position
Instantiate (enemy, spawnPoint, Quaternion.identity);
}
}
P.s. Does anyone know how to delete the spawned object once it exit out of the main camera's view. :)
I recommend you use Coroutines to control how many objects you want to spawn, but I found a turnaround using your code.
Declare two variables that tells the max amount of objects to spawn and the current amount of objects in the scene public int spawnMax = 6, currentTotal = 0;
Add this line to addEnemy function if (currentTotal >= spawnMax) CancelInvoke("addEnemy");
For deleting objects outside of the camera view I would put an empty gameobjects as a children of the camera, and in the children put colliders that mach the borders of the camera view, and finally use tags and OnCollision/OnTrigger functions to detect if any object is outside.
The whole trick is you have to keep an empty gameObject behind the view(Users view) lets call it destroyer .Add a tag to the Game objects so that u can identify the objects that are colliding with destroyer.Check for tags if they qualify to be destroyed then use Destroy (gameObject) should destroy the gameObject.

How to replace content element in an Array Controller

Currently working on part of the app that requires cloning an element from the content, then modifying cloned element and saving back to model. I am having a problem when saving the cloned element and having to replace the old item with cloned one. What I am currently doing is changing all the properties of the old item like so (it works):
Blocks.replace = function(item1, item2) {
for(var k in item2) {
Ember.set(item1, k, item2[k]);
}
};
var selectedEmployment = this.get("controllers.employmentDataEntry").get("selectedEmployment");
var modelItem = content.findBy("#id", selectedEmployment["#id"]);
Blocks.replace(modelItem, selectedEmployment);
I'm trying to use the ArrayController replaceContent method, but I get an error saying "Invalid array length" when trying to run the following code:
var employmentIndex = content.indexOf(modelItem);
this.replaceContent(employmentIndex, 0, selectedEmployment);
Am I doing this incorrectly? Is there a better way of replacing an item?
Note: I am using JSON as a model. The ArrayController that is used when calling replaceContent contains an array of length 2.
Fix: Need to send in an array to replaceContent method. So change selectedEmployment to [SelectedEmployment]. Also, change 0 to 1, otherwise, content will end up having both element and cloned element.
this.replaceContent(employmentIndex, 1, [selectedEmployment]);

LoaderMax: setting array as a container (ImageLoader)

So, I have a LoaderMax instance loading images from various URLs. I want to add all loaded images to an array.
Here's my code:
var photosArray:Array = new Array(5);
var imageLoadingQueue:LoaderMax = new LoaderMax({name:"mainQueue", onComplete:completeHandler});
for (var g:uint=0; g<5; g++)
{
imageLoadingQueue.append(new ImageLoader("/img" + g + ".jpg", {name:"photo", container:photosArray[g], noCache:false, smoothing:true, width:126, height:126, scaleMode:"proportionalOutside"}));
}
imageLoadingQueue.load();
private function completeHandler(e:LoaderEvent):void
{
trace("finished loading pictures!");
//the next two lines will return an error (saying that photosArray[1] is null)
stage.addChild(photosArray[1]);
photosArray[1].x = 250;
}
A few problems:
If I set the container of the image being loaded to the Array, it won't work. I'm not being able to access the image inside the array because it says it's null.
If I set the container of the image being loaded to "this" (using the container property when appending a new ImageLoader) and, on the completeHandler, set my array equal to event.target.content, it kinda works (but it's not the ideal). The problem is that, by doing so, the images are appearing on the stage as they are loaded, and I do no want them to do so.
Any help would be heavily appreciated.
Thanks!!
David is correct, but I also wanted to mention that the LoaderMax's "content" is actually an array of all of its children's content, so you could just use that for simplicity. Keep in mind that ImageLoaders automatically create a Sprite (technically called a "ContentDisplay") to drop the image into so you probably don't need to create ANOTHER Sprite (a container for the container).
var photos:Array = imageLoadingQueue.content;
stage.addChild(photos[1]);
The other nice thing is that it creates the ContentDisplay Sprites immediately, even before any content is loaded into them, so you can place them and size them however you want while (or before or after) loading occurs.
The container needs to be a DisplayObjectContainer. ImageLoader will try to add the image to the container using addChild(), so obviously this won't work with an empty array. Create a new Sprite for each image and add it into the array first:
for (var g:uint=0; g<5; g++)
{
photosArray[g] = new Sprite();
imageLoadingQueue.append(new ImageLoader("/img" + g + ".jpg", {name:"photo", container:photosArray[g], noCache:false, smoothing:true, width:126, height:126, scaleMode:"proportionalOutside"}));
}

flex 3: Can anybody help me optimize this array -> arrayCollection function?

I'm using a parent to pass a multi-dimensional array to a child. Structure of the array, named projectPositions is as follows (with example data):
projectPositions[0][0] = 1;
projectPositions[0][1] = 5;
projectPositions[0][2] = '1AD';
projectPositions[0][3] = 'User name';
I need to take this inherited array and turn it into an arrayCollection so that I can use it as a dataProvider. Currently, my init function (which runs onCreationComplete) has this code in it to handle this task of array -> arrayCollection:
for (var i:int = 0; i < projectPositions.length; i++)
{
tempObject = new Object;
tempObject.startOffset = projectPositions[i][0];
tempObject.numDays = projectPositions[i][1];
tempObject.role = projectPositions[i][2];
tempObject.student = projectPositions[i][3];
positionsAC.addItemAt(tempObject, positionsAC.length);
}
Then, during a repeater, I use positionsAC as the dataprovider and reference the items in the following way:
<mx:Repeater id="indPositions" dataProvider="{positionsAC}" startingIndex="0" count="{projectPositions.length}">
<components:block id="thisBlock" offSet="{indPositions.currentItem.startOffset}" numDays="{indPositions.currentItem.numDays}" position="{indPositions.currentItem.role}" sName="{indPositions.currentItem.student}" />
</mx:Repeater>
This all works fine and returns the desired effect, but the load time of this application is around 10 seconds. I'm 99% sure that the load time is caused by the array -> arrayCollection for loop. Is there an easier way to achieve the desired effect without having to wait so long for the page to load?
The issue your having loading items could be because you are using a repeater instead of a list class.
With a repeater, there will be a block created in memory, and drawn on the screen. So, if you have 100 items in your array, then 100 blocks will be created. this could slow down both initial creation and the overall app.
A list based class focuses on a technique called renderer recycling; which means only the displayed elements are created and rendered on the screen. So, depending on settings, you'd usually have 7-10 'block' instances on the screen, no matter how many items you have in your array.
change
positionsAC.addItemAt(tempObject, positionsAC.length);
to
positionsAC.addItem(tempObject);
addItemAt is causing a reindex of the collection which can greatly slow down the collection.
[EDIT]
Put this trace statement before and after the loop
take the output and subtract one from the other and that will show how many milliseconds the loop has run.
var date:Date = new Date( );
trace( date.getTime())

Resources