IDs and SubIDs for collision in AS3 SHMUP - actionscript-3

My collision process involves checking simple hitbox and pixel perfect bitmap overlap before using object variables to determine if things SHOULD hit. Weapons, enemies, and objects have an ID number and collisionID array that say what should be able to affect what eg. ID = 1, collisionID = [2,3,4], ID 1 collision with ID 2, 3, or 4 are valid.
I want enemy bullets (which share an ID number with all other Weapon objects) to only be affected by a shield weapon. I figured I could make a subID variable, but I can't figure a concise way for that to be referenced. Below is the function that uses the current IDs.
private function compareHitID(object1:WorldObject, object2:WorldObject):Boolean{
var included:Boolean = false;
if(object1 != null && object2 != null){
for(var i:int = 0; i <= object1.collisionID.length - 1; i++){
if(object1.collisionID[i] == object2.gameID)
included = true;
}
}
return included;
}
Any ideas on how to include subIDs, and store and reference them neatly would be greatly appreciated.

Related

Actions with a list of instances - AS3

what is the best way to do an action with many instances at the same time?
Lets say I have 50 movieclip instances called A1 to A50, and I want to run an action with only A20 to A35.
For example:
(A20-A35).gotoAndStop(2)
You want an algorithm operation called loop. You are not able to abstractly address things in bunches at once, but you can loop and iterate the bunch one by one which produces basically the same result. Please read this: https://en.wikipedia.org/wiki/Control_flow#Loops When you need to do a quantity of similar operations it is always loop.
With regard to your problem:
// Loop iterator from 20 to 35 inclusive.
for (var i:int = 20; i <= 35; i++)
{
trace("");
// Compose the name of the MovieClip to retrieve.
var aName:String = "A" + i;
trace("Retrieving the MovieClip by name", aName);
// Retrieve the instance by its instance name.
var aChild:DisplayObject = getChildByName(aName);
// Sanity checks about what exactly did you find by that name.
if (aChild == null)
{
// Report the essence of the failure.
trace("Child", aName, "is not found.");
// Nothing to do here anymore, go for the next i.
continue;
}
else if (aChild is MovieClip)
{
// Everything is fine.
}
else
{
// Report the essence of the failure.
trace("Child", aName, "is not a MovieClip");
// Nothing to do here anymore, go for the next i.
continue;
}
// Type-casting: tell the compiler that the child is actually
// a MovieClip because DisplayObject doesn't have gotoAndStop(...)
// method so you will get a compile-time error even if you are
// sure the actual object is a valid MovieClip and definitely has
// the said method. Compile-time errors save us a lot of pain
// we would get from run-rime errors otherwise, so treasure it.
var aClip:MovieClip = aChild as MovieClip;
trace(aClip, "is a MovieClip and has", aClip.totalFrames, "frames.");
if (aClip.totalFrames < 2)
{
// Nothing to do here anymore, go for the next i.
continue;
}
// Now you can work with it.
aClip.gotoAndStop(2);
}
Now that you understand the while idea step by step, if you are sure all of them are present and all of them are MovieClips you can go for a shorter version:
for (var i:int = 20; i <= 35; i++)
{
(getChildByName("A" + i) as MovieClip).gotoAndStop(2);
}
UPD: You can as well address children with square bracket access operator.
for (var i:int = 20; i <= 35; i++)
{
// You can skip type-casting as this["A" + i] returns an untyped reference.
this["A" + i].gotoAndStop(2);
}
Yet there are differences and complications. Method getChildByName(...) always returns a DisplayObject with the given name (or null if none found). Square brackets operator returns an untyped OOP field of the current object.
It will not work with dynamically added children (unless you pass their references to the respective fields).
It will not work if "Automatically Declare Stage Instances" publish option is off.
Finally, this["A" + 1] and A1 are not exactly the same because the latter could refer to a local method variable rather than object member.
I'm not saying that square brackets are evil, they're as fine, yet, as always, programming is not a magick thus understanding what you are doing is the key.

actionscript 3 - random object selection

So I want a unit to be able to randomly target a player unit or a players allies.
I have all ally ships stored in an array and the player is on the stage separately.
Here is the code for the bullet creation, with the irrelevant stuff removed.
private function createBullet(): void {
var rand = allies[Math.floor(Math.random()*allies.length)];
_endX = rand.x
_endY = rand.y
}
With the code above I can make them target random ally ships, but I also want it to include the player ship (_player) when randomly selecting a target, but I cant add the player to the ally array so Im not really sure what to do.
When you multiply a random number by length of array, add plus one to length.
If generated index is equal to the allies length, this means that "rand" is _player.
var randomIndex:int = Math.floor(Math.random() * (allies.length + 1));
var rand:*;
if (randomIndex == allies.length - 1)
rand = _player;
else
rand = allies[randomIndex];
...

How to call function for object I want?

I didnt know how to exactly ask the question in the title but I can explain it here. So I have this class for pawns in my game.
And in my main program i call a bunch of instances of it with different names.
var z1:ZeleniPijun = new ZeleniPijun();
var z2:ZeleniPijun = new ZeleniPijun();
Basicly I have functions for movement and other variables that I use in my code in the class.
I'm making a multiplayer game and z1 and z2 would be pawns that I move around.
Until now I have used Switch and by knowing the ID of the player and the pawn that was clicked I moved them around the board. That means I have a switch for selecting a player and a switch inside that switch for selecting a pawn. And every time it goes trough the switch it goes to the same code but with a "different name".
For example if I roll a 4 for pawn number 1 it does
z1.movePawn(4);
z1.location += 4;
and other stuff that I need it to do
and if I roll a 3 for pawn number 2 it does
z2.movePawn(4);
z2.location += 4;
and other stuff that I need it to do
I have to copy the same code 16 times and just change the name from z1 to z2 to z3 etc...
Is there anyway I can make a function that would do that for me?
Something like this:
public function doStuff(pawnName:String, number:int):void{
pawnName.movePawn(number);
pawnName.location = number;
and other stuff that I need it to do
}
and then I can just give it the parameters I want 16 times instead of copying the same code everywhere.
send to the doStuff function the object that you want to do changes like
public function doStuff(theObj:ZeleniPijun ):void{
theObj.movePawn(number);
theObj.location = number;
and other stuff that I need it to do
}
if you have many objects, put them in a collection, like an array an iterate on it something like
foreach (obj in collection){
doStuff(obj);
}
this is just more or less pseudo-code, but you get the idea
You can use the object ZeleniPijun as parameter and call the method passing the instance you want.
// example creating multiples objects
var numObjs : uint = 5;
var objectsControl : Vector.<ZeleniPijun> = new Vector.<ZeleniPijun>(numObjs);
var zeleninPijun : ZeleniPijun;
for (var i : int = 0; i < numObjs; i++)
{
zeleninPijun = new ZeleniPijun();
objectsControl[i] = zeleninPijun;
}
// if you want to animate one object
doStuff(objectsControl[0], 4);
// if you want to animate them all
for each (var zeleninPijunObj : ZeleniPijun in objectsControl)
{
doStuff(zeleninPijunObj, 4);
}
function doStuff(pawnObj:ZeleniPijun, location:int):void
{
pawnObj.movePawn(location);
pawnObj.location = location;
}

AS3 Isometric game Sorting Object Index

I am creating an isometric game, and I would like to know how to correctly position the (Z-index) of objects when the player goes behind them and infront of them.
I have been using
if(y>stage.stageHeight/2){
parent.setChildIndex(this,parent.getChildIndex(this)+1);
gotoAndStop(2);
} else if (y<stage.stageHeight/2){
parent.setChildIndex(this,parent.getChildIndex(this)+1);
gotoAndStop(1);
}
So far yet I have been receiving this error
RangeError: Error #2006: The supplied index is out of bounds.
My logic for this is; "If the object is UNDER the player then move its index up so that it is over the player, but if the object is ABOVE the player, then decrease it's index so that is under the player."
Any ideas on how I could improve this code so that it works without giving me errors?
Firstly if you're going to be swapping many objects it's best to work from outside the object. For example a Level class that contains an array of all your swappable objects. It will also be responsible for looping through each object and swapping it according to its y value.
public var objectArray:Array = [];
for (var ob1:Object in objectArray){
for (var ob2:Object in objectArray){
if(ob1 == ob2) continue;
swap(ob1, ob2);
}
}
//...
public function swap(a:Object, b:Object):void {
if (a.y > b.y != a.parent.getChildIndex(a) > b.parent.getChildIndex(b)) {
a.parent.swapChildren(a, b);
}
}
Keep in mind this is not the most efficient way to do it, because you have to check each object against each other object O(n^2).
you have to keep in mind that the index you provide is the index of the object in the container's children array. it cannot be less than zero and it cannot be more or equal to the actual childCount of the container.
so parent.getChildIndex(this)+1 is very unsafe
var nextIndex:int = parent.getChildIndex(this)+1;
if(nextIndex < parent.numChildren && nextIndex >= 0)
parent.setChildIndex(this, nextIndex);

As3 - Get Movieclips That The Name Start With A Specific String

I'm making a tile based game where ta_*(number)* and ca_*(number)* acts like bins. You drag things towards it and drop. But the level may put several these tiles.
I am not going to make something like:
if (my_mc.hitTestObject(ta_0) || my_mc.hitTestObject(ta_1) || my_mc.hitTestObject(ta_2).........)
Because some may not exist and throw an error at me, and I don't want to make like hundreds of them.
Is there a way to find movieclips on stage that start with the name "ta_" and "ca_"?
So that I can get: ta_1, ta_2.....?
No, you can't. Unless you loop on getChildAt() and check all children's names.
But, why don't you add your bins to an array when creating them?
(I assume you create them dynamically)
var myBinArray:Array = new Array(10);
for (var i:int = 0; i < myBinArray.length; i++)
{
var myBin = new Bin();
myBinArray[i] = myBin;
}
Then you simply loop on your array:
for (var i:int = 0; i < myBinArray.length; i++)
{
if (mybinArray[i] != null)
if (my_mc.hitTestObject(mybinArray[i])
{
// statements
// and here I assume you want to break for loop
}
}