Circular Slider in ActionScript 3 - actionscript-3

I'm hoping to get a round slider into ActionScript, very similar to what this page shows:
It's going to ultimately be altering the hue of an object (returning a CMY value), however if it just spits out the degree I can totally work with that. If you know of any resources, tutorials, pseudocode, or a snippet with this functionality, I would hugely appreciate it. Thanks!

Below is my solution to this problem.
It's worth noting that angles in Flash are handled in radians instead of degrees, which is why you'll notice the conversion methods in the code. Personally, I find setting angles in degrees much easier to visualize and understand, which is why the CircleSlider constructor accepts a value in degrees and why the CircleSliderEvent class dispatches both degrees and radians.
Use Case:
var circleSlider:CircleSlider = new CircleSlider(100, 270);
circleSlider.x = stage.stageWidth / 2;
circleSlider.y = stage.stageHeight / 2;
circleSlider.addEventListener(CircleSliderEvent.CHANGE, circleSliderEventHandler);
addChild(circleSlider);
function circleSliderEventHandler(event:CircleSliderEvent):void
{
trace(event.degrees, event.radians);
}
CircleSlider Class:
package
{
//Imports
import flash.display.Sprite;
import flash.display.Shape;
import flash.events.Event;
import flash.events.MouseEvent;
//Class
public class CircleSlider extends Sprite
{
//Properties
private var mRadius:uint;
private var mAngle:Number;
private var mThumb:Sprite;
//Constructor
public function CircleSlider(radius:uint, degrees:Number)
{
mRadius = radius;
mAngle = degrees;
init();
}
//Init
private function init():void
{
createCircle();
createThumb();
positionThumb(degreesToRadians(mAngle));
}
//Create Circle
private function createCircle():void
{
var circle:Shape = new Shape();
circle.graphics.lineStyle(4.0, 0xFFDDDD, 1.0);
circle.graphics.drawCircle(0, 0, mRadius);
addChild(circle);
}
//Create Thumb
private function createThumb():void
{
mThumb = new Sprite();
mThumb.graphics.beginFill(0xFF2222, 1.0);
mThumb.graphics.drawCircle(0, 0, 10);
mThumb.graphics.endFill();
mThumb.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownEventHandler);
addChild(mThumb);
}
//Mouse Down Event Handler
private function mouseDownEventHandler(event:MouseEvent):void
{
mThumb.addEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);
stage.addEventListener(Event.MOUSE_LEAVE, mouseUpEventHandler);
}
//Enter Frame Event Handler
private function enterFrameEventHandler(event:Event):void
{
positionThumb(Math.atan2(mouseY, mouseX));
}
//Mouse Up Event Handler
private function mouseUpEventHandler(event:MouseEvent):void
{
mThumb.removeEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);
stage.removeEventListener(Event.MOUSE_LEAVE, mouseUpEventHandler);
}
//Position Thumb
private function positionThumb(radians:Number):void
{
mThumb.x = Math.cos(radians) * mRadius;
mThumb.y = Math.sin(radians) * mRadius;
mAngle = radiansToDegrees(radians);
dispatchEvent(new CircleSliderEvent(CircleSliderEvent.CHANGE, mAngle, radians));
}
//Degrees To Radians
private function degreesToRadians(degrees:Number):Number
{
return degrees * Math.PI / 180;
}
//Radians To Degrees
private function radiansToDegrees(radians:Number):Number
{
return radians * 180 / Math.PI;
}
//Set Angle
public function set angle(degrees:Number):void
{
positionThumb(degreesToRadians(degrees));
}
//Get Angle
public function get angle():Number
{
return mAngle;
}
}
}
CircleSliderEvent Class:
package
{
//Imports
import flash.events.Event;
//Class
public class CircleSliderEvent extends Event
{
//Constants
public static const CHANGE:String = "change";
//Properties
public var degrees:Number;
public var radians:Number;
//Constructor
public function CircleSliderEvent (type:String, degrees:Number = NaN, radians:Number = NaN)
{
super(type);
this.degrees = degrees;
this.radians = radians;
}
//Clone
public override function clone():Event
{
return new CircleSliderEvent (type, degrees, radians);
}
//To String
public override function toString():String
{
return formatToString("CircleSliderEvent", "type", "degrees", "radians");
}
}
}

Related

AS3 Windows style drag and drop

I'm making a windows style app with different windows which contain different elements. I know how to code a drag and drop function to change the position of the windows on the stage but I'd like to use a single code for all windows without repeating infinite functions. My code is:
public function fl_WindowDrag(event: MouseEvent): void {
instance.startDrag();
}
public function fl_WindowDrop(event: MouseEvent): void {
instance.stopDrag();
}
I'd like the istance name was retrived automatically from the selected window, is it possible?
I hope you understand my need
Any help is well accepted
Thanks in advance
package {
import flash.display.*;
import flash.text.*;
import flash.events.*;
import flash.ui.Keyboard;
import flash.ui.Mouse;
import flash.display.MovieClip;
public class MainTimeline extends MovieClip {
//Variabili
public var VFullscreen: int = 1;
//Import var
public var VTerminal: Terminal = new Terminal();
public var nTerminal:String;
public function MainTimeline(): void {
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
//Import
//Terminal
VTerminal.x = 288;
VTerminal.y = 384;
stage.addChild(VTerminal);
//Event Listeners
//addEventListener(MouseEvent.CLICK, fl_BringToFront);
VTerminal.addEventListener(MouseEvent.MOUSE_DOWN, fl_WindowDrag);
VTerminal.addEventListener(MouseEvent.MOUSE_UP, fl_WindowDrop);
}
//public functions
//Gestione Fullscreen
public function fl_Fullscreen(event: MouseEvent): void {
switch (VFullscreen) {
case 0:
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
VFullscreen = 1;
break;
case 1:
stage.displayState = StageDisplayState.NORMAL;
VFullscreen = 0;
break;
}
}
public function fl_FSCheck(event: Event): void {
if (stage.displayState == StageDisplayState.NORMAL) {
VFullscreen = 0;
}
if (stage.displayState == StageDisplayState.FULL_SCREEN_INTERACTIVE) {
VFullscreen = 1;
}
}
//Primo Piano Finestre
public function fl_BringToFront(event: MouseEvent): void {
this.addChild(event.currentTarget as DisplayObject);
}
public function fl_WindowDrag(event: MouseEvent): void {
event.currentTarget.startDrag();
nTerminal = event.currentTarget.name.toString();
trace(nTerminal);
}
public function fl_WindowDrop(event: MouseEvent): void {
event.currentTarget.stopDrag();
}
//Chiusura
public function fl_Close(event: MouseEvent): void {
stage.nativeWindow.close();
}
//Apertura/Chiusura Terminal
public function fl_Terminal(event: MouseEvent): void {
if (contains(VTerminal)) {
removeChild(VTerminal);
} else {
VTerminal.x = 288;
VTerminal.y = 320;
addChild(VTerminal);
}
}
}
}
There are many ways you can do this.
You can prepare base class for all windows wich will inherit this behavior and if you plan to design over a dozen of windows this is definitelly thing you should consider. Another way is to create sperarate class designed to only do this and register all windows you want to it.
But since you asking if this is even possible I would recommend you to try some third party libraries.
GreenShock has a good tool for this but i didn't use their libralies a while and I don't know what are their licecing programs.
In case you don't like it, you can use my code i made some time ago.
It's very easy to use but it's not fully implemented(can't rotate and such) and documentation is very weak but if you were interested i can help you with this.
All you need to do is pass objects you want to move along with some bassic properties:
TransformTool.addClient(target:InteractiveObject, operations:uint = 3, edgesMask:uint = 15, sizeBounds:Array = null, dragBounds:Array = null, grabRange:Number = 5):TransformData
terget - that would be your window.
operations - bit-flags representing type of transformation (scale, drag, rotate)
edgesMask - bit-flags defining which edges should be involved in scaling operation (left, right, top, bottom) all these flags values as well as operations flags can be found in TransformData class.
sizeBounds - array contian minimum and maximum size of scaled object accordingly for with and height.
dragBounds - position boundries for draged object. Basically those are arguments for flash Rectangle class.
grabRange - distance from mouse to edge in which you can grab and edge (or edges in case of corner). You can grab an edge also with mouse outside the object and scale two separate objects edges at once.
So assuming w and w2 are your windows, usage looks like this:
TransformTool.addClient(w, TransforData.SCALE|TransformData.DRAG, TransformData.BOTTOM_EDGE|TransformData.RIGHT_EDGE, null, null, 10);
TransformTool.addClient(w2, 3, 15, [20, 10, 350, 350], [100, 100, 600, 500], 10);
That is only this line required to use it.
You can also add listener if you would like to change cursor.
TransformTool.eventDispatcher.addEventListener(TransformToolEvent.EDGES_HIT, transformTestHit);
private function transformTestHit(e:TransformToolEvent):void
{
trace(TransformData(e.data).hitEdges);
}
Below is all the code involved. You can use it as you wish however be Aware that TransformTool is static class and uses only one stage instance.
I you want to develop app in Air and use native windows you would need to modify this code because each navtive window instance has its own unique stage.
TransformTool class:
package utils
{
import flash.display.DisplayObject;
import flash.display.InteractiveObject;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
* ...
* #author Audionysos
*/
public class TransformTool
{
private static var clients:Vector.<TransformData> = new Vector.<TransformData>();
private static var transforming:Vector.<TransformData> = new Vector.<TransformData>();
private static var _stage:Stage;
public static var checkEdgesOnMMove:Boolean = true;
private static var _eventDispatcher:EventDispatcher = new EventDispatcher();
public static function addClient(target:InteractiveObject, operations:uint = 3, edgesMask:uint = 15, sizeBounds:Array = null, dragBounds:Array = null, grabRange:Number = 5):TransformData {
var sBR:Rectangle;
var dBR:Rectangle;
if (sizeBounds) sBR = new Rectangle(sizeBounds[0], sizeBounds[1], sizeBounds[2], sizeBounds[3]);
if (dragBounds) dBR = new Rectangle(dragBounds[0], dragBounds[1], dragBounds[2], dragBounds[3]);
var td:TransformData = new TransformData(target, operations, edgesMask, sBR, dBR, grabRange);
if (operations & TransformData.SCALE) td.allowDrag = true;
clients.push(td);
if (stage) return td;
if (!target.stage) target.addEventListener(Event.ADDED_TO_STAGE, onStage);
else { stage = target.stage; addStageListeners(); }
return td;
}
/**
* Return TransformData object associated with given target.
* #param target object associated with searched TransformData.
* #return TransformData object associated with given target.
*/
static public function getTransformData(target:InteractiveObject):TransformData {
for (var i:int = 0; i < clients.length; i++){
if (clients[i].targetObject == target) return clients[i];
}return null;
}
/**
* Mouse position relative to specifed object.
* #param target InteractiveObject or TransformData object.
* #return Mouse position relative to specifed object.
*/
static public function getTargetMouse(target:*):Point
{
var t:InteractiveObject = target as InteractiveObject;
if (!t && target as TransformData) t = TransformData(target).targetObject;
else throw new Error ("property object must be of type InteractiveObject or TransformData");
return new Point(t.parent.mouseX, t.parent.mouseY);
}
/**
* Adds MOUSE_DOWN and MOUSE_UP listener for current stage;
*/
static private function addStageListeners():void
{
//trace("TT adding stage listeners");
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMUp);
}
static private function onStage(e:Event):void
{
//trace("TT client on stage");
InteractiveObject(e.target).removeEventListener(Event.ADDED_TO_STAGE, onStage);
stage = InteractiveObject(e.target).stage;
addStageListeners();
}
static private function onMUp(e:MouseEvent):void
{
for (var i:int = 0; i < transforming.length; i++){
transforming[i].isTransforming = false;
}
transforming = new Vector.<TransformData>();
}
static private function onMDown(e:MouseEvent):void
{
//trace("TT MousDown");
findAffectedObjects();
}
static private function findAffectedObjects():void
{
for (var i:int = 0; i < clients.length; i++) {
clients[i].hitEdges = findEdges(clients[i]);
if (!clients[i].hitEdges) continue;
//trace("TT got R", clients[i].hitEdges);
transforming.push(clients[i]);
clients[i].isTransforming = true;
clients[i].updateMouseVector();
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMMove);
}
}
static private function onMMove(e:MouseEvent):void
{
//trace("Transforming", transforming.length);
if (TransformTool.checkEdgesOnMMove) dispatchEdges();
//trace("TT Moving");
for (var i:int = 0; i < transforming.length; i++) {
if (transforming[i].operations & TransformData.ROTATE) rotateTarget();
//if (!checkEdgesOnMMove)
transforming[i].updateMouseVector();
scaleTarget(transforming[i]);
fixSize(transforming[i]);
fixPlacement(transforming[i]);
}
}
/**
* Performs fingEdges() operation on each client TransformData object and dispatches EDGES_HIT event if result is different form last hitEdges state;
*/
static private function dispatchEdges():void
{
for (var i:int = 0; i < clients.length; i++) {
if (clients[i].isTransforming) continue;
var r:uint = findEdges(clients[i]);
if (r != clients[i].hitEdges) {
clients[i].hitEdges = r;
_eventDispatcher.dispatchEvent(new TransformToolEvent(TransformToolEvent.EDGES_HIT, clients[i]));
}
}
}
static private function rotateTarget():void
{
}
/**
* If a part of an object is outside defined dragBounds rectangle area it will move this object to closest allowed position.
* #param td
*/
static public function fixPlacement(td:TransformData):void
{
if (!td.dragBounds) return;
td.targetObject.x = Math.max(td.targetObject.x, td.dragBounds.x);
td.targetObject.x = Math.min(td.dragBounds.right - td.targetObject.width, td.targetObject.x);
td.targetObject.y = Math.max(td.targetObject.y, td.dragBounds.y);
td.targetObject.y = Math.min(td.dragBounds.bottom-td.targetObject.height, td.targetObject.y);
}
/**
* Changes the object to fit min/max size defined in sizeBounds object of the transformation data.
* #param td
*/
static public function fixSize(td:TransformData):void
{
if (!td.sizeBounds) return;
td.targetObject.width = Math.min(td.targetObject.width, td.sizeBounds.width);
td.targetObject.width = Math.max(td.targetObject.width, td.sizeBounds.x);
td.targetObject.height = Math.min(td.targetObject.height, td.sizeBounds.height);
td.targetObject.height = Math.max(td.targetObject.height, td.sizeBounds.y);
}
/**
* Scales the object accordingly to grabed edges and move of the mouse.
* #param td
*/
static public function scaleTarget(td:TransformData):void
{
//trace("TT mouse vector", td.mouseVector);
var rD:Point = td.mouseVector//new Point(td.mouseVector.x * td.targetObject.parent.scaleX, td.mouseVector.y * td.targetObject.parent.scaleY); //relativeDisplacement
if (td.hitEdges & TransformData.LEFT_EDGE) { td.targetObject.width -= rD.x; td.targetObject.x += rD.x; }
if (td.hitEdges & TransformData.RIGHT_EDGE) { td.targetObject.width += rD.x; }
if (td.hitEdges & TransformData.TOP_EDGE) { td.targetObject.height -= rD.y; td.targetObject.y += rD.y; }
if (td.hitEdges & TransformData.BOTTOM_EDGE) { td.targetObject.height += rD.y; }
}
/**
* Check if mouse position is in grab range to any of specified object edge.
* #param target examined object
* #param grabRange minimal distance from mouse position to edge of the object.
* #return resul of the inspection.
*/
static public function findEdges(td:TransformData):uint
{
if (!isMouseNearTarget(td)) return 0;
var t:InteractiveObject = td.targetObject;
var gR:Number = td.grabRange;
var r:uint;
if (Math.abs(t.x - t.parent.mouseX) < gR && t.parent.mouseX) r |= TransformData.LEFT_EDGE;
if (Math.abs(t.x + t.width- t.parent.mouseX) < gR) r |= TransformData.RIGHT_EDGE;
if (Math.abs(t.y - t.parent.mouseY) < gR) r |= TransformData.TOP_EDGE;
if (Math.abs(t.y + t.height - t.parent.mouseY) < gR) r |= TransformData.BOTTOM_EDGE;
return r;
}
/**
* Check if mouse relative position is cantained within target rectangle + grabRange;
* #param td object to examine.
* #return true if mouse is near object (edges can be grabbed);
*/
static public function isMouseNearTarget(td:TransformData):Boolean
{
td.updateMouseVector();
var exRect:Rectangle = td.targetObject.getRect(td.targetObject.parent).clone();
exRect.inflate(td.grabRange, td.grabRange);
return exRect.containsPoint(td.mouseStart);
}
/**
* Dispatches events associated with transformed client objects.
* TransformToolEvent contains reference to interested TransformData object.
* #eventType TransformToolEvent.EDGE_HIT dispatched when mouse cursor is close enought client object edges to let it to be scaled.
* You can for example use it's hitEdges property to change cursor icon accordingly.
*/
static public function get eventDispatcher():EventDispatcher
{
return _eventDispatcher;
}
/**
* Stage property on which mouse events will be proceded.
* This will be set automaticly from client object (it it was null before).
*/
static public function get stage():Stage
{
return _stage;
}
static public function set stage(value:Stage):void
{
if (_stage) {
_stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMMove);
_stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMUp);
_stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMDown);
}
_stage = value;
addStageListeners();
if(checkEdgesOnMMove) value.addEventListener(MouseEvent.MOUSE_MOVE, onMMove);
}
}
}
TransformData class:
package utils
{
import flash.display.InteractiveObject;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
* ...
* #author Audionysos
*/
public class TransformData
{
public static const SCALE:uint = 1;
public static const DRAG:uint = 2;
public static const ROTATE:uint = 4;
public static const TOP_EDGE:uint = 1;
public static const RIGHT_EDGE:uint = 2;
public static const BOTTOM_EDGE:uint = 4;
public static const LEFT_EDGE:uint = 8;
public var targetObject:InteractiveObject;
public var grabRange:Number;
public var sizeBounds:Rectangle;
public var dragBounds:Rectangle;
public var mouseStart:Point;
public var mouseVector:Point;
public var hitEdges:uint;
public var edgesMask:uint;
public var operations:uint;
public var isTransforming:Boolean;
private var _allowDrag:Boolean;
private var isDraging:Boolean;
public function TransformData(target:InteractiveObject, operations:uint = 3, edgesMask:uint = 15, sizeBounds:Rectangle = null, dragBounds:Rectangle = null, grabRange:Number = 5)
{
targetObject = target;
this.sizeBounds = sizeBounds;
this.dragBounds = dragBounds;
this.grabRange = grabRange;
this.edgesMask = edgesMask;
this.operations = operations;
}
public function updateMouseVector () {
var mP:Point = new Point(targetObject.parent.mouseX, targetObject.parent.mouseY);
if (!mouseStart) mouseStart = mP;
mouseVector = mP.subtract(mouseStart);
mouseStart = mP;
}
public function get allowDrag():Boolean
{
return _allowDrag;
}
public function set allowDrag(value:Boolean):void
{
if (_allowDrag && !value) {
targetObject.stage.removeEventListener(MouseEvent.MOUSE_UP, onMUp);
targetObject.removeEventListener(MouseEvent.MOUSE_DOWN, onMDown);
if (isDraging) targetObject.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMMove);
}
_allowDrag = value;
if (value) targetObject.addEventListener(MouseEvent.MOUSE_DOWN, onMDown);
}
private function onMDown(e:MouseEvent):void
{
isTransforming = true;
mouseStart = TransformTool.getTargetMouse(this);
targetObject.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMMove);
targetObject.stage.addEventListener(MouseEvent.MOUSE_UP, onMUp);
}
private function onMUp(e:MouseEvent):void
{
isTransforming = false;
targetObject.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMMove);
}
private function onMMove(e:MouseEvent):void
{
updateMouseVector();
targetObject.x += mouseVector.x;
targetObject.y += mouseVector.y;
TransformTool.fixPlacement(this);
}
}
}
TransformToolEvent:
package utils
{
import flash.events.Event;
/**
* ...
* #author Audionysos
*/
public class TransformToolEvent extends Event
{
public static const EDGES_HIT:String = "edgesHit";
private var _data:TransformData;
public function TransformToolEvent(type:String, data:TransformData, bubbles:Boolean=false, cancelable:Boolean=false) {
super(type, bubbles, cancelable);
_data = data;
}
public override function clone():Event {
return new TransformToolEvent(type, _data, bubbles, cancelable);
}
public override function toString():String {
return formatToString("TransformToolEvent", "type", "bubbles", "cancelable", "eventPhase", "data");
}
public function get data():TransformData {
return _data;
}
}
}
You can use the target or currentTarget propterty of the mouse-event to reference the instance that triggers the event, like this (i have not tested this code):
public function fl_WindowDrag(event: MouseEvent): void {
event.currentTarget.startDrag();
}
this way you can add the event handler to multiple instances. You can read more about the events properties here

Movement Keys not Working

Nothing is happening when I press the arrow keys, but neither are there any errors: what's wrong with this? If I remove the key press testing it accelerates accordingly...
At this stage I am just trying to move a block around a screen in an inertial manner using the arrow keys. However, this is my first foray into AS3 so I may be going about it in completely the wrong manner.
Any help would be greatly appreciated.
Unit.AS:
package {
import flash.display.MovieClip;
import flash.events.*
import flash.ui.Keyboard
public class Unit extends MovieClip {
var velocityX:Number = 1;
var velocityY:Number = 1;
var accellerationX:Number = 1;
var accellerationY:Number = 1;
public function Unit(){
addEventListener("enterFrame", move);
}
private function move(e:Event){
accellerate()
this.x += velocityX;
this.y += velocityY;
}
private function accellerate(){
if (Key.isDown(Keyboard.UP)){
velocityY += accellerationY;
trace("Accellerating");
}
if (Key.isDown(Keyboard.DOWN)){
velocityY -= accellerationY;
trace("Accellerating");
}
if (Key.isDown(Keyboard.RIGHT)){
velocityX += accellerationX;
trace("Accellerating");
}
if (Key.isDown(Keyboard.LEFT)){
velocityX -= accellerationX;
trace("Accellerating");
}
}
}
}
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();
}
}
}
On your unit constructor function call the initialize(stage) static function.
Key.initialize(stage);

AS3 - Why am I getting this 1009 error? (Cannot access a property or method of a null object)

I can't get this program to work. I Always get this error: Error #1009: Cannot access a property or method of a null object reference.
I don't understand why and would appreciate some help.
Here's my code:
Main class:
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite
{
private var enginge:Engine = new Engine(stage);
private var enemy:Enemy = new Enemy(100, 100);
public function Main():void
{
addChild(enemy);
}
}
}
Engine class:
package
{
import flash.display.Sprite;
import flash.display.Stage;
public class Engine
{
public static var stage:Stage;
public static var gravity:int = 1;
public function Engine(stage:Stage)
{
Engine.stage = stage;
}
public static function gravitate(object:Sprite):void
{
object.y += Engine.gravity;
if (object.y < Engine.stage.stageHeight - object.height / 2)
{
Engine.gravity += 1;
}
else
{
Engine.gravity = 0;
object.y = Engine.stage.stageHeight - object.height / 2;
}
}
}
}
Enemy class:
package
{
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
public class Enemy extends Sprite
{
private var gravity:int = 1;
public function Enemy(x:int, y:int)
{
this.graphics.beginFill(1, 1);
this.graphics.drawRect(this.x - 25, this.y - 40, 50, 80);
this.graphics.endFill();
this.x = x;
this.y = y;
this.addEventListener(Event.ENTER_FRAME, function(e:Event):void
{
Engine.gravitate(this);
});
}
}
}
In order to fix the problem you need to get rid of the anonymous function in the Enemy class.
You will have:
public function Enemy(x:int, y:int)
{
this.graphics.beginFill(1, 1);
this.graphics.drawRect(this.x - 25, this.y - 40, 50, 80);
this.graphics.endFill();
this.x = x;
this.y = y;
this.addEventListener(Event.ENTER_FRAME,handler);
}
private function handler(event:Event):void
{
Engine.gravitate(Sprite(this));
}
and the code will be working. This is due to context difference of word this inside anonymous function.
Usage of anonymous function is terrible practice and you should refrain from doing it.

Actionscript 3 cannot access a property or method of a null object reference

I'm still really new about classes and stuffs. So, I tried making this and I got an error: Access of undefined property.
Why speedX and speedY var still error although I've defined it in public var in the main class?
Thanks!
EDITED: I've tried calling the variables from other class with main.speedX and main.speedY
But it got error : Cannot access a property or method of a null object reference.
at Ball/moveBall()
This is the Main code:
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class Main extends MovieClip
{
public var speedX:Number = 5;
public var speedY:Number = 5;
public var speedMax:Number = 10;
private var ball:MovieClip = new Ball();
private var paddle:MovieClip = new Paddle();
public function Main()
{
paddle.addEventListener(Event.ENTER_FRAME, movePaddle);
addChild(ball);
addChild(paddle);
}
}
}
This is the Ball Movie Clip Code:
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class Ball extends MovieClip
{ public var main:Main;
public function Ball()
{addEventListener(Event.ENTER_FRAME, moveBall);
main= new Main();
}
public function moveBall(e:Event):void
{
x += main.speedX;
y += main.speedY;
}
}
}
That's because your class Ball cannot access speedX and speedY inside the event callback. Why not add speedX and speedY to your Ball class directly instead ?
public class Ball extends MovieClip
{
public var speedX:Number;
public var speedY:Number;
public function Ball(sX:Number = 0, sY:Number = 0)
{
this.speedX = sX;
this.speedY = sY;
addEventListener(Event.ENTER_FRAME, moveBall);
}
public function moveBall(e:Event):void
{
x += speedX;
y += speedY;
}
}
Here's another possible solution where you would be passing main to ball to use the values of speed stored in Main.
public class Main extends MovieClip
{
public var speedX:Number = 5;
private var ball:MovieClip;
public function Main()
{
ball=new Ball(this);
addChild(ball);
}
}
and
public class Ball extends MovieClip
{
private var _main:Main;
public function Ball(main:Main)
{
_main=main;
addEventListener(Event.ENTER_FRAME, moveBall);
}
public function moveBall(e:Event):void
{
x += _main.speedX;
}
}
}

AS3 ActionScript 3 - Instantiating Objects With A Timer?

I'm making a vertical (constantly) scrolling shooter & am trying to instantiate objects based on a timer. For example: At 30 seconds, place a building # x, y.
My problem is that the "building" is instantiated when the game starts and then again at the 30 second mark - instead of only # the 30 second mark.
If anyone could steer me in the correct direction, it would be greatly appreciated.
package com.gamecherry.gunslinger
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class ObjectPlacer extends MovieClip
{
private var Build01Timer:Timer;
private var canPlace:Boolean = true;
private var stageRef:Stage;
private var startX:Number;
private var startY:Number;
private var time:int = 5000;
public function ObjectPlacer(stageRef:Stage) : void
{
this.stageRef = stageRef;
var Build01Timer = new Timer(time, 1);
Build01Timer.addEventListener(TimerEvent.TIMER, placeTimerHandler, false, 0, true);
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
Build01Timer.start();
}
private function loop(e:Event): void
{
if (canPlace)
{
var BuildingsLeft01:BuildingsLeft = new BuildingsLeft(stage, 720, -540);
BuildingsLeft01.scaleX = -1;
stageRef.addChildAt((BuildingsLeft01), 2);
canPlace = false;
}
}
private function placeTimerHandler(e: TimerEvent) : void
{
canPlace = true;
}
private function removeSelf() : void
{
removeEventListener(Event.ENTER_FRAME, loop);
if (stageRef.contains(this))
stageRef.removeChild(this);
}
}
}
Where am I going wrong?
Thank you for looking.
Here's the first of your class:
public class ObjectPlacer extends MovieClip
{
private var Build01Timer:Timer;
**private var canPlace:Boolean = true;**
You're setting it to TRUE at the start, set it to false, and that would solve your problem :)