AS3 lineTo method alternative - actionscript-3

This is more of a logical question than just looking for code, although it might be needed.
So i'm creating a drawing application and the first thing to do is use the lineTo method to draw a line -- that's all fine. But I learned this is not what I want, it does draw fine etc. but I want a tool that wouldn't "draw a line". I want a tool that doesn't lay the line down as you let go of click, but it lays down right when you click.
Now I don't really have a clue how to create this; can someone explain how one would code such a thing? This would sort of be an alternative to lineTo -- sorry if this sounds confusing, it's hard to word.

Here are two examples:
Drawing application that draws like a pen
Drawing application that draws lines / arrows
Pen Drawing (SWF Example)
This draws lines as curve to match the input device, persisting the line as it's drawn:
Code:
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.MouseEvent;
import flash.geom.Point;
[SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0xefefef, frameRate = 30)]
public class DrawingExample extends Sprite
{
//------------------------------
// model
//------------------------------
protected var lastPoint:Point;
//------------------------------
// lifecycle
//------------------------------
public function DrawingExample()
{
super();
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
beginDrawing();
}
protected function beginDrawing():void
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
}
protected function mouseDownHandler(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
// mark mouse down location
lastPoint = new Point(mouseX, mouseY);
// listen for movement or up/out
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
stage.addEventListener(MouseEvent.MOUSE_OUT, mouseUpHandler);
}
protected function mouseMoveHandler(event:MouseEvent):void
{
var g:Graphics = graphics;
g.lineStyle(1, 0x0000ff);
// draw line segment
g.moveTo(lastPoint.x, lastPoint.y);
g.lineTo(mouseX, mouseY);
// mark end of line segment
lastPoint = new Point(mouseX, mouseY);
}
protected function mouseUpHandler(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
stage.removeEventListener(MouseEvent.MOUSE_OUT, mouseUpHandler);
beginDrawing();
}
}
}
Line Drawing (SWF Example)
Although tuned for arrow heads, the concept is the same for lines. When the input device is down, a line / arrow is staged but not persisted until the input device is up. Once drawn, the line persists.
Code:
package
{
import flash.display.CapsStyle;
import flash.display.Graphics;
import flash.display.JointStyle;
import flash.display.LineScaleMode;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
[SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0xefefef, frameRate = 30)]
public class Arrows extends Sprite
{
public var arrows:Vector.<Sprite> = new Vector.<Sprite>();
public var canvas:Sprite;
public var lineColor:uint = Math.random() * 0xffffff;
public var lineWeight:Number = 5;
private var startPoint:Point;
public function Arrows()
{
super();
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
protected function addedToStageHandler(event:Event):void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
addCanvas();
}
protected function addCanvas():void
{
canvas = new Sprite();
addChild(canvas);
lineColor = Math.random() * 0xffffff;
// give alpha for interaction
var g:Graphics = canvas.graphics;
g.beginFill(0x0, 0.0);
g.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
g.endFill();
// listen for mouse down
canvas.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
}
protected function mouseDownHandler(event:MouseEvent):void
{
canvas.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
// mark start point
startPoint = new Point(event.localX, event.localY);
// start rendering
canvas.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
// listen for mouse up / out to end arrow
canvas.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
canvas.addEventListener(MouseEvent.MOUSE_OUT, mouseUpHandler);
}
protected function enterFrameHandler(event:Event):void
{
var angle:Number = polarAngle(new Point(mouseX, mouseY), new Point(startPoint.x, startPoint.y));
// draw line
var g:Graphics = canvas.graphics;
g.clear();
// give alpha for interaction
g.beginFill(0x0, 0.0);
g.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
g.endFill();
g.lineStyle(lineWeight, lineColor, 1, true, LineScaleMode.NORMAL, CapsStyle.SQUARE, JointStyle.MITER);
g.moveTo(startPoint.x, startPoint.y);
g.lineTo(mouseX, mouseY);
// draw arrow head
g.moveTo(mouseX - (20 * Math.cos((angle - 45) * Math.PI / 180)),
mouseY - (20 * Math.sin((angle - 45) * Math.PI / 180)));
g.lineTo(mouseX + (5 * Math.cos((angle) * Math.PI / 180)),
mouseY + (5 * Math.sin((angle) * Math.PI / 180)));
g.lineTo(mouseX - (20 * Math.cos((angle + 45) * Math.PI / 180)),
mouseY - (20 * Math.sin((angle + 45) * Math.PI / 180)));
}
protected function polarAngle(point:Point, center:Point=null):Number
{
if (!center)
center = new Point(0, 0);
return Math.atan2(point.y - center.y, point.x - center.x) * 180 / Math.PI;
}
protected function mouseUpHandler(event:MouseEvent):void
{
canvas.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
canvas.removeEventListener(MouseEvent.MOUSE_OUT, mouseUpHandler);
// stop rendering
canvas.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
// push canvas to arrows collection
arrows.push(canvas);
// add a fresh canvas
addCanvas();
}
}
}

Related

hitTest not working

I don't understand. HitTest is pretty basic but it won't work. I want my movieclip Faller to hitTest Touch1 but I get error 1061. I tought I had it done when I did fallerThingsLeft to hitTest Touch1 to tell me "HIT" on the score_txt, but it tells me Hit like 3 sec
before it really hits. I don't get it. can't someone tell me what im doing wrong
import flash.display.Graphics;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
var objectSpawner: Timer;
var fallers: Array;
function initGame(): void {
fallers = [];
objectSpawner = new Timer(1000);
objectSpawner.addEventListener(TimerEvent.TIMER, createEnemy);
objectSpawner.start();
addEventListener(Event.ENTER_FRAME, dropEnemies);
}
function createEnemy(e: TimerEvent): void {
var enemy: Faller = new Faller();
enemy.y = -stage.stageHeight;
enemy.x = Math.random() * 380;
MovieClip(enemy).cacheAsBitmap = true;
addChild(enemy);
fallers.push(enemy);
drawConnectors();
}
function dropEnemies(e: Event): void {
trace(fallers.length);
for each(var mc: Faller in fallers) {
mc.y += 10;
if (mc.y > stage.stageHeight * 2)
fallers.splice(fallers.indexOf(removeChild(mc)), 1);
drawConnectors();
}
}
function drawConnectors(): void {
if (fallers.length == 0) return;
var g: Graphics = this.graphics;
g.clear();
g.lineStyle(10,0xFFFFFF);
var mc: Faller = fallers[0];
g.moveTo(mc.x, mc.y);
for each(mc in fallers) g.lineTo(mc.x, mc.y);
}
init()
function init():void
{
var fallingThingsLeft:FallingThings = new FallingThings
(stage.stageWidth / 2, stage.stageHeight);
var fallingThingsRight:FallingThings = new FallingThings
(stage.stageWidth / 2, stage.stageHeight);
addChild(fallingThingsLeft);
addChild(fallingThingsRight);
fallingThingsRight.x = stage.stageWidth / 2;
}
import flash.events.Event;
this.addEventListener( Event.ENTER_FRAME, handleCollision)
function handleCollision( e:Event ):void
{
if(fallingThingsLeft.hitTestObject(Touch1))
{
output_txt.text = "HIT"
}
else
{
output_txt.text = "MISS"
}
}
Without seeing the objects, I can't be certain; however a common issue when getting started with hitTestObject is understanding the hit test is performed on the bounding box. See the image below. This will register a 'hit' with hitTestObject because the bounding boxes pass the hit test.

Actionscript 3: User input events not firing from children blit sprite objects

Still programming an iPad game in Actionscript 3, I am encountering a problem that keeps me from advancing any further. I use blitting for animation, and as such, all my object use blitting for rendering. All objects are children of a game class which has a bitmapData canvas on which are rendered the game elements.
That's for how it should work. So far, there are no compilation or runtime errors, but for some reason I can't get any user input event from any object apart from the game itself. I have checked the event flow as well as the layering of the objects, but so far all I could find out is that for some reason the main canvas is the only element that can be targeted for events. Because players need to be able to touch them, two game elements are concerned: Twinkys and Racquets.
I have tried changing the layering of the elements, in order of instanciation and rendering, hiding some, changing event types (using mouse event instead of touch events) and toggling the mouseEnabled property of the game class with no positive result. All I can be sure of is that the game class is intercepting all events targeted at its children, making it impossible to play. I hope someone can see what I've done wrong.
Game class:
package Game
{
import Game.*;
import Game.Worlds.Level1.Level1;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display3D.IndexBuffer3D;
import flash.events.Event;
import flash.events.TouchEvent;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
public class Game extends Sprite
{
/** Hold each racquet so as to retrieve them when collision detection is needed. **/
internal var racquetList:Vector.<Racquet>= new Vector.<Racquet>(2,true);
/** Hold each Zwig so as to retrieve them when collision detection is needed. **/
internal var zwigColliderList:Vector.<Collider>= new Vector.<Collider>(2,true);
/** Object that contains the coordinates for the Twinkys in the counter. **/
internal var twinkyScore0:Object= {firstX:727,firstY:950,secondX:710,secondY:911,
thirdX:690,thirdY:872,fourthX:674,fourthY:840,
fifthX:657,fifthY:808};
internal var twinkyScore1:Object= {firstX:41,firstY:74,secondX:58,secondY:113,
thirdX:78,thirdY:152,fourthX:94,fourthY:184,
fifthX:111,fifthY:216};
/** Speed decay coefficient. The closer to 1 the less speed decays. **/
private var friction:Number= .96;
/** Maximum speed cap for twinkys. The higher the number the grater the maximal speed. **/
private var speedMax:Number= 10;
/** Important positions for the placement of game elements.
* LianaHeight is the height at which the liana on the players' HUDs is ending their zone and on which the racquet travels.
* TwinkyHeight is the height at which the players stop controlling their Twinkys.
* YMargin is the vertical margin for the Twinkys. Used to place them at the end of the tube when added.
* XMargin is the horizontal margin for the Twinkys. Used to place them at the end of the tube when added. **/
private var positions:Object= {LianaHeight:165,TwinkyHeight:265,YMargin:8.0,XMargin:200.0};
private var _mRef:ZwigsIpad;
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
private var _Canvas:BitmapData= new BitmapData(ZwigsIpad.BORDERS.right,ZwigsIpad.BORDERS.bottom,false);
private var _Background:Background;
private var _HUD1:HUD;
private var _HUD2:HUD;
private var _Score:Score;
private var _Zwig1:Zwig;
private var _Zwig2:Zwig;
private var _Racquet1:Racquet;
private var _Racquet2:Racquet;
private var _Twinky1:Twinky;
private var _Twinky2:Twinky;
/** Create the first level. It will create the stage and add the background, HUDs, Zwigs, Racquets and Twinkys, and manages the game until the end. **/
public function Game(m:ZwigsIpad)
{
this._mRef= m;
this.addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE,init);
// Add game canvas on which all assets are rendered
addChild(new Bitmap(this._Canvas));
// Get informations from Level1
// LATER make it dependant from what level was chosen (switch case)
this.positions.LianaHeight= Level1.LIANA_HEIGHT;
this.positions.TwinkyHeight= Level1.TWINKY_HEIGHT;
this.positions.YMargin= Level1.TWINKY_MARGIN_Y;
this.positions.XMargin= Level1.TWINKY_MARGIN_X;
this.friction= Level1.TWINKY_FRICTION;
this.speedMax= Level1.TWINKY_SPEED_MAX;
// Add background
this._Background= new Background(this._Canvas,0);
addChild(this._Background);
// Add HUD
this._HUD1= new HUD(this._Canvas);
this._HUD2= new HUD(this._Canvas,true,1);
addChild(this._HUD1);
addChild(this._HUD2);
// Add scoring
this._Score= new Score(this,this._mRef);
addChild(this._Score);
// Add zwigs
this._Zwig1= new Zwig(this._Canvas);
this._Zwig2= new Zwig(this._Canvas,true,1);
addChild(this._Zwig1);
addChild(this._Zwig2);
// Add zwigs' colliders to vector
this.zwigColliderList[0]= this._Zwig1.collider;
this.zwigColliderList[1]= this._Zwig2.collider;
// Add racquets
this._Racquet1= new Racquet(this.positions,this._Canvas);
this._Racquet2= new Racquet(this.positions,this._Canvas,false,1);
addChild(this._Racquet1);
addChild(this._Racquet2);
// Add racquets to vector
this.racquetList[0]= this._Racquet1;
this.racquetList[1]= this._Racquet2;
// Add twinkys
this._Twinky1= new Twinky(this,this._Score,this,this.positions,this.friction,this.speedMax,this._Canvas,0);
this._Twinky2= new Twinky(this,this._Score,this,this.positions,this.friction,this.speedMax,this._Canvas,1,false,1);
addChild(this._Twinky1);
addChild(this._Twinky2);
this.addEventListener(Event.ENTER_FRAME,renderLevel);
}
private function renderLevel(e:Event):void
{
this._Canvas.lock();
this._Background.render();
this._HUD1.render();
this._HUD2.render();
this._Score.render();
this._Zwig1.render();
this._Zwig2.render();
this._Racquet1.render();
this._Racquet2.render();
this._Twinky1.render();
this._Twinky2.render();
this._Canvas.unlock();
}
}
}
Twinky class:
package Game
{
import Game.Game;
import Game.Score;
import com.greensock.TweenMax;
import com.greensock.easing.*;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TouchEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
/** The Twinky is the main player controlled class. **/
internal class Twinky extends Sprite
{
private var _mRef:Game;
private var _sRef:Score;
private var player:uint;
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
private var _touchMoveID:int= 0;
private var _speedX:Number= 0;
private var _speedY:Number= 0;
private var xOffset:Number;
private var yOffset:Number;
private var currentX:Number;
private var currentY:Number;
private var oldX:Number;
private var oldY:Number;
private var dragging:Boolean= false;
private var launched:Boolean= false;
private var _point:Point= new Point();
private var positions:Object;
private var friction:Number;
private var speedMax:Number;
private var canvas:BitmapData;
private var isAtBottom:Boolean;
private var skin:uint;
private var _image:BitmapData;
private var _idleArray:Array= new Array();
private var i:uint= 0;
// Yellow twinky
[Embed (source= "Assets/Players/twinky1.png")]
private const Twinky1idle:Class;
private var _twinky1idleArray:Array;
// Red twinky
[Embed (source= "Assets/Players/twinky2.png")]
private const Twinky2idle:Class;
private var _twinky2idleArray:Array;
private const twinkyWidth:uint= 64;
private const twinkyHeight:uint= 64;
private var t1i001:Rectangle= new Rectangle(0,0,twinkyWidth,twinkyHeight);
private var t2i001:Rectangle= new Rectangle(0,0,twinkyWidth,twinkyHeight);
/** Create Twinky. Twinkys must be flicked to the same colored Zwig to
* feed it and die when they lost momentum. **/
public function Twinky(daddy:Game,score:Score,m:Game,positions:Object,friction:Number,speedMax:Number,canvas:BitmapData,player:uint,isAtBottom:Boolean=true,skin:uint=0)
{
// Get score and game object reference
this._sRef= score;
this._mRef= daddy;
this.positions= positions;
this.friction= friction;
this.speedMax= speedMax;
this.canvas= canvas;
this.player= player;
this.isAtBottom= isAtBottom;
this.skin= skin;
this._twinky1idleArray= [t1i001];
this._twinky2idleArray= [t2i001];
this.addEventListener(Event.ADDED_TO_STAGE,init,false,0,true);
}
private function init(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE,init);
// Get skin
switch (this.skin)
{
case 0:
this._image= new this.Twinky1idle().bitmapData;
this._idleArray= this._twinky1idleArray;
break;
case 1:
this._image= new this.Twinky2idle().bitmapData;
this._idleArray= this._twinky2idleArray;
break;
default:
this._image= new this.Twinky1idle().bitmapData;
this._idleArray= this._twinky1idleArray;
break;
}
// Give position
if (this.isAtBottom)
{
this.x= this.positions.XMargin;
this.y= ZwigsIpad.BORDERS.bottom - this.positions.YMargin;
// Animate entrance
TweenMax.from(this,1,{x:this.x-70,y:this.y-12,rotation:-180,alpha:.5});
}
else
{
this.x= ZwigsIpad.BORDERS.right - this.positions.XMargin;
this.y= this.positions.YMargin;
// Animate entrance
TweenMax.from(this,1,{x:this.x+70,y:this.y+12,rotation:-180,alpha:.5});
}
this._point.x= this.x;
this._point.y= this.y;
aText.appendText("\n position: "+this.x+" "+this.y);
// Detect touched
this.addEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
// Always detect untouched
this._mRef.addEventListener(TouchEvent.TOUCH_END,touchUp);
// Always do kinetics
this._mRef.addEventListener(Event.ENTER_FRAME,freeMove);
}
/** Render the Twinky at its current coordinates by redrawing it. **/
internal function render():void
{
this._point.x= this.x - this._idleArray[i].width * .5;
this._point.y= this.y - this._idleArray[i].height * .5;
this.canvas.copyPixels(this._image,this._idleArray[0/*i*/],this._point);
// When idle finished restart, else pursue with animation
/*if (i==this._idleArray.length - 1)
i= 0;
else
i++;*/
}
// TWINKY AND RACQUET DO NOT DETECT TOUCH EVENTS because the main canvas covers them
// Start dragging when touched
private function touchDown(e:TouchEvent):void
{
aText.appendText("\n Twinky touched!");
if (this._touchMoveID != 0)
return;
this._touchMoveID= e.touchPointID;
this.dragging= true;
// Get the mouse's offset on the object
this.xOffset= e.localX;
this.yOffset= e.localY;
this._mRef.addEventListener(TouchEvent.TOUCH_MOVE,touchMove);
}
private function touchMove(e:TouchEvent):void
{
if (e.touchPointID != this._touchMoveID)
return;
// Move twinky to where the mouse is
this.x= e.stageX - this.xOffset;
this.y= e.stageY - this.yOffset;
// Don't go farther than borders
if (this.x <= this.width * .5)
{
this.x= (this.width * .5) + .1;
}
if (this.x >= ZwigsIpad.BORDERS.right - (this.width * .5))
{
this.x= ZwigsIpad.BORDERS.right - (this.width * .5) - .1;
}
if (this.y <= this.height * .5)
{
this.y= (this.height * .5) + .1;
}
if (this.y >= ZwigsIpad.BORDERS.bottom - (this.height * .5))
{
this.y= ZwigsIpad.BORDERS.bottom - (this.height * .5) - .1;
}
// Be undraggable if zone is left
if (this.isAtBottom)
{
if (this.y < (ZwigsIpad.BORDERS.bottom - this.positions.TwinkyHeight))
{
this._touchMoveID= 0;
this.dragging= false;
this._mRef.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
return;
}
}
else
{
if (this.y > this.positions.TwinkyHeight)
{
this._touchMoveID= 0;
this.dragging= false;
this._mRef.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
return;
}
}
// Refresh coordinates for display
this._point.x= this.x;
this._point.y= this.y;
e.updateAfterEvent();
}
private function touchUp(e:TouchEvent):void
{
if (e.touchPointID != this._touchMoveID)
return;
this._touchMoveID= 0;
this.dragging= false;
this._mRef.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
}
private function freeMove(e:Event):void
{
// Be undraggable if liana crossed
if (this.isAtBottom)
{
if (this.y < (ZwigsIpad.BORDERS.bottom - this.positions.TwinkyHeight))
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(Event.ENTER_FRAME,touchUp);
this.dragging= false;
this.launched= true;
}
}
else
{
if (this.y > this.positions.TwinkyHeight)
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(Event.ENTER_FRAME,touchUp);
this.dragging= false;
this.launched= true;
}
}
// Move the twinky and calculate its speed if player is dragging it
if (this.dragging)
{
aText.appendText("\n Twinky dragged!");
this.oldX= currentX;
this.oldY= currentY;
currentX= this.x;
currentY= this.y;
// Calculate speed in X and Y axis
this._speedX= this.currentX - this.oldX;
this._speedY= this.currentY - this.oldY;
// Cap maximal speed
if (this._speedX > this.speedMax)
this._speedX= this.speedMax;
if (this._speedY > this.speedMax)
this._speedY= this.speedMax;
}
// Otherwise move the twinky using its speed
else
{
this.x+= this._speedX;
this.y+= this._speedY;
}
// Detect collision with zwigs
for (i= 0 ; i < this._mRef.zwigColliderList.length ; i++)
{
var cemp:Collider= this._mRef.zwigColliderList[i] as Collider;
if (this.hitTestObject(cemp))
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(TouchEvent.TOUCH_END,touchUp);
this._mRef.removeEventListener(Event.ENTER_FRAME,freeMove);
this._sRef.die(this,this.player,true,i);
return;
}
}
// Detect collision with borders: left border
if (this.x <= this.width / 2)
{
// Don't go any further
this.x= (this.width / 2) + .1;
// Reverse speed to bounce
this._speedX*= -1;
}
// Right border
if (this.x >= ZwigsIpad.BORDERS.right - (this.width / 2))
{
this.x= ZwigsIpad.BORDERS.right - (this.width / 2) - .1;
this._speedX*= -1;
}
// Top border
if (this.y <= this.height / 2)
{
this.y= (this.height / 2) + .1;
this._speedY*= -1;
}
// Bottom border
if (this.y >= ZwigsIpad.BORDERS.bottom - (this.height / 2))
{
this.y= ZwigsIpad.BORDERS.bottom - (this.height / 2) - .1;
this._speedY*= -1;
}
// Detect collision with racquets
for (var i:uint= 0 ; i < this._mRef.racquetList.length ; i++)
{
var temp:Racquet= this._mRef.racquetList[i] as Racquet;
if (this.hitTestObject(temp))
{
this._speedY*= -1;
this.y+= this._speedY;
}
}
// Speed decay
this._speedX*= this.friction;
this._speedY*= this.friction;
// Set speed to 0 if speed is smaller than .5
if (Math.abs(this._speedX) < .5) this._speedX= 0;
if (Math.abs(this._speedY) < .5) this._speedY= 0;
// If speed is null and it has been launched, kill twinky
if (this._speedX == 0 && this._speedY == 0 && this.launched)
{
this.removeEventListener(TouchEvent.TOUCH_BEGIN,touchDown);
this._mRef.removeEventListener(TouchEvent.TOUCH_END,touchUp);
this._mRef.removeEventListener(Event.ENTER_FRAME,freeMove);
TweenMax.to(this, 1.5, {alpha:0, ease:Linear.easeNone});
this._sRef.die(this,this.player);
return;
}
// Refresh coordinates for display
this._point.x= this.x;
this._point.y= this.y;
}
}
}
Racquet class:
package Game
{
import Game.Worlds.Level1.Level1;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TouchEvent;
import flash.geom.Point;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
internal class Racquet extends Sprite
{
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
private var _touchMoveID:int= 0;
private var xOffset:Number;
private var dragging:Boolean= false;
private var positions:Object;
private var canvas:BitmapData;
private var isAtBottom:Boolean;
private var skin:uint;
private var _image:BitmapData;
private var _point:Point= new Point();
// Yellow racquet
[Embed (source= "Assets/Players/racq1.png")]
private const Racquet1:Class;
// Red racquet
[Embed (source= "Assets/Players/racq2.png")]
private const Racquet2:Class;
public function Racquet(positions:Object,canvas:BitmapData,isAtBottom:Boolean=true,skin:uint=0)
{
this.positions= positions;
this.canvas= canvas;
this.isAtBottom= isAtBottom;
this.skin= skin;
this.addEventListener(Event.ADDED_TO_STAGE,init,false,0,true);
}
private function init(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE,init);
// Get skin
switch (this.skin)
{
case 0:
//this._image= new R.Racquet1().bitmapData;
this._image= new this.Racquet1().bitmapData;
break;
case 1:
//this._image= new R.Racquet2().bitmapData;
this._image= new this.Racquet2().bitmapData;
break;
default:
this._image= new this.Racquet1().bitmapData;
break;
}
// Give position
if (this.isAtBottom)
{
this.x= ZwigsIpad.BORDERS.centerX;
this.y= ZwigsIpad.BORDERS.bottom - this.positions.LianaHeight;
}
else
{
this.x= ZwigsIpad.BORDERS.centerX;
this.y= this.positions.LianaHeight;
}
this._point.x= this.x;
this._point.y= this.y;
this.addEventListener(TouchEvent.TOUCH_BEGIN,touchDown,false,0,true);
this.parent.addEventListener(TouchEvent.TOUCH_END,touchUp,false,0,true);
}
internal function render():void
{
this._point.x= this.x - this._image.rect.width * .5;
this._point.y= this.y - this._image.rect.height * .5;
this.canvas.copyPixels(this._image,this._image.rect,this._point);
}
private function touchDown(e:TouchEvent):void
{
aText.appendText("\n Racquet touched!");
if(this._touchMoveID != 0)
return;
this._touchMoveID= e.touchPointID;
this.xOffset= e.localX;
this.parent.addEventListener(TouchEvent.TOUCH_MOVE,touchMove,false,0,true);
}
private function touchMove(e:TouchEvent):void
{
if(e.touchPointID != this._touchMoveID)
return;
Multitouch.inputMode= MultitouchInputMode.TOUCH_POINT;
this._point.x= e.stageX - this.xOffset;
if (this._point.x <= ZwigsIpad.BORDERS.left + (this._image.width*.5))
this._point.x= ZwigsIpad.BORDERS.left + (this._image.width*.5);
else if (this._point.x >= ZwigsIpad.BORDERS.right - (this._image.width*.5))
this._point.x= ZwigsIpad.BORDERS.right - (this._image.width*.5);
}
private function touchUp(e:TouchEvent):void
{
if(e.touchPointID != this._touchMoveID)
return;
this._touchMoveID= 0;
this.parent.removeEventListener(TouchEvent.TOUCH_MOVE,touchMove);
}
}
}
Touch events will only fire when you touch a sprite's graphics. But all your graphics are drawn onto a single bitmap so your various sprites have nothing to interact with.
Flash provides a display list and does a good job of rendering it, so you shouldn't need to build your own complicated structures like this.
You should consider making each sprite contain its own graphics and things will just work out easier. If performance is a huge concern, I suggest getting it working first, and then play around with different optimisation strategies afterwards (e.g. cacheAsBitmap, clipping/scrolling with scrollRect etc.)

AS3: Live drawing?

I have one strange problem, if I use graphics.lineTo while moving the mouse (MOUSE_MOVE), the lines are created live. But if I change it to MOUSE_DOWN, the lines are straight, and unresponsive if the mouse is still being pressed.
Here's an example:
stage.addEventListener(MouseEvent.MOUSE_MOVE, follow);
stage.addEventListener(MouseEvent.MOUSE_DOWN, draw);
private function follow(e:MouseEvent){
trace(e.localY);
activeChalk.x = e.stageX;
activeChalk.y = e.stageY;
}
private function draw(e:MouseEvent){
trace(e.localY);
activeChalk.x = e.stageX;
activeChalk.y = e.stageY;
board.graphics.lineTo(e.stageX,e.stageY);
}
EDIT: I managed to make it to work using the following example:
http://www.foundation-flash.com/tutorials/as3drawingbymouse/
Your application is fundamentally flawed in a variety of ways.
Instead of going in to detail, here's a very simply implementation of drawing:
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.MouseEvent;
import flash.geom.Point;
[SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0xefefef, frameRate = 30)]
public class Chalk extends Sprite
{
protected var lastPoint:Point;
public function Chalk()
{
super();
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
initializeDrawing();
}
protected function initializeDrawing():void
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
}
protected function mouseDownHandler(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
// mark mouse down location
lastPoint = new Point(mouseX, mouseY);
// listen for movement or up/out
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
stage.addEventListener(MouseEvent.MOUSE_OUT, mouseUpHandler);
}
protected function mouseMoveHandler(event:MouseEvent):void
{
var g:Graphics = graphics;
g.lineStyle(1, 0x0000ff);
// draw line segment
g.moveTo(lastPoint.x, lastPoint.y);
g.lineTo(mouseX, mouseY);
// mark end of line segment
lastPoint = new Point(mouseX, mouseY);
}
protected function mouseUpHandler(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
stage.removeEventListener(MouseEvent.MOUSE_OUT, mouseUpHandler);
// prepare for next line
initializeDrawing();
}
}
}
Not really strange, a single MOUSE_DOWN event is dispatched when you click the mouse, thereafter MOUSE_MOVE events are dispatched.
You can simply trace your events to find out exactly what's happening.

AS3 How to find current location of mc?

Thanks for the startdrag() suggestions, but I'm trying to avoid that atm
I'm trying to create a drag motion by using mouse_down then the mc = mouseX. Here is an image of the situation
But when I click, the mc always jumps to its registration point, which is the top left corner atm.
I can't work my head around how to grab the current location of the mc. Note that the mc (all_mc) is wider than the stage.
Can someone please help me out?
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler(e:MouseEvent) {
this.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
function mouseMoveHandler(e:MouseEvent) {
all_mc.x = mouseX;
}
Edit:
Ok I kind of worked out the x location of the mouse in relation to the registration point of the mc (the registration is at the top left):
Math.abs(stage.x - all_mc.x) + mouseX
But how to I select that point of on the mc?
Modified Marty Wallace's answer to handle the difference between where you click and the registration point:
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
public class DummyTest extends Sprite {
private var mDeltaX:Number = 0;
private var mDeltaY:Number = 0;
private var mGfx:Sprite;
public function DummyTest() {
mGfx = new Sprite();
with(mGfx.graphics) {
beginFill(0x00FF00);
drawRect(0, 0, 200, 200);
endFill();
}
addChild(mGfx);
addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private function onMouseDown(e:MouseEvent) : void {
mDeltaX = mGfx.x - mouseX;
mDeltaY = mGfx.y - mouseY;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onMouseUp(e:MouseEvent) : void {
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onEnterFrame(e:Event) : void {
mGfx.x = parent.mouseX + mDeltaX;
mGfx.y = parent.mouseY + mDeltaY;
}
}
}
import flash.events.MouseEvent;
import flash.display.Sprite;
var mc:MovieClip;
var sprite:Sprite = new Sprite ;
sprite.graphics.beginFill(0x000000);
sprite.graphics.drawRect(0,0,100,100);
sprite.graphics.endFill();
this.addChild(sprite);
sprite.addEventListener(MouseEvent.MOUSE_DOWN,function(){
sprite.startDrag();}
);
sprite.addEventListener(MouseEvent.MOUSE_UP,function(){
sprite.stopDrag();}
);
startDrag() has a lockCenter argument which you could try playing with.
lockCenter:Boolean (default =
false) — Specifies whether the
draggable sprite is locked to the
center of the mouse position (true),
or locked to the point where the user
first clicked the sprite (false).
Without startDrag as per comment
Make this the base class of an object that you want to drag:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
public class Draggable extends Sprite
{
// vars
private var _hx:Number = 0;
private var _hy:Number = 0;
/**
* Constructor
*/
public function Draggable()
{
addEventListener(MouseEvent.MOUSE_DOWN, _mouseDown);
}
/**
* MouseEvent.MOUSE_DOWN
*/
private function _mouseDown(e:MouseEvent):void
{
_hx = mouseX;
_hy = mouseY;
addEventListener(Event.ENTER_FRAME, _handle);
addEventListener(MouseEvent.MOUSE_UP, _mouseUp);
}
/**
* MouseEvent.MOUSE_UP
*/
private function _mouseUp(e:MouseEvent):void
{
removeEventListener(Event.ENTER_FRAME, _handle);
removeEventListener(MouseEvent.MOUSE_UP, _mouseUp);
}
/**
* Event.ENTER_FRAME
*/
private function _handle(e:Event):void
{
x = parent.mouseX - _hx;
y = parent.mouseY - _hy;
}
}
}
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
var positionX:Number = 0;
var positionY:Number = 0;
function mouseDownHandler(e:MouseEvent) {
positionX = all_mc.mouseX;// save the x position for future reference
positionY = all_mc.mouseY;// save the y position for future reference
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
function mouseMoveHandler(e:MouseEvent) {
all_mc.x = stage.mouseX - positionX ;
all_mc.y = stage.mouseY - positionY ;
}
function mouseUpHandler(e:MouseEvent) {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}

Need some help completing a bumptop-ish selection tool

I'm in the midst of creating a Bumptop styled selection tool. Right now I got as far as creating the tool itself (which actually works pretty good) and spreading some random square items on the stage. This is the class that creates the selection tool :
package com.reyco1.medusa.selectiontool
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
public class SelectionBase extends Sprite
{
private var points:Array = [];
public function SelectionBase()
{
super();
addEventListener(Event.ADDED_TO_STAGE, initialize);
}
private function initialize(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, initialize);
points.push(new Point(mouseX, mouseY)); stage.addEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
}
private function handleMouseMove(e:MouseEvent):void
{
graphics.clear();
graphics.beginFill(0x33CCFF, .5);
graphics.drawCircle(0, 0, 20);
graphics.endFill();
graphics.moveTo(0, 0);
graphics.lineStyle(1.5, 0x33CCFF, .5);
graphics.lineTo(mouseX, mouseY);
points.push(new Point(mouseX, mouseY));
graphics.beginFill(0x33CCFF, .1);
graphics.moveTo(points[0].x, points[0].y);
for (var i:uint = 1; i < points.length; i++)
{
graphics.lineTo(points[i].x, points[i].y);
}
graphics.lineTo(points[0].x, points[0].y);
graphics.endFill();
dispatchEvent(new Event("UPDATE"));
}
public function clear():void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
graphics.clear();
}
}
}
And this is the document class that implements it :
package
{
import com.reyco1.medusa.selectiontool.SelectionBase;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
[SWF(width = '1024', height = '768', backgroundColor = '0x000000')]
public class SelectionToolPrototype extends Sprite
{
private var selectionTool:SelectionBase;
public function SelectionToolPrototype()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.quality = StageQuality.MEDIUM;
stage.addEventListener(MouseEvent.MOUSE_DOWN, handleDown);
stage.addEventListener(MouseEvent.MOUSE_UP, handleUp);
placeShapesRandomly();
}
private function placeShapesRandomly():void
{
for(var a:Number = 0; a<25; a++)
{
var s:Sprite = new Sprite();
s.graphics.beginFill(Math.random() * 0xCCCCCC);
s.graphics.drawRect(0, 0, 50, 50);
s.graphics.endFill();
s.x = Math.floor(Math.random() * 900 - 40) + 40;
s.y = Math.floor(Math.random() * 700 - 40) + 40;
s.rotation = Math.floor(Math.random() * 360 - 40) + 40;
s.buttonMode = true;
addChild(s);
}
}
private function handleUp(e:MouseEvent):void
{
selectionTool.removeEventListener("UPDATE", handleToolUpdate);
removeChild(selectionTool);
selectionTool = null;
}
private function handleDown(e:MouseEvent):void
{
selectionTool = new SelectionBase();
selectionTool.addEventListener("UPDATE", handleToolUpdate);
selectionTool.x = mouseX;
selectionTool.y = mouseY;
addChild(selectionTool);
}
private function handleToolUpdate(e:Event):void
{
// logic to determin if items are within selection goes here
}
}
}
I've tried using collision detection by means of BitmapData and even using collision libraries like CDK but I cant get anything to work. Anybody have an idea what I should use in the handleToolUpdate(e:MouseEvent); ? Thanks!
Update:
I'll break it down. Basically I am trying to create a prototype of the BumpTop Lasso or Selection tool.
I need help in finding out which objects either collide or have a point within the bounds of the drawn lasso.
I have upload what I have so far to my server here : http://labs.reyco1.com/bumptop/SelectionToolPrototype.html. You can see the source by right clicking and selecting "View Source".
Like I said in my earlier post, I tried using Bitmapdata collision testing and even tried using the Collision Detection Kit to no avail. Thanks in advance.
Loop through the display object you are attaching your random sprites to, and using for each, check their value of hitTestObject against your selectionTool instance.
Here are the Adobe docs for hitTestObject():
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html#hitTestObject%28%29