Drawing app. How to create undo function in action script 3? - actionscript-3

Can anyone show me how can I make undo function? so this is my current action script. I cant figure how to do it and i see some example in some web site, the action script is to long to under stand. Pls show a simple way that i can make this work.
sorry for bad grammar...
import flash.display.MovieClip;
import flash.events.MouseEvent;
var pen_mc:MovieClip;
var drawing:Boolean = false;
var penSize:uint = 1;
var penColor:Number = 0x000000;
function init():void{
pen_mc = new MovieClip();
stage.addEventListener(MouseEvent.MOUSE_DOWN, startDrawing);
stage.addEventListener(MouseEvent.MOUSE_MOVE, isDrawing);
stage.addEventListener(MouseEvent.MOUSE_UP, finishedDrawing);
addChild(pen_mc);
}
init();
function startDrawing(e:MouseEvent):void{
trace("Pen Has started drawing");
drawing = true;
pen_mc.graphics.lineStyle(penSize, penColor);
pen_mc.graphics.moveTo(mouseX, mouseY);
}
function isDrawing(e:MouseEvent):void{
if(drawing){
pen_mc.graphics.lineTo(mouseX, mouseY);
}
}
function finishedDrawing(e:MouseEvent):void{
trace("finished drawing");
drawing = false;
}

You want to store every line that the user draws in a history array. When the user wants to undo, you can then step backwards through the array and remove each line one by one.

Related

Lined drawn at stage appear on the next and previous frames

I am using code for matching objects by drawing lines, the code working well but the lines drawn appear on next and previous frames when pressing next and previous buttons
`
import flash.events.MouseEvent;
import flash.display.Shape;
import flash.geom.Point;
var p1:Point = new Point();
var p2:Point = new Point();
stage.addEventListener(MouseEvent.MOUSE_DOWN, setP1);
function setP1(e:MouseEvent):void {
p1.x=mouseX;
p1.y=mouseY;
stage.addEventListener(MouseEvent.MOUSE_MOVE, draw);
s=new Shape();
stage.addChild(s);
}
var s:Shape;
function draw(e:MouseEvent):void {
s.graphics.clear();
s.graphics.lineStyle(4,0xff0000, 1);
s.graphics.moveTo(p1.x, p1.y);
p2.setTo(mouseX, mouseY);
s.graphics.lineTo(p2.x, p2.y)
}
stage.addEventListener(MouseEvent.MOUSE_UP, end);
function end(e:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, draw);
if (MC_1.hitTestPoint(p1.x,p1.y) && MC_1_1.hitTestPoint(p2.x, p2.y))
{
}
else {
s.graphics.clear();
}
}
`
Ok, I put a bit of thought into it and found out that you
attach the Shapes directly to the stage rather then to the current context
don't bother to keep track of them
I enhanced your script a bit so that it keeps everything you create there (I don't know if you are working with multiple lines, so just in case), and there's a cleanUp() method you should call to undo literally everything the rest of the script does.
import flash.events.MouseEvent;
import flash.display.Shape;
import flash.geom.Point;
var P1:Point = new Point;
var P2:Point = new Point;
// A list of Shapes that will probably stockpile here.
var Slist:Array = new Array;
// The Shape to work with.
var S:Shape;
// Subscribe to the event to start drawing.
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
function onDown(e:MouseEvent):void
{
// Subscribe to the relevant events.
stage.addEventListener(MouseEvent.MOUSE_MOVE, onDraw);
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
// Create an object for drawing.
S = new Shape;
Slist.push(S);
stage.addChild(s);
P1.x = S.mouseX;
P1.y = S.mouseY;
// First draw.
onDraw(e);
}
// Draw the line every time the mouse moves.
function onDraw(e:MouseEvent):void
{
// Memorize the endpoint coordinates.
P2.x = S.mouseX;
P2.y = S.mouseY;
// Drawing routine.
S.graphics.clear();
S.graphics.lineStyle(4,0xff0000, 1);
S.graphics.moveTo(P1.x, P1.y);
S.graphics.lineTo(P2.x, P2.y);
}
// End the drawing process.
function onUp(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onDraw);
// Last draw,
onDraw(e);
// Convert Points to stage coordinates. I know they are identical in
// the present setup, but it is not the reason to ignore the operation.
var GP1:Point = S.localToGlobal(P1);
var GP2:Point = S.localToGlobal(P2);
var aHit1:Boolean = MC_1.hitTestPoint(GP1.x, GP1.y);
var aHit2:Boolean = MC_1_1.hitTestPoint(GP2.x, GP2.y);
if (aHit1 && aHit2)
{
// Whatever you need to do here.
}
else
{
// Erase the unneeded Shape.
stage.removeChild(S);
var anIndex:int = Slist.indexOf(S);
if (anIndex > -1) Slist.splice(anIndex, 1);
S.graphics.clear();
S = null;
}
}
// Call this at the same time you go to another frame.
function cleanUp():void
{
// Clean the stockpiled objects if any.
while (Slist.length)
{
S = Slist.pop();
if (!S) continue;
if (!(S is Shape)) continue;
S.graphics.clear();
if (!S.parent) continue;
S.parent.removeChild(S);
}
// Destroy all the relevant objects.
S = null;
P1 = null;
P2 = null;
Slist = null;
// Finally, unsubscribe from DOWN handler (and the rest just in case).
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onUp);
stage.removeEventListener(MouseEvent.MOUSE_DOWN, onDown);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onDraw);
}

How would I play a sound when the collision occurs?

I am new to flash and using as3. I am in the process of making a simple catching game where the items fall from the top and you control a basket at the bottom to catch them. My script is fine and is playing without erros throughout which I am happy about, but how would I add a sound clip to this script to play when the item lands in the basket? Thanks in advance!!!
import flash.events.MouseEvent;
import flash.events.Event;
import flash.text.TextField;
var catcher:Catcher;
var createEnemyID:uint;
var gameSpeed:uint;
var droppedText:TextField;
var caughtText:TextField;
var score:uint=0;
function initGame():void{
catcher=new Catcher();
catcher.x=500;
catcher.y=1400;
addChild(catcher);
stage.addEventListener(MouseEvent.MOUSE_MOVE,moveCatcher);
Mouse.hide();
gameSpeed=500;
createEnemyID=setInterval(createEnemy,gameSpeed);
droppedText=new TextField();
droppedText.x=50;
droppedText.y=50;
addChild(droppedText);
caughtText=new TextField();
caughtText.x=250;
caughtText.y=50;
addChild(caughtText);
droppedText.text=caughtText.text='0';
}
function moveCatcher (e:MouseEvent):void{
catcher.x=this.mouseX;
e.updateAfterEvent();
}
function createEnemy():void{
var enemy:Faller=new Faller();
enemy.y=-1;
enemy.x=Math.random()*stage.stageWidth;
enemy.addEventListener (Event.ENTER_FRAME, dropEnemy);
addChild(enemy);
}
function dropEnemy(e:Event):void{
var mc:Faller=Faller(e.target);
mc.y+=15;
if(mc.hitTestObject(catcher)) {
caught(mc);
}
else if (mc.y>stage.stageHeight){
dropped(mc);
}
}
function caught(mc:Faller):void{
mc.removeEventListener (Event.ENTER_FRAME,dropEnemy);
removeChild(mc);
caughtText.text=String(Number(caughtText.text)+1);
}
function dropped(mc:Faller):void{
mc.removeEventListener (Event.ENTER_FRAME,dropEnemy);
removeChild(mc);
droppedText.text=String(Number(droppedText.text)+1);
if(droppedText.text=='5'){
gameOver();
}
}
function gameOver():void{
score=Number(caughtText.text);
stage.removeEventListener(MouseEvent.MOUSE_MOVE,moveCatcher);
removeChild(catcher);
clearInterval(createEnemyID);
removeChild(caughtText);
removeChild(droppedText);
while(numChildren>0){
getChildAt(0).removeEventListener(Event.ENTER_FRAME,dropEnemy);
removeChildAt(0);
}
Mouse.show();
gotoAndStop('gameover');
}
initGame();
import the sound into flash.
edit the properties and set the class of the sound to MySoundClass or whatever you like but you have to reference it later.
In your code write the following in the collision method.
var sound:Sound = new MySoundClass();
sound.play();
See this AS3 Sound tutorial

Flash Actionscript 3 - Simple Btn Click save game/app

I'm working on a project that requires me to save all of the bits and pieces on the second frame of the stage. This is a glorified dress up game where the user game make design or a piece of art and save the project and come back to it later by clicking the "restore_btn"
This will have multiple 'dragable' bits and pieces on the stage, on the second frame. Could someone give me some insight in how to make it so the app can save on the desktop and when the user opens it up and clicks the 'restore' button their last design loads up on the stage? Thanks for you help. I've had bit of trawl of the net and i can't find any simple tuts for what I need.
Code added, just in case.
p.s please keep it simple as I'm designer. :-)
stop();
Mouse.hide();
stage.addEventListener(MouseEvent.MOUSE_MOVE,follow);
function follow(evt:MouseEvent){
tweezer_cur.x = mouseX;
tweezer_cur.y = mouseY;
}
//Resetter btn ---------------------
reset_btn.addEventListener(MouseEvent.CLICK, startover);
function startover(event:MouseEvent):void
{
gotoAndPlay(1);
}
//------------------------------ fullscreen
function setFullScreen():void {
if (stage.displayState== "normal") {
stage.displayState="fullScreen";
stage.scaleMode = StageScaleMode.NO_SCALE;
} else {
stage.displayState="normal";
}
}
fullbtn.addEventListener(MouseEvent.CLICK, goFull);
// btn declared - - - - - - - -
function goFull(event:MouseEvent):void {
setFullScreen();
};
//---------------------------- print project
//--- all the draggables will live here
dragme.addEventListener(MouseEvent.MOUSE_DOWN, pickupObject);
dragme.addEventListener(MouseEvent.MOUSE_UP, dropObject);
function pickupObject(event:MouseEvent):void {
event.target.startDrag(true);
}
function dropObject(event:MouseEvent):void {
event.target.stopDrag();
}
//--------
//creating a container as main canvas
var artworkContainers:Sprite = new Sprite();
addChild(artworkContainers);
//example adding content
//var anyContentIWantToPrint:Sprite = new Sprite();
//anyContentIWantToPrint.graphics.beginFill(0, 1);
//anyContentIWantToPrint.graphics.drawRect(0, 0, 1024, 768);
//anyContentIWantToPrint.graphics.endFill();
//artworkContainers.addChild(anyContentIWantToPrint);
printme_btn.addEventListener(MouseEvent.CLICK, startPrintJobHandler, false, 0, true);
function startPrintJobHandler(event:MouseEvent):void
{
var printJob:PrintJob = new PrintJob();
printJob.start()
var printJobOptions:PrintJobOptions = new PrintJobOptions();
printJobOptions.printAsBitmap = true;
//When 'artworkContainer' will be your artwork canvas, where the user will drag and drop. Replace for the instance name you are using.
printJob.addPage(artworkContainers, null, printJobOptions);
printJob.send();
}
// making all of the functions save! --------------------------------
var saveData:SharedObject = SharedObject.getLocal("MyDesign");
if(!saveData.data.test)
saveData.data.test = "Test string";
trace(saveData.data.test); // Test string
This is too long to answer in a comment, so here it goes:
import flash.net.SharedObject;
import flash.geom.Point;
import flash.events.MouseEvent;
var restore_values:SharedObject=SharedObject.getLocal("dress_up_game");
if(!restore_values.data.shirt_point){
restore_values.data.shirt_point=new Point(shirt.x,shirt.y);
restore_values.flush();
}
restore_btn.addEventListener(MouseEvent.CLICK,restore);
function restore(e:MouseEvent){
if(restore_values.data.shirt_point){
shirt.x=restore_values.data.shirt_point.x;
shirt.y=restore_values.data.shirt_point.y;
}
}
shirt.addEventListener(MouseEvent.MOUSE_DOWN,start_shirt_drag);
function start_shirt_drag(e:MouseEvent){
shirt.startDrag()
}
shirt.addEventListener(MouseEvent.MOUSE_UP,stop_shirt_drag);
function stop_shirt_drag(e:MouseEvent){
shirt.stopDrag()
restore_values.data.shirt_point=new Point(shirt.x,shirt.y);
restore_values.flush();
}
It took me a few minutes to scratch this out. Once again, the button's instance name is "restore_btn". The garment or "draggable bit" goes by the instance name "shirt". The code places the shirt at the last saved position if you click the restore button. You should be able to adapt this code to your project's situation on your own.
Cheers,
Drake Swartzy
Yeah, Atriace has the right idea. Check this out:
http://www.republicofcode.com/tutorials/flash/as3sharedobject/
Cheers,
Drake Swartzy

Movieclips clashing with bitmap mask

I am trying to reveal this movie clip image which is originally a bitmap but needs to be used as a bitmap for this purpose. for some reason it's not working ...
It's not throwing any errors... I need this image to be masked as the user presses on it... and later be compared with another bitmap to carry out a function. but for some reason as I mentioned before it's not working out. can somebody please help me?? this is the code for it...
import flash.display.Graphics;
import flash.display.MovieClip;
import flash.display.BitmapData;
var mouseclick:Number=0;
var maskedbg_mc:maskedbg = new maskedbg ();
var masking:Sprite = new Sprite()
addChild (maskedbg_mc);
maskedbg_mc.x = 18;
maskedbg_mc.y = 343;
var bitmapDataCopy:BitmapData = new BitmapData(742,165,true,0x00FFFFFF);
var b:Bitmap = new Bitmap(bitmapDataCopy);
bitmapDataCopy.draw(maskedbg_mc);
b.mask = masking;
var Testing:BitmapData = new BitmapData(maskedbg_mc.width, maskedbg_mc.height, true, 0x00000000);
addChild(masking);
stage.addEventListener(MouseEvent.MOUSE_DOWN, Pressing);
stage.addEventListener(MouseEvent.MOUSE_MOVE, Moving);
stage.addEventListener(MouseEvent.MOUSE_UP, Lifting);
function Pressing(event:MouseEvent):void {
mouseclick = 1;
}
function Moving(event:MouseEvent):void {
if (mouseclick == 1) {
masking.graphics.beginFill(0x000000);
masking.graphics.drawEllipse(mouseX, mouseY, 70, 60);
masking.graphics.endFill();
}
}
function Lifting(event:MouseEvent):void {
mouseclick = 0;
}
if ( bitmapDataCopy.compare(Testing) ==0 )
{
trace ("Awesomness")
}
Overlooking your code, I notice you are not adding "b" (the masked DisplayObject) to the display list, while you are adding "maskedbg_mc" which actually isn't being masked in your code. Do you have a reason for having these 2 display objects?
I would recommend you following actionscript coding conventions:
http://sourceforge.net/adobe/flexsdk/wiki/Coding%20Conventions/
Your code looks quite confusing when you have both variables and functions with initial letter in uppercase, they look like classes.

AS3 button firing off multiple times if clicked fast only

ok so, i wrote this code:
import flash.events.Event;
import flash.display.MovieClip;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.MouseEvent;
import flash.display.Stage;
stop();
var loader:Loader = new Loader();
var defUrlReq = new URLRequest("indexCoontentLoad.swf");
var urlRequest:URLRequest = new URLRequest();
var myLoadedSwf:MovieClip = null;
var swfStage:Stage = this.stage;
/////////////// INITIATE LOADERS ///////////////
loader.load(defUrlReq);
/////////////// START MAIN HANDLER FUNCTION ///////////////
/////IMPORT DEFAULT SWF /////
loader.contentLoaderInfo.addEventListener(Event.INIT, loadedHandler);
function loadedHandler(event:Event){
myLoadedSwf = event.target.content;
addChild(myLoadedSwf);
trace(myLoadedSwf);
myLoadedSwf.gotoAndPlay("intro");
trace("STEP 1 -- ext def swf loaded");
}
///////END IMPORT. ///////////////
///// START LISTENERS AND THEIR FUNCTIONS /////
load1.addEventListener(MouseEvent.CLICK,btn4Clicked);
load2.addEventListener(MouseEvent.CLICK,btn4Clicked);
load3.addEventListener(MouseEvent.CLICK,btn4Clicked);
///// END LISTENERS /////
///// START FUNCTIONS /////
function btn4Clicked(e:MouseEvent):void { //-- START btn4Loaded
if (e.target == load1 || e.target == load2 || e.target == load3) {
myLoadedSwf.gotoAndPlay("outro");
removeChild(myLoadedSwf);
urlRequest = new URLRequest(e.target.name+".swf");
loader.load(urlRequest);
addChild(myLoadedSwf);
}
}
and it works, once clicked, it does what it has to do. Ofcourse, me trying to break it, i found that if i click the buttons fast, it will re-import the external swfs causing me to have multiple instances of the external swf.
so in short, if i click like normal(slow ) ie like a person that clicked to view a section etc, then its fine, if i click fast or repeated clicking ie like a person that double clicks etc, then the problem occurs.
any ideas how to fix this?
thanks in advance.
edit*** heres a link to test file to show what i mean
http://www.somdowprod.net/4testing/flash/tst
When you set doubleClick to enabled on your movieclip, this will work. The Flash runtime will thencheck for you if it is a double click and only trigger your method once. If you want to listen for the double clicks, you can by changing the event handler.
mySprite.doubleClickEnabled = true;
mySprite.addEventHandler(MouseEvent.CLICK, onClick);
Good luck.
You could try adding a boolean variable that is set to false. Once the .swf is loaded then change that variable to equal true. Then don't let the swf be loaded unless it is set to false. That way it'll only be allowed to be loaded once.
var isLoaded:Boolean = false;
function btn4Loaded(e:Event):void
{ //-- START btn4Loaded
if(!isLoaded)
{
if (e.target == load1 || e.target == load2) {
myLoadedSwf.gotoAndPlay("outro");
removeChild(myLoadedSwf);
urlRequest = new URLRequest(e.target.name+".swf");
loader.load(urlRequest);
addChild(myLoadedSwf);
isLoaded = false;
}
}
} // end btn4Loaded.