How to Save positions for 3 objects in Array to make random position between each other by AS3? - actionscript-3

How to Save positions for 3 objects in Array to make random position between each other by AS3?
import flash.geom.Point;
var arry:Point = new Point();
arry[0] = arry[78,200];
arry[1] = arry[217,200];
arry[2] = arry[356,200];
//object called b1
b1.x = arry[0][0];
b1.y = arry[0][1];
//object called b2
b2.x = arry[1][0];
b2.y = arry[1][1];
//object called b3
b3.x = arry[2][0];
b3.y = arry[2][1];
//make objects swap positions between each other
var rand:Number = (Math.random()*arry.length);
//output to see random position [[78,200],[217,200],[356,200]]
trace(arry);
to get random with tween like this... https://www.youtube.com/watch?v=8m_m64plQ6E

At compile time you should get this Error I suppose : "ReferenceError: Error #1069"
Here is a way to store the positions (like in the link you provided from youtube) :
import flash.geom.Point;
var squareWidth:uint = 40;
var squareHeight:uint = 40;
var marginX:uint = 100;
var marginY:uint = 75;
var spacer:uint = 10;
var positions:Vector.<Point > = new Vector.<Point > (9);
function setPositions(v:Vector.<Point>):void {
var count:uint = 0;
var posx:uint;
var posy:uint;
for (var i = 0; i < 3; i ++)
{
for (var j = 0; j < 3; j ++)
{
posx = (j * squareWidth) + (spacer * j) + marginX;
posy = (i * squareHeight) + (spacer * i) + marginY;
v[count] = new Point(posx,posy);
count++;
}
}
}
setPositions(positions);
trace(positions);
// output :
// (x=100, y=75),(x=150, y=75),(x=200, y=75),(x=100, y=125),(x=150, y=125),(x=200, y=125),(x=100, y=175),(x=150, y=175),(x=200, y=175)
So here you have nine Points to place the clips like in the video.
You just have to add a function to swap the nine boxes stored in another Vector.
In your case.
For 3 positions do the following if I understand your question.
import flash.geom.Point;
var positions:Vector.<Point> = new Vector.<Point>(3);
var p1:Point = new Point(78,200);
var p2:Point = new Point(217,200);
var p3:Point = new Point(356,200);
positions[0] = p1;
positions[1] = p2;
positions[2] = p3;
trace(positions);
// output : (x=78, y=200),(x=217, y=200),(x=356, y=200)

So, you're still unclear!
Your issue is to find a random position?
This may help you if this is the problem you're facing :
import flash.geom.Point;
var positions:Vector.<Point > = new Vector.<Point > (3);
var numbers:Vector.<uint> = new Vector.<uint>();
var numbersAllowed:uint = 3;
var rndNmbrs:Vector.<uint> = new Vector.<uint>(3);;
var p1:Point = new Point(78,200);
var p2:Point = new Point(217,200);
var p3:Point = new Point(356,200);
positions[0] = p1;
positions[1] = p2;
positions[2] = p3;
trace(positions);
function populateRndNmbrs(n:uint):void {
for (var i:uint = 0; i < n; i++)
{
numbers[i] = i;
}
}
populateRndNmbrs(numbersAllowed);
function populateRandomNumbers(n:uint):void
{
var rnd:uint;
for (var i:uint = 0; i < n; i++)
{
rnd = numbers[Math.floor(Math.random() * numbers.length)];
for (var j:uint = 0; j < numbers.length; j++)
{
if (rnd == numbers[j])
{
numbers.splice(j,1);
}
}
rndNmbrs[i] = rnd;
}
}
populateRandomNumbers(numbersAllowed);
trace("rndNmbrs = " + rndNmbrs);
for (var i:uint = 0; i < numbersAllowed; i++)
{
trace("b"+ (i+1) + ".x = " + positions[rndNmbrs[i]].x);
trace("b"+ (i+1) + ".y = " + positions[rndNmbrs[i]].y);
// In place of trace, you should place the boxes at those random positions.;
}
//output:
//(x=78, y=200),(x=217, y=200),(x=356, y=200)
//rndNmbrs = 2,0,1
//b1.x = 356
//b1.y = 200
//b2.x = 78
//b2.y = 200
//b3.x = 217
//b3.y = 200
Is that what you want? Or do you want to know how to create a motion effect?
I'm not sure about what you really need...
This will help you to place all the boxes in a random position.
You may do this like here bellow, and add a function to check if the random positions are not the same.
With only 3 MovieClips, you will often have the same random positions as long they're stored in the "positions Vector"
var squares:Vector.<MovieClip> = new Vector.<MovieClip>(3);
function populateMCs(target:DisplayObjectContainer,n:uint):void{
for (var i:uint = 0; i < n; i++){
squares[i] = target["b"+(i+1)];
}
}
function swapMCs():void{
for (var i:uint=0; i<squares.length; i++){
squares[i].x = positions[rndNmbrs[i]].x;
squares[i].y = positions[rndNmbrs[i]].y;
}
}
populateMCs(this,numbersAllowed);
swapMCs();

I give you a last example to get a motion effect in AS3.
I'm not a translator AS2 -> AS3 and a video is not the best way to show your code :(
This will make your boxes move smoothly, but not the way you want.
Now, you have to learn AS3 and try to make the job by yourself.
Then, if you have another issue, just ask clearly what you want.
var friction:Number = 0.15;
setDestination(squares[0],squares[0].x,350,friction);
setDestination(squares[1],squares[1].x,350,friction);
setDestination(squares[2],squares[2].x,350,friction);
squares[0].addEventListener(Event.ENTER_FRAME,moveClip);
squares[1].addEventListener(Event.ENTER_FRAME,moveClip);
squares[2].addEventListener(Event.ENTER_FRAME,moveClip);
function setDestination(mc:MovieClip,x:uint,y:uint,friction:Number):void{
mc.destinx = x;
mc.destiny = y;
mc.f = friction;
}
function moveClip(e:Event):void{
var mc:MovieClip = e.target as MovieClip;
trace(mc.name)
mc.speedx = (mc.destinx - mc.x);
mc.speedy = (mc.destiny - mc.y);
mc.x += mc.speedx*mc.f;
mc.y += mc.speedy*mc.f;
if((Math.floor(mc.speedx)<1) && (Math.floor(mc.speedy)<1)){
mc.removeEventListener(Event.ENTER_FRAME,moveClip);
trace("STOP MOVE FOR " + mc.name);
}
}

Related

How can I solve a "Type Error #2007 Parameter child must be non-null"?

I am working on a small game and am having some success.
I have encountered a few issues and managed to solve them (I think) but this one is stumping me.
The game is working but it throws up the above error, which I would like to resolve.
Can anyone offer any advice on how to solve this?
I am sure it is this line (because when I comment it out the error doesn't happen) but have spent the last two hours trying various ways of solving it with no joy.
for (var i:int = 0;i <=20;i++)
{
addToys(1200 * Math.random(), 200 * Math.random() * 2);
}
If someone could point the way it would help a lot.
I tried googling but my mind was fried trying to do it that way.
What am I missing?
Could the problem be that I have two layers on the timeline that contain animations? (I only did that as I couldn't figure how to add them through actionscript alone).
I have attached the full code below.
Bear in mind I am still learning, so please be gentle. :D
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class MyGame extends MovieClip {
public function MyGame() {
const BG_SPEED:int = 5;
const BG_MIN:int = -550;
const BG_MAX:int = 0;
var bg:BackGround = new BackGround;
var toy1:Toy1 = new Toy1;
var toy2:Toy2 = new Toy2;
var toy3:Toy3 = new Toy3;
var toy4:Toy4 = new Toy4;
var toy5:Toy5 = new Toy5;
var toy6:Toy6 = new Toy6;
var toy7:Toy7 = new Toy7;
var toy8:Toy8 = new Toy8;
var toy9:Toy9 = new Toy9;
var toy10:Toy10 = new Toy10;
var toy11:Toy11 = new Toy11;
var toy12:Toy12 = new Toy12;
var toy13:Toy13 = new Toy13;
var toy14:Toy14 = new Toy14;
var toy15:Toy15 = new Toy15;
var toy16:Toy16 = new Toy16;
var toy17:Toy17 = new Toy17;
var toy18:Toy18 = new Toy18;
var toy19:Toy19 = new Toy19;
var toy20:Toy20 = new Toy20;
var toyArray:Array = new Array();
toyArray.push(toy1);
toyArray.push(toy2);
toyArray.push(toy3);
toyArray.push(toy4);
toyArray.push(toy5);
toyArray.push(toy6);
toyArray.push(toy7);
toyArray.push(toy8);
toyArray.push(toy9);
toyArray.push(toy10);
toyArray.push(toy11);
toyArray.push(toy12);
toyArray.push(toy13);
toyArray.push(toy14);
toyArray.push(toy15);
toyArray.push(toy16);
toyArray.push(toy17);
toyArray.push(toy18);
toyArray.push(toy19);
toyArray.push(toy20);
addChildAt(bg, 0);
stage.addEventListener(Event.ENTER_FRAME, bgScroll);
function addToys(xpos, ypos)
{
addChild(toyArray[i]);
toyArray[i].x = xpos;
toyArray[i].y = ypos;
}
for (var i:int = 0;i <=20;i++)
{
addToys(1200 * Math.random(), 200 * Math.random() * 2);
}
function bgScroll (e:Event)
{
if (stage.mouseX > 600 && bg.x > BG_MIN)
{
bg.x -= BG_SPEED;
for (var i:int=0; i< toyArray.length; i++)
{
(toyArray[i] as MovieClip).x -=BG_SPEED
}
}
else if (stage.mouseX < 50 && bg.x < BG_MAX)
{
bg.x += BG_SPEED;
for (var j:int=0; j< toyArray.length; j++)
{
(toyArray[j] as MovieClip).x +=BG_SPEED
}
}
}
}
}
}
Any help would be greatly appreciated.
Your for loop do 21 iterations but your array has only 20 elements, so you should do :
...
for (var i:int = 0; i < toyArray.length; i++){
addToys(1200 * Math.random(), 200 * Math.random() * 2)
}
...

AS3: Car movement speed

I'm beginer in AS3. I'm working follow a tutorial frogger game, you can view full code at here http://www.makeflashgames.com/tutorialsplus/tutorial-frogger.php. At Function startGame(), I know "speedX" is moving speed of the car in the direction of X. I try to change speedX to speedY, but nothing happen, the car just dose not move. Please help me write a function to moving the car follow X and Y. Or please help me make it clear...Thanks :)
public function startGame()
{
timeElapsed = 0;
totalTimer = 99;
life = 3;
p1speedX = 0;
p1speedY = 0;
gotoWin = false;
gotoLose = false;
standingOnLog = false;
cars = new Array();
logs = new Array();
homes = new Array();
logsYPos = new Array(115,165,215,265);
carsYPos = new Array(365,415,465,515);
setupGame();
//Spawn Cars
//Row 1
for (var i=1; i<=2; i++)
{
var newCar = new Car();
newCar.x = -300 * i;
newCar.y = carsYPos[0];
newCar.speedX = 150;
cars.push(newCar);
addChild(newCar);
}
//Row 2
for (var i=1; i<=3; i++)
{
var newCar = new Car();
newCar.x = (170 * i) + 500;
newCar.y = carsYPos[1];
newCar.speedX = -5;
cars.push(newCar);
addChild(newCar);
}
//Row 3
for (var i=1; i<=3; i++)
{
var newCar = new Car();
newCar.x = (-220 * i) + 100;
newCar.y = carsYPos[2];
newCar.speedX = 8;
cars.push(newCar);
addChild(newCar);
}
//Row 4
for (var i=1; i<=3; i++)
{
var newCar = new Car();
newCar.x = (200 * i) + 350;
newCar.y = carsYPos[3];
newCar.speedX = -5;
cars.push(newCar);
addChild(newCar);
}
This function doesn't move the cars, it just sets their speed.
Look at Part 9, handleGameLogic(), for movement.

error while converting AS2 starfield code to AS3

I've tried to convert a nice AS2 script for starfirld effect to AS3 But i'm still getting strange errors
would really appreciate if any one could help me understand what am i doing wrong
here is the original AS2 code:
var stars = 100;
var maxSpeed = 16;
var minSpeed = 2;
var i = 0;
while (i < stars)
{
var mc = this.attachMovie("star", "star" + i, i);
mc._x = random(Stage.width);
mc._y = random(Stage.height);
mc.speed = random(maxSpeed - minSpeed) + minSpeed;
var size = random(2) + 6.000000E-001 * random(4);
mc._width = size;
mc._height = size;
++i;
} // end while
this.onEnterFrame = function ()
{
for (var _loc3 = 0; _loc3 < stars; ++_loc3)
{
var _loc2 = this["star" + _loc3];
if (_loc2._y > 0)
{
_loc2._y = _loc2._y - _loc2.speed;
continue;
} // end if
_loc2._y = Stage.height;
_loc2.speed = random(maxSpeed - minSpeed) + minSpeed;
_loc2._x = random(Stage.width);
} // end of for
};
and here is my AS3 version:
import flash.events.Event;
import flash.events.MouseEvent;
function starField():void
{
var stars:int = 100;
var maxSpeed:int = 16;
var minSpeed:int = 2;
var i:int = 0;
while (i < stars)
{
var mc = new Star();
addChild(mc)
mc._x = Math.random()(stage.stageWidth);
mc._y = Math.random()(stage.stageHeight);
mc.speed = Math.random()(maxSpeed - minSpeed) + minSpeed;
var size = Math.random()(2) + 6.000000E-001 * Math.random()(4);
mc._width = size;
mc._height = size;
++i;
} // end while
}
addEventListener(Event.ENTER_FRAME, update);
function update(_e:Event):void
{
for (var _loc3 = 0; _loc3 < 100; ++_loc3)
{
var _loc2 = this["star" + _loc3];
if (_loc2._y > 0)
{
_loc2._y = _loc2._y - _loc2.speed;
continue;
} // end if
_loc2._y = stage.stageHeight;
_loc2.speed = Math.random()(maxSpeed - minSpeed) + minSpeed;
_loc2._x = Math.random()(stage.stageWidth);
} // end of for
};
the error message I'm getting is: "TypeError: Error #1010: A term is undefined and has no properties. at _fla::MainTimeline/update()"
I understand it has a problem with the 'update' function but I'm net sure which term it refer to?
I'll bet a can of juice here is your problem:
var _loc2 = this["star" + _loc3];
put these into an associative array and access them from there.
#Discipol is right.
Just wanted to add a few more notes:
You can also use the display list to get the movie clip by name:
var _loc2:MovieClip = MovieClip(getChildByName("star" + _loc3));
You've got untyped variables and your are relying on MovieClip as a dynamic class to add properties (such as speed) at runtime. For a really simple project the impact is barely noticeable, but on the long run, for bigger projects, it's worth extending Sprite if you don't use the timeline and add the properties you need:
package {
import flash.display.Sprite;
import flash.events.Event;
public class Star extends Sprite {
private var speed:Number;
private var minSpeed:Number;
private var maxSpeed:Number;
public function Star(min:Number,max:Number) {
minSpeed = min;
maxSpeed = max;
var size = (Math.random()*2) + 1.82211880039 * (Math.random()*4);
width = size;
height = size;
this.addEventListener(Event.ADDED_TO_STAGE,reset);
}
private function reset(e:Event = null):void{
speed = (Math.random() * (maxSpeed-minSpeed)) + minSpeed;
x = Math.random() * stage.stageWidth;
if(e != null) y = Math.random() * stage.stageHeight;//initialized from added to stage event
else y = stage.stageHeight;//otherwise reset while updating
}
public function update():void{
if (y > 0) y -= speed;
else reset();
}
}
}
and the rest of the code would be as simple as:
var stars:int = 100;
var starClips:Vector.<Star> = new Vector.<Star>(stars,true);//a typed fixed vector is faster than a dynamically resizable untyped Array
for(var i:int = 0 ; i < stars; i++) starClips[i] = addChild(new Star(16,2)) as Star;
this.addEventListener(Event.ENTER_FRAME,updateStars);
function updateStars(e:Event):void{
for(var i:int = 0 ; i < stars; i++) starClips[i].update();
}

adding movieclips from random generated no in array

hey i am trying to add movie clips to the stage randomly from a list of cards, no 1- 10,
this is what i have tried so far but i get an error saying its my randomly selected card is not a function, just wondering if anybody can help or know the proper way of accomplishing it
thank you
var printArray:Array =new Array();
var randPrint:String;
var rand
for(var n:int = 1; n <= 28; n++)
{
randNo=Math.round(Math.random() * 10+.5);
randPrint = "cardPrint"+randNo;
printArray.push(randPrint);
}
var cardPrint1:MovieClip = new card_1();
var cardPrint2:MovieClip = new card_2();
var cardPrint3:MovieClip = new card_3();
var cardPrint4:MovieClip = new card_4();
var cardPrint5:MovieClip = new card_5();
var cardPrint6:MovieClip = new card_6();
var cardPrint7:MovieClip = new card_7();
var cardPrint8:MovieClip = new card_8();
var cardPrint9:MovieClip = new card_9();
var cardPrint10:MovieClip = new card_10();
for(var p:int = 1; p <= 1; p++)
{
trace(printArray[p]);
addChild(printArray[p]);
}
some help would be great, thank you so much
I think something like the following will do what you want. I populated an array with all the available assets and then filled an array with random numbers between 0-9. The last for loop just creates the movieclips and adds them to the stage.
var printArray:Array = [];
var mcs:Array = [card_1, card_2, card_3, card_4, card_5, card_6, card_7, card_8, card_9, card_10];
for(var n:int = 1; n <= 28; n++)
{
var randNo:int = int(Math.random() * 10);
printArray.push(randNo);
}
for(var p:int = 0; p < printArray.length; p++)
{
trace(printArray[p]);
var mc:MovieClip = new mcs[printArray[p]];
addChild(mc);
}

removeChild is removing all my Movie clips

I am making a tool which obscures an image with squares. What I want to happen is to have a bouncing ball which hits the squares and makes them disappear. However, the removeChild command isn't working right. I set it up to populate the image with empty movie clips and colorize them. However, when I click the square, I am running into problems with the parent/child. I keep running into this error. "The supplied DisplayObject must be a child of the caller." I cannot think of a good way to assign the eventListeners to each individual squares. I'm sure it is obvious. Here is my code. Thank you in advance
EDIT:If I get it to work, it deletes all instances of the square, not just the one I clicked.
Here is my code
var mc:MovieClip = bgIMG;
var bd:BitmapData = new BitmapData(mc.width,mc.height);
bd.draw(mc);
var _img:Bitmap = new Bitmap(bd);
var _imgNodes:Array = [];
var _tiledImg:MovieClip = container_tiled_img;
var pad:int = 0;
var rows:int = 10;
var cols:int = 10;
var zero:Point = new Point();
createImgNodeGrid(rows, cols, pad);
pixelateNodes(_imgNodes);
function removeMC(e:MouseEvent)
{//removes the movie clip
trace(e.currentTarget.x);
stage.removeChild(e.currentTarget.parent.parent);
}
function pixelateNodes(nodes:Array = null):void
{
for each (var node:Bitmap in nodes)
{
node.bitmapData.fillRect(node.bitmapData.rect, avgColor(node.bitmapData));
}
}
function avgColor(src:BitmapData):uint
{
var A:Number = 0;
var R:Number = 0;
var G:Number = 0;
var B:Number = 0;
var idx:Number = 0;
var px:Number;
for (var x:int = 0; x < src.width; x++)
{
for (var y:int = 0; y < src.height; y++)
{
px = src.getPixel32(x,y);
A += px >> 24 & 0xFF;
R += px >> 16 & 0xFF;
G += px >> 8 & 0xFF;
B += px & 0xFF;
idx++;
}
}
A /= idx;
R /= idx;
G /= idx;
B /= idx;
return A << 24 | R << 16 | G << 8 | B;
}
function createImgNodeGrid(rows:int = 1, cols:int = 1, pad:Number = 0):void
{
var w:Number = _img.width / rows;
var h:Number = _img.height / cols;
var numNodes:int = rows * cols;
_imgNodes = [];
var nodeCount:int = 0;
for (var i:int = 0; i < rows; i++)
{
for (var j:int = 0; j < cols; j++)
{
// get area of current image node
var sourceRect:Rectangle = new Rectangle(i * w, j * h, w, h);
// copy bitmap data of current image node
var tempBd:BitmapData = new BitmapData(w,h,true);
tempBd.copyPixels(_img.bitmapData, sourceRect, zero);
// place image node bitmap data into sprite
var imgNode:Bitmap = new Bitmap(tempBd);
imgNode.x = i * (w + pad);
imgNode.y = j * (h + pad);
// store each image node
//_imgNodes.push(imgNode);
_imgNodes[nodeCount++] = imgNode;
// add each image node to the stage
_tiledImg.addChild(imgNode);
_tiledImg.addEventListener(MouseEvent.CLICK,removeMC);
}
}
}
The problem you have is your are adding the event to the parent of the node(_tiledImg).
function createImgNodeGrid(rows:int = 1, cols:int = 1, pad:Number = 0):void
{
var w:Number = _img.width / rows;
var h:Number = _img.height / cols;
var numNodes:int = rows * cols;
_imgNodes = [];
var nodeCount:int = 0;
for (var i:int = 0; i < rows; i++)
{
for (var j:int = 0; j < cols; j++)
{
// get area of current image node
var sourceRect:Rectangle = new Rectangle(i * w, j * h, w, h);
// copy bitmap data of current image node
var tempBd:BitmapData = new BitmapData(w,h,true);
tempBd.copyPixels(_img.bitmapData, sourceRect, zero);
// place image node bitmap data into sprite
var imgNode:Bitmap = new Bitmap(tempBd);
imgNode.x = i * (w + pad);
imgNode.y = j * (h + pad);
// store each image node
//_imgNodes.push(imgNode);
_imgNodes[nodeCount++] = imgNode;
// you need a container since you can not attach event listeners to a BitMap
var sprite:Sprite = new Sprite()
sprite.mouseChildren = false;
sprite.addEventListener(MouseEvent.CLICK,removeMC);
sprite.addChild(imgNode);
// add each image node to the stage
_tiledImg.addChild(sprite);
// _tiledImg.addEventListener(MouseEvent.CLICK,removeMC);
}
}
}
function removeMC(e:MouseEvent)
{
var target:Sprite = event.currentTarget as Sprite;
target.parent.removeChild(target)
}
If I am following correctly, you are trying to remove an imgNode on MouseClick. If that is the case, you should change removeMC function to this:
function removeMC(e:MouseEvent)
{
//removes the movie clip
trace(e.target);
_tiledImg.removeChild(event.currentTarget);
}
Also, you shouldn't add the listener within the for loop, but instead add it outside of the for loops (since you are just adding the listener to _tiledImg and that doesn't change in the for loops).
A easy way to always remove a child from the right parent is to do as following
function removeMC(e:MouseEvent)
{
//removes the movie clip
var target:Sprite = event.currentTarget as Sprite;
target.parent.removeChild(target)
}