Handling Multiple TimerEvent - actionscript-3

Below is simplified version of a game I am creating. Basically, the game have some circles. Each circle shoot bullets that is dispatched with timerEvent. When the circle is clicked it is removed from the stage. However, the bullet still keeps on dispatching. I couldn't figure out how to stop timerEvent of each individual circle when it is clicked.
var _timer:Timer = new Timer(1000);
var speed:int = 20;
for(var i:int=0; i<= 3; i++)
{
var _shape:MovieClip = new MovieClip();
_shape.graphics.beginFill(0x999999);
_shape.graphics.lineStyle(1, 0x000000);
_shape.graphics.drawCircle(0, 0, 20);
_shape.graphics.endFill();
addChild(_shape);
_shape.x = (stage.stageWidth)/5;
_shape.y = (stage.stageHeight)/3 + _shape.height*i*1.5;
_shape.name = "_shape"+i;
_shape.buttonMode = true;
_shape.addEventListener(MouseEvent.CLICK, removeMovieClip);
bullets(_shape);
}
function bullets(_shape:MovieClip):void
{
_timer = new Timer(Math.random()*100);
_timer.addEventListener(TimerEvent.TIMER, startFiring);
_timer.start();
function startFiring(e:TimerEvent):void
{
speed ++;
var _bullet:MovieClip = new MovieClip();
_bullet.graphics.beginFill(0x999999);
_bullet.graphics.lineStyle(1, 0x000000);
_bullet.graphics.drawRect(0, 0, 5,2);
_bullet.graphics.endFill();
addChild(_bullet);
_bullet.x = _shape.x + speed ;
_bullet.y = _shape.y;
}
}
function removeMovieClip(e:MouseEvent):void
{
removeChild(getChildByName(e.currentTarget.name));
// how to stop the timerEvent of clicked circle?
}

//var _timer:Timer = new Timer(1000); //I don't think this is necessary
var speed:int = 20;
for(var i:int=0; i<= 3; i++)
{
var _shape:MovieClip = new MovieClip();
_shape.graphics.beginFill(0x999999);
_shape.graphics.lineStyle(1, 0x000000);
_shape.graphics.drawCircle(0, 0, 20);
_shape.graphics.endFill();
addChild(_shape);
_shape.x = (stage.stageWidth)/5;
_shape.y = (stage.stageHeight)/3 + _shape.height*i*1.5;
_shape.name = "_shape"+i;
_shape.buttonMode = true;
bullets(_shape);
}
function bullets(_shape:MovieClip):void
{
_shape.timer = new Timer(Math.random()*100);
_shape.timer.addEventListener(TimerEvent.TIMER, startFiring);
_shape.timer.start();
_shape.addEventListener(MouseEvent.CLICK, removeMovieClip);
function startFiring(e:TimerEvent):void
{
speed ++;
var _bullet:MovieClip = new MovieClip();
_bullet.graphics.beginFill(0x999999);
_bullet.graphics.lineStyle(1, 0x000000);
_bullet.graphics.drawRect(0, 0, 5,2);
_bullet.graphics.endFill();
addChild(_bullet);
_bullet.x = _shape.x + speed ;
_bullet.y = _shape.y;
}
function removeMovieClip(e:MouseEvent):void
{
//stop the time and remove its listeners
e.target.timer.stop(); // you might need to cast this into Timer object
e.target.timer.removeEventListener(TimerEvent.TIMER, startFiring);
removeChild((MovieClip)e.target);
// how to stop the timerEvent of clicked circle?
}
}

Related

Applying Drag, Snap Back Into Original Position To An Array

I am attempting to drag a movie clip and then have it snap back into its original position after being released. I want to apply this functioniality to an array with actionscript3. Here is the code so far:
var dragArray:Array = new Array;
dragArray.push(blockSmalla);
dragArray.push(blockSmallb);
dragArray.push(blockSmallc);
dragArray.push(blockSmalld);
dragArray.push(blockSmalle);
var startPosition:Point;
function drag(e:Event):void {
dragArray[i].startDrag();
startPosition = new Point( dragArray[i].x, dragArray[i].y);
}
function dragStop(e:Event):void {
dragArray[i].stopDrag();
dragArray[i].x = startPosition.x;
dragArray[i].y = startPosition.y;
startPosition = null;
}
for (var i:uint = 0; i < dragArray.length; i++) {
dragArray[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
dragArray[i].stage.addEventListener(MouseEvent.MOUSE_UP, dragStop);
}
The function is not being applied to the array. Any suggestions?
I think what null was trying to tell you is that within each function scope you should remove dragArray[i] and use e.currentTarget instead.
Here's a simple fix:
var dragArray:Array = new Array;
dragArray.push(blockSmalla);
dragArray.push(blockSmallb);
dragArray.push(blockSmallc);
dragArray.push(blockSmalld);
dragArray.push(blockSmalle);
var startPosition:Point;
function drag(e:Event):void {
e.currentTarget.startDrag();
startPosition = new Point( e.currentTarget.x, e.currentTarget.y);
}
function dragStop(e:Event):void {
e.currentTarget.stopDrag();
e.currentTarget.x = startPosition.x;
e.currentTarget.y = startPosition.y;
startPosition = null;
}
for (var i:uint = 0; i < dragArray.length; i++) {
dragArray[i].addEventListener(MouseEvent.MOUSE_DOWN, drag);
dragArray[i].addEventListener(MouseEvent.MOUSE_UP, dragStop);
}
Also note I removed the stage reference on your MouseUp listener.

Test for collision between a sprite and a bitmap

How do i test for collision between a Sprite and a Bitmap image with a transparent background?
I've look as much as i can for a reason why this isn't working but i cant find it.
the collision that isn't working as i expect is in the function called BridgeCollision
Please help?
var bridgeSpriteArr:Array = new Array(bridgeArr.length);
var bridge_BMArr:Array = new Array(bridgeArr.length);
for ( var i:int = 0; i < bridgeArr.length; i++)
{
var bridgeSprite:Sprite = new Sprite();
bridgeSprite.graphics.lineStyle(4, 0x00ff00);
bridgeSprite.graphics.moveTo(bridgeArr[i].x, bridgeArr[i].y);
switch (bridgeArr[i].nVector)
{
case 0:
bridgeSprite.graphics.lineTo(bridgeArr[i].x, bridgeArr[i].y + bridgeArr[i].maxRange);
break;
case 1:
bridgeSprite.graphics.lineTo(bridgeArr[i].x - bridgeArr[i].maxRange, bridgeArr[i].y);
break;
case 2:
bridgeSprite.graphics.lineTo(bridgeArr[i].x, bridgeArr[i].y - bridgeArr[i].maxRange);
break;
case 3:
bridgeSprite.graphics.lineTo(bridgeArr[i].x + bridgeArr[i].maxRange, bridgeArr[i].y);
break;
}
var bridge_BMD:BitmapData = new BitmapData(bridgeSprite.width, bridgeSprite.height,true,0);
var bridgeBounds:Rectangle = bridgeSprite.getBounds(bridgeSprite);
var m:Matrix = new Matrix();
m.translate(-bridgeBounds.x, -bridgeBounds.y);
bridge_BMD.draw(bridgeSprite, m);
var bridge_BM:Bitmap = new Bitmap(bridge_BMD);
bridge_BMArr[i] = bridge_BM;
bridgeSpriteArr[i] = bridgeSprite;
Main.getStage().addChild(bridgeSprite);
}
var bridgeCollision:Boolean = false;
var shipCollision:Boolean = false;
Main.getStage().addEventListener( Event.ENTER_FRAME,
function bridgeCollision(e:Event):void
{
bridgeCollision = false;
for (var i:int = 0; i < bridgeSpriteArr.length; i++)
{
if ( object1.hitTestObject(bridgeSpriteArr[i]))
{
trace("hit bridge - trans");
if (object1_BMD.hitTest(new Point(object1.x, object1.y), 255, bridge_BMArr[i].bitmapData,
new Point(bridgeSpriteArr[i].x, bridgeSpriteArr[i].y),0)) // this is the collision with the problem
{
trace("hit bridge - visible");
bridgeCollision = true;
}
}
}
});

How to add Looped URLRequest image and add them to 1 viewport?

I am trying to loop (add images from Loader thru URLRequest), And the images are added to contentHolder, and then i place all these images which are inside contentHolder into a viewport. But at the moment I have to put the add images to viewport step inside the loop, so it creates a problem, which is each loop, a viewport is added. So 10 viewport overlaps each other. I tested it in debug mode and when the first image is loaded i can quickly slide it, because the viewport has a scrollpane, then second image is added, and i can slide that one, and third one is added on top etc.
But if i put the add Holder to viewport step outside the loop, it gives me the error Error #2007: Parameter child must be non-null, i dont know what to do. Please help, thanks for your time! I had been trying this for 6 hrs already!
And the error is on the line viewport.addChild(_contentHolder1); which is the last part of the code, if you scroll to the bottom.
for (var j:int = 5; j < somedata.length; j++)
{
if(somedata[j]){
var myLoader:Loader = new Loader();
var image:Bitmap;
var url:URLRequest = new URLRequest("http://www.rentaid.info/rent/"+somedata[j]);
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
myLoader.load(url);
function onImageLoaded(e:Event):void {
image = new Bitmap(e.target.content.bitmapData);
var currentY:int = 10;
var h = image.height;
var k=image.width/image.height;
_contentHolder = new Sprite();
_contentHolder.y = currentY;
currentY += _contentHolder.height + 10;
addChild(_contentHolder);
_contentHolder.addChild(image);
for (var j:int = 5; j <somedata.length; j++)
{
_contentHolder1 = new Sprite();
addChild(_contentHolder1);
_contentHolder1.addChild(_contentHolder);
var viewport:Viewport = new Viewport();
viewport.y = 0;
viewport.addChild(_contentHolder1);
var scroller:TouchScroller = new TouchScroller();
scroller.width = 300;
scroller.height = 265;
scroller.x = 10;
scroller.y = 100;
scroller.viewport = viewport;
addChild(scroller);
}
}}
Edit:
var loadedArray:Array = new Array();
var counter:int=0;
function loadImage():void{
for (var j:int = 5; j < somedata.length; j++)
{
if(somedata[j]){
var loader:Loader = new Loader();
var image:Bitmap;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
loader.load(new URLRequest("http://www.rentaid.info/rent/"+somedata[j][counter]));
}
}
}
function onImageLoaded(e:Event):void {
loadedArray.push(e.currentTarget.loader.content as Bitmap);
if(counter == somedata.length-1){
var _contentHolder: Sprite = new Sprite;
addChild(_contentHolder);
for(var i:uint = 5; i < loadedArray.length; i++){
_contentHolder.addChild(loadedArray[i]);
currentY += _contentHolder.height + 10;
}
}
else{
counter++;
loadImage();
}
var viewport:Viewport = new Viewport();
viewport.y = 0;
viewport.addChild(_contentHolder);
var scroller:TouchScroller = new TouchScroller();
scroller.width = 300;
scroller.height = 265;
scroller.x = 10;
scroller.y = 100;
scroller.viewport = viewport;
addChild(scroller);
}
you can use Starling Framework and a loader loop such as:
private var count:uint = 0; //add this in your class
private var imagesVector:Vector.<Image> = new Vector.<Image>(); //add this in your class
private var imagesUrlVector:Vector.<String> = new <String>["url1","url2","url3","etc"]; //add this in your class
private function loadImages():void
{
//create the loader
var loader:Loader = new Loader();
//when texture is loaded
loader.contentLoaderInfo.addEventListener ( Event.COMPLETE, onComplete );
//load the texture
loader.load( new URLRequest (imagesUrlVector[count]));
}
private function onComplete ( e : Event ):void
{
// grab the loaded bitmap
var loadedBitmap:Bitmap = e.currentTarget.loader.content as Bitmap;
// create a texture from the loaded bitmap
var texture:Texture = Texture.fromBitmap ( loadedBitmap );
var card:CustomImage = new CustomImage(texture);
imagesVector.push(card);
trace("load image number" + count);
count++;
if (count < imagesUrlVector.length) {
loadImages();
} else displayImages();
}
private function displayImages():void {
var x:uint = 150;
var i:Number;
for (i = 0; i < cardVector.length; i++ )
{
x += 100;
imagesVector[i].x = x;
addChild(imagesVector[i]);
}
}

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

AS3 proportionally scaling external image

Currently I am using a for loop to dynamically load XML images and place them in a grid as thumbnails. I have the arrangement set and all the data is loading smoothly, but now I need to make the images scale to small 100px x 100px thumbs in small container movieclips. My code is as follows.
import gs.*;
import gs.easing.*;
var bttnHeight:Number = 20;
var select:Number = 0;
var xmlLoader:URLLoader = new URLLoader();
xmlLoader.addEventListener(Event.COMPLETE, showXML);
xmlLoader.load(new URLRequest("testxml.xml"));
var list_mc:Array = new Array();
function showXML(e:Event):void {
XML.ignoreWhitespace = true;
var nodes:XML = new XML(e.target.data);
var gallcount = nodes.gallery.length();
var list_mc = new listitem();
//Generate menu to select gallery
function populateMenu():void {
var spacing:Number = 0;
for (var i=0; i<gallcount; i++) {
list_mc[i] = new listitem();
list_mc[i].name = "li" + i;
list_mc[i].y = i*bttnHeight;
list_mc[i].gallname.text = nodes.gallery[i].attributes();
menu_mc.addChild(list_mc[i]);
list_mc[i].addEventListener(MouseEvent.ROLL_OVER, rollover);
list_mc[i].addEventListener(MouseEvent.ROLL_OUT, rollout);
list_mc[i].buttonMode = true;
list_mc[i].mouseChildren = false;
}
menu_mc.mask = mask_mc;
}
//list_mc.mask(mask_mc);
var boundryWidth = mask_mc.width;
var boundryHeight = mask_mc.height;
var diff:Number = 0;
var destY:Number = 0;
var ratio:Number = 0;
var buffer:Number = bttnHeight*2;
function findDest(e:MouseEvent):void {
if (mouseX>0 && mouseX<(boundryWidth)) {
if (mouseY >0 && mouseY<(boundryHeight)) {
ratio = mouseY/boundryHeight;
diff = menu_mc.height-boundryHeight+buffer;
destY = Math.floor(-ratio*diff)+buffer/2;
}
}
}
var tween:Number = 5;
//This creats the scroll easing
function moveMenu() {
if (menu_mc.height>boundryHeight) {
menu_mc.y += (destY-menu_mc.y)/tween;
if (menu_mc.y>0) {
menu_mc.y = 0;
} else if (menu_mc.y<(boundryHeight-menu_mc.height)) {
menu_mc.y = boundryHeight-menu_mc.height;
}
}
}
function rollover(e:Event):void {
TweenLite.to(e.currentTarget.li_bg, .4, {tint:0x334499});
}
function rollout(e:Event):void {
TweenLite.to(e.currentTarget.li_bg, .4, {removeTint:true});
}
stage.addEventListener(MouseEvent.MOUSE_MOVE, findDest);
stage.addEventListener(Event.ENTER_FRAME, moveMenu);
populateMenu();
select = 0;
//Generate thumbnails
function genThumb():void {
var photos = nodes.gallery[select].photo;
var thumbframe:Array = new Array();
var row = 0;
var column = 0;
var loaderArray:Array = new Array();
for (var i=0; i<photos.length(); i++) {
thumbframe[i] = new Sprite;
thumbframe[i].graphics.beginFill(0x0000FF);
thumbframe[i].graphics.drawRect(0,0,100,100);
thumbframe[i].graphics.endFill();
thumbframe[i].y = row;
thumbframe[i].x = column;
loaderArray[i] = new Loader();
loaderArray[i].load(new URLRequest(photos[i].text()));
trace(loaderArray[i].height);
var index = i+1;
container_mc.addChild(thumbframe[i]);
if (index%5 == 0) {
row=row+120;
column = 0;
} else {
column=column+120;
}
thumbframe[i].addChild(loaderArray[i]);
}
}
genThumb();
}
Both the loaders and the containers are in respective arrays. The images load correctly, but I am at a loss for how to scale them (ultimately I'd like to integrate a tween to animate as they load as well if possible.)
Thanks in advance for any aid!
You look like you need to scale your bitmaps into a 100x100 square. You'll need to wait until the loader has completed loading to do that because until then you won't know what the dimensions of the item are.
When you create your loader, add an event listener, like this:
loaderArray[i].contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
and then add this function:
function onLoadComplete(event:Event):void
{
var info:LoaderInfo = LoaderInfo(event.currentTarget);
info.removeEventListener(Event.COMPLETE);
var loader:Loader = info.loader;
var scaleWidth:Number = 100 / loader.width;
var scaleHeight:Number = 100 / loader.height;
if (scaleWidth < scaleHeight)
loader.scaleX = loader.scaleY = scaleWidth;
else
loader.scaleX = loader.scaleY = scaleHeight;
}
This may be a bit complicated, but all it really does is clean up the event listener that you had added, and find the dimensions of the loader (which it can get now because it's finished loading), and scale the loader appropriately.
If you need it to be centered within your thumbnail, add this to the bottom of the onLoadComplete method:
loader.x = (100 - loader.width) * 0.5;
loader.y = (100 - loader.height) * 0.5;
or you need it to take up the whole thumbnail and cut off the edges, change it to this (the inequality is the other-way around)
if (scaleWidth > scaleHeight)
loader.scaleX = loader.scaleY = scaleWidth;
else
loader.scaleX = loader.scaleY = scaleHeight;
and add this:
var shape:Shape = new Shape();
var g:Graphics = shape.graphics;
g.beginFill(0x00FF00);
g.drawRect(0, 0, 100, 100);
g.endFill();
loader.mask = g;
I haven't tested this, so there may be a few glitches, but hopefully it gives you the right idea.