Randomising array coordinates with no duplicates AS3 - actionscript-3

very new to this kind of thing so please bear with me.
So basically I have 4 buttons that I have put to the stage using the Actions panel. They all have set coordinates so every time I run my game, they are in the same place.
Now here's my issue, I want these buttons to randomise their positions using those coordinates, but I often get duplicates, meaning one button is on top of another.
Here is my code so far
var coordArray : Array = [
new Point(44,420),
new Point(270,420),
new Point(44,550),
new Point(270,550),
];
var pointRange:Number = 4;
var randomPoint:int = Math.random()*pointRange;
answerButtons.x = coordArray[randomPoint].x;
answerButtons.y = coordArray[randomPoint].y;
var pointRange_2:Number = 4;
var randomPoint_2:int = Math.random()*pointRange_2;
answerButtons_2.x = coordArray[randomPoint_2].x;
answerButtons_2.y = coordArray[randomPoint_2].y;
var pointRange_3:Number = 4;
var randomPoint_3:int = Math.random()*pointRange_3;
answerButtons_3.x = coordArray[randomPoint_3].x;
answerButtons_3.y = coordArray[randomPoint_3].y;
var pointRange_4:Number = 4;
var randomPoint_4:int = Math.random()*pointRange_4;
answerButtons_4.x = coordArray[randomPoint_4].x;
answerButtons_4.y = coordArray[randomPoint_4].y;
I have googled this profusely and I keep getting answers to do with the splice and shift methods. Is this the type of thing I need? I'm assuming I need a function that removes a point from the array after it is used.
Cheers.

Just remove the coordinate from the list when you pick it randomly using splice:
var coordinates:Vector.<Point> = new <Point>[
new Point(44, 420),
new Point(270, 420),
new Point(44, 550),
new Point(270, 550)
];
function positionAtRandomCoordinate(object:DisplayObject):void {
var index:int = Math.random() * coordinates.length;
var coordinate:Point = coordinates.splice(index, 1)[0];
object.x = coordinate.x;
object.y = coordinate.y;
}
positionAtRandomCoordinate(answerButtons);
positionAtRandomCoordinate(answerButtons_2);
positionAtRandomCoordinate(answerButtons_3);
positionAtRandomCoordinate(answerButtons_4);

Related

how to call just 2 value in array randomly specific location flash

I've 3 mc. I want to call 2 of them on stage randomly in specific locations. I don't know how to call them. I just tried with array. I think array is the best way but still confused.
this's code I tried :
import flash.geom.Point;
var Batumc:batu_mc = new batu_mc(); // creates a instance of the movieclip, i.e, an object
var Batumc1:L = new L();
var Pisangmc:pisang_mc = new pisang_mc();
var Batumc2:MovieClip = new MovieClip();
var Status:int = 0;
button.addEventListener(MouseEvent.CLICK, tombol);
function tombol(e:MouseEvent):void{
//addChild(Batumc);
//addChild(Batumc1);
//addChild(Pisangmc);
var P:Array = [new Point(80.2, 100), new Point(260, 100), new Point(430, 100)];
var M:Array = [Batumc, Batumc1, Pisangmc];
//random benda
var benda:int = Math.random()*M.length;
// Remove the selected benda from its list.
M.splice(benda, 1);
while (M.length){
// Get the last MovieClip and remove it from the list.
Batumc2 = M.pop();
trace(Batumc2);
// Produce a random Point.
var anIndex:int = Math.random() * P.length;
var aPo:Point = P[anIndex];
// Remove the selected Point from its list.
P.splice(anIndex, 1);
// Move the selected MovieClip to the selected Point coordinates.
Batumc2.x = aPo.x;
Batumc2.y = aPo.y;
addChild(Batumc);
addChild(Batumc1);
addChild(Pisangmc);
}
Status = 1;
}
button.addEventListener(Event.ENTER_FRAME, frame);
function frame(e:Event):void{
if(Status == 1 ){
removeChild(Batumc2);
Status = 0;
}
}
when i run this code, sometimes 3 mc appear again
I think the problem is with this line:
M[i] = P.splice(randomPos, 1);
You assign M[i] (array of mc) with value from P (array of points), so M[i] = array with point and not an mc.
If you want to avoid such issues you can use Vectors instead of arrays. Its more efficient and also must contain the type you declared.
Vector class Docs.
To use the vector, instead of:
var P:Array = [...];
var M:Array = [...];
Do:
var P:Vector.<Point> = new <Number>[...];
var M:Vector.<MovieClip> = new <MovieClip>[...];
And the rest is just like arrays (pop, push, slice, ...)
To remove item from M, just splice M, i don't understand why you need to iterate over M.
M.splice(randomPos, 1);
Try getDefinitionByName
var myClass:Class = getDefinitionByName("Class_Name") as Class;
var classInstance:MovieClip = new myClass as MovieClip;
addChild(classInstance);
You just have to determine the specific location in the array for the mc'c, beside that you can get the classes from the library like this;
var locations:Array = [{xpos:100, ypos:12} , {xpos:30, ypos:50} , {xpos:400, ypos:28}, ......];
for(var i:uint=0; i<YOUR_MCS_LENGTH; i++) {
var myClass:Class = getDefinitionByName("Batumc"+i) as Class;
var mc:MovieClip = new myClass as MovieClip;
mc.x = locations[i].xpos;
mc.y = locations[i].ypos;
}
I have followed your advice #Özgün Sandal, but I get this error
ReferenceError: Error #1065: Variable Batumc10 is not defined.
at global/flash.utils::getDefinitionByName()
at nyoba9_fla::MainTimeline/frame1()
this my code :
import flash.utils.getDefinitionByName;
import flash.geom.Point;
var Batumc:batu_mc = new batu_mc(); // creates a instance of the movieclip, i.e, an object
var Batumc1:L = new L();
var Pisangmc:pisang_mc = new pisang_mc();
var P:Array = [new Point(80.2, 100), new Point(260, 100), new Point(430, 100)];
var M:Array = [Batumc, Batumc1, Pisangmc];
for(var i:uint=0; i<M.length; i++) {
var myClass:Class = getDefinitionByName("Batumc1"+i) as Class;
var mc:MovieClip = new myClass as MovieClip;
// Produce a random Point.
var anIndex:int = Math.random() * P.length;
var aPo:Point = P[anIndex];
// Remove the selected Point from its list.
P.splice(anIndex, 1);
mc.x = aPo.x;
mc.y = aPo.y;
}
where's my fault?

how to save array in array randomly

I tried to show a random number in three movieclip boxes below(blue, yellow, red) when push button(grey box). to make random numbers I use math.ceil and I keep it in a var. I make 3 var (so I've 3 formula random number). after that, I want to call that 3 var into 3 new var randomly (hasil,hasil2,hasil3). last, i put the 3 new var into random dynamic text. the dynamic text is in three movieclip boxes.
these the formula random number
mtk = Math.ceil(Math.random()*10);
mtk1 = Math.ceil(Math.random()*20);
mtk2 = mtk+mtk1;
these the dynamic text
mc.jwb1.text = hasil.toString();
mc.jwb2.text = hasil2.toString();
mc.jwb3.text = hasil3.toString();
I tried to call the 3 var in 3 random numbers use 2 arrays, but I still confused about how to call them or you have better idea, Please tell me?
var mc:jwb = new jwb();
var mtk:Number;
var mtk1:Number;
var mtk2:Number;
var hasil:int;
var hasil2:int;
var hasil3:int;
btn.addEventListener(MouseEvent.CLICK, button);
function button(e:MouseEvent):void{
addChild(mc);
}
Batas_mc.addEventListener(Event.ENTER_FRAME, batas);
function batas(e:Event):void{
mc.x = 270;
mc.y = 130;
mtk = Math.ceil(Math.random()*10);
mtk1 = Math.ceil(Math.random()*20);
mtk2 = mtk+mtk1;
//Array object acak
var P:Array = [mtk, mtk1, mtk2];
var M:Array = [hasil, hasil2, hasil3];
while (M.length){
// Get the last MovieClip and remove it from the list.
var Batumc2:MovieClip = M.pop();
// Produce a random Point.
var anIndex:int = Math.random() * P.length;
var aPo = P[anIndex];
// Remove the selected Point from its list.
P.splice(anIndex, 1);
// Move the selected MovieClip to the selected Point coordinates.
Batumc2 = aPo;
}
mc.jwb1.text = hasil.toString();
mc.jwb2.text = hasil2.toString();
mc.jwb3.text = hasil3.toString();
}

Make movieclips appear randomly in AS3

Right now I have six mice places in spesific places on the stage. These mice move based on adjustments made on the timeline inside the movieclip itself. What I aim to do is to start these six movieclips randomly based on a timer. This task im currently struggeling with..
Here is my code;
var clipArray:Array = new Array();
clipArray[0] = musx0_mc;
clipArray[1] = musx1_mc;
clipArray[2] = musx2_mc;
clipArray[3] = musx3_mc;
clipArray[4] = musx4_mc;
clipArray[5] = musx5_mc;
var i:int = 0;
var musTimer:Timer = new Timer(100);
musTimer.addEventListener(TimerEvent.TIMER, playMus);
function playMus(event:TimerEvent):void
{
for(i=0; i<clipArray.length; i++)
{
var randomMus:Number = Math.floor(Math.random()*100);
clipArray[randomMus].play();
}
}
musTimer.start();
It seems that you want to get 0 to 5 random number.
//var randomMus:Number = Math.floor(Math.random()*100); // returns 0 to 99
var randomMus:int = Math.floor(Math.random()*6); // returns 0 to 5
Maybe this code works.
var clipArray:Array = new Array();
clipArray[0] = musx0_mc;
clipArray[1] = musx1_mc;
clipArray[2] = musx2_mc;
clipArray[3] = musx3_mc;
clipArray[4] = musx4_mc;
clipArray[5] = musx5_mc;
var musTimer:Timer = new Timer(100);
musTimer.addEventListener(TimerEvent.TIMER, playMus);
function playMus(event:TimerEvent):void
{
//for(i=0; i<clipArray.length; i++) // What is this loop??
//{
//var randomMus:Number = Math.floor(Math.random()*100);
var randomMus:int = Math.floor(Math.random()*6);
clipArray[randomMus].play();
//}
}
musTimer.start();

Issues with BitmapData of a MovieClip with rotationY applied to it

So I have a simple file right now that eventually will take a movieclip and save it as an image. I am currently rotating the clip's y by 45 to give it kind of a 3D look and adding it back to the stage. I've tried googling and a couple different things, but I can't quite get it to work. The first thing I tried was getting the BitmapData of the movieclip I rotated. That flattened the clip:
test_mc.response_mc.rotationY = 45;
var mc:MovieClip = test_mc.response_mc;
var bmp:BitmapData = new BitmapData(mc.width, mc.height);
bmp.draw(mc);
var output:Bitmap = new Bitmap(bmp);
output.x = 270;
output.y = 191;
addChild(output);
The next thing I tried was getting the parent clip's BD. That gave it an angle... just the wrong one:
(same code as above with this line change)
var mc:MovieClip = test_mc;
Any thoughts here would be nice. I tried doing stuff with matrices, but had no luck. I also have images... just can't post them yet :(
Something else I've tried with no luck:
var target:DisplayObject = test_mc as DisplayObject;
var targetTransform:Matrix = target.transform.concatenatedMatrix;
var targetGlobalBounds:Rectangle = target.getBounds(target.stage);
var targetGlobalPos:Point = target.localToGlobal(new Point());
var targetOriginOffset:Point = new Point(targetGlobalPos.x - targetGlobalBounds.left, targetGlobalPos.y - targetGlobalBounds.top);
targetTransform.tx = targetOriginOffset.x;
targetTransform.ty = targetOriginOffset.y;
var cloneData:BitmapData = new BitmapData(targetGlobalBounds.width, targetGlobalBounds.height, true, 0x00000000);
cloneData.draw(target, targetTransform);
var output:Bitmap = new Bitmap(cloneData);
**Another update**
So hopefully this will help a little. I was able to recreate what I was doing using Matrix3D.
test_mc.response_mc.rotationY = 45;
var matrix:Matrix3D = new Matrix3D();
matrix.prependRotation(45, Vector3D.Y_AXIS);
test2_mc.response_mc.transform.matrix3D = matrix;
test2_mc.response_mc.transform.matrix3D.appendTranslation(0, 0, 0);
And I've come closer to getting the bitmap to look correct (thank to a Mike Chambers blog).
var mcOffset:Matrix3D = test2_mc.response_mc.transform.matrix3D;
var rawMatrixData:Vector.<Number> = mcOffset.rawData;
var globalBounds:Rectangle = test2_mc.response_mc.getBounds(test2_mc);
var matrix:Matrix = new Matrix();
matrix.a = rawMatrixData[0];
matrix.c = rawMatrixData[1];
matrix.tx = test2_mc.response_mc.x - globalBounds.x;
matrix.b = rawMatrixData[4];
matrix.d = rawMatrixData[5];
matrix.ty = test2_mc.response_mc.y - globalBounds.y;
var bmp:BitmapData = new BitmapData(150, test2_mc.height);
test2_mc.response_mc.transform.matrix3D = null;
bmp.draw(test2_mc.response_mc, matrix);
test2_mc.response_mc.transform.matrix3D = mcOffset;
var output:Bitmap = new Bitmap(bmp);
Well I took it a step further back and went to the stage. For whatever reason trying to draw the parent (test_mc) of the rotated movie clip (response_mc) WON'T work, however drawing the stage and setting the bounds to the area of the parent DOES work. Here's my code (which is sadly very simple):
var bmp:BitmapData = new BitmapData(test_mc.width, test_mc.height);
bmp.draw(stage.getChildAt(0), new Matrix(1, 0, 0, 1, -test_mc.x, -test_mc.y));
var output:Bitmap = new Bitmap(bmp);

AS3 removing dynamically created child movieclips

I'm fairly new to AS3. Anyways, I'm try to remove a dynamically created child movieclip when clicked on. When a dirt block is clicked on, which is a child movieclip of 'world' I want to remove it.
I've tried various ways of removing it using removeChild. I've also tried moving the function inside/outside of the for loop that creates the movieclips.
var blockCount:Number = 0;
var blockArray:Array = [];
var world:MovieClip = new World();
world.x = 50;
world.y = 50;
world.name = "world";
addChild(world);
for(var i:Number=1;i<=100;i++){
blockCount++;
var tempGrassBlock:MovieClip = new GrassBlock();
tempGrassBlock.x = i*16;
tempGrassBlock.y = 256;
tempGrassBlock.name = "b"+blockCount;
world.addChild(tempGrassBlock);
tempGrassBlock.addEventListener(MouseEvent.CLICK, removeBlock);
function removeBlock(event:Event){
world.removeChild(getChildByName(event.target.name));
}
}
Thanks for the help.
Try this
function removeBlock(event:Event){
world.removeChild(event.currentTarget as DisplayObject);
}
No function definition should be inside a for. I changed that in your code and rewrited a little below:
var blockCount:Number = 0;
var blockArray:Array = [];
var world:MovieClip = new World();
world.x = 50;
world.y = 50;
world.name = "world";
addChild(world);
for(var i:Number=1;i<=100;i++){
blockCount++;
var tempGrassBlock:MovieClip = new GrassBlock();
tempGrassBlock.x = i*16;
tempGrassBlock.y = 256;
tempGrassBlock.name = "b"+blockCount;
world.addChild(tempGrassBlock);
tempGrassBlock.addEventListener(MouseEvent.CLICK, removeBlock);
}
function removeBlock(event:MouseEvent){
trace("Is click really working? This target name is " + event.currentTarget.name);
world.removeChild(event.currentTarget));
}