AS3: Live drawing? - actionscript-3

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.

Related

How to have different mouse cursor on MOUSE_DOWN in as3?

I'm new to as3 and I need to do a very simple thing. I have following code and it works pretty well. But what I need and can't figure out how to do it is:
change mouse cursor when I hold mouse button (choose from symbols)
ability to move with it (normally it would disappear when I move with mouse)
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import fl.motion.MotionEvent;
var CursorStill: Sprite;
var CursorAnim: Sprite;
function init() {
Mouse.hide();
CursorStill = new CursorStillClass();
CursorStill.mouseEnabled = false;
CursorStill.visible = false;
addChild(CursorStill);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
}
function mouseMoveHandler(evt: MouseEvent): void {
CursorStill.visible = true;
CursorStill.x = evt.stageX;
CursorStill.y = evt.stageY;
evt.updateAfterEvent();
}
function mouseLeaveHandler(evt: Event): void {
CursorStill.visible = false;
}
function mouseDownHandler (evt: MouseEvent): void {
CursorStill.visible = false;
}
init();
a friend of mine helped me and i figured it out. i hope it will help other newbies at least :)
import flash.events.Event;
import flash.events.MouseEvent;
import fl.motion.MotionEvent;
function init() {
Mouse.hide();
// this creates an instance of the library MovieClip with the
// name, "MyCursorClass". this contains your mouse cursor art
//
Cursor = new CursorClass();
Cursor.mouseEnabled = false;
Cursor.visible = false;
// you'll want to make sure the child is added above everything
// else, possibly in its own container
//
addChild(Cursor);
// respond to mouse move events
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
function mouseMoveHandler(evt: MouseEvent): void {
// whenever the mouse moves, place the cursor in the same spot
Cursor.visible = true;
Cursor.x = evt.stageX;
Cursor.y = evt.stageY;
// for smoother mouse pointer
evt.updateAfterEvent();
}
function mouseLeaveHandler(evt: Event): void {
Cursor.visible = false;
}
function mouseDownHandler(evt: MouseEvent): void {
Cursor.gotoAndStop(xx);
}
function mouseUpHandler(evt: MouseEvent): void {
Cursor.gotoAndStop(xx);
}
init();
most credits goes to this tutorial though
http://danielmclaren.com/2008/03/tips-for-using-custom-mouse-cursors-in-flash-as3

AS3 lineTo method alternative

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();
}
}
}

AS3 MouseEvent.CLICK Interaction on Different Indexes

I'm currently working through a AS3 game tutorial on Lynda.com and am coming across a problem with the MouseEvent.CLICK and child indexes. The game is a simple point and shoot, where the player must shoot all of the approaching enemies before they get too close. It works initially, however the custom cursor I added displays behind the enemies. However when I try and adjust the index (I've used the addChildAt function and moving the addChild(cursor) line of code below the enemy container initializer) the on click interaction, which is supposed to remove the enemy when clicked on, doesn't work.
My document class:
package {
import flash.display.*;
import flash.utils.*;
import flash.events.*;
import flash.ui.*;
public class Game extends MovieClip {
public var cursor:Cursor;
public var enemy:Enemy;
public var numberOfEnemies:uint;
public var enemyContainer:MovieClip;
public var enemyTimer:Timer;
public function Game() {
addEventListener(Event.ADDED_TO_STAGE, init);
Mouse.hide();
}
public function init(event:Event):void {
cursor = new Cursor;
addChild(cursor);
stage.addEventListener(MouseEvent.MOUSE_MOVE, dragCursor);
numberOfEnemies = 10;
enemyTimer = new Timer(1000, numberOfEnemies);
enemyContainer = new MovieClip();
addChild(enemyContainer);
enemyTimer.addEventListener(TimerEvent.TIMER, createEnemies);
enemyTimer.start();
}
public function dragCursor(event:MouseEvent) {
cursor.x = this.mouseX;
cursor.y = this.mouseY;
}
public function createEnemies(event:TimerEvent):void {
enemy = new Enemy();
enemy.x = 25 + Math.random() * (stage.stageWidth - 75);
enemy.y = 25 + Math.random() * (stage.stageHeight - 75);
enemyContainer.addChild(enemy);
enemy.timerStart();
}
}
}
My enemy class:
package {
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.ui.Mouse;
import flash.events.*;
public class Enemy extends MovieClip {
public var scaleObj:Number = 0.50;
public var growTimer:Timer;
public function Enemy() {
scaleX = scaleObj;
scaleY = scaleObj;
addEventListener(MouseEvent.CLICK, shootEnemy);
}
public function timerStart() {
growTimer = new Timer(50);
growTimer.addEventListener(TimerEvent.TIMER, objectGrow);
growTimer.start();
}
public function objectGrow(event:TimerEvent):void {
if(scaleObj <= 1.0) {
scaleObj += 0.01;
scaleX = scaleObj;
scaleY = scaleObj;
}
else {
killEnemy();
}
}
public function killEnemy():void {
this.parent.removeChild(this);
growTimer.stop();
}
public function shootEnemy(event:MouseEvent):void {
killEnemy();
}
}
}
There also is a cursor class, however there is no code beyond the package and class definers. Please let me know of any questions or comments you might have, thanks.
Most likely the Cursor object is intercepting the mouse click since it is above the Enemy object.
You can stop the Cursor from intercepting mouse events by setting in the cursor class:
this.mouseEnabled = false;
this.mouseChildren = false;
Also, you should ideally be using a native mouse cursor instead of manually creating your own. Check out this Adobe tutorial for an example.
Set your Cursor instance to not receive mouse events itself as it would block the click events from getting to the objects behind it. Code would be something like
cursor = new Cursor;
cursor.mouseEnabled = false;
cursor.mouseChildren = false;

Dragging a movieclip as3

I have a Movieclip which is a child of another movieclip. I use startDrag() and stopDrag() with first (parent) Movieclip but the nested one doesnt move. Why?
relevant code on stage:
var main:rt = new rt(); // rt being a class in my library, which extends MovieClip object.
addChild(main);
stage.addEventListener(MouseEvent.MOUSE_DOWN, stage_mousedownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseupHandler);
function stage_mousedownHandler(event_object:Event) {
main.startDrag();
}
function stage_mouseupHandler(event_object:Event) {
main.stopDrag();
}
rt's constructor code:
public function rt() {
var bmp_bar:Bitmap;
var br_male:Bar_male; // Bar_male is a Bitmap in my library. (AS Linkage)
bmp_bar = new Bitmap(br_male);
this.addChild(bmp_bar);
}
Made this simple program to test and it works as expected in Flash Develop, there is a main sprite and a child bitmap when I mouse down any where on stage the main sprite is dragged and the child bitmap is moved.
So I am guessing there is something going on in your workflow in flash professional and linkage. Make sure the mouse event handlers are triggered put some breakpoints and debug.
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
public class Test extends Sprite
{
private var sp:Sprite = new Sprite();
public function Test()
{
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
var bmpData:BitmapData = new BitmapData(100, 100,false,0x000000);
bmpData.fillRect(new Rectangle(0, 0, 100, 100), 0xff0000);
var bmp:Bitmap = new Bitmap(bmpData);
sp.addChild(bmp);
addChild(sp);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onMouseUp(e:MouseEvent):void
{
sp.stopDrag();
}
private function onMouseDown(e:MouseEvent):void
{
sp.startDrag();
}
}
}

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);
}