AS3: Line graph is glitchy - actionscript-3

Having a bit of a problem with some code I've written. Basically what it does is take 3 values that constantly change and graphs them over time in the form of a cumulative line graph. It almost works except I get this weird line drawn across the entire stage and further and I can't figure out what the issue is. The full code is below, you can run it by pasting it into flash.
import flash.display.Shape;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.utils.Timer;
var y1:Array = new Array();
var y2:Array = new Array();
var y3:Array = new Array();
var avg:Array = new Array();
var y1Shape:Shape = new Shape();
var y2Shape:Shape = new Shape();
var y3Shape:Shape = new Shape();
var avgShape:Shape = new Shape();
var container:Sprite = new Sprite();
var scale:uint = 1;
var redrawGraph:int = setInterval(reDraw,500);
var y1Int:int = 0;
var y2Int:int = 0;
var y3Int:int = 0;
container.addChild(y1Shape);
container.addChild(y2Shape);
container.addChild(y3Shape);
container.addChild(avgShape);
this.addChild(container);
function reDraw():void
{
y1Shape.graphics.clear();
y2Shape.graphics.clear();
y3Shape.graphics.clear();
avgShape.graphics.clear();
y1Shape.graphics.lineStyle(1, 0x0066FF, 1);
y1Shape.graphics.beginFill(0x0066FF, 0.5);
y2Shape.graphics.lineStyle(1, 0x009900, 1);
y2Shape.graphics.beginFill(0x009900, 0.5);
y3Shape.graphics.lineStyle(1, 0x990000, 1);
y3Shape.graphics.beginFill(0x990000, 0.5);
avgShape.graphics.lineStyle(1, 0x000000, 1);
y1Int = rand();
y2Int = rand();
y3Int = rand();
trace(y1Int, y2Int, y3Int);
y1.unshift(y1Int);
y2.unshift(y2Int);
y3.unshift(y3Int);
popOut(y1);
popOut(y2);
popOut(y3);
var i:uint,sum:uint,aLength:uint,len:uint = y1.length,max:int = 0,height_:int = 400;
scale = 10;
for (i=0; i<len; i++)
{
max = Math.max(y1[i] + y2[i] + y3[i],max);
}
for (i=0; i<len; i++)
{
sum += y1[i] + y2[i] + y3[i];
}
avg.unshift(Math.round(sum/len));
/*--------------------------------MATCHED GRAPH------------------------------------------*/
var y1_commands:Vector.<int> = new Vector.<int>();
var y1_coord:Vector.<Number>= new Vector.<Number>();
var y1_coord_rev:Vector.<Number> = new Vector.<Number>();
y1_commands.push(1);
y1_coord.push(400,height_);
for (i=0; i<len; i++)
{
y1_commands.push(2);
y1_coord.push((400-i*scale),height_-(Math.round((y1[i]/max)*height_)));
y1_coord_rev.unshift((400-i*scale),height_-(Math.round((y1[i]/max)*height_)));
}
for (i=len; i>0; i--)
{
y1_commands.push(2);
y1_coord.push(400 - i*scale,height_);
}
y1_commands.push(2);
y1_coord.push(400,height_);
/*--------------------------------MATCHED GRAPH------------------------------------------*/
/*----------------------------------BUSY GRAPH-------------------------------------------*/
var y2_commands:Vector.<int> = new Vector.<int>();
var y2_coord:Vector.<Number>= new Vector.<Number>();
var y2_coord_rev:Vector.<Number> = new Vector.<Number>();
y2_commands.push(1);
y2_coord.push(400,height_-(Math.round((y1[i]/max)*height_)));
for (i=0; i<len; i++)
{
y2_commands.push(2);
y2_coord.push((400-i*scale),height_-(Math.round(((y1[i]+y2[i])/max)*height_)));
y2_coord_rev.unshift((400-i*scale),height_-(Math.round(((y1[i]+y2[i])/max)*height_)));
}
for (i=len; i>0; i--)
{
y2_commands.push(2);
y2_coord.push(400 - i*scale, height_-(Math.round((y1[i]/max)*height_)));
}
y2_commands.push(2);
y2_coord.push(400,height_-(Math.round((y1[i]/max)*height_)));
/*----------------------------------BUSY GRAPH-------------------------------------------*/
/*----------------------------------VAC GRAPH-------------------------------------------*/
var y3_commands:Vector.<int> = new Vector.<int>();
var y3_coord:Vector.<Number>= new Vector.<Number>();
var y3_coord_rev:Vector.<Number> = new Vector.<Number>();
y3_commands.push(1);
y3_coord.push(400,height_-(Math.round(((y1[i]+y2[i])/max)*height_)));
for (i=0; i<len; i++)
{
y3_commands.push(2);
y3_coord.push((400-i*scale),height_-(Math.round(((y1[i]+y2[i]+y3[i])/max)*height_)));
y3_coord_rev.unshift((400-i*scale),height_-(Math.round(((y1[i]+y2[i]+y3[i])/max)*height_)));
}
for (i=len; i>0; i--)
{
y3_commands.push(2);
y3_coord.push(400 - i*scale, height_-(Math.round(((y1[i]+y2[i])/max)*height_)));
}
y2_commands.push(2);
y2_coord.push(400,height_-(Math.round(((y1[i]+y2[i])/max)*height_)));
/*----------------------------------BUSY GRAPH-------------------------------------------*/
//y3Shape.graphics.drawPath(y3_commands, y3_coord);
y2Shape.graphics.drawPath(y2_commands, y2_coord);
y1Shape.graphics.drawPath(y1_commands, y1_coord);
}
function popOut(a:Array):void
{
if (a.length >=Math.ceil(400/scale))
{
a.pop();
}
}
function rand():int
{
return Math.floor(Math.random() * (1 + 5 - 0) + 0);
}
y3Shape is commented out until the problem with y2Shape is fixed (having both drawn just makes the problem harder to figure out).
Any ideas what could be up?
Thanks

If you insert trace your vectors near .drawPath, you'll see something like that:
trace(y2_commands); // 1,2,2,2,2
trace(y2_coord); // 400,171,400,57,390,NaN,400,171,400,57
So, NaN (Not a Number) means, that you have error in coordinates calculating.
ps. y1[i] in first calculating of BUSY GRAPH is undefined

You seem to be using beginFill(), when you draw a path that's not looped, Flash requires your path to get looped in order to fill it with something. So, it loops it implicitly by adding a line to your starting point and filling it. In order to receive a non-overlapping path, add two points to your path that will be right below 0 point in X axis, one right under the last point on your graph, and one right under the FIRST point on the graph.
Actually, you already have them installed, but for some reason you place not 2 points, but a whole lot of em, and height position of that line is plainly wrong. Your code states:
for (i=len; i>0; i--)
{
y2_commands.push(2);
y2_coord.push(400 - i*scale, height_-(Math.round((y1[i]/max)*height_)));
}
You should have:
for (i=len; i>0; i--)
{
y2_commands.push(2);
y2_coord.push(400 - i*scale, height_);
}
Or even better:
y2_commands.push(2);
y2_commands.push(2);
y2_coord.push(400 - len*scale, height_);
y2_coord.push(400, height_);

Related

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

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);
}
}

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)
}
...

how to call objects created in a loop?

Newbie question:
If I create several shape objects in a loop, like:
var i:int;
for (i = 0; i < 3; i++) {
var circle:Shape = new Shape();
circle.graphics.beginFill(color);
circle.graphics.drawCircle(100,100, radius);
circle.graphics.endFill();
addChild(circle);
}
How can I then call those different shapes separately, so I could manipulate their properties? It would seem to me they would all have the same name?
You can access them via their index (the order they have been put on the stage).
So something like:
DisplayObject(getChildAt(1)).x = 100; // Where the 1 is the index (starting at 0)
Actually, you can just have an array (or vector) of objects, so you won't depend on current displaylist.
var i:int;
var circleArray:Array = new Array();
for (i = 0; i < 3; i++) {
var circle:Shape = new Shape();
circleArrayList.push(circle);
circle.graphics.beginFill(color);
circle.graphics.drawCircle(100,100, radius);
circle.graphics.endFill();
addChild(circle);
}
//And then access them with
for(i = 0; i < circleArray.length, i++)
{
circleArrayList[i].x = 15 * i;
}
//Or
foreach(var circle:DisplayObject in circleArray)
{
circle.x = 15 * i;
}
for(int i=0;i<3;i++)
{
class x =new class(i);
x.print()
}

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);
}

Intermittent/staggered loading of an object

I've just recently tried my hand at actionscript 3 and have come across a road block.
How do I go about rendering the cubes (cube1) intermittently, ie. staggered loading. I need the cubes to load a split second from each other.
Below is a snippet of what I have so far:
var rows:int = 5;
var cols:int = 3;
var spacery:int = 100;
var spacerx:int = 120;
var box_count:int = 8;
for(var i:int; i < box_count; i++) {
cube1 = new Cube(ml,100,10,80,1,1,1);
cube1.y = ((i % rows)) * (cube1.x + spacery);
cube1.x = Math.floor(i/rows) * (cube1.x +spacerx);
cube1.z = 0;
bigBox.addChild(cube1);
}
//Create an array out side the function; as a global (instance) variable:
var cubes:Array = [];
//instead of bigBox.addChild(cube1), store them in the array:
cubes.push(cube1);
//initialize a timer outside after for loop
//Fire every 100 milliseconds, box_count times
var timer:Timer = new Timer(100, box_count);
timer.addEventListener(TimerEvent.TIMER, onTick);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, onTickDone);
function onTick(e:Event):void
{
bigBox.addChild(cubes[timer.currentCount]);
}
function onTickDone(e:Event):void
{
cubes = null;
timer.removeEventListener(TimerEvent.TIMER, onTick);
timer.removeEventListener(TimerEvent.TIMER_COMPLETE, onTickDone);
timer = null;
}