Action script 3 drawing app undo and redo function - actionscript-3

Can anyone show me how can I make undo and redo 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;
var shapes:Vector.<Shape>=new Vector.<Shape>();
var position:int=0;
const MAX_UNDO:int=10;
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;
var sh:Shape=new Shape();
sh.graphics.copyFrom(pen_mc.graphics); // put current state into the vector
shapes.push(sh);
if (shapes.length>MAX_UNDO) shapes.unshift(); // drop oldest state
position=shapes.indexOf(sh);
}
function undo():void {
if (position>0) {
position--;
pen_mc.graphics.copyFrom(shapes[position].graphics);
} // else can't undo
}
function redo():void {
if (position+1<shapes.length) {
position++;
pen_mc.graphics.copyFrom(shapes[position].graphics);
} // else can't redo
}
function btn_undo(e:MouseEvent):void
{
undo();
}
function btn_redo(e:MouseEvent):void
{
redo();
}
undo_btn.addEventListener(MouseEvent.CLICK, btn_undo);
redo_btn.addEventListener(MouseEvent.CLICK, btn_redo);

You can use copyFrom() in Shape.graphics to store current condition, and the same to "redo", as your canvas is a Shape.
var shapes:Vector.<Shape>=new Vector.<Shape>();
var position:int=0;
const MAX_UNDO:int=10;
...
function finishedDrawing(e:MouseEvent):void{
trace("finished drawing");
drawing = false;
var sh:Shape=new Shape();
sh.graphics.copyFrom(penMC.graphics); // put current state into the vector
shapes.push(sh);
if (shapes.length>MAX_UNDO) shapes.unshift(); // drop oldest state
position=shapes.indexOf(sh);
}
function undo():void {
if (position>0) {
position--;
penMC.graphics.copyFrom(shapes[position].graphics);
} // else can't undo
}
function redo():void {
if (position+1<shapes.length) {
position++;
penMC.graphics.copyFrom(shapes[position].graphics);
} // else can't redo
}
This approach lacks some features, as to drop part of undo/redo stack if first undone to a certain point, then drawn. You can try adding this function yourself.

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 to stop the timer and move to next scene when puzzle is solved

I created a jigsaw in action script and kept it a separate class. In the project i linked the code and i added a timer to the scene so that the player have to solve the puzzle within the time specified. Now what i want is that if the player solved the puzzle correctly the timer will stop and go to next scene.
this is the puzzle.as
var xpos:Array=new Array();
var ypos:Array=new Array();
var numDone,i:int;
var numPieces:int=3;
var dif:int=25; //how close do they have to drag the piece
var sound:Sound=new Sound();
function playSound(file:String): void {
//var sound:Sound=new Sound();
var req:URLRequest=new URLRequest(file);
sound.load(req);
sound.play();
} //playSound
function scramble(): void {
for(i=0;i<numPieces;i++){
this["piece"+i].x=Math.random()*300;
this["piece"+i].y=Math.random()*500;
this["piece"+i].alpha=.8;
} //for each piece
numDone=0;
txtMessage.text="Drag the pieces to solve the puzzle";
sound.close();
} //scramble
function init(): void {
for(i=0;i<numPieces;i++){
xpos[i]=this["piece"+i].x;
ypos[i]=this["piece"+i].y;
this["piece"+i].addEventListener(MouseEvent.MOUSE_DOWN, beginMove);
this["piece"+i].addEventListener(MouseEvent.MOUSE_UP, endMove);
} //for each piece
txtMessage.text="Drag the pieces to solve the puzzle";
} //init
function beginMove(e:MouseEvent): void {
if(e.target.alpha<1)
e.target.startDrag();
} //beginMove
function endMove(e:MouseEvent): void {
if(e.target.alpha<1) {
e.target.stopDrag();
//figure out which piece it is
var piece:int=0;
while(e.target!=this["piece"+piece]){
piece++;
} //
var curX:int=this["piece"+piece].x;
var curY:int=this["piece"+piece].y;
if(curX<=xpos[piece]+dif && curX>=xpos[piece]-dif &&
curY<=ypos[piece]+dif && curY>=ypos[piece]-dif) { //close enough
this["piece"+piece].x=xpos[piece];
this["piece"+piece].y=ypos[piece];
this["piece"+piece].alpha=1;
numDone++;
if(numDone>=numPieces) gameOver();
else playSound("http://www.zebra0.com/langResource/ok.mp3");
} //in position
} //not already done
}//endMove
function gameOver(): void {
txtMessage.text="You did it!";
playSound("http://www.zebra0.com/langResource/win.mp3");
gotoAndStop(1,"Scene 2");
} //gameOver
function scrambleHandler(e:MouseEvent): void {
scramble();
} //clickHandler
btnScramble.addEventListener(MouseEvent.CLICK,scrambleHandler);
function solve(e:MouseEvent): void {
for(i=0;i<numPieces;i++) {
this["piece"+i].x=xpos[i];
this["piece"+i].y=ypos[i];
this["piece"+i].alpha=1;
} //for each piece
} //solve
the code for linking the puzzle.as to the project. i kept in a layer called 'ActionScript'
include "Puzzle.as"
numPieces=20;
init();
scramble();
stop();
timer code i kept in a layer called 'action'
var nCount:Number = 90;
var myTimer:Timer = new Timer(1000, nCount);
timer_txt.text = nCount.toString();
myTimer.start();
myTimer.addEventListener(TimerEvent.TIMER, countdown);
myTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onComplete);
function countdown(e:TimerEvent):void
{
nCount--;
timer_txt.text = nCount.toString();
}
function onComplete(e: TimerEvent):void{
gotoAndStop(35);
}
if any one have an idea of how to achieve this.

AS3 Fill Color inside line by pen

I was trying to make a flash app with AS3 where I can draw line with pen tool with different colors , also fill the shapes on an image with different colors, now I have went through various tutorials and achieved it, however in the end I am faced with 2 problems that I am unable to solve even after 3 days of efforts:
How can I fill color inside the shapes formed by using the pen tool,
say if I draw a rough circle using pen tool and then I try and fill
it with green, how can I detect MovieClips which I need to fill.
When I draw lines over shapes and then try and fill the shapes, the
shapes gets filled but the lines still appear on top of the shapes
filled with color.
You can get a better idea of what I have achieved by visiting this link, click the pen symbol and paint bucket symbol to see how it works.
Below is my code for pen tool and fill color:
I draw a sprite add an image and then use the property to detect color to draw a line of color I choose, followed by code to fill color where I divide the image in various MovieClips and then make then into one and detect if mouse is clicked on which clip and fill it with selected color.
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
bucbut.addEventListener(MouseEvent.CLICK,nClick0PC);
/////////////pentool code --------
convertToBMD();
pbut.addEventListener(MouseEvent.CLICK,nClick0P);
function nClick0P(event:MouseEvent):void{
spBoard.addEventListener(MouseEvent.ROLL_OUT,boardOut);
spBoard.addEventListener(MouseEvent.MOUSE_MOVE,boardMove);
spBoard.addEventListener(MouseEvent.MOUSE_DOWN,boardDown);
spBoard.addEventListener(MouseEvent.MOUSE_UP,boardUp);
}
var spBoard:Sprite=new Sprite();
this.addChildAt(spBoard,0);
spBoard.x=20;
spBoard.y=100;
var owl2:owl;
owl2 = new owl();
owl2.name="owl1";
spBoard.addChildAt(owl2,0);
owl2.x=315;
owl2.y=180;
var shDrawing:MovieClip = new MovieClip();
//var shDrawing:Shape=new Shape();
spBoard.addChild(shDrawing);
//spBoard.addChildAt(shDrawing,1);
function nClick0PC(event:MouseEvent):void{
owl2.addEventListener(MouseEvent.CLICK,on_owl_click);
}
var doDraw:Boolean=false;
var lineSize:Number=10;
var currentColor:Number;
spBoard.graphics.lineStyle(1,0x000000);
spBoard.graphics.beginFill(0xFFFFFF);
spBoard.graphics.drawRect(0,0,602,330);
spBoard.graphics.endFill();
spBoard.filters = [ new DropShadowFilter() ];
function boardOut(e:MouseEvent):void {
doDraw=false;
}
function boardDown(e:MouseEvent):void {
doDraw=true;
trace(activeColor);
shDrawing.graphics.lineStyle(lineSize,activeColor);
shDrawing.graphics.endFill();
shDrawing.graphics.moveTo(shDrawing.mouseX,shDrawing.mouseY);
}
function boardUp(e:MouseEvent):void {
doDraw=false;
}
function boardMove(e:MouseEvent):void {
var curX:Number=shDrawing.mouseX;
var curY:Number=shDrawing.mouseY;
if(doDraw && checkCoords(curX,curY)){
shDrawing.graphics.lineTo(curX,curY);
e.updateAfterEvent();
}
}
function checkCoords(a:Number,b:Number):Boolean {
if(a>=605-lineSize/2 || a<=lineSize/2 || b>=311-lineSize/2 || b<=lineSize/2){
return false;
}
else {
return true;
}
}
/////////////---------------------color picker
colors.addEventListener(MouseEvent.MOUSE_UP, chooseColor);
var pixelValue:uint;
var activeColor:uint = 0x000000;
var ct:ColorTransform = new ColorTransform();
var colorsBmd:BitmapData;
function convertToBMD():void
{
colorsBmd = new BitmapData(colors.width,colors.height);
colorsBmd.draw(colors);
}
function chooseColor(e:MouseEvent):void
{
pixelValue = colorsBmd.getPixel(colors.mouseX,colors.mouseY);
activeColor = pixelValue;//uint can be RGB!
ct.color = activeColor;
//shapeSize.transform.colorTransform = ct;
}
////////////////////========================================Fill color
function on_owl_click(e:MouseEvent):void {
for (var i:int = 0; i < owl2.numChildren; i++) {
if (owl2.getChildAt(i).hitTestPoint(mouseX,mouseY,true)) {
trace(owl2.getChildAt(i).name);
owl2.getChildAt(i).transform.colorTransform= ct;
}
}
}
I deleted a lot of your code and left this:
convertToBMD();
colors.addEventListener(MouseEvent.MOUSE_UP, chooseColor);
var activeColor: uint = 0x000000;
var colorsBmd: BitmapData;
function convertToBMD(): void
{
colorsBmd = new BitmapData(colors.width, colors.height);
colorsBmd.draw(colors);
}
function chooseColor(e: MouseEvent): void
{
var pixelValue:uint = colorsBmd.getPixel(colors.mouseX, colors.mouseY);
activeColor = pixelValue; //uint can be RGB!
}
Also I removed an owl at the stage. Download my FLA to see changes.
Next. I added two canvases.
var canvasData:BitmapData = new BitmapData(650, 437, false, 0xEFEFEF);
var canvas:Bitmap = new Bitmap(canvasData);
canvas.x = 0;
canvas.y = 102;
addChild(canvas);
var penCanvas:Shape = new Shape();
penCanvas.x = canvas.x;
penCanvas.y = canvas.y;
You can read about Bitmap and BitmapData here.
First canvas it's a raster image. Second canvas it's a Shape, so you can use moveTo and lineTo methods to draw with a pencil.
Next. In library i found an owl image and export it to code.
If not understand, I can explain more detailed.
Next. Registration event handlers.
bucbut.addEventListener(MouseEvent.CLICK, clickBucket);
pbut.addEventListener(MouseEvent.CLICK, clickPen);
function clickBucket(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_DOWN, canvasDown);
stage.addEventListener(MouseEvent.CLICK, clickOnCanvas);
}
function clickPen(event:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, canvasDown);
stage.removeEventListener(MouseEvent.CLICK, clickOnCanvas);
}
Let's see at clickOnCanvas method:
function clickOnCanvas(event:MouseEvent):void
{
// If we click at the canvas
if (canvas.hitTestPoint(mouseX,mouseY))
{
canvasData.floodFill(canvas.mouseX, canvas.mouseY,activeColor);
}
}
About floodFill you can read here.
And the last three methods used to draw by pen.
function canvasDown(event:MouseEvent):void
{
penCanvas.graphics.lineStyle(10, activeColor);
penCanvas.graphics.moveTo(penCanvas.mouseX, penCanvas.mouseY);
// only when mouse button is down we register two handlers, one for move and another for mouse up
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
}
function mouseMove(event:MouseEvent):void
{
// when mouse is moving we are drawing line
penCanvas.graphics.lineTo(penCanvas.mouseX, penCanvas.mouseY);
// As I said earlier canvasData it's a raster image. So we copy penCanvas and paste to canvasData.
canvasData.draw(penCanvas);
// For a smoother drawing
event.updateAfterEvent();
}
function mouseUp(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp);
}
That's all!
Here you can download sources.

How to make a movie clip visible if only five movie clips (not more) are clicked

I have 25 movie clips on stage and they all can be clicked and colored. I want a movie clip named text_mc to became visible if only 5 specific buttons from those are clicked and colored - not more. If the user choose more than those five movie clips (even thought that 5 movie clips are included) then the movie clip named text_mc should stay invisible. I can' t do the last part: if more than those 5 specific movie clips are clicked then the text_mc should stay invisible. Can you please help me? This is my code
stop();
import flash.display.MovieClip;
var sximata:MovieClip = square1;
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.ColorTransform;
text_mc.visible=false;
square1.addEventListener(MouseEvent.CLICK, onsquare1);
function onsquare1(e:MouseEvent):void {
sximata = square1;
}
square2.addEventListener(MouseEvent.CLICK, onsquare2);
function onsquare2(e:MouseEvent):void {
sximata = square2;
}
square3.addEventListener(MouseEvent.CLICK, onsquare3);
function onsquare3(e:MouseEvent):void {
sximata = square3;
}
square4.addEventListener(MouseEvent.CLICK, onsquare4);
function onsquare4(e:MouseEvent):void {
sximata = square4;
}
square5.addEventListener(MouseEvent.CLICK, onsquare5);
function onsquare5(e:MouseEvent):void {
sximata = square5;
}
square6.addEventListener(MouseEvent.CLICK, onsquare6);
function onsquare6(e:MouseEvent):void {
sximata = square6;
}
square7.addEventListener(MouseEvent.CLICK, onsquare7);
function onsquare7(e:MouseEvent):void {
sximata = square7;
}
square8.addEventListener(MouseEvent.CLICK, onsquare8);
function onsquare8(e:MouseEvent):void {
sximata = square8;
square8Clicked = true;
checkButtons();
}
square9.addEventListener(MouseEvent.CLICK, onsquare9);
function onsquare9(e:MouseEvent):void {
sximata = square9;
square9Clicked = true;
checkButtons();
}
square10.addEventListener(MouseEvent.CLICK, onsquare10);
function onsquare10(e:MouseEvent):void {
sximata = square10;
square10Clicked = true;
checkButtons();
}
square11.addEventListener(MouseEvent.CLICK, onsquare11);
function onsquare11(e:MouseEvent):void {
sximata = square11;
}
square12.addEventListener(MouseEvent.CLICK, onsquare12);
function onsquare12(e:MouseEvent):void {
sximata = square12;
}
square13.addEventListener(MouseEvent.CLICK, onsquare13);
function onsquare13(e:MouseEvent):void {
sximata = square13;
square13Clicked = true;
checkButtons();
}
square14.addEventListener(MouseEvent.CLICK, onsquare14);
function onsquare14(e:MouseEvent):void {
sximata = square14;
square14Clicked = true;
checkButtons();
}
square15.addEventListener(MouseEvent.CLICK, onsquare15);
function onsquare15(e:MouseEvent):void {
sximata = square15;
}
square16.addEventListener(MouseEvent.CLICK, onsquare16);
function onsquare16(e:MouseEvent):void {
sximata = square16;
}
square17.addEventListener(MouseEvent.CLICK, onsquare17);
function onsquare17(e:MouseEvent):void {
sximata = square17;
}
square18.addEventListener(MouseEvent.CLICK, onsquare18);
function onsquare18(e:MouseEvent):void {
sximata = square18;
}
square19.addEventListener(MouseEvent.CLICK, onsquare19);
function onsquare19(e:MouseEvent):void {
sximata = square19;
}
square20.addEventListener(MouseEvent.CLICK, onsquare20);
function onsquare20(e:MouseEvent):void {
sximata = square20;
}
square21.addEventListener(MouseEvent.CLICK, onsquare21);
function onsquare21(e:MouseEvent):void {
sximata = square21;
}
square22.addEventListener(MouseEvent.CLICK, onsquare22);
function onsquare22(e:MouseEvent):void {
sximata = square22;
}
square23.addEventListener(MouseEvent.CLICK, onsquare23);
function onsquare23(e:MouseEvent):void {
sximata = square23;
}
square24.addEventListener(MouseEvent.CLICK, onsquare24);
function onsquare24(e:MouseEvent):void {
sximata = square24;
}
square25.addEventListener(MouseEvent.CLICK, onsquare25);
function onsquare25(e:MouseEvent):void {
sximata = square25;
}
var myColorTransform:ColorTransform=transform.colorTransform;
red_btn.addEventListener(MouseEvent.CLICK, changeColour);
function changeColour(event:MouseEvent):void {
myColorTransform.color=0xBD8D46;
sximata.transform.colorTransform=myColorTransform;
}
resetButton.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler);
function fl_MouseClickHandler(event:MouseEvent):void
{
gotoAndPlay(1);
}
var square8Clicked:Boolean = false;
var square9Clicked:Boolean = false;
var square10Clicked:Boolean = false;
var square13Clicked:Boolean = false;
var square14Clicked:Boolean = false;
function checkButtons():void
{
if(square8Clicked && square9Clicked && square10Clicked && square13Clicked && square14Clicked)
{
text_mc.visible = true;
}
}
You could add a boolean variable to each of the other functions that turns to true if any of the other squares are clicked. For example:
var isClicked:Boolean = false;
square1.addEventListener(MouseEvent.CLICK, onsquare1);
function onsquare1(e:MouseEvent):void {
sximata = square1;
isClicked = true;
}
And then in your check buttons function, check to see if "isClicked" is still false:
function checkButtons():void
{
if(!isClicked && square8Clicked && square9Clicked && square10Clicked && square13Clicked && square14Clicked)
{
text_mc.visible = true;
}
}
My solution is below. It's based on counting the number of clicks received by each type of MovieClip the user can click on.The relevant parts of the code would be in the onClick() and checkClickCounts() methods.
First, you'll see that in the buildMCs() method I simply create a bunch of MovieClips and place them on the stage in a grid. I've made it so that the "specific" MCs that you mention are the first items on each row of the grid. To each of these "specific" MCs, I've added a property: isSpecial:Boolean and set it to true. Later, when a MC is clicked, the OnClick() method will check to see if the MC was special or not, and will increment the relevant click count property. Then, checkClickCounts() is called. If 5 good clicks and 0 bad clicks are counted up, then we let the user know. This is where you'd display your textfield. (In my case, I just draw a big red rectangle on the screen.
Another suggestion I demo here is to avoid repeating your mouse click code. If you look in the constructor, you'll see that I used this line:
this.addEventListener(MouseEvent.CLICK, onClick);
This tells the main stage sprite to listen to all mouse clicks, even the ones that happen to MovieClips inside of it. In the onClick() method I check to see if the item clicked - the target of the event - was a MovieClip. If it was, then I do the additional checking to see if the MC clicked was one that I wanted. By doing this, I was able to write the code for handling the mouse clicks once, and now if I need to change something, I only have to do it one time, rather than 25 times. Saves me time, but also makes the code less error-prone because I'm less likely to miss something if there's a change that needs to be made.
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
public class Clicky extends Sprite
{
public function Clicky()
{
this.buildMCs();
this.addEventListener(MouseEvent.CLICK, onClick);
}
private function buildMCs ():void
{
var rows:int = 5;
var cols:int = 5;
var boxSize:int = 10;
for (var r:int = 0; r < rows; r++)
{
for (var c:int = 0; c < cols; c++)
{
var newMC:MovieClip = new MovieClip();
newMC.graphics.lineStyle(0, 0x00ff00);
// want to mark the "specific" movieclips
if (c == 0)
{
newMC.graphics.beginFill(0x0000ff);
// just something that makes this MC unique... ideally
// this would be not a MovieClip, but a class that defines
// actual properties worth checking for
newMC.isSpecial = true;
}
else
{
newMC.graphics.beginFill(0x00ff00);
}
newMC.graphics.drawRect(0, 0, boxSize, boxSize);
this.addChild(newMC);
newMC.x = (c * boxSize);
newMC.y = (r * boxSize);
}
}
}
private function onClick (e:MouseEvent):void
{
if (e.target is MovieClip)
{
var mc:MovieClip = e.target as MovieClip;
mc.alpha = .25;
// disable the clicking for the clicked item
mc.mouseEnabled = false;
if (mc.isSpecial)
{
_specialClicks++;
}
else
{
_badClicks++;
}
this.checkClickCounts();
}
}
private var _specialClicks:int = 0;
private var _badClicks:int = 0;
private function checkClickCounts ():void
{
if (_specialClicks == 5 && _badClicks == 0)
{
// do your thing - show the text_mc, play a sound, award a prize, etc.
this.graphics.beginFill(0xff0000);
this.graphics.drawRect(0, 0, 1000, 1000);
}
}
}
}

Drawing app undo and redo function action script 3

Can anyone show me how can I make undo and redo 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...
var drawingLine:Shape=new Shape();
board.addChild(drawingLine);
var doDraw:Boolean=false;
var lineSize:Number=7;
var activeColor:uint = 0x000000;
function PencilTool(event:MouseEvent):void{
board.addEventListener(MouseEvent.MOUSE_DOWN, MouseDown);
board.addEventListener(MouseEvent.MOUSE_UP, MouseUp);
}
function MouseDown(e:MouseEvent):void{
doDraw=true;
drawingLine.graphics.moveTo(drawingLine.mouseX, drawingLine.mouseY);
drawingLine.graphics.lineStyle(lineSize, activeColor);
board.addEventListener(MouseEvent.MOUSE_MOVE, MouseMove);
}
function MouseMove(e:MouseEvent):void{
var curX:Number=drawingLine.mouseX;
var curY:Number=drawingLine.mouseY;
if(doDraw && checkCoords(curX,curY)){
if(active=="Line"){
clearTemp();
temporaryDrawing.graphics.lineTo(curX,curY);
}else{
drawingLine.graphics.lineTo(curX,curY);
}
e.updateAfterEvent();
}
}
function MouseUp(event:MouseEvent):void{
doDraw=false;
}
btn_Pencil.addEventListener(MouseEvent.MOUSE_UP, PencilTool);
this,o Using two graphics,would not be the way to go
The way I would approach this is by creating a lineInfo class (seeing how you are using lines only), and have the information of startpoint, endpoint, lineColour, lineWidth, and lineAlpha .
Then create an array or Vector and populate it with a new LineInfo class, and update the graphics with the line. If you need to undo, you can set the last item use value to false, and redraw the graphics from the instruction of the array. Create a undo step integer, that keeps track of how many (counting from the back) actions should be omitted.
To improve performance, you can create a maximum of 25 instructions, and create a graphics that caches the items not in the undo list.
You could save all movements after clicks in an array or vector, then if you want to undo, you redraw all movements in the array except the last one.
Could be something like this:
var drawingLine:Shape=new Shape();
board.addChild(drawingLine);
// MOVEMENTS INFORMATION
var movements:Array = new Array();
var doDraw:Boolean = false;
var cacheIndex:int = 0;
var lineSize:Number=7;
var activeColor:uint = 0x000000;
function PencilTool(event:MouseEvent):void{
board.addEventListener(MouseEvent.MOUSE_DOWN, MouseDown);
board.addEventListener(MouseEvent.MOUSE_UP, MouseUp);
}
function MouseDown(e:MouseEvent):void{
function PencilTool(event:MouseEvent):void{
board.addEventListener(MouseEvent.MOUSE_DOWN, MouseDown);
board.addEventListener(MouseEvent.MOUSE_UP, MouseUp);
}
function MouseDown(e:MouseEvent):void{
doDraw=true;
drawingLine.graphics.moveTo(drawingLine.mouseX, drawingLine.mouseY);
drawingLine.graphics.lineStyle(lineSize, activeColor);
board.addEventListener(MouseEvent.MOUSE_MOVE, MouseMove);
lastTracing = {
mainPoint: {
x:drawingLine.mouseX,
y:drawingLine.mouseY
},
lineSize: lineSize,
activeColor:activeColor,
points:new Array()
}
cacheIndex = 0;
movements.splice(movements.length - cacheIndex, cacheIndex);
movements.push(lastTracing );
}
function MouseMove(e:MouseEvent):void{
var curX:Number=drawingLine.mouseX;
var curY:Number=drawingLine.mouseY;
if(doDraw && checkCoords(curX,curY)){
if(active=="Line"){
clearTemp();
temporaryDrawing.graphics.lineTo(curX,curY);
}else{
drawingLine.graphics.lineTo(curX,curY);
lastTracing.points.push({x:curX, y:curY});
}
e.updateAfterEvent();
}
}
function MouseUp(event:MouseEvent):void{
doDraw=false;
}
function undoFunction(event:MouseEvent=null):void {
if(cacheIndex+1 <= movements.length){
cacheIndex++;
}
drawCache();
}
function redoFunction(event:MouseEvent = null):void {
if(cacheIndex-1 >= 0){
cacheIndex--;
}
drawCache();
}
function drawCache():void {
for(var i:uint=0;i<(movements.length-cacheIndex);i++){
var tracingInfo:Object = movements[i];
drawingLine.graphics.clear();
drawingLine.graphics.moveTo(tracingInfo.mainPoint.x, tracingInfo.mainPoint.y);
drawingLine.graphics.lineStyle(tracingInfo.lineSize, tracingInfo.activeColor);
for(var j:uint=0;j<tracingInfo.points.length;j++){
drawingLine.graphics.lineTo(tracingInfo.points[j].x,tracingInfo.points[j].y);
}
}
}
btn_Pencil.addEventListener(MouseEvent.MOUSE_UP, PencilTool);