error while converting AS2 starfield code to AS3 - actionscript-3

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

Related

Type Coercion failed: cannot convert []#13a355b9 to flash.display.DisplayObject

I get this error when running, no compile errors.
package {
import flash.display.*;
import flash.events.*;
import flash.utils.*;
public class mainCode extends MovieClip{
//global variables go here
public var circled:Shape = new Shape();
public var circled2:Shape = new Shape();
public var circled3:Shape = new Shape();
public var angled:int = new int();
public var circlearray1:Array = new Array(4);
public var circlearray2:Array = new Array(4);
public function mainCode(){
makeCircle(circled, 100);
makeCircle(circled2, 50);
makeCircle(circled3, 50);
for(var i:int=0; i<4; i++){circlearray1[i] = new Array(20);}
for(var n:int=0; n<4; n++){circlearray2[n] = new Array(20);}
stage.addEventListener(Event.ENTER_FRAME, mainLoop);
}
//functions go here
private function mainLoop(e:Event){
trace(1);
angled+=1;
angled%=360;
circled.x = stage.stageWidth / 2;
circled.y = stage.stageHeight/ 2;
circled2.x = circled.x + 100*Math.cos(radians(angled));
circled2.y = circled.y + 100*Math.sin(radians(angled));
circled3.x = circled.x + 100*Math.cos(radians((angled + 180) % 360));
circled3.y = circled.y + 100*Math.sin(radians((angled + 180) % 360));
trace(2);
for (var i:int = 0; i < 4; i++)
{
trace(3);
if (circlearray1[i][0] != undefined)
{removeChild(circlearray1[i][0]);}
if (circlearray2[i][0] != undefined)
{removeChild(circlearray2[i][0]);}
trace(4);
for (var m:int = 0; m < 19; m++)
{
circlearray1[i][m] = circlearray1[m+1];
circlearray2[i][m] = circlearray2[m+1];
}
circlearray1[i][19] = new Shape();
circlearray2[i][19] = new Shape();
makeCircle(circlearray1[i][19], 25);
makeCircle(circlearray2[i][19], 25);
circlearray1[i][19].x = circled2.x + 50*Math.cos(radians(((-angled + (i*90)) * 2) % 360));
circlearray1[i][19].y = circled2.y + 50*Math.sin(radians(((-angled + (i*90)) * 2) % 360));
circlearray2[i][19].x = circled3.x + 50*Math.cos(radians(((-angled + (i*90)) * 2) % 360));
circlearray2[i][19].y = circled3.y + 50*Math.sin(radians(((-angled + (i*90)) * 2) % 360));
trace(8);
}
}
private function makeCircle(circles:Shape, radius:int)
{
circles.graphics.clear();
circles.graphics.lineStyle(2,0x000000);
circles.graphics.beginFill(0x990000);
circles.graphics.drawCircle(0,0,radius);
circles.graphics.endFill();
addChild(circles);
}
private function degrees(radians:Number):Number
{
return radians * 180/Math.PI;
}
private function radians(degrees:Number):Number
{
return degrees * Math.PI / 180;
}
private function killCircle(circlei:Shape):void {
removeChild(circlei);
}
}
}
I've traced it down to {removeChild(circlearray1[i][0]);}, which seems to be returning the error. I have no idea why it's doing this, I've tried alternatives such as circlearray1[i][0].parent.removeChild(circlearray1[i][0]); and if (circlearray1[i][0] is Shape) ... , but no dice.
For reference, I'm trying to make some circles circle around other circles, but have the outermost circles leave an "image lag" (or afterimage) while moving. I do this by creating objects and deleting them using for loops and multidimensional arrays, as I dont feel like typing out 50 create object calls manually and edit each one manually.
Probably, this part:
for (var m:int = 0; m < 19; m++)
{
circlearray1[i][m] = circlearray1[m+1];
circlearray2[i][m] = circlearray2[m+1];
}
You assign to endpoint elements, which you initially assume to be Shapes the elements which are Arrays. Then later you go at circlearray1[i][0] assuming it is Shape if it is not empty, but it is already an Array due to the assignment above. It's probably a typo and you meant this:
for (var m:int = 0; m < 19; m++)
{
circlearray1[i][m] = circlearray1[i][m+1];
circlearray2[i][m] = circlearray2[i][m+1];
}
There's actually a more clean way to do that. Array in AS3 is a lot like C# ArrayList, you can insert elements to either end and extract elements from either end without re-indexing elements manually:
trace(3);
// If you are sure the first element is not empty
// you can get its reference removing them from
// the Array at the same time.
removeChild(circlearray1[i].shift());
removeChild(circlearray2[i].shift());
trace(4);
// All Array elements are automatically shifted
// by -1 so you don't need to move each of them manually.
circlearray1[i][19] = new Shape();
circlearray2[i][19] = new Shape();

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

Action Script 3. How to remember last object x coordinates

I'm creating a flash game where objects are falling from the sky and the player needs to destroy them by clicking on them. But I have a problem, sometimes they spawning one on top of each other.
Here is an example what I mean:
Objects should be spawned near other, but not one on other.
Here is my constant vars:
public static const GRAVITY:Number = 3;
public static const HIT_TOLERANCE:Number = 50;
//Powerup
public static const APPLE_END_Y:Number = 640;
public static const APPLE_SPAWN_CHANCE:Number = 0.02; //per frame per second
public static const APPLE_START_Y:Number = 110;
public static const APPLE_SPAWN_START_X:Number = 50;
public static const APPLE_SPAWN_END_X:Number = 500;
//Scoring
public static const PLAYER_START_SCORE:Number = 0;
public static const SCORE_PER_APPLE:Number = 10;
Here is part of code where objects spawning:
private function update(evt:Event)
{
//Spawn new apples
if (Math.random() < randomChance)
{
//spawn x coordinates
var newPirmas = new Pirmas();
newPirmas.x = Math.random() * C.APPLE_SPAWN_END_X + C.APPLE_SPAWN_START_X;
var newAntras = new Antras();
newAntras.x = Math.random() * C.APPLE_SPAWN_END_X + C.APPLE_SPAWN_START_X;
var newTrecias = new Trecias();
newTrecias.x = Math.random() * C.APPLE_SPAWN_END_X + C.APPLE_SPAWN_START_X;
var newApple = new Apple();
newApple.x = Math.random() * C.APPLE_SPAWN_END_X + C.APPLE_SPAWN_START_X;
//spawn y coordinates
newPirmas.y = C.APPLE_START_Y;
newAntras.y = C.APPLE_START_Y;
newTrecias.y = C.APPLE_START_Y;
newApple.y = C.APPLE_START_Y;
newPirmas.addEventListener(MouseEvent.CLICK, onClick);
newAntras.addEventListener(MouseEvent.CLICK, onClick);
newTrecias.addEventListener(MouseEvent.CLICK, onClick);
newApple.addEventListener(MouseEvent.CLICK, onClick);
itemsToSpawn.push(newPirmas, newAntras, newTrecias, newApple);
}
}
As someone said: As for making sure they don't overlap, you can keep a history of their spawn points, and change how you get their random X value. Just iterate through the array of previous X values, and make sure the new one isn't within (oldX + (width/2)).
But I can't make It successfully, could you help me with keeping history of their spawn points? Thank you very much.
var t:Array = [];
t[0] = [APPLE_SPAWN_START_X, APPLE_SPAWN_END_X + APPLE_WIDTH/2];
t will keep the available intervals the you can generate new apple.
In the start time, there is no apple, and the t has only one interval, the starX of the interval is APPLE_SPAWN_START_X, the endX of the interval is APPLE_SPAWN_END_X + APP_WIDTH/2.
where you want to generate a new apple, you would find a availble interval in t, if we find the interval as mInterval(the interval could put in the apple, means endX - starX >= APPLE_WIDTH), then we could generate your new apple.
We just need to change the lines in you update function like
newPirmas.x = Math.random() * C.APPLE_SPAWN_END_X + C.APPLE_SPAWN_START_X;
Instead
newPirmas.x = mInterval[0] + Math.random()*APPLE_WIDTH;
When we set newPirmas.x, we have break the mInterval and generate two new interval,
the values are [mInterval[0],newPirmas.x] and []newPirmas.x + APPLE_WIDTH, mInterval[0]],
so we need to delete the mInterval in t and put the two new intervals into t.
/**
*
* #return index of available interval in target array
*/
public static function findAvailInterval(target:Array, appleWidth:int):int {
if (target == null || target.length == 0) {
return -1;
}
var endX:int = 0;
var startX:int = 0;
var length:int = target.length;
for (var i:int = 0; i < length; i++) {
var temp:Array = target[i] as Array;
if (temp == null || temp.length < 2) {
return -1;
}
startX = temp[0];
endX = temp[1];
var intervalWidth:int = endX - startX;//the interval width
if (intervalWidth >= appleWidth) {//find an available one
return i;
}
}
return -1;
}
public static function breakInterval(target:Array, appleWidth:int, index:int):int {
var temp:Array = target[index];
var startX:int = temp[0];
var endX:int = temp[1];
var width:int = endX - startX;
var availableNewXRange:int = width - appleWidth;//the appleā€˜s max x, and the min x is startX
//random a position
var appleX:int = startX + availableNewXRange*Math.random();
var leftInterval:Array = [startX, appleX];//the left interval of apple
var rightInterval:Array = [appleX+appleWidth, endX];//the right interval of apple
//delete temp
target.splice(index, 1);
if (isAvailableInterval(leftInterval, appleWidth)) {
target.push(leftInterval);
}
if (isAvailableInterval(rightInterval, appleWidth)) {
target.push(rightInterval);
} else {
trace("vvv");
}
return appleX;
}
private static function isAvailableInterval(interval:Array, appleWidth:int):Boolean {
if (interval == null || interval.length < 2) {
return false;
}
return (interval[1] - interval[0]) >= appleWidth;
}
Put the three functions into a class A
var target:Array = [[0, 1000]];
var appWidth:int = 80;
for (var i:int = 0; i < 4; i++) {
var index:int = A.findAvailInterval(target, appWidth);
if (index != -1) {
var interval:Array = target[index];
RR.breakInterval(target, appWidth, index);
trace(interval);
}
}

Collision detection and clipping issues in AS3

I've recently started putting together a little physics simulation from scratch, something I've never tried before, and I've run into an issue regarding the interaction between the collision of the objects I have on stage, and what I think is my constant gravity. I'm not sure if 200 lines of code is too large for here, but this is what I have.
package {
import flash.events.*;
import flash.display.*;
import flash.geom.Rectangle;
[SWF (width="1500", height="1000", frameRate="24")]
public class ElasticityV2 extends MovieClip{
/* Gravity is 9.8 m/s2, which for flash, since it's being applied every frame, needs to be
divided out by the frame rate as to not have super fast acceleration. GravMulti is to balance
out gravity's speed, as it seemed a little slow after the framerate division. Resistance is acting
like friction for now, and slows down the objects in the air and on the ground at the same rate.
Elasticity is how bouncy each object is and how the force it recieves is applied*/
public var gravMulti:Number = 5;
public var gravity:Number = gravMulti *(9.8/stage.frameRate);
public var resistance:Number = 0.98;
public var elasticity:Number = 0.8;
public var floor:Number = stage.stageHeight - 100;
public var objectList:Array = new Array();
public var shadowList:Array = new Array();
public var yVelocityList:Array = new Array();
public var xVelocityList:Array = new Array();
public var massList:Array = new Array();
public var frictionList:Array = new Array();
public var lastXList:Array = new Array();
public var lastYList:Array = new Array();
public var elasticityList:Array = new Array();
public var dragList:Array = new Array();
public var spawnNum:int = 20;
public var bounding:Rectangle = new Rectangle(0,0,stage.stageWidth - 100,stage.stageHeight);
public var distantBackground:Background = new Background();
public var starLight:Light = new Light();
public function ElasticityV2() {
addChild(starLight);
starLight.x = stage.stageWidth/2;
starLight.y = -400;
starLight.addEventListener(MouseEvent.MOUSE_DOWN, onLightDrag);
starLight.addEventListener(MouseEvent.MOUSE_UP, onLightDrag);
starLight.addEventListener(MouseEvent.MOUSE_OUT, onLightDrag);
for(var s:int=0;s<spawnNum;s++){
var ballShadow:Shadow = new Shadow();
addChild(ballShadow);
setChildIndex(ballShadow,0);
ballShadow.y = floor - (ballShadow.height/2);
ballShadow.x = 100;
shadowList.push(ballShadow);
var ball:ElasticBall = new ElasticBall();
var dragging:Boolean = false;
addChild(ball);
ball.y = 100;
ball.x = s * 200;
objectList.push(ball);
yVelocityList.push(randomMe(20,-20));
xVelocityList.push(randomMe(40,-40));
massList.push(randomMe(20,5));
frictionList.push(randomMe(0.6,0.01));
objectList[s].width = objectList[s].height = massList[s] * 10;
elasticityList.push(elasticity);
dragList.push(dragging);
ball.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
ball.addEventListener(MouseEvent.MOUSE_UP, onDrag);
ball.addEventListener(MouseEvent.MOUSE_OUT, onDrag);
}
addChild(distantBackground);
distantBackground.y = stage.stageHeight - distantBackground.height;
distantBackground.width = stage.stageWidth;
setChildIndex(distantBackground,0);
addEventListener(Event.ENTER_FRAME, onGameLoop);
}
public function onGameLoop(e:Event):void{
//checkCollision();
for(var i:int=0;i<objectList.length;i++){
updatePhysics(i);
updateShadows(i,starLight);
}
}
public function updatePhysics(objRef:int):void{
if(lastXList[objRef] != undefined){
if(lastXList[objRef] != objectList[objRef].x){
xVelocityList[objRef] = objectList[objRef].x - lastXList[objRef];
}
}
if(lastYList[objRef]!= undefined){
if(lastYList[objRef] != objectList[objRef].y){
yVelocityList[objRef] = 4*(objectList[objRef].y - lastYList[objRef])/stage.frameRate;
}
}
if(objectList[objRef].y>= floor - objectList[objRef].height){
yVelocityList[objRef] = -(yVelocityList[objRef] * elasticityList[objRef]);
objectList[objRef].y = floor - objectList[objRef].height;
}
if(objectList[objRef].y<= 0){
yVelocityList[objRef] = -(yVelocityList[objRef] * elasticityList[objRef]);
objectList[objRef].y = 0;
}
if(objectList[objRef].x > (stage.stageWidth - objectList[objRef].width)){
xVelocityList[objRef]=-xVelocityList[objRef];
objectList[objRef].x = stage.stageWidth - objectList[objRef].width;
}
if (objectList[objRef].x <0){
xVelocityList[objRef]=-xVelocityList[objRef];
objectList[objRef].x = 0;
}
if(!dragList[objRef]){
yVelocityList[objRef]+=gravity;
objectList[objRef].y += yVelocityList[objRef];
xVelocityList[objRef]= (xVelocityList[objRef] * resistance);
if(-0.5<xVelocityList[objRef] && xVelocityList[objRef]<0.5){
xVelocityList[objRef] = 0;
}
objectList[objRef].x += xVelocityList[objRef];
}
lastXList[objRef] = objectList[objRef].x;
lastYList[objRef] = objectList[objRef].y;
if(xVelocityList[objRef] == 0){
xVelocityList[objRef]=randomMe(90,-90);
yVelocityList[objRef]=randomMe(90,-90);
}
}
public function onDrag(e:Event):void{
if(e.type == "mouseDown"){
setChildIndex(DisplayObjectContainer(e.target),numChildren - 1)
e.target.startDrag(false,bounding);
//xVelocityList[objRef] = yVelocityList[objRef] = 0;
//dragging = true;
}else{
e.target.stopDrag();
//dragging = false;
}
}
public function onLightDrag(e:Event):void{
if(e.type == "mouseDown"){
e.target.startDrag(false,bounding);
}else{
e.target.stopDrag();
}
}
public function updateShadows(objRef:int, lightSource:MovieClip):void{
//-----Cut for convenience------
}
public function checkCollision():void{
for(var v:int=0;v<objectList.length;v++){
var ball1 = objectList[v];
for(var w:int=v+1;w<objectList.length;w++){
var ball2 = objectList[w];
if((ball1.x + getRadius(ball1) + getRadius(ball2) > ball2.x) && (ball1.x < ball2.x + getRadius(ball1) + getRadius(ball2)) && (ball1.y + getRadius(ball1) + getRadius(ball2) > ball2.y) && (ball1.y < ball2.y + getRadius(ball1) + getRadius(ball2))){
var dx:Number = ball2.x - ball1.x;
var dy:Number = ball2.y - ball1.y;
var dist:Number = Math.sqrt((dx * dx) + (dy * dy));
if(dist < getRadius(ball1)+getRadius(ball2)){
var newX1:Number;
var newY1:Number;
var newX2:Number;
var newY2:Number;
trace("Magnitude 1 is : " + (Math.sqrt((xVelocityList[v] * xVelocityList[v]) + (yVelocityList[v] * yVelocityList[v]))));
trace("Magnitude 2 is : " + (Math.sqrt((xVelocityList[w] * xVelocityList[w]) + (yVelocityList[w] * yVelocityList[w]))));
newX1 = ((massList[v] * xVelocityList[v])+(massList[w] * xVelocityList[w]))/(massList[v] + massList[w]) * 2 - xVelocityList[v];
newY1 = ((massList[v] * yVelocityList[v])+(massList[w] * yVelocityList[w]))/(massList[v] + massList[w]) * 2 - yVelocityList[v];
newX2 = ((massList[v] * xVelocityList[v])+(massList[w] * xVelocityList[w]))/(massList[v] + massList[w]) * 2 - xVelocityList[w];
newY2 = ((massList[v] * yVelocityList[v])+(massList[w] * yVelocityList[w]))/(massList[v] + massList[w]) * 2 - yVelocityList[w];
xVelocityList[v] = newX1;
yVelocityList[v] = newY1;
xVelocityList[w] = newX2;
yVelocityList[w] = newY2;
ball1.x += newX1;
ball1.y += newY1;
ball2.x += newX2;
ball2.y += newY2;
}
}
}
}
}
public function randomMe(high:Number, low:Number = 0):Number{
return Math.random() * (high - low) + low;
}
public function getRadius(obj:MovieClip):Number{
return obj.width/2;
}
public function centerX(obj:MovieClip):Number{
return obj.x + getRadius(obj);
}
public function centerY(obj:MovieClip):Number{
return obj.y + getRadius(obj);
}
}
}
It's a very simple system to check for collision, just comparing the radius of the objects, and midair collisions seem fine, but if one ball lands on top of another that has no x or y velocity, it just sinks into it. Any ideas as to why?
I expect your balls behave like this: When one ball lands on top of the other, that's actually lying on the ground, the other ball gets pushed down into the ground, then you react at it within updatePhysics() by placing it into the position where it originated, thus, those balls become one within another. One of the suggestions that could remedy this will be to hold last collided object for each of the balls for one cycle of physics, say like this:
if(dist < getRadius(ball1)+getRadius(ball2)){
// process collision
ball1.lastCollided=ball2;
ball2.lastCollided=ball1;
}
Then, when you update your coordinates in updatePhysics(), check if lastCollided is null, if not, update that ball's coordinates and speed the same way, essentially simulating another collision. After checking for all the events within update physics cycle, assign null to lastCollided of all balls.

Detect when the Shader is done mixing the audio

so this the code with it i am able to mix several tracks
with a Shader done in pixel bender.
the problem here i don't know when the mixing is finish or all the sound reache their end
to be able to save the bytearray into a file any Event or something like that
help plz ?
package
{
import flash.display.*;
import flash.media.*;
import flash.events.*;
import flash.net.*;
import flash.utils.*;
import fl.controls.Slider;
import org.bytearray.micrecorder.encoder.WaveEncoder;
[SWF(width='500', height='380', frameRate='24')]
public class AudioMixer extends Sprite{
[Embed(source = "sound2.mp3")] private var Track1:Class;
[Embed(source = "sound1.mp3")] private var Track2:Class;
[Embed(source = "mix.pbj",mimeType = "application/octet-stream")]
private var EmbedShader:Class;
private var shader:Shader = new Shader(new EmbedShader());
private var sound:Vector.<Sound> = new Vector.<Sound>();
private var bytes:Vector.<ByteArray> = new Vector.<ByteArray>();
private var sliders:Vector.<Slider> = new Vector.<Slider>();
private var graph:Vector.<Shape> = new Vector.<Shape>();
private var recBA:ByteArray = new ByteArray();
private var BUFFER_SIZE:int = 0x800;
public var playback:Sound = new Sound();
public var container:Sprite = new Sprite();
public var isEvent:Boolean = false;
public function AudioMixer():void{
container.y = stage.stageHeight * .5;
addChild(container);
sound.push(new Track1(), new Track2(),new Track2(),new Track2(),new Track2(),new Track2(),new Track2(),new Track2(),new Track2(),new Track2(),new Track2(),new Track2());
for(var i:int = 0; i < sound.length; i++){
var slider:Slider = new Slider();
slider.maximum = 1;
slider.minimum = 0;
slider.snapInterval = 0.025;
slider.value = 0.8;
slider.rotation += -90;
slider.x = i * 40 + 25;
container.addChild(slider);
sliders.push(slider);
var line:Shape = new Shape();
line.graphics.lineStyle(1, 0x888888);
line.graphics.drawRect(i * 40 + 14, 0, 5, -80);
line.graphics.endFill();
container.addChild(line);
var shape:Shape = new Shape();
shape.graphics.beginFill(0x00cc00);
shape.graphics.drawRect(i * 40 + 15, 0, 3, -80);
shape.graphics.endFill();
container.addChild(shape);
graph.push(shape);
}
playback.addEventListener(SampleDataEvent.SAMPLE_DATA, onSoundData);
playback.play();
}
private function onSoundData(event:SampleDataEvent):void {
for(var i:int = 0; i < sound.length; i++){
bytes[i] = new ByteArray();
bytes[i].length = BUFFER_SIZE * 4 * 2;
sound[i].extract(bytes[i], BUFFER_SIZE);
var volume:Number = 0;
bytes[i].position = 0;
for(var j:int = 0; j < BUFFER_SIZE; j++){
volume += Math.abs(bytes[i].readFloat());
volume += Math.abs(bytes[i].readFloat());
}
volume = (volume / (BUFFER_SIZE * .5)) * sliders[i].value;
shader.data['track' + (i + 1)].width = BUFFER_SIZE / 1024;
shader.data['track' + (i + 1)].height = 512;
shader.data['track' + (i + 1)].input = bytes[i];
shader.data['vol' + (i + 1)].value = [sliders[i].value];
graph[i].scaleY = volume;
}
var shaderJob:ShaderJob = new ShaderJob(shader,event.data,BUFFER_SIZE / 1024,512);
shaderJob.start(true);
var shaderJob2:ShaderJob = new ShaderJob(shader,recBA,BUFFER_SIZE / 1024,512);
shaderJob2.start(true);
}
}
}
You can tell when a shader has completed it's job using the ShaderEvent.COMPLETE listener. Like so:
shaderJob.addEventListener(ShaderEvent.COMPLETE, onShaderComplete);
private function onShaderComplete(e:Event):void
{
//Do Something here
}
See this link for more details.
One thing about your code though. You're doing this shader job inside of a sampleDataEvent and I can see this being problematic (possibly) in the sense that your mixing may be out of sync with your playback (that is, if you plan on mixing live and writing the mixed data back into the sound stream). Anyway that's perhaps an issue for a new question. This should solve your problem with needing to know when the mixing is complete.
Note you also need to add "false" to the shaderJob.start(false) function. From the documentation about the ShaderEvent.COMPLETE:
"Dispatched when a ShaderJob that executes asynchronously finishes processing the data using the shader. A ShaderJob instance executes asynchronously when the start() method is called with a false value for the waitForCompletion parameter."
Update
In response to your inquiry about how to only process inside the sampleDataEvent if the sound isnt being processed:
private var isProcessing:Boolean = false;
private function onSoundData(event:SampleDataEvent):void {
if(isProcessing != true){
for(var i:int = 0; i < sound.length; i++){
bytes[i] = new ByteArray();
bytes[i].length = BUFFER_SIZE * 4 * 2;
sound[i].extract(bytes[i], BUFFER_SIZE);
var volume:Number = 0;
bytes[i].position = 0;
for(var j:int = 0; j < BUFFER_SIZE; j++){
volume += Math.abs(bytes[i].readFloat());
volume += Math.abs(bytes[i].readFloat());
}
volume = (volume / (BUFFER_SIZE * .5)) * sliders[i].value;
shader.data['track' + (i + 1)].width = BUFFER_SIZE / 1024;
shader.data['track' + (i + 1)].height = 512;
shader.data['track' + (i + 1)].input = bytes[i];
shader.data['vol' + (i + 1)].value = [sliders[i].value];
graph[i].scaleY = volume;
}
var shaderJob:ShaderJob = new ShaderJob(shader,event.data,BUFFER_SIZE / 1024,512);
shaderJob.start(false);
shaderJob.addEventListener(ShaderEvent.COMPLETE, onShaderComplete);
var shaderJob2:ShaderJob = new ShaderJob(shader,recBA,BUFFER_SIZE / 1024,512);
shaderJob2.start(false);
}
}
private function onShaderComplete(e:ShaderEvent):void
{
//Do something here
isProcessing = false;
}