ActionScript 3: Tween stops mid animation...Probably the garbage collector - actionscript-3

I have been relentlessly trying to get my tweens in ActionScript 3 to work correctly, however with reaserch I have founf that the cause for the freezing mid animation is because of the garbage collector... I have tried both these methods, and have tried putting it in my document class, and yet it still happens to freeze randomly. It looks like I may have to go for something like tween lite, however something so simple shouldn't be so hard...
Attempt 1:
function createScrollingMC(mc:MovieClip, stageLeft:int, stageRight:int, durationSecs:int) {
var scrollingTween01:Tween;
var multiplyer:int = 100;
scrollingTween01 = new Tween(mc, "x", None.easeNone, stageLeft - mc.width, stageRight + mc.width, durationSecs * multiplyer, true);
scrollingTween01.looping = true;
}
createScrollingMC(Cloud_01, 0, 1024, 1);
createScrollingMC(Cloud_02, 0, 1024, 2);
createScrollingMC(Cloud_03, 0, 1024, 3);
createScrollingMC(Cloud_04, 0, 1024, 4);
Attempt 2:
var scrollingTween01:Tween;
function createScrollingMC(mc:MovieClip, stageLeft:int, stageRight:int, durationSecs:int) {
var multiplyer:int = 100;
scrollingTween01 = new Tween(mc, "x", None.easeNone, stageLeft - mc.width, stageRight + mc.width, durationSecs * multiplyer, true);
scrollingTween01.looping = true;
}
createScrollingMC(Cloud_01, 0, 1024, 1);
createScrollingMC(Cloud_02, 0, 1024, 2);
createScrollingMC(Cloud_03, 0, 1024, 3);
createScrollingMC(Cloud_04, 0, 1024, 4);

You are re-using the Tween instance scrollingTween01. It's a good thing, but you start using it before the last one finished tweening. After you re-assign it, it will stop animation of the previous one and this has nothing to do with GC.
Create new instances for the Tween class and that should solve your problem.
function createScrollingMC(mc:MovieClip, stageLeft:int, stageRight:int, durationSecs:int)
{
var multiplyer:int = 100;
var tween = new Tween(mc, "x", None.easeNone, stageLeft - mc.width, stageRight + mc.width, durationSecs * multiplyer, true);
tween.looping = true;
}

Related

Separate fill for each shape in Flex graphics

I am drawing a bunch of circles in 2 horizontal rows across a sprite and would like a gradient applied to each circle individually but flex is applying it to the entire graphics area. What do I need to change to draw each circle with its own gradient?
var s:Sprite = new Sprite();
var g:Graphics = s.graphics;
g.beginBitmapFill(bd, new Matrix(), false, false);
g.drawRect(0, 0, s.width, s.height);
g.endFill();
var m:Matrix = new Matrix();
g.lineStyle(1, 0x888888, 1);
for(var i:int = 0; i < numSpirals; i++) {
g.beginGradientFill(GradientType.LINEAR, [0x666666, 0xFFFFFF], [1, 1], [0, 255], m);
xc = i * spiralWidth + spiralHoleRadius;
yc = bdCenter - (spiralBoxHeight / 2) + (spiralHoleRadius / 2);
g.drawCircle(xc, yc, spiralHoleRadius);
g.endFill();
}
for(i = 0; i < numSpirals; i++) {
g.beginGradientFill(GradientType.LINEAR, [0x666666, 0xFFFFFF], [1, 1], [0, 255], m);
xc = i * spiralWidth + spiralHoleRadius;
yc = bdCenter + (spiralBoxHeight / 2) - (spiralHoleRadius / 2);
g.drawCircle(xc, yc, spiralHoleRadius);
g.endFill();
}
Thanks for your help!
Edit - I forgot this part (may or may not be relevant). Before drawing the circles I drew the BitmapData from an ImageSnapshot of some UI elements onto the sprite as well.
Solution:
I needed to create a new matrix and 'createGradientBox' for each circle individually
m = new Matrix();
m.createGradientBox(spiralHoleRadius * 2, spiralHoleRadius * 2, 0, xc - spiralHoleRadius / 2, yc - spiralHoleRadius / 2);
Following is a simular question on this site, maybe it helps (I cannot comment so I put this in a answer)
AS3: beginGradientFIll() doesn't make me a gradient!

Add the same child shape to multiple objects

Ok so I have this vector shape:
my_shape.graphics.lineStyle(1, 0x00FF00, 1);
my_shape.graphics.moveTo(30, 38);
my_shape.graphics.lineTo(7, 38);
my_shape.graphics.curveTo(-1, 38, -1, 36);
my_shape.graphics.lineTo(-1, 3);
my_shape.graphics.curveTo(-1, -1, 3, -1);
my_shape.graphics.lineTo(35, -1);
my_shape.graphics.curveTo(39, -1, 39, 3);
my_shape.graphics.lineTo(39, 30);
Since I couldn't find how can I change color of the existing shape I created 3 of these with only difference in the color,is it possible to change color of the existing shape?
Is it possible to use that same shape in other classes? Or I have to create it again?
if(ability3.Locked == true && Ability.suma >= 5){
ability3.Locked = false;
ability3.addChild(my_shape);
ability4.Locked = false;
ability4.addChild(my_shapea);
ability5.Locked = false;
ability5.addChild(my_shapeb);
}
if(ability6.Locked == true && Ability.suma >= 10){
ability6.Locked = false;
ability6.addChild(my_shapeb);
ability7.Locked = false;
ability7.addChild(my_shapea);
ability8.Locked = false;
ability8.addChild(my_shape);
ability9.Locked = false;
ability9.addChild(my_shape);
}
When this first code (ability 3 to 5) runs all 3 childs show but when it comes to running other if command abilities 6 to 9 get their children but 3 to 5 got their removed..can i use multiple times the same shape?
I hope you understand what I meant xD
Thanks.
Here is an example of copying graphics from one object to another, and changing their color:
var newShape:Shape = new Shape();
newShape.graphics.copyFrom(my_shape.graphics);
var colorTrans:ColorTransform = new ColorTransform();
colorTrans.color = 0xFFFFFF;
newShape.transform.colorTransform = colorTrans;
A display object can only be on a single display list at a time. This means that if I do the following:
container1.addChild(my_shape);
container2.addChild(my_shape);
my_shape will end up on container2
Normally, you would create a class for this particular shape and instantiate it as needed, but judging from your code, I'm not sure that you're using OOP (please correct me if I'm wrong and I'll update my answer).
Having said that, you can always write a function that creates the shape you need using the color of your choosing:
function createShape(color:uint):Shape
{
var shape:Shape = new Shape();
shape.graphics.lineStyle(1, color, 1);
shape.graphics.moveTo(30, 38);
shape.graphics.lineTo(7, 38);
shape.graphics.curveTo(-1, 38, -1, 36);
shape.graphics.lineTo(-1, 3);
shape.graphics.curveTo(-1, -1, 3, -1);
shape.graphics.lineTo(35, -1);
shape.graphics.curveTo(39, -1, 39, 3);
shape.graphics.lineTo(39, 30);
return shape;
}
Now you can call that function whenever you need to create the shape:
if(ability3.Locked == true && Ability.suma >= 5){
ability3.Locked = false;
ability3.addChild(createShape(someColor));
ability4.Locked = false;
ability4.addChild(createShape(someOtherColor));
ability5.Locked = false;
ability5.addChild(createShape(anotherColor));
}
Where someColor, someOtherColor, and anotherColor each represent a different uint (color).

Draw Kinetic.Shape in for-loop - var i of for-loop isn't taken properly in drawFunc()

Is it possible to use the variable i of a for-loop (for(i=0; i<3; i++)) in wich the Kinetic.Shape is created to set the y-value in the custom drawFunc();
My code of the for-loop for the dynamic shape creation looks the following:
var layer = new Kinetic.Layer();
for (i = 0; i < 3; i++){
layer.add(new Kinetic.Shape({
x: 0,
y: 0,
width: 400,
height: 400,
drawFunc: function(canvas){
console.log(i); //THIS LOG ALWAYS OUTPUTS THE MAX i-VALUE (here 3)
var ctx = canvas.getContext();
ctx.beginPath();
ctx.fillStyle = 'black';
ctx.fillRect(10, i*30+2, 200, 30);
ctx.closePath();
ctx.fill();
}
}));
}
stage.add(layer);
If i log the i-value in the custom drawFunc(); the result is always 3instead of 0, 1, 2, and because of that the ctx.fillRect draws all three shapes at y = 92.
Here is a fiddle of my code with the explained behaviour.
Am I missing something obvious? Any help is greatly appreciated.
You can try something like this. By adding the layers using a function the value passed to the createLayer function is saved with each Kinetic.Shape object that's created through closures.
function createLayer(nbr){
layer.add(new Kinetic.Shape({
x: 0,
y: 0,
width: 400,
height: 400,
drawFunc: function(canvas){
console.log(nbr);
var ctx = canvas.getContext();
ctx.beginPath();
ctx.fillStyle = 'black';
ctx.fillRect(10, nbr*30+2, 200, 30);
ctx.closePath();
ctx.fill();
}
}));
}
for (var i = 0; i < 3; i++){
createLayer(i);
}

nested array does not work

I have the following problem: I have this multi-level array (nested array) which contains two rows of bitmapData. Row 1:360 rotated bitmapData objects; row 2: 360 rotated and colored bitmapData objects.
I try to access row 2 but that doesn't work. There are some mysterious error messages coming up ("TypeError: Error #1034: Type Coercion failed: cannot convert []#36d7e9e9 to flash.display.BitmapData. at BasicBlitArrayObject/updateFrame()").
Please can someone help me out with this problem? Thank you very much.
this function rotates and colors bitmapData; the rotated bitmapData is thrown into an array and the colored bitmapData is thrown into another array; a third array is used as a level array for nesting the other two arrays inside of it
public function createColoredRotationBlitArrayFromBD(sourceBitmapData:BitmapData, inc:int, offset:int = 0, color:Number = 1, $alpha:Number = 1):Array
{
tileList = [];
tileListSec = [];
levelArray = [tileList, tileListSec];
var rotation:int = offset;
while (rotation < (360 + offset))
{
var angleInRadians:Number = Math.PI * 2 * (rotation / 360);
var rotationMatrix:Matrix = new Matrix();
rotationMatrix.translate(-sourceBitmapData.width * .5, -sourceBitmapData.height * .5);
rotationMatrix.rotate(angleInRadians);
rotationMatrix.translate(sourceBitmapData.width * .5, sourceBitmapData.height * .5);
var matrixImage:BitmapData = new BitmapData(sourceBitmapData.width, sourceBitmapData.height,
true, 0x00000000);
matrixImage.draw(sourceBitmapData, rotationMatrix);
tileList.push(matrixImage.clone());
bitmapData = new BitmapData(matrixImage.width, matrixImage.height, true, 0x00000000);
bitmapData = matrixImage;
var colorMatrix:ColorMatrixFilter = new ColorMatrixFilter (
[color, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, $alpha, 0]);
matrixImage.applyFilter(bitmapData, bitmapData.rect, point0, colorMatrix);
tileListSec.push(matrixImage.clone());
rotation += inc;
matrixImage.dispose();
matrixImage = null;
rotationMatrix = null;
bitmapData.dispose();
bitmapData = null;
colorMatrix = null;
}
return(levelArray);
}
creating my rotated and colored bitmapData
animationFrames = tempBlitArrayAsset.createRotationBlitArrayFromBD($bitmapData, 1, 270);
here I try to access the first row of my level array (that doesn't work; I can't access it)
tempEnemy.animationList = animationFrames;
tempEnemy.bitmapData = tempEnemy.animationList[1][tempEnemy.frame];
This function is for updating the frames
public function updateFrame(inc:int, row:int = 0):void
{
frame += inc;
if (frame > animationList.length - 1){
frame = 0;
}
bitmapData = animationList[row][frame];
}
}
this is a line showing how the updateFrame-function is used in my game (trueRotation is 0)
tempEnemy.updateFrame(tempEnemy.trueRotation);
I can't find anything wrong with createColoredRotationBlitArrayFromBD
var $bitmapData:BitmapData = new BitmapData(40,40,false, 0x7f7f7f);
var animationFrames:Array = createColoredRotationBlitArrayFromBD($bitmapData, 1, 270);
trace(animationFrames.length); // 2
trace(animationFrames[0].length); // 360
trace(animationFrames[1].length); // 360
var bitmap:Bitmap = new Bitmap();
this.addChild(bitmap);
bitmap.bitmapData = animationFrames[1][0]; // works..
That seems correct. Right? I get a red tinted bitmap.
The only 'bug' I see in the code you listed is in updateFrame
if (frame > animationList.length - 1){
frame = 0;
}
should probably be:
if (frame > animationList[row].length - 1){
frame = 0;
}
because animationList.length == 2
But everything else looks okay in the code you've provided, so without more code, i'm not sure there is anything to help.

Change pixel color with ActionScript 3

Say I have drawn a triangle with:
import flash.geom.Matrix;
function drawTriangle(sideLength:uint):void {
var triangleHeight:uint = Math.sqrt(Math.pow(sideLength,2) - Math.pow(sideLength / 2,2));
var triangleShape:Shape = new Shape();
triangleShape.graphics.beginFill(0x2147AB);
triangleShape.graphics.lineStyle(1,0xff00ff00);
triangleShape.graphics.moveTo(sideLength/2, 0);
triangleShape.graphics.lineTo(sideLength, triangleHeight);
triangleShape.graphics.lineTo(0, triangleHeight);
triangleShape.graphics.lineTo(sideLength/2, 0);
addChild(triangleShape);
var matrix:Matrix = new Matrix;
matrix.translate(50, 50);
transform.matrix = matrix;
}
drawTriangle(400);
How can I achieve the following:
When the user clicks a point inside the triangle, we will get the x and y coordinates, do some calculation with those values and get some (lots) of pixel coordiantes accordingly (all of those calculated points will be within the triangle). And finally, change the color of those points (something different than triangleShape fill color).
Here's a solution using a triangle drawn to some BitmapData, added to a Bitmap, and then contained in a Sprite.
var box:Sprite = new Sprite();
box.graphics.beginFill(0x000000, 1);
box.graphics.lineStyle(1, 0x000000, 1);
box.graphics.moveTo(100, 50);
box.graphics.lineTo(50, 100);
box.graphics.lineTo(150, 100);
box.graphics.lineTo(100, 50);
box.graphics.endFill();
addChild(box);
var boxCopied:BitmapData = new BitmapData(box.width, box.height, true, 0x00000000);
var matr:Matrix = new Matrix();
matr.tx = -50;
matr.ty = -50;
boxCopied.draw(box, matr);
box.graphics.clear();
var boxCopy:Bitmap = new Bitmap(boxCopied);
box.addChild(boxCopy);
box.addEventListener(MouseEvent.CLICK, clicked, false, 0, true);
function clicked(evt:MouseEvent):void
{
for(var i=0;i<50;i++)
{
var pixel = new Point(Math.floor(Math.random() * boxCopy.width), Math.floor(Math.random() * boxCopy.height));
if(boxCopied.hitTest(new Point(boxCopy.x, boxCopy.y), 1, pixel))
{
boxCopied.setPixel32(pixel.x, pixel.y, Math.random() * 0xFFFFFFFF);
}
}
}
http://www.swfupload.com/view/162170.htm
Note I'm using setPixel32 to send a 32-bit integer (essentially an ARBG instead of RGB) to manipulate alpha as well.
50 random pixels are being generated. If they're inside of the triangle, they're kept.