AS3 - how to get mouse events on embedded bitmaps? - actionscript-3

I'm embedding an image, creating a grid, and trying to cast each embedded image as a DisplayObject so I can use MouseEvents on each image in the grid, however, I can't get a mouseEvent to work. Any help is greatly appreciated. I think I'm missing something simple perhaps.
public class ImageGrid extends Sprite
{
private var gridItems:Array;
private var grid:Sprite;
private var sprite:Sprite
private var reveals:uint = 0;
private var exceededNumReveals:SimpleText;
[Embed(source="../Assets/images/tile-grad5-108.png")]
public var imgCls:Class;
public function ImageGrid(tileSize:Number, numTiles:Number, rows:Number)
{
gridItems = new Array();
grid = new Sprite();
addChild(grid);
for (var i:int = 0; i < numTiles; i++) {
gridItems[i] = new imgCls() as DisplayObject;
trace(gridItems[i] is DisplayObject) //true
gridItems[i].rotation = 180
gridItems[i].x = (i % rows) * (tileSize)
gridItems[i].y = int(i / rows) * (tileSize)
gridItems[i].addEventListener(MouseEvent.CLICK, gridItemClick, false, 0, false);
grid.addChild(gridItems[i]);
}
}
private function gridItemClick (event:MouseEvent):void {
trace(event.currentTarget);
reveals ++
if (reveals < AssetManager.numReveals) {
TweenLite.to(event.currentTarget, 0.5, {y:900,rotation:Math.random() * 360, ease:Sine.easeOut});
} else {
exceededNumReveals = new SimpleText ('You have exceeded your number of reveals', false, false, null, true, true, false, null, null, 20, 'right');
exceededNumReveals.y = this.y + 300;
exceededNumReveals.x = this.x + 30;
addChild(exceededNumReveals)
}
}
}
}
Here is how I fixed it:
public function ImageGrid(tileSize:Number, numTiles:Number, rows:Number)
{
gridItems = new Array();
grid = new Sprite();
addChild(grid);
for (var i:int = 0; i < numTiles; i++) {
var imageHolder:Sprite = new Sprite()
gridItems[i] = new imgCls() as DisplayObject;
gridItems[i].rotation = 180
gridItems[i].x = (i % rows) * (tileSize)
gridItems[i].y = int(i / rows) * (tileSize)
imageHolder.addChild(gridItems[i]);
imageHolder.addEventListener(MouseEvent.CLICK, gridItemClick, false, 0, false);
grid.addChild(imageHolder);
}
}

Wrap them in an interactive object (MovieClip, Sprite, etc.) to add a Mouse Click Event to them. Bitmaps are not interactive objects.

bitmaps are not interactive objects, you will have to add the listener to the parent

Related

multiple buttons not being able to set off different things

To clarify, the button is NOT a user interface element. It is an in-game object.
Here's a picture of the issue : It shows my main problem; I pressed the button that's circled, but it activated the one on the right.
I'm making a game where you have to complete 10 "chambers" of varying difficulty.
I have currently finished the first level and while finishing up I found an annoying bug I cant seem to fix.
If I have two buttons on a map, it seems that no matter which button I press, it will always do whatever the last one put on the map is going to do.
Also, if one button is activated, the other can't be activated.
I'm using the flashpunk engine/library/whatever and AS3.
The button class:
package Sprites
{
import net.flashpunk.Entity;
import net.flashpunk.graphics.Tilemap;
import net.flashpunk.masks.Grid;
import net.flashpunk.*;
/**
* ...
* #author Brad
*/
public class Button extends Entity
{
public var _tiles:Tilemap
private var _grid:Grid
private var xa:Number
private var ya:Number
private var conTiles:Array
public function Button(xN:Number, yN:Number, tiles:Array)
{
xa = xN
ya = yN
conTiles = []
_tiles = new Tilemap(Assets.Switch, 640, 480, 32, 32)
graphic = _tiles;
layer = 1
conTiles = tiles
_tiles.setTile(xN, yN, 0)
_grid = new Grid(640, 480, 32, 32, 0, 0)
mask = _grid
_grid.setTile(xN, yN, true)
name = "Button"
type = "button"
}
public function Activate():void
{
var Activated:Boolean = false
if (!Activated)
{
for (var i:Number = 0; i < conTiles.length; i++)
{
trace("Hi!")
FP.world["map"]["_tiles"].setTile(conTiles[i].x, conTiles[i].y, 3)
FP.world["map"]["_grid"].setTile(conTiles[i].x, conTiles[i].y, false)
}
_tiles.setTile(xa, ya, 1)
Activated = true
}
else
trace("Activated already!")
}
}
}
How I put the buttons into the world:
public class World1 extends World
{
public var startPos:Object = {"x": 45, "y": 135}
public var player:Player = new Player(startPos["x"], startPos["y"])
public var button:Button = new Button(5, 6, [new Point(10, 10), new Point(10, 11)])
public var button2:Button = new Button(7, 6, [new Point(10, 10), new Point(10, 11)])
public var map:Map1 = new Map1()
public var finish:Finish = new Finish(14,2,"map1")
public function World1()
{
add(map)
add(finish)
add(button)
add(button2)
add(player)
player.layer = 0
for (var i2:Number = 0; i2 < 9; i2++)
add(new Wall3D(i2+1, 1))
for (var i3:Number = 0; i3 < 11; i3++)
add(new Wall3D(i3, 13))
trace("Hi!")
}
}

Actionscript3 Clone and Drag object over other

I am building a simple flash game where user can drag objects from a tool-box and drag over to an area. On dragging the object, I create a clone of that object and place it over the area. Here is my code that works somewhat fine..
package {
imports...
public class DocumentClass extends MovieClip {
//variables...
var someArray:Array = new Array();
var totalObjs = 5;
var objOnStage:Array = new Array();
var ogx;
var ogy;
public function DocumentClass() {
// constructor code
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
_width = stage.stageWidth;
_height = stage.stageHeight;
setGameObjects();
}//constructor close
//scaling Functions
public function scalingheight(clip:MovieClip, percent:Number){
var ratio = clip.width / clip.height;
clip.height = percent * _height;
clip.width = clip.height * ratio;
}
public function scalingwidth(clip:MovieClip, percent:Number){
var ratio = clip.height / clip.width;
clip.width = percent * _width;
clip.height = clip.width * ratio;
}
public function setGameObjects():void{
mc_toolbox = new mctoolbox;
addChild(mc_toolbox);
mc_toolbox.x = mc_toolbox.y = 0;
scalingwidth(mc_toolbox, 0.08);
mc_toolbox.height = _height;
mc_board = new mcboard;
addChild(mc_board);
mc_board.x = mc_toolbox.width;
mc_board.y = 0;
scalingwidth(mc_board, 0.75);
mc_board.height = _height;
mc_optbox = new mcoptbox;
addChild(mc_optbox);
scalingwidth(mc_optbox, 0.10);
mc_optbox.height = _height;
mc_optbox.x = _width - mc_optbox.width;
mc_optbox.y = 0;
setobjects();
}
public function setobjects():void{
for(var i = 1; i <= totalObjs; i++){
var className:String = "obj" + i;
var ClassReference:Class = getDefinitionByName(className) as Class;
var myInstance = new ClassReference;
addChild(myInstance);
scalingwidth(myInstance, 0.08);
someArray.push(myInstance);
myInstance.x = stage.stageWidth - 0.09 * _width;
myInstance.y = myInstance.height * (i-1);
}
for(var i = 1; i <= totalObjs; i++){
someArray[i-1].addEventListener(MouseEvent.MOUSE_DOWN, startMove);
someArray[i-1].addEventListener(MouseEvent.MOUSE_UP, stopMove);
}
}
function startMove(evt:MouseEvent):void {
//clone your movieclip here
ogx = evt.currentTarget.x;
ogy = evt.currentTarget.y;
evt.currentTarget.startDrag();
}
function stopMove(evt:MouseEvent):void {
var newobj = new evt.currentTarget.constructor;
addChild(newobj);
newobj.width = evt.currentTarget.width;
newobj.height = evt.currentTarget.height;
newobj.x = evt.currentTarget.x;
newobj.y = evt.currentTarget.y;
evt.currentTarget.x = ogx;
evt.currentTarget.y = ogy;
evt.currentTarget.stopDrag();
objOnStage.push(newobj);
}
}//class close
}//package close
My problem arises when I drag one object on the area and then I drag one more on the previous object. In such case the mouse up event is not called and hence the object movieclip does not clone itself. I think I am making some silly mistake, please guide.
I got this solved. The second movieclip came behind the first so I just brought it in front of all other movieclips while dragging using this
function startMove(evt:MouseEvent):void {
//clone your movieclip here
ogx = evt.currentTarget.x;
ogy = evt.currentTarget.y;
var myobj = evt.currentTarget as DisplayObject;
setChildIndex(myobj, numChildren - 1); // < The solution
evt.currentTarget.startDrag();
}
Try, removing MouseEvent.MOUSE_UP after dropping the object on the stage like so,
evt.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, stopMove);

Child not added, when check index it shows -1

I am not sure why i addedChild but when i check it's index it still shows -1.
What i am trying to do is:
1.)Loop a URLRequest and load bitmap pictures.
2.)Put them in individual _contentHolder
3.)Put everything in a viewport
4.)Check the index of the image when its clicked
5.)Display just the picture that is clicked(With a black background) (Picture viewer)
6.)When the picture or background is clicked again, it closes the "picture viewer"(The single picture with black background), and just display the list from before.
At the moment i can upload the pictures in a loop, then add them into a viewport, but i can not managed to get the index of the image and reload it.
Thanks for your time!
Code:
public var _contentHolder:Sprite = new Sprite;
public var _contentHolder1:Sprite;
public var loadedArray:Array = new Array;
public var blackBox:Sprite = new Sprite();
private var somedata:Array;
protected var Holder:Listing9 = new Listing9;
public var viewport:Viewport = new Viewport();
public var scroller:TouchScroller = new TouchScroller();
var my_url:Array = somedata;
function loadImage():void
{
somedata = SearchVectorTest.lists;
for (var i:int = 5; i < somedata.length; i++)
{
if (somedata[i])
{
var loader:Loader = new Loader();
loader.load(new URLRequest("http://www.rentaid.info/rent/" + somedata[i]));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
}
}
}
function onImageLoaded(e:Event):void
{
loadedArray.push(e.currentTarget.loader.content as Bitmap);
for (var i:int = 0; i < loadedArray.length; i++)
{
var currentY1:int = 200;
e.currentTarget.loader.content.height = 200;
e.currentTarget.loader.content.y += currentY1;
currentY1 += e.currentTarget.loader.content.height + 300;
_contentHolder.mouseChildren = false; // ignore children mouseEvents
_contentHolder.mouseEnabled = true; // enable mouse on the object - normally set to true by default
_contentHolder.useHandCursor = true; // add hand cursor on mouse over
_contentHolder.buttonMode = true;
_contentHolder.addChild(loadedArray[i]);
}
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);
_contentHolder.addEventListener(MouseEvent.CLICK, gotoscene);
}
loadImage();
public function gotoscene(e:MouseEvent):void
{
var searchString = loadedArray;
var index:Number;
index = searchString.indexOf(e.target);
trace(index);
trace(_contentHolder);
trace(_contentHolder.parent);
blackBox.graphics.beginFill(0x000000);
blackBox.graphics.drawRect(-1, -1, stage.width, stage.height);
blackBox.alpha = 0.7;
addChild(blackBox);
Holder.height = 300;
Holder.width = stage.width;
Holder.x = 0;
Holder.y = 100;
trace(blackBox);
trace(blackBox.parent);
addChild(Holder);
}
function gotoscene1(e:MouseEvent):void
{
removeChild(Holder);
removeChild(blackBox);
}
The indexOf you are using strict equality (===). e.target is of type Sprite and your array is filled with Bitmaps.
The strict equality will fail because the objects are not of the same type.
You need to use items of the same type to make the comparison succeed.

AS3 - removeEventListener(ADDED_TO_STAGE)

I'm having some problems with trying to remove Event.ADD_TO_STAGE basically in this game ive developed once the lives is less than or equal to zero the game will end and switch to the game over screen however when I do that it kicks back with this error.
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::DisplayObjectContainer/removeChild()
at States/changeState()
at AvoiderGame/onTick()
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
This then turns into..
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Enemy/StayOnScreen()
at AvoiderGame/onTick()
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
I'm not entirely sure why - could anyone clarify why it does and how I could fix it?
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.Event;
import flash.events.TimerEvent;
import com.freeactionscript.CollisionTest;
import flash.display.Stage;
public class AvoiderGame extends MovieClip
{
var theCallBackFunction:Function;
public static var enemyArray:Array;
public var enemy:Enemy
public var Background:gameBackground;
public var Lives:Number = 3;
public var avatar:Avatar;
public var gameTimer:Timer;
private var _collisionTest:CollisionTest;
private var numStars:int = 80;
private var fireTimer:Timer; //causes delay between fires
private var canFire:Boolean = true; //can you fire a laser
public function AvoiderGame(callBack)
{
this.addEventListener(Event.ADDED_TO_STAGE, init);
theCallBackFunction = callBack;
}
private function init(e:Event):void
{
Background = new gameBackground();
addChild(Background);
enemyArray = new Array();
avatar = new Avatar(stage);
addChild(avatar);
avatar.x = stage.stageWidth / 2;
avatar.y = stage.stageHeight / 2;
_collisionTest = new CollisionTest();
gameTimer = new Timer(25);
gameTimer.addEventListener(TimerEvent.TIMER, onTick);
gameTimer.start();
for (var i:int = 0; i < numStars; i++)
{
stage.addChildAt(new Star(stage), 1);
}
fireTimer = new Timer(1000, 1);
fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true);
fireTimer.start();
}
public function onTick(timerEvent:TimerEvent):void
{
if (Math.random() < 0.1)
{
trace('array length: ', AvoiderGame.enemyArray.length);
enemy = new Enemy(Math.round(1 + (500 - 1) * Math.random()), - 28, stage);
enemyArray.push(enemy);
addChild(enemy);
enemy.gotoAndStop("Enemy" + Math.round(1 + (5 - 1) * Math.random()))
}
canFire = avatar.UpdateAvatar(canFire);
if (canFire == false)
{
fireTimer.start();
}
avatar.StayOnScreen();
for each (var enemy:Enemy in enemyArray)
{
enemy.moveDown();
enemy.StayOnScreen();
if (_collisionTest.complex(enemy, avatar))
{
gameTimer.stop();
for each (var enemy:Enemy in enemyArray)
{
for(var i:int = 0; i < enemyArray.length; i++)
{
removeChild(enemyArray[i]);
enemyArray.splice(i, 1); //remove the i'th element as i'th element is the enemy containing the ID of hit enemy
}
}
Lives--;
trace('lives: ', Lives);
gameTimer.start();
}
}
if (Lives == 0)
{
removeEventListener(Event.ADDED_TO_STAGE, init)
theCallBackFunction(this, "over");
}
}
private function fireTimerHandler(e:TimerEvent) : void
{
//timer ran, we can fire again.
canFire = true;
}
}
}
//use weak references so the listener can be disposed of if necessary
this.addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
private function init(e:Event):void {
//remove this now as we have added the object to the stage
this.removeEventListener(Event.ADDED_TO_STAGE, init);
//add a new listener that will fire when the object is removed from stage
this.addEventListener(Event.REMOVED_FROM_STAGE, reset, false, 0, true);
...
private function reset(e:Event):void {
//this function is called when the object has been removed from the stage
this.removeEventListener(Event.REMOVED_FROM_STAGE, reset);
//now make sure all timers and stopped and nulled if required
//as well as all objects removed from stage and nulled if required. e.g.
fireTimer.stop();
fireTimer = null;
enemyArray = [];
enemyArray = null;
enemy
removeChild(Background);
Background = null;
removeChild(avatar);
avatar = null;
gameTimer.stop();
gameTimer = null;
_collisionTest = null;
}
//NB. You are adding stars to the stage and have no way of referencing them to remove them.
for (var i:int = 0; i < numStars; i++)
{
stage.addChildAt(new Star(stage), 1);
}
//you might want to add them to an array so you can remove them.
var starArray = [];
for (var i:int = 0; i < numStars; i++)
{
var newStar:Star = new Star(stage);
stage.addChildAt(newStar, 1);
starArray.push(newStar);
}
Then to remove them:
for (var i:int = starArray.length; i > 0; i--)
{
stage.removeChild(starArray[starArray.length-1]);
}
starArray = [];
starArray = null;

Chess board interface. Cannot remove child. Any suggestions?

Hello
I am in the process of creating a chess board where you can move the pieces. Currently i am working on the rook and the coding is below. I know it is not elegant and probably the most inefficient code out there, but this is day 2 of my actionscript 3.0 life and i am kinda a beginner. Anyway, so the thing is, when you click the piece the code below figures out the possible ways to go. Then green squares appear at those places. You can then press those green squares and then the rook will move there.
Ok, now to the problem. The squares will not go away. I want them all to be deleted when i have clicked on one of them and the rook will move there.
I have tried removeChild(), but since that happens in a different function it does not work. So if you are so kind to look through the code and suggest a solution, your help is much appreciated.
Kind Regards Emile
https://picasaweb.google.com/109156245246626370734/Jun42011?authkey=Gv1sRgCMy4v_b01aikzAE&feat=directlink
import flash.display.Sprite
import flash.events.MouseEvent
import flash.text.TextField;
import flash.geom.Point;
import caurina.transitions.*
myPoint.addEventListener(MouseEvent.MOUSE_DOWN, startMove);
function startMove(evt:MouseEvent) {
var boxNum:int = Math.floor(myPoint.y/100)+1;
for (var i:int = 1; i <boxNum; i++) {
var box:Ball = new Ball();
box.x = myPoint.x;
box.y = myPoint.y - i * box.height;
addChild(box);
Tweener.addTween(box, {alpha:0.5});
box.buttonMode = true;
box.addEventListener(MouseEvent.ROLL_OVER, onOver,
false, 0, true);
box.addEventListener(MouseEvent.ROLL_OUT, onOut,
false, 0, true);
box.addEventListener(MouseEvent.MOUSE_DOWN, onclick);
}
var boxNum1:int = Math.floor((800-myPoint.y)/100)+1;
for (var i:int = 1; i <boxNum1; i++) {
var box1:Ball = new Ball();
box1.x = myPoint.x;
box1.y = myPoint.y + i * box.height;
addChild(box1);
Tweener.addTween(box1, {alpha:0.5});
box1.buttonMode = true;
box1.addEventListener(MouseEvent.ROLL_OVER, onOver,
false, 0, true);
box1.addEventListener(MouseEvent.ROLL_OUT, onOut,
false, 0, true);
box1.addEventListener(MouseEvent.CLICK, onclick);
}
var boxNum2:int = Math.floor(myPoint.x/100)+1;
for (var i:int = 1; i <boxNum2; i++) {
var box2:Ball = new Ball();
box2.x = myPoint.x - i * box.height;
box2.y = myPoint.y;
addChild(box2);
Tweener.addTween(box2, {alpha:0.5});
box2.buttonMode = true;
box2.addEventListener(MouseEvent.ROLL_OVER, onOver,
false, 0, true);
box2.addEventListener(MouseEvent.ROLL_OUT, onOut,
false, 0, true);
box2.addEventListener(MouseEvent.CLICK, onclick);
}
var boxNum3:int = Math.floor((800-myPoint.x)/100)+1;
for (var i:int = 1; i <boxNum3; i++) {
var box3:Ball = new Ball();
box3.x = myPoint.x + i * box.height;
box3.y = myPoint.y;
addChild(box3);
Tweener.addTween(box3, {alpha:0.5});
box3.buttonMode = true;
box3.addEventListener(MouseEvent.ROLL_OVER, onOver, false, 0, true);
box3.addEventListener(MouseEvent.ROLL_OUT, onOut, false, 0, true);
box3.addEventListener(MouseEvent.CLICK, onclick);
}
}
function onOver(evt:Event):void {
var box:MovieClip = MovieClip(evt.target);
addChild(box)
box.scaleX = box.scaleY = 1.1;
}
function onOut(evt:Event):void {
evt.target.scaleX = evt.target.scaleY = 1;
}
function onclick(Event:MouseEvent):void {
var xcod:int = Math.ceil(mouseX/100)*100-50;
var ycod:int = Math.ceil(mouseY/100)*100-50;
Tweener.addTween(myPoint, {x:xcod, y:ycod, time:1, transition:"linear"});
}
alxx's answer is correct, you wouldn't need to keep a special list for them. The other way you could do it, using an Array to save references, would look like this:
var boxes:Array = new Array();
function startMove(evt:MouseEvent):void {
...
var box:Ball = new Ball();
addChild(box);
boxes.push(box);
...
var box1:Ball = new Ball();
addChild(box1);
boxes.push(box1);
...
}
function onClick(evt:MouseEvent):void {
for each (var box:Ball in boxes) {
removeChild(box);
}
boxes = new Array();
}
You can put temporary highlights in separate Sprite. Then your board will looks as follows:
Stage children: base board, highlights, pieces, in that order.
When you need to remove highlights, you can iterate highlights' children with numChildren and getChildAt and call removeChild on each, you don't even need a special list for them.