Play movieClip before initialize - actionscript-3

So I have a custom preloader with 200 frames and the corresponding in Flex:
gotoAndStop(Math.ceil(e.bytesLoaded/e.bytesTotal*100));
So basically each procent is one frame in the movieClip. So when 100% the movie ends and application initializes.
How can I say for example so that when 100% don't start the app but play from frame 100-200 in the movieClip and then initialize the app?
Thanks,

How about adding an event listener when loading is complete, then displaying the MovieClip frame one after another from 100-200. When that is done, you can dispatch the complete event.
private var _currentFrame:int;
private function initComplete(e:Event):void
{
_currentFrame = 100;
addEventListener( Event.ENTER_FRAME, onEnterFrame );
}
private function onEnterFrame( e:Event ):void {
if ( _currentFrame < 200 ) {
_currentFrame++;
cp.gotoAndStop( _currentFrame );
} else {
removeEventListener( Event.ENTER_FRAME, onEnterFrame );
dispatchEvent(new Event(Event.COMPLETE));
}
}

Related

Collision detection: TypeError: Error #1009: Cannot access a property or method of a null object reference

I'm trying to make a game but I'm stuck at this point:
in my game you are supposed to evade balls who come in from the right and disappear left. When you hit a ball you'll be redirected to another screen.
Here's the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Evader/cleanUpObjects()
at Evader/update()
This is my code:
Evader.as (lines with the hyphens are the erroneous lines):
public class Evader extends MovieClip
{
public var penguin:Penguin;
private var objects:Array;
public function Evader()
{
initGame();
Mouse.hide();
objects = new Array();
addEventListener( Event.ENTER_FRAME, update );
//addEventListener( Event.ENTER_FRAME, hitObject );
}
private function initGame():void
{
penguin = new Penguin();
addChild( penguin );
}
private function update( event:Event ):void
{
if( Math.random() < 0.04 )
{
spawnObject();
}
//--------------------->cleanUpObjects();
}
private function cleanUpObjects():void
{
var currentObject:Object1;
for( var i:int = objects.length-1; i >= 0; i-- )
{
currentObject = objects[ i ];
//----------------------------->if( currentObject.x > stage.stageWidth )
{
removeChild( currentObject );
objects.splice( i, 1 );
}
}
}
private function spawnObject():void
{
var object1:Object1 = new Object1(penguin);
addChild( object1 );
objects.push( object1 );
}
/**
*private function hitObject(event:Event)
*{
* if (penguin.hitTestObject(object1))
* {
* Mouse.show();
* trace("geraakt!");
* removeEventListener( Event.ADDED_TO_STAGE, init );
* removeEventListener( Event.ENTER_FRAME, update );
* removeEventListener( Event.ENTER_FRAME, hitObject );
* Project.instance.switchScreen( "vierde" );
* }
}*/
}
}
Object1.as:
public class Object1 extends MovieClip
{
private var speed:Number;
private var penguin;
public function Object1(aPenguin: Penguin)
{
penguin = aPenguin;
addEventListener( Event.ADDED_TO_STAGE, init );
addEventListener( Event.ENTER_FRAME, hitObject );
}
private function init( event:Event ):void
{
removeEventListener( Event.ADDED_TO_STAGE, init );
addEventListener( Event.REMOVED_FROM_STAGE, unInit );
addEventListener( Event.ENTER_FRAME, move );
speed = -(1 + Math.random() * 2);
x = stage.stageWidth;
y = Math.random() * stage.stageHeight;
}
private function unInit( event:Event ):void
{
removeEventListener( Event.REMOVED_FROM_STAGE, unInit );
removeEventListener( Event.ENTER_FRAME, move );
}
private function move( event:Event ):void
{
this.x += speed;
}
private function hitObject(event:Event)
{
if (penguin.hitTestObject(this))
{
Mouse.show();
trace("geraakt!");
removeEventListener( Event.ADDED_TO_STAGE, init );
removeEventListener( Event.ENTER_FRAME, hitObject );
Project.instance.switchScreen( "vierde" );
}
}
}
}
The thing is, I need to have the hitTestObject function work for all the balls, so that it checks for collisions with all the appearing balls. Penguin is my character who is supposed to evade the balls.
If I comment the hitObject code in Object1.as and uncomment it at Evader.as, I don't know what to put in if (penguin.hitTestObject(???))
Using Objects doesn't work because it will give error #1067: Implicit coercion of a value of type Array to an unrelated type Function.
Could someone help me in getting it work?
Thanks in advance!
Evader is a DisplayObject, specifically type MovielCip. Each display object has a stage field, but the stage field is null until the display object (Evader) gets added to the stage display list (using addChild, eg. stage.addChild( myEvaderInstance) ).
So just from looking at the code you provided, it's possible you haven't added Evader to the display list, therefore its stage is null in the line:
if( currentObject.x > stage.stageWidth )
In which case you wouldn't want to add the event frame listener in its constructor. You'd want to add that listener after it's been added to the stage. So, here's how you can do that. In the Evador constructor:
public function Evader()
{
initGame();
Mouse.hide();
objects = new Array();
//don't update yet, we haven't been added to the display list
//addEventListener( Event.ENTER_FRAME, update );
addEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
}
private function onAddedToStage( e:Event ):void {
removeEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
//add the update listener!
addEventListener( Event.ENTER_FRAME, update );
}
That should do it. We wait till Evader has been added to the display list, then add the event frame listener.

Play timeline in reverse when holding a button

Basically i'm trying to create two buttons. They both call actions while the user has their cursor held on them (rather than onClick or anything like that).
The first one plays the timeline, which works great.
The second one I need it to play the timeline in reverse while the user is holding down the button, how do I do that? Code below:
import flash.events.MouseEvent;
// Play timeline forwards on click //
function onButtonClick( event:MouseEvent ):void
{
play();
}
RotateRight.addEventListener(MouseEvent.MOUSE_DOWN, onButtonClick);
// Stop timeline forwards on release //
function onButtonClick2( event:MouseEvent ):void
{
stop();
}
RotateRight.addEventListener(MouseEvent.MOUSE_UP, onButtonClick2);
// Play timeline in reverse on click //
function onButtonClick3( event:MouseEvent ):void
{
// PLAY IN REVERSE?
}
RotateLeft.addEventListener(MouseEvent.MOUSE_DOWN, onButtonClick3);
// Stop timeline in reverse on release //
function onButtonClick4( event:MouseEvent ):void
{
stop();
}
RotateLeft.addEventListener(MouseEvent.MOUSE_UP, onButtonClick4);
Any help is most appreciated :)
You should add an ENTER_FRAME event on MOUSE_DOWN:
RotateLeft.addEventListener(MouseEvent.MOUSE_DOWN, onButtonClick3);
function onButtonClick3( event:MouseEvent ):void
{
stop();
stage.addEventListener(Event.ENTER_FRAME, reverse);
}
function reverse(e:Event):void {
//currently, this is reversing the main timeline. Can also do it to a specific movieclip with something like myMovieClip.gotoAndStop(myMovieClip.currentFrame-1) instead.
gotoAndStop(currentFrame - 1);
}
RotateLeft.addEventListener(MouseEvent.MOUSE_UP, onButtonClick4);
// Stop timeline in reverse on release //
function onButtonClick4( event:MouseEvent ):void
{
stage.removeEventListener(Event.ENTER_FRAME, reverse);
//You don't need stop() here, but you can change it to play() if you want to resume playback when the mouse is released.
}

Flash AS3 hit test go to next frame

I have a object that can be dragged into another object. I have set up a hit test for the collision. When the collision occurs I would like to progress to the next frame however, I have to click on the draggable object for it to do so. I would like it to move to the next frame right away without clicking. Is there anyway to fix this?
I mean after I have dragged the objected to create the collision I need to click on the object again to progress to the next frame. I do not want to have to click on the object again I want it to go to the next frame as the collision occurs.
This is my code
bottle.buttonMode = true;
bottle.addEventListener(MouseEvent.MOUSE_DOWN, drag);
bottle.addEventListener(MouseEvent.MOUSE_UP, drop);
function collision():void{
if(bottle.hitTestObject(hit)){
nextFrame();
}
}
function drag(e:MouseEvent):void{
bottle.startDrag();
collision();
}
function drop(e:MouseEvent):void{
bottle.stopDrag();
}
You should be checking for collisions after the drop, not at the start of the drag:
function collision():void{
if(bottle.hitTestObject(hit)){
nextFrame();
}
}
function drag(e:MouseEvent):void{
bottle.startDrag();
}
function drop(e:MouseEvent):void{
bottle.stopDrag();
collision();
}
Change collision() into an event listener and attach it to bottle.
Try this one ( adapted from Gary Rosenzweig ) :
bottle.buttonMode = true;
bottle.addEventListener( MouseEvent.MOUSE_DOWN, startBottleDrag );
stage.addEventListener( MouseEvent.MOUSE_UP, stopBottleDrag );
function collision():void {
if( bottle.hitTestObject( hit ) ) {
stopBottleDrag();
nextFrame();
}
}
// to keep bottle location as it is when clicked
var clickOffset:Point = null;
function startBottleDrag( e:MouseEvent ) {
clickOffset = new Point( e.localX, e.localY );
bottle.addEventListener( Event.ENTER_FRAME, dragBottle );
}
function stopBottleDrag( e:MouseEvent = null ) {
clickOffset = null;
bottle.removeEventListener( Event.ENTER_FRAME, dragBottle );
}
function dragBottle( e:Event ) {
bottle.x = mouseX - clickOffset.x;
bottle.y = mouseY - clickOffset.y;
collision();
}

MOUSE_DOWN trigger every frame, ActionScript 3

as I am new to as3, I want to implement a MachineGun, that fires while has ammo, and the trigger is pulled, In my case, the MouseEvent.MOUSE_DOWN.
The problem is that this event fires only once.
The closest I get is to this is MouseEvent.MOUSE_MOVE, but it fails my purpose when the mouse position is sustained
EDIT:
I need the updated mouse cursor every frame
When your MouseEvent.MOUSE_DOWN event handler you can create an event listener that listens for the Event.ENTER_FRAME event to be dispatched. Using the Event.ENTER_FRAME event handler you can repeatedly call a method that handles shooting the bullet. The following is an example I modeled after an example at http://www.benoitfreslon.com/actionscript-throw-bullets-to-mouse-direction:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
[SWF(width="500", height="500", frameRate="24", backgroundColor="0xFFFFFF")]
public class Main extends Sprite
{
private var _gun:Gun;
private var _interval:int;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
_gun = new Gun();
_gun.x = stage.stageWidth / 2 - _gun.width / 2;
_gun.y = stage.stageHeight / 2 - _gun.height / 2;
addChild(_gun);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);
}// end function
private function onStageMouseDown(e:MouseEvent):void
{
stage.addEventListener(Event.ENTER_FRAME, onStageEnterFrame);
stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
}// end function
private function onStageEnterFrame(e:Event):void
{
shootBullet();
}// end function
private function shootBullet():void
{
if (_interval > 5)
{
var bullet:Bullet = new Bullet();
bullet.addEventListener(Event.ENTER_FRAME, onBulletEnterFrame);
bullet.x = _gun.x;
bullet.y = _gun.y;
bullet.angleRadian = Math.atan2(stage.mouseY - _gun.y, stage.mouseX - _gun.x);
bullet.addEventListener(Event.ENTER_FRAME, onBulletEnterFrame);
addChild(bullet);
_interval = 0; // reset
}// end if
_interval++;
}// end function
private function onBulletEnterFrame(e:Event):void
{
var bullet:Bullet = Bullet(e.target);
bullet.x += Math.cos(bullet.angleRadian) * bullet.SPEED;
bullet.y += Math.sin(bullet.angleRadian) * bullet.SPEED;
if ( bullet.x < 0 || bullet.x > 500 || bullet.y < 0 || bullet.y > 500)
{
removeChild(bullet);
bullet.removeEventListener(Event.ENTER_FRAME, onBulletEnterFrame);
}// end if
}// end function
private function onStageMouseUp(e:MouseEvent):void
{
stage.removeEventListener(Event.ENTER_FRAME, onStageEnterFrame);
stage.removeEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
_interval = 0;
}// end function
}// end class
}// end package
import flash.display.Sprite;
internal class Gun extends Sprite
{
public function Gun()
{
graphics.beginFill(0x000000);
graphics.drawCircle(0, 0, 10);
graphics.endFill();
}// end function
}// end class
internal class Bullet extends Sprite
{
public var angleRadian:Number;
public const SPEED:Number = 10;
public function Bullet()
{
graphics.lineStyle(1, 0x000000);
graphics.drawCircle(0, 0, 10);
graphics.endFill();
}// end function
}// end class
The point of interest is in the onStageEnterFrame() method. There's an if statement that checks whether the _interval property's value is greater than 5, if so, a new bullet is created and shot otherwise the _interval property's value is incremented. The purpose of the _interval property is to space out the bullets being shot.
[UPDATE]
Here is an image of the example flash application running:
The mouse button is being held down in the top right corner hence the bullets being shot in that direction.
On receiving a MouseEvent.MOUSE_DOWN event, run a while loop making the machine gun fire. The loop breaks on receiving a MouseEvent.MOUSE_UP event. Something like this
private function handleMouseDown( event:Event ):void
{
this.addEventListener( MouseEvent.MOUSE_UP , handleMouseUp );
startFiring();
}
private function handleMouseUp( event:Event ):void
{
this.removeEventListener( MouseEvent.MOUSE_UP , handleMouseUp );
this.addEventListener( MouseEvent.MOUSE_DOWN , handleMouseDown);
stopFiring();
}
EDIT: For clarification, the stop and start firing functions are functions that run a loop to keep the machine gun firing animation going however that may be.
add firing action to ENTER_FRAME event when mouse is pressed and remove when mouse is up
this.addEventListener( MouseEvent.MOUSE_DOWN, this.handler_down );
this.addEventListener( MouseEvent.MOUSE_UP, this.handler_up );
private function handler_down(event:Event):void {
super.addEventListener( Event.ENTER_FRAME, this.handler_frame );
}
private function handler_up(event:Event):void {
super.removeEventListener( Event.ENTER_FRAME, this.handler_frame );
}
private function handler_frame(event:Event):void {
this.fire();
}
I have to do this regularly, and instead of using an enter_frame listener, I opt for a Timer() and TimerEvent.Timer listener. That way I have more control over how often the repeat is fired without accounting for frame rate and what not.
private var fireRepeat:Timer;
private function triggerDown(e:MouseEvent):void {
if (!this.fireRepeat) { // create the repeater
this.fireRepeat = new Timer(500, 0);
this.fireRepeat.addEventListener(TimerEvent.TIMER, this.fire);
}
fire(); // fire the first bullet
this.fireRepeat.reset(); // reset the repeater
this.fireRepeat.start(); // start the repeater
}
private function triggerUp(e:MouseEvent):void {
if (this.fireRepeat) { this.fireRepeat.stop(); }
}
public function fire(e:* = null):void {
trace('fire!');
}

AS3 function running before variables are defined!

I am trying to add an init() function to a MovieClip, but when I run the function from scene1 the variables that were set in the MovieClip are not defined yet... The MovieClip was dragged to the stage from the library.
scene1:
mc.init(null);
MovieClip:
var _default = 5;
function init(num) {
if(num == null) {
trace(_default);
} else {
trace(num);
}
}
This is tracing "undefined" instead of "5"; Is there a way of fixing this problem?
The problem is that any code thats placed directly in the main timeline will always run before the code thats directly in the MovieClip.
The way to get around this would be to let flash finish running that code in both timeline and the MovieClip first, and then call the function from the timeline after its done.
The easiest way to do this would be to use an event listener:
Timeline:
addEventListener( Event.ENTER_FRAME, onEnterFrame );
function onEnterFrame( e:Event ):void {
myObject.init(null);
removeEventListener( Event.ENTER_FRAME, onEnterFrame );
}
That way the timeline will wait until the first frame has started to call the init function of your MovieClip.