AS3: Error 1009: Null reference - actionscript-3

I am making a game in ActionScript 3. I have a Menu Class with a method that renders a Menu.
I make an instance of Menu in my Main class, and then call the method. When I debug the application I get a null reference error. This is the code of the menu class:
package
{
import flash.display.MovieClip;
import menucomponents.*;
public class Menu extends MovieClip
{
public function Menu()
{
super();
}
public function initMenuComponents():void{
var arrMenuButtons:Array = new Array();
var btnPlay:MovieClip = new Play();
var btnOptions:MovieClip = new Options();
var btnLikeOnFacebbook:MovieClip = new LikeOnFacebook();
var btnShareOnFacebook:MovieClip = new ShareOnFacebook()
arrMenuButtons.push(btnPlay);
arrMenuButtons.push(btnOptions);
arrMenuButtons.push(btnLikeOnFacebbook);
arrMenuButtons.push(btnShareOnFacebook);
var i:int = 0;
for each(var item in arrMenuButtons){
item.x = (stage.stageWidth / 2) - (item.width / 2);
item.y = 100 + i*50;
item.buttonMode = true;
i++;
}
}
}
}
Thanks in advance.

Your issue is likely that stage is not populated yet when your for loop runs. Try the following:
public class Main extends MovieClip {
public function Main() {
super();
var menu:Menu = new Menu();
//it's good practice - as sometimes stage actually isn't populated yet when your main constructor runs - to check, though in FlashPro i've never actually encountered this (flex/flashBuilder I have)
if(stage){
addedToStage(null);
}else{
//stage isn't ready, lets wait until it is
this.addEventListener(Event.ADDED_TO_STAGE,addedToStage);
}
}
private function addedToStage(e:Event):void {
menu.addEventListener(Event.ADDED_TO_STAGE,menuAdded); //this will ensure that stage is available in the menu instance when menuAdded is called.
stage.addChild(menu);
}
private function menuAdded(e:Event):void {
menu.initMenuComponents();
}
}

Related

How to define that a child should only appear in one scene?

We are making an space impact game. Here are 3 of our classes. Our problem is that when we create our InimigoNoite, they appear all over the game(menus, other levels, etc), instead of only appearing in the Scene that we want. How should we restrict the child to only appear in the CenárioCidade?
We've tried to use gotoandPlay, addChildAt, and also tried to create the Inimigo not in the Main class, but in the Inimigo class itself, but it doesnt appear at all. Please can someone help us? Thank you very much!
KEY.as
package {
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;
public class Key {
private static var initialized:Boolean = false;
private static var keysDown:Object = new Object();
public static function initialize(stage:Stage) {
if (!initialized) {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.DEACTIVATE, clearKeys);
initialized = true;
}
}
public static function isDown(keyCode:uint):Boolean
{
return Boolean(keyCode in keysDown);
}
private static function keyPressed(event:KeyboardEvent):void {
keysDown[event.keyCode] = true;
}
private static function keyReleased(event:KeyboardEvent):void {
if (event.keyCode in keysDown) {
delete keysDown[event.keyCode];
}
}
private static function clearKeys(event:Event):void {
keysDown = new Object();
}
}
}
INIMIGO NOITE.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class InimigoNoite extends MovieClip{
var speed:Number;
static var list:Array = new Array();
var balaTimer: Timer;
function InimigoNoite(){
list.push(this);
this.x = 1160;
this.y = 150 + (450-150) * Math.random();
speed = Math.random()*5 + 5;
addEventListener("enterFrame", enterFrame);
var intervalo: Number = Math.random()*500 + 1000;
balaTimer = new Timer(intervalo);
balaTimer.addEventListener("timer", bala);
balaTimer.start();
}
function enterFrame (e:Event){
this.x -= speed;
if(this.x < -100){
matar();
return;
}
if(this.hitTestObject(SpaceImpact.navecnoite)){
matar();
}
}
function matar(){
var explosao = new ExplosaoNoite();
stage.addChild(explosao);
explosao.x = this.x;
explosao.y = this.y;
balaTimer.stop();
balaTimer.removeEventListener("timer",bala);
removeEventListener("enterFrame", enterFrame);
stage.removeChild(this);
for(var i in list){
if(list[i] == this){
delete list[i];
}
}
}
function bala(e:Event){
var b = new BalaInimigo();
b.x = this.x -50;
b.y = this.y;
stage.addChild(b);
}
}
}
MAIN.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class SpaceImpact extends MovieClip{
static var navecnoite:MovieClip;
var inimigoNoiteTimer:Timer;
function SpaceImpact(){
Key.initialize(stage);
inimigoNoiteTimer = new Timer(8000);
inimigoNoiteTimer.addEventListener("timer", criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
var inimigo = new InimigoNoite();
stage.addChild(inimigo);
addChildAt(inimigo, 3);
}
}
}
You never stop the timer. So your inimigo is created and added every 8seconds.
Stop the timer in criaInimigo and/or use the timerComplete Event
function SpaceImpact(){
Key.initialize(stage);
inimigoNoiteTimer = new Timer(8000,1);
inimigoNoiteTimer.addEventListener(TimerEvent.TIMER_COMPLETE, criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
//inimigoNoiteTimer.stop();//only needed if you use the 'timer'-Event
var inimigo = new InimigoNoite();
stage.addChild(inimigo);
addChildAt(inimigo, 3);
}
Right when you application starts, you are creating a new InimigoNoite every 8 seconds. Since you are adding them to the stage, they will appear over top anything you have on your timeline.
The issue (besides creating them when the application starts and never stopping your timer), is that when you through code use addChild, that child will stay on the screen until it's explicitly removed via removeChild (or one of it's parents are - but since the parent is stage that isn't going to happen).
I see that your have a hit test in the InimigoNoite class that can potentially remove it, but I don't see anywhere else where you remove it (so if the hit test never happens, it will never be removed from the stage regardless of scene).
It seem though that the solution to your problem is more advice on how to architect your application.
Don't use scenes.
Your best bet is to create a class file for each distinct state of your game. So something like this as a basic example:
Main Menu State
Game Play State(either 1 game state that encompasses all levels, or one state for each level - or both - depending on how much functionality changes between levels)
Game Over State
Make your game state class files extend Sprite or MovieClip, and if you want you can even create a new MovieClip in flash pro and attach the class to that (thereby being able to drop visual assets on the timeline).
So then your Main class would just be in charge of managing states (and any anything else that is global to the application)
package{
import flash.display.MovieClip;
import flash.events.Event;
public class SpaceImpact extends MovieClip {
private var menu:Menu; //Assumes you have a Menu.as class file
private var game:MainGame; //MainGame.as file
private var gameOver:GameOver; //GameOver.as file
public function SpaceImpact(){
Key.initialize(stage);
goMenu();
}
public function goMenu(e:Event = null):void {
removeAll();
menu = new Menu();
addChild(menu);
menu.addEventListener(Event.COMPLETE, startGame,false,0,true);
}
private function removeMenu():void {
if(menu){
if(menu.parent) removeChild(menu); //remove it from the screen
menu = null;
}
}
public function startGame(e:Event = null):void {
removeAll();
game = new MainGame();
addChild(game);
game.addEventListener(Event.COMPLETE, gameOver,false,0,true);
}
private function removeGame():void {
if(game){
if(game.parent) removeChild(game); //remove it from the screen
game = null;
}
}
public function gameOver(e:Event = null):void {
removeAll();
gameOver = new GameOver();
addChild(gameOver);
gameOver.addEventListener(Event.COMPLETE, goMenu,false,0,true);
}
private function removeGameOver():void {
if(gameOver){
if(gameOver.parent) removeChild(gameOver); //remove it from the screen
gameOver = null;
}
}
private function removeAll():void {
removeGameOver();
removeMenu();
removeGame();
}
}
}
then, your game state for example:
MainGame.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class MainGame extends MovieClip {
private var inimigoNoiteTimer:Timer;
public function MainGame() {
this.addEventListener(Event.ADDED_TO_STAGE, addedToStage, false, 0, true); //don't do anything until this object has been added to the screen
}
private function addedToStage(e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
//start spawning
inimigoNoiteTimer = new Timer(8000);
inimigoNoiteTimer.addEventListener("timer", criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
var inimigo = new InimigoNoite();
addChild(inimigo);
}
//when whatever happens that makes your game finished
function gameComplete():void {
dispatchEvent(new Event(addEventListener.COMPLETE));
}
}
}

Accessing timeline objects from a class, giving null object reference?

All late comers this question in still active a answer is not yet reached, what you might see below is a irrelevent syntax error a nice member found for me
error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Player()
at Maintest_fla::MainTimeline/createPlayer()
When i'm attempted to add the instance name wall0x objects that are in the object with the instance name world, I find that I get a null object error.
Also ignore the long list of variables, not relevant.
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.filters.BlurFilter;
import flash.utils.Timer;
public class Player extends MovieClip
{
// player settings
private var _rotateSpeedMax:Number = 20;
public var _gravity:Number = .10;
// projectile gun settings
public var _bulletSpeed:Number = 4;
public var _maxDistance:Number = 200;
public var _reloadSpeed:Number = 250;//milliseconds
public var _barrelLength:Number = 20;
public var _bulletSpread:Number = 5;
// gun stuff
private var _isLoaded:Boolean = true;
private var _isFiring:Boolean = false;
private var _endX:Number;
private var _endY:Number;
private var _startX:Number;
private var _startY:Number;
private var _reloadTimer:Timer;
private var _bullets:Array = [];
// array that holds walls
public var _solidObjects:Array = [];
//
private var _player:MovieClip;
private var _dx:Number;
private var _dy:Number;
private var _pcos:Number;
private var _psin:Number;
public var _trueRotation:Number;
public function Player()
{
// constructor code //Right hereVVVthe instance name is wall0x and it's in the object world on the stage.
_solidObjects = [MovieClip(root).world.wall01,MovieClip(root).world.wall02,MovieClip(root).world.wall03,MovieClip(root).world.wall04];
/*addEventListener(Event.ENTER_FRAME, enterFrameHandler);
addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler);
addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);*/
}
}
}
Code I'm using in frame 2 create the player and then continuously set it's chords to another objects.
stage.addEventListener(Event.ENTER_FRAME, createPlayer);
function createPlayer(e:Event):void
{
// attach player movieclip from library
// position player in center
if (character!=null&&_player!=null)
{
_player.x = character.x + 5;
_player.y = character.y + 5;
}
else if (_player ==null && world.wall01 != null)
{
var _player:Player;
_player = new Player();
// add to display list
stage.addChild(_player);
}
}
First: You have a syntax error in these two lines:
_player.x = MovieClip.(root).character.x + 5;
_player.y = MovieClip.(root).character.y + 5;
There should not be a period after MovieClip, so it should look like this:
_player.x = MovieClip(root).character.x + 5;
_player.y = MovieClip(root).character.y + 5;
Second: You are always creating a new Player every frame. In your createPlayer method, you have the following conditional:
if(character != null && _player != null) //_player is not a defined in this scope, so it will either throw an error, or always return null/undefined
You do not have a _player var defined in the scope of that frame or the scope of the createPlayer method, you have defined it inside the scope of the else statement (which makes only available in the else statement)
Move the var _player:Player to the top of your timeline code with the other frame scoped vars.
Third: you are trying to access root in your Player constructor, the problem with this, is that when the contructor runs, your Player is not yet on the display tree, so root is null until you've added player to the stage.
example:
_player = new Player(); //this will run your contructor, but root will be null
stage.addChild(_player); //after this, your Player class will now have access to root/stage/parent object
Change your Player class so it listens for being ADDED_TO_STAGE before trying access root.
public function Player()
{
this.addEventListener(Event.ADDED_TO_STAGE, init);
// constructor code
}
private function init(e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, init);
_solidObjects = [MovieClip(root).world.wall01,MovieClip(root).world.wall02,MovieClip(root).world.wall03,MovieClip(root).world.wall04];
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler);
addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);
}

Flash AS3 Error: 1013: The private attribute may be used only on class property definitions

C:\Users\Lab3project\MainDocument.as, Line 103, Column 7 1013: The
private attribute may be used only on class property definitions.
The lines of code concerned:
package {
//these are flash built-in classes
import flash.display.MovieClip;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.events.Event;
//Our own custom class
import MainTimer;
public class MainDocument extends MovieClip{
private var gameTimer:MainTimer;
private var thePlayer:Player;
private var theEnemy:Enemy;
private var maxEnemies: int = 3;
private var e:int = 0;
private var childrenOnStage:int;
public function MainDocument() {
// constructor code
trace("the main document is alive");
// new instance MainTimer class
gameTimer = new MainTimer();
// must add it to the stage
addChild(gameTimer);
//adjust its postion on stage
gameTimer.x = 20;
gameTimer.y = 20;
//add the player
thePlayer = new Player();
addChild(thePlayer);
// adjust its postion on the stage
thePlayer.x = stage.stageWidth * 0.5;
//assign the name property
thePlayer.name = "player";
while(e < maxEnemies){
createEnemy();
e++;
} //end while
//Update this variable every time a child is added to the stage
childrenOnStage = this.numChildren
// Add event listener to control timing of main game loop
addEventListener(Event.ENTER_FRAME,mainGameLoop);
}//end function MainDocument
private function createEnemy():void{
trace("create enemy");
theEnemy = new Enemy();
addChild(theEnemy);
//Place in a random spot on stage
theEnemy.x = (Match.random() * stage.stageWidth);
theEnemy.y = 0;
//assign the name property
theEnemy.name = "enemy";
//Update this variable every time a child is added to the stage
childrenOnStage = this.numChildren
} //end function createEnemy
//the main loop for the game
private function mainGameLoop(event:Event): void{
checkForGameReset();
processCollisions();
scrollStage();
} // end functiom mainGameLoop
private function checkForGameReset():void{
//define conditions
} //end function checkForGameReset
private function processCollisions():void{
//set up the main loop to look through all collidale objects on stage
for(var c:int;c < childOnStage;c++){
//trace ("Child on stage c= " + c +
//test for a player of enemy child on stage
if (getChildAt(c).name == "player" || getChildAt(c).name == "enemy"){
//see if object is touching the game stage
if( theGameStage.hitTestPoint(getChildAt(c).x, getChildAt(c).y,true)){
//while it is still touching the game stage
while( theGameStage.hitTestPoint(getChildAt(c).x, getChildAt(c).y,true)==true){
//called from CollisionObject class,so force the connection
CollisionObject(getChildAt(c)).incrementUpward();
if( theGameStage.hitTestPoint(getChildAt(c).x, getChildAt(c).y,true)==false){
}CollisionObject(getChildAt(c)).keepOnBoundary(); //make it stick
} // end if
} // end while
} //end if touching
} //end if player or enemy
} //end for loop
} //end function processCollisions
The lines of code concerned: is here where im getting the error
private function scrollStage(): void
{
// figure out logic
}
// end function scrollStage
//add the enemy for testing
theEnemy = new Enemy();
addChild(theEnemy);
// adjust its postion on the stage
theEnemy.x = stage.stageWidth * 0.5;
theEnemy.y = 200;
} // end public function MainDocument
} // end public class
} // end package
After I have change that code ,it then says I have a extra character at the end but the characters I have to have at the end.
Problems like this often occur because of a slight typo in syntax. Perhaps you have accidentally declared your private function within another function?
public function doSomething() {
//a whole bunch of stuff
//then we forget to close the function with a brace "}"
private function scrollStage() {
//but we're still defining doSomething! Throw error!
}
Go and look for errors like this, and hopefully you can find the problem.

Actionscript 3 Call to a possibly undefined method

Here is the problem, the object is moved together with the clicked object. I want it to be moveable following the mouse pointer, but let the clicked object stays. so when an object is clicked, there will be 2 objects in the stage(the static and moving one).
I think I've figured it out by adding a new object to be moved. in function onClickHero I've tried movingHero = new heroes but it says "call to a possibly undefined method heroes". My question is there any other way how to make another clone of the clicked object since I made it in array? And why does movingHero = new heroes doesn't work?
I'm still amateur at classes. Sorry if it's messed up. Thanks for helping.
package {
import flash.display.MovieClip
import flash.events.MouseEvent
import flash.events.Event
import flash.display.Sprite
public class Hero {
private var heroesArray:Array;
private var heroContainer:Sprite = new Sprite;
private var hero1:MovieClip = new Hero1();
private var hero2:MovieClip = new Hero2();
private var moveHero:Boolean = false;
private var movingHero:MovieClip;
private var _money:Money = new Money();
private var _main:Main;
public function Hero(main:Main)
{ _main = main;
heroesArray = [hero1,hero2];
heroesArray.forEach(addHero);
}
public function addHero(heroes:MovieClip,index:int,array:Array):void
{
heroes.addEventListener(Event.ENTER_FRAME, playerMoving);
heroes.addEventListener(MouseEvent.CLICK, chooseHero);
}
public function playerMoving(e:Event):void
{
if (moveHero == true)
{
movingHero.x = _main.mouseX;
movingHero.y = _main.mouseY;
}
}
public function chooseHero(e:MouseEvent):void
{
var heroClicked:MovieClip = e.currentTarget as MovieClip;
var cost:int = _main._money.money ;
if(cost >= 10 && moveHero == false)
{
_main._money.money -= 10;
_main._money.addText(_main);
onClickHero(heroClicked);
moveHero = true;
}
}
public function onClickHero(heroes:MovieClip):void
{
movingHero = heroes;
heroContainer.addChild(movingHero);
}
public function displayHero(stage:Object):void
{
stage.addChild(heroContainer);
for (var i:int = 0; i<2;i++)
{
stage.addChild(heroesArray[i]);
heroesArray[i].x = 37;
heroesArray[i].y = 80+i*70;
heroesArray[i].width=60;
heroesArray[i].height=55;
heroesArray[i].buttonMode = true;
}
}
}
}
EDIT: I've tried to make movingHero = new Hero1(); but since I don't know which hero will be clicked so I can't just use Hero1 from library. and If I use movingHero = heroClicked I only get the value of hero1 which is a var from Hero1 movieclip. So, is there any way to call the movie clip from library the same as which hero was clicked in stage?
You seemingly want to clone an object while not knowing its type. If that object also containg game logic, it's not the best idea to say spawn new heroes of either type, this might make a mess of your code. But if not, you can get the exact class of the object given, and make an object of that class via the following code:
public function onClickHero(heroes:MovieClip):void
{
if (!heroes) {
trace('heroes is null!');
return;
}
var heroClass:Class = getDefinitionByName(getQualifiedClassName(heroes)) as Class;
movingHero = new heroClass(); // instantiate that class
heroContainer.addChild(movingHero);
// movingHero.startDrag(); if needed
}
Don't forget to clean up the movingHero once it's no longer needed.

AS3 Scrolling Movieclip

I have a problem with my code whereby I have a spawned vertical movieclip where there are button instances in it which makes it look like a list.
The problem is that I am trying to recreate a iOS-style drag scrolling. When I hold and drag my movieclip, it works fine, scrolling up and down. But when I release my left mouse button, It registers a click on one of my buttons.
I tried to remove the event listeners on the buttons but the scrolling only works once, after I released my left mouse button, the whole scrolling does not work the second time.
Is it possible to have maybe like a mouse drag (up or down) ignoring the button click listeners however when the user want to click the button instead, the scrolling won't kick in?
My buttons' class
public function PlaceOneButtons()
{
for (var a=0; a<buttons.length; a++)
{
stationsone1[a].addEventListener(clicked,StationSelectOne);
stationsone2[a].addEventListener(clicked,StationSelectOne);
stationsone3[a].addEventListener(clicked,StationSelectOne);
stationsone4[a].addEventListener(clicked,StationSelectOne);
stationsone5[a].addEventListener(clicked,StationSelectOne);
}
}
My Main (spawner) class
package
{
import flash.display.MovieClip;
import flash.display.*;
import flash.text.*;
import flash.events.*;
import flash.ui.*;
import flash.utils.*;
import flash.media.*;
import IconSpawn;
import Scrolling;
public class MainClass extends MovieClip
{
private var iconspawn:IconSpawn = new IconSpawn();
private var touchay:int = new int;
private var touchPoint:int = new int;
private var touchPoint2:int = new int;
private var touchString:int = new int;
private var AYint:int = new int;
private var touchTimer:Timer = new Timer(150,1);
private var endTime:Timer = new Timer(1,1);
private var speed:int = new int;
public static var scrollDiff:int = new int;
public static var doubleDiff:int = new int;
public static var dragging:Boolean = new Boolean
//private var scrolling:Scrolling = new Scrolling();
//public static var Ystore:Point;
public function MainClass()
{
// constructor code
AYint = IconSpawn.A_Y.y;
}
public function startApp()
{
addChild(iconspawn);
iconspawn.MenuSpawn();
dragging = false;
}
public function directionsApp()
{
addChild(iconspawn);
iconspawn.KeyboardOne();
}
public function placeOneApp()
{
addChild(iconspawn);
iconspawn.PlaceOneSpawn();
Evtlistener();
}
private function Evtlistener()
{
addEventListener(Event.ENTER_FRAME,update);
addEventListener(MouseEvent.MOUSE_DOWN,spawnTouch);
addEventListener(MouseEvent.MOUSE_UP,endScroll);
}
public function directionsApp2()
{
addChild(iconspawn);
iconspawn.KeyboardTwo();
}
public function update(evt:Event)
{
//trace(touchTimer);
//trace(touchString);
touchPoint2 = mouseY;
scrollDiff = touchPoint2 - touchPoint;
doubleDiff = scrollDiff - scrollDiff;
trace(dragging);
if(dragging == true)
{
//iconspawn.PlaceOneButtons();
}
}
public function spawnTouch(evt:MouseEvent)
{
touchPoint = mouseY;
touchTimer.addEventListener(TimerEvent.TIMER,timerTouch);
endTime.addEventListener(TimerEvent.TIMER,endTimer);
touchTimer.start();
dragging = true;
touchay = IconSpawn.A_Y.y;
}
public function timerTouch(evt:TimerEvent):void
{
if(dragging == true)
{
addEventListener(Event.ENTER_FRAME,startScroll);
}
}
public function startScroll(evt:Event)
{
if(mouseY > 540 && mouseY < 1510)
{
IconSpawn.A_Y.y = touchay + (touchPoint2 - touchPoint);
}
}
public function endScroll(evt:MouseEvent)
{
removeEventListener(MouseEvent.MOUSE_DOWN,spawnTouch);
removeEventListener(Event.ENTER_FRAME,startScroll);
touchTimer.reset();
endTime.start();
}
private function endTimer(evt:TimerEvent):void
{
dragging = false;
Evtlistener();
}
}
}
Help will be appreciated! Have been stuck at this problem for days now.
UPDATE: Added new updated code
Hi guys, now my problem is that after I scroll my movieclip, the code will listen out for scrollDiff if its = 0.
When scrollDiff is 0, the buttons of the movieclip is clickable but if its more or less than that, the buttons are not clickable. Now my new problem is that after I release my left click, the code does not update the scrollDiff to 0, so user have to double click to select the button. Help!
package
{
import flash.display.MovieClip;
import flash.display.*;
import flash.text.*;
import flash.events.*;
import flash.ui.*;
import flash.utils.*;
import flash.media.*;
import IconSpawn;
import Scrolling;
public class MainClass extends MovieClip
{
private var iconspawn:IconSpawn = new IconSpawn();
private var touchPoint:int = new int;
private var touchPoint2:int = new int;
private var AYint:int = new int;
private var touchTimer:Timer = new Timer(150,1);
private var endTimer:Timer = new Timer(150,1);
private var IconSpwnY:int = new int;
private var touchbool:Boolean = new Boolean
public static var scrollDiff:int = new int;
//private var scrolling:Scrolling = new Scrolling();
//public static var Ystore:Point;
public function MainClass()
{
// constructor code
}
public function startApp()
{
addChild(iconspawn);
iconspawn.MenuSpawn();
}
public function directionsApp()
{
addChild(iconspawn);
iconspawn.KeyboardOne();
}
public function placeOneApp()
{
AYint = IconSpawn.A_Y.y;
addChild(iconspawn);
iconspawn.PlaceOneSpawn();
addEventListener(Event.ENTER_FRAME,update);
addEventListener(MouseEvent.MOUSE_DOWN,spawnTouch);
addEventListener(MouseEvent.MOUSE_UP,endScroll);
touchbool = false;
//IconSpawn.container.mouseChildren = true;
}
public function directionsApp2()
{
addChild(iconspawn);
iconspawn.KeyboardTwo();
}
public function update(evt:Event)
{
touchPoint2 = mouseY;
scrollDiff = touchPoint2 - touchPoint;
trace(scrollDiff);
}
public function spawnTouch(evt:MouseEvent)
{
touchPoint = mouseY;
touchTimer.addEventListener(TimerEvent.TIMER,timerTouch);
touchTimer.start();
IconSpwnY = IconSpawn.A_Y.y;
if(scrollDiff == 0)
{
IconSpawn.container.mouseChildren = true; //Important <-
}
else
{
IconSpawn.container.mouseChildren = false; //Important <-
}
}
public function timerTouch(evt:TimerEvent):void
{
addEventListener(Event.ENTER_FRAME,startScroll);
touchbool = true
}
public function startScroll(evt:Event)
{
if(mouseY > 0 && mouseY < 1510)
{
IconSpawn.A_Y.y = IconSpwnY + (touchPoint2 - touchPoint);
}
}
public function endScroll(evt:MouseEvent)
{
removeEventListener(MouseEvent.MOUSE_DOWN,spawnTouch);
removeEventListener(Event.ENTER_FRAME,startScroll);
endTimer.addEventListener(TimerEvent.TIMER,endTiming);
endTimer.start();
trace("CALLL")
scrollDiff = touchPoint2 - touchPoint;
//touchTimer.reset();
}
private function endTiming(evt:TimerEvent)
{
IconSpawn.container.mouseChildren = true;
addEventListener(MouseEvent.MOUSE_DOWN,spawnTouch);
//addEventListener(Event.ENTER_FRAME,startScroll);
scrollDiff = 0;
}
}
}
While you're moving set <container_mc>.mouseChildren = false. When the container clip stops moving, set the mouseChildren property to 'true'.
Adding to Craig's answer (which I definitely recommend implementing, to make life easier!), here is the list of the event listeners you should have hooked up for this to work as planned. This is theory, so you may have to play around with it a bit.
container.addEventListener(MouseEvent.MOUSE_DOWN, response);: You'll want to raise some sort of flag that the mouse is down, and wait for the next mouse event, which determines the action.
container.addEventListener(MouseEvent.MOUSE_MOVE, response);: If the mouse is down, disable child clicking (Craig's answer) and initiate dragging. You'll also want to raise a dragging flag.
container.addEventListener(MouseEvent.MOUSE_UP, response);: If the dragging flag is raised, stop drag and enable child clicking. If it isn't raised, do nothing, so the item can take over from there.
item.addEventListener(MouseEvent.MOUSE_UP, itemResponse);: Your click action.
Theoretically, this should work fine with your nested MovieClips, as long as you use MouseEvent.MOUSE_UP as the listener on them (as shown above). Using MouseEvent.MOUSE_DOWN or MouseEvent.CLICK may mess your timing up. However, I'd experiment a bit to find the right combination, as I could be wrong on that last point.