<img src="http://dl.getdropbox.com/u/1013446/s/s.png">
Let's learn.
Even if you grabbed the cap file from the previous post, please redownload it. The events have been reordered to make the tutorial flow better. http://dl.getdropbox.com/u/1013446/s/objectarray3.cap
try the cap first, and then let's look at the events
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/1.png">
Ok, in the start of layout we are creating two object arrays.
There are some extra considerations for object arrays we will go over briefly. Future updates will reduce or eliminate these issues, however, the main thing to understand is that for now, if you destroy an object, attempting to read from that object or alter the object through the reference after the object's destruction will invariably cause a crash. There are several features already implemented to help you avoid this that will be covered in this tutorial, and there are several updates planned that will make it difficult or impossible to crash, while maintaining the same power and flexibility.
With object arrays there are some extra options to consider when creating a new array. If you double-click the " object array" actions you get this:
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/0.png">
We name the array "thingstochase". This array will hold references to all the enemy sprites that's have been clicked and are targeted for attack. until next tutorial we ignore "within which super".
object, for the type. For the default value we have the type of the object we want as the default. If there is more than one of that type picked, the first instance will be the default.
The ot({"objecttype address"}) expression can be used any where objecttypes can be entered. This is not limited to 's', and this includes the dropdown boxes you use to pick types. You can right click on that parameter, and click "use expression", and that allows you to enter a type in quotation marks, or the ot({"objecttype address"}). There is an equivalent operation that returns the type of an object. This would be o({"object address"}).
At the bottom there are two options specifically for object arrays.
The first is "objecttype for default". Object variables only reference the object, they are not the objects themselves. You can have an array of ten, and have every one point to the same object. Any default values created will be multiple references to the same object if you leave ObjectType for Default as "notype". If you were to insert an object to the array at index 43, 0-42 will be filled with references to the single default object. There are certain situations where this might be the ideal solution. For instance, you are adding speed boosts to physics objects in an array. Each instance of the objecttype in the array would add to the total boost of that object.
The default sprite is not destroyable using any of s's methods of object destruction. Commands issued to destroy the default are ignored. This is to prevent you from accidentally accessing the default after accidentally destroying it. Also, this allows you to freely delete objects from your array without any special provisions for the default object.
While having multiple references to the same object is ideal sometimes, in other instances, when you insert an object at 43, you want 0-42 to be 43 different instance of a specific type. This is what ObjectType for Default is for. You specify a default type, of which an instance will be created each time an object is inserted to an array index outside the range of the array. So you would get 43 unique sprites of the default type. They are spawned on the layer specified in the last parameter. Even when using ObjectTypes for defaults, you still need a default object, which will be returned if an attempt is made to read from an object outside the range of the array. The default object can be something as simple as an invisible 1x1 dummy sprite, or the properties of default objects can be used as part of the logic, as is the case in this tutorial.
{"thingstochase"} will be an array for the enemy targets.
and {"drones"} will be an array for our drone missiles
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/5.PNG">
the first part of the always event with sprite4 was just part of the code to make it look cool.
Next we come to :
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/6.PNG">
"On left click on blue" (blue is all the ships)
Insert object blue to "end" of {"thingstochase"}
so if a blue object is left clicked, add a reference to that object in {"thingtochase"}
If the right mouse button is clicked, make the player ship spawn one of our drone missiles (the pink thing), and then add a reference to this new drone missile instance to the {"drones"} array
Now we have unlimited access to the picking of these objects. Remember that you don't need to add objects at the end, they can be inserted and overwritten at any point in the array.
The first subevent
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/2.png">
is an Object Array 'for each' loop
If you double click and take a look inside:
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/3.png">
First we have the name of the loop, "killthem!". Then the address of the object array we are looping through.
The third option is new.
Picking method:
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/4.png">
This decides what effect the object array loop has on picking
- "Do Not Alter Picking" does not alter picking
- "Pick Only Current Object", which is selected in this particular loop, picks only the object pointed to at the current index of the loop
- "Toggle Current Pick" picks each object if it is not picked, and unpicks it if it is
- "Add Object to Current Picking" adds the current object to the list of picked objects, instead of only picking the one object. The picking method option is present in other actions and conditions, but in the case of a loop, this makes the list of picked object continue to grow as the loop goes on
- "Unpick Current Object" mostly self-explanatory. I may add an option for this in the future, but the way picking works, before any conditions are met, nothing is picked, so actions act on everything, but "unpicking" in this case does not remove the item from "everything". If any conditions have changed the picking of the object type, then this will work as expected.
- "Pick All of Object Type" picks every object of the same type as the object at that index in the array
Underneath this, you see "pick as"
"Pick as", takes either "self", where an object is picked as it's own type, or the name of a family. If you put in a family name, the object is picked as a member of the specified family. This is useful if you need to act on an array that contains several different object types. This also enables you to use non 's' actions, conditions, and expressions to refer to more than one specific object of the same type in an array. This is essentially the "family trick".
For those unfamiliar with the "family trick". Here's an example of when this is useful.
Let's say "Sprite13" is a member of the family "red", and a specific "Sprite13" is picked. you want to check if this instance of Sprite13 has a collision only with another Sprite13. And you want to do something different to the originally picked Sprite13, and the one it collided with. If you were to just check for collision with Sprite13, there would be no way of telling the first Sprite13 to go the left, and the one it collided with to go right. But if we check for collision with "red" (of which Sprite13 is the only family member), then we can do actions to either Sprite13 or "red".
We are picking each object one by one in the object array "drones".
The drones have the bullet behavior on, and we are telling them to turn towards S.x({"thingstochase",S.li("killthem!")}),S.y({"thingstochase",S.li("killthem!")})
This is much simpler than it looks
S.x is an expression to retrieve the x position of an object in an object array.
{"thingstochase",S.li("killthem!")}
is simply an object address
S.li("killthem!") is the loopindex for for the "killthem!" loop.
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/2.png">
"killthem!" is looping through the drone missiles.
The first time through the loop, the first drone missile will get picked, and it will go for the first target in line.
if there is more than one missile, the second missile would go to the second target.
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/arrays.gif">
The next action is to pick the {"thingstochase"} object at the same loopindex as "blue", since we're not sure what it will be.
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/8.png">
here, on collision between sprite and "blue" (the only "blue" picked right now is the one on the current loopindex, so this collision check will be only between the drone and it's current target)
if "blue" is of type "sprite", which is the player ship. This condition simply checks if an object is of a certain type, you can give the name of a picked instance, or you can give an object address.
if the blue that the drone collided with is the player sprite type
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/9.png">
delete the drone sprite at the current loopindex. When the drones return to the player ship, they're supposed to disappear. when deleting an object reference from an object array, or several references from an object array, you have the option to "destroy all objects". If this is the only way you destroy objects that are in an array, you're safe from accessing a destroyed object accidentally. I will also be adding an option to destroy all instances within the array of the same object. That will make the system truly foolproof. Back to the cap, now we've gotten rid of the "drones" object reference and the drone sprite itself.
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/10.png">
if the "blue" that the drone missile collided with isn't the players ship,
Delete the current loopindex object reference in "thingstochase", the enemy ship, and destroy the ship object itself
Next we delete the current drone object reference, but this time we don't destroy the object, it is still picked, and we add it to the end of the array.
the reason this is done, is because if not all the drones would change targets when one of the targets was deleted:
<img src="http://dl.getdropbox.com/u/1013446/s/objectarray3cap/arrays.gif">
imagine the top enemy ship being deleted, and the rest moving up to fill in the gap. then the second drone missile would be aligned with a different target.
Because the mothership is the default, when all enemy ships are destroyed, the drone's current targets are the mothership. because of the way we are looping through both arrays with a single array index, we know missiles will not pursue one another's targets. This is just one type of logic. There are an infinite number of ways you can use object arrays.
The next tutorial(s) will introduce supers, and we will be done with all the basic tutorials.
Thanks to everyone who's using s and reading the tuts