FloodFill in AS3 - actionscript-3

I have been making a basic painting application similar to MS-Paint with basic paint, eraser and fill tools. It's this last one that's giving me some trouble.
I'm pretty new to using BitmapData but the idea is that when the user clicks the board, it triggers the startFloodFill method. This is shown below:
public static function startFloodFill(e:MouseEvent):void
{
trace("FLOODFILL");
var boardRef:MovieClip = e.currentTarget.parent.board; //Creates a reference to the board
var boardData:BitmapData = new BitmapData(boardRef.width, boardRef.height); //Creates a new BitmapData with the same size as boardRef
boardData.floodFill(e.localX, e.localY, 0x00CCCCCC); //Applies the FloodFill
boardData.draw(boardRef); //Saves the boardRef as bitmapData
boardRef.bitmapData = boardData; //Updates the board
boardRef.parent.addChild(boardRef);
}
Can anybody tell me what I've done wrong here? When I click, the board does not change. I expected the FloodFill to fill the entire bitmap with the chosen colour as the board is blank when I click.
I also tried replacing the last two lines with:
boardRef.addChild(new Bitmap(boardData) ); //Updates the board
Thanks

The problem is that you first use the floodFill, and then use the draw method, which actually fills the BitmapData with whatever param you give it - in your case it's the boardRef.
You should first draw the boardRef into the boardData, and then use floodFill. At the end, you need to create new Bitmap and display it.
Now you are setting the bitmapData of a MovieClip?! Don't know what you wanted, but you just need to add new child (new Bitmap)

Related

Box2d MovieClip to original position

I want to try a simple task where if i move a object inside the world and then press a button it should go back to its original position , but its not working , below is the code i am using - the file is here - http://www.fastswf.com/yAnIvBs (when i remove the event listener)
with event listener - http://www.fastswf.com/rpYsIt8
////////========================
stop();
var startXPos:Number = level1WorldObj.box1.x;
var startYPos:Number = level1WorldObj.box1.y;
function areaS(e:Event) {
level1WorldObj.box1.y= startYPos;
level1WorldObj.box1.x= startXPos;
level1WorldObj.box1.removeEventListener(Event.ENTER_FRAME, areaS);
}
but1.addEventListener(MouseEvent.CLICK,nClick3);
function nClick3(event:MouseEvent):void{
level1WorldObj.box1.addEventListener(Event.ENTER_FRAME, areaS);
level1WorldObj.box1.y= startYPos;
level1WorldObj.box1.x= startXPos;
}
/////////////////======================
Now i want to be able to do it many time so i kept the variables that detect the initial x, y as global ...
Here you can see how it behaves in debugdraw mode , strangely only the clip moves not the actual body - http://www.fastswf.com/-Ijkta4
Can some one please guide me here ...
Thanks in advance ...
Jin
The graphics that you see (box1) aren't related to the physical object behind the scenes - you're currently only moving the graphics not the object itself.
You need to use either SetPosition() or SetTransform() on the b2Body of the object
Edit 07/7
As you're using the Box2D World Construction Kit, I took a look at the source code (available here: https://github.com/jesses/wck). The main class seems to be BodyShape (https://raw.githubusercontent.com/jesses/wck/master/wck/BodyShape.as).
Looking through it, you should be able to access the b2Body directly. If it's null (which is probably the source of the TypeError that you're getting, then you haven't called createBody(), which is what actually takes all of your properties as creates the physical object behind the scenes.
Once you have a b2Body, if you want to position it based on the graphics, there's a function syncTransform() to do just that.
You should turn on debugDraw on your World class to make it easier to see what's going on in the background. NOTE: this needs to be done before calling create()
I was able to find solution to this problem , i found the starting point by using this -
trace(level1WorldObj.box1.b2body.GetPosition().x);
trace(level1WorldObj.box1.b2body.GetPosition().y);
then once i had the position manually i took down the coordinates and used the below code ....
level1WorldObj.box1.b2body.SetTransform(new V2(-2, 2),0 );
Thanks #divillysausages for all the help ...
Regards

Saving the state of a movieclip containing multiple movieclips inside

this is actually a noobish question, but is there a possible way to save a certain state of a movieclip?, example i dynamically added a movieclip called big_mc, then inside big_mc contains three(3) smaller movie called child_mc1 and child_mc2 and a close_big to remove big_mc from the stage, when i click either of child_mc1 and child_mc2, the child_mc will disappear prior to which child_mc i clicked.
so the scenario is when I click child_mc1 which remove itself from the scene, then next I'll click the close_big movieclip to remove big_mc from the stage and will save it's own state, so then the next time i run the SWF file and dynamically add big_mc to stage, child_mc1 would be still missing and child_mc2 would still be displayed (EVEN IF I CLOSE THE SWF FILE, the state should be saved). please help..much is appreciated.
code in main time line:
var big_mc:mother_mc = new mother_mc;
add_big_btn.addEventListener(MouseEvent.CLICK, call_big);
function call_big(e:MouseEvent):void
{
addChild(big_mc);
}
the code inside big_mc:
child_mc1.addEventListener(MouseEvent.CLICK, remove_child1);
child_mc2.addEventListener(MouseEvent.CLICK, remove_child2);
close_big.addEventListener(MouseEvent.CLICK, bye);
function remove_child1(e:MouseEvent):void
{
removeChild(child_mc1);
}
function remove_child2(e:MouseEvent):void
{
removeChild(child_mc2);
}
function bye(e:MouseEvent):void
{
this.parent.removeChild(this);
}
You want to start with SharedObject, which as Adobe puts it, "is used to read and store limited amounts of data on a user's computer or on a server". To save the "state" of the MovieClip is more complicated.
What about it do you want to save? The x property? Perhaps the alpha? EVERYTHING? Each object is stored in a default state in your swf. Library items in the Flash IDE are technically miniature classes, as evidenced by the way we instantiate them. Assuming you create something called customButton, you could spawn thousands of them onscreen (or one) like this:
var foo:customButton = new customButton();
Like a hand-written class, a copy of the customButton is created with all the properties you defined on it before you compiled it. If you want to change those properties, you have to address each and every one you want different.
Looking at this broadly, let's assuming you want to save the position of your button every time you load the swf. Load with getLocal(), and save with flush().
var settings:Object = SharedObject.getLocal("foo");
function updateState(e:Event):void {
myButton.x = settings.x;
myButton.y = settings.y;
}
function saveState():void {
settings.x = myButton.x;
settings.y = myButton.y;
settings.flush();
}
It's not impossible; there's simply no push-button solution for it. If you wanted, you could write a function which iterates over all DisplayObjects, and loads/saves each relavent property from/into your SharedObject. Might be overkill, though.

cocos2dx/coco2d layer transition

I hope to pop down a score panel when players win and pass the gate.
Normally it will pop down score board.
I think the best way is to use layer and pull down it.
But I only get the transition of scene, just wonder is there any way for layer transition?
Did not see an equivalent of CCTransitionScene :CCScene for CCLayer but layers can runActions using which we can bring out most of the animations/transitions.
Here is what I do in such situations but I guess you are thinking of the same thing. Nevertheless,
1.Create a layer and add it as a child at a position outside of your screen frame.
2.Then use CCMoveTo to move it to the desired location when you want to pull it down.
I have done something similar in the past.
Display your layer offscreen
i.e setposition(0, CCDirector::sharedDirector()->getWinSize().height*1.5f);
create an action to move it onscreen (I like to use CCEaseSineOut)
you can also use a callfunc to call a function when it has finished its animation
scoreLayer->runAction( CCSequence::create( CCEaseSineOut::create(CCMoveTo::create(1.0f, ccp(0, 0-_screenHeight*1.5f))), CCCallFunc::create(this, callfunc_selector(MainLayer::scorefinishedMove)), NULL));
Note: that function might need some fixes to ending brackets etc. And you may want to seperate out some of those actions rather than putting the initialization right in the runAction function
For layer transition you can do this:
CCScene* newScene = CCTransitionCrossFade::create(.5f,Layer2::scene());
CCDirector::sharedDirector()->pushScene(newScene);
In Layer2.cpp
CCScene* Layer2::scene()
{
CCScene* scene = CCScene::create();
CCLayer* layer = new Layer2();
scene->addChild(layer,1);
return scene;
}

Create a Button with only code AS3

I feel like something like this exists but how would I create a button in only action script 3 code? I mean without making a shape and converting it to a button symbol or something. It would probably make it easier to only work in FlashDevelop.
You can use the SimpleButton class or roll your own using the Sprite class. Then you can draw anything or use any image as the button and it's over, down and default states.
For example a simple button can be like this :
var goButton:SimpleButton = new SimpleButton();
var myButtonSprite:Sprite = new Sprite();
myButtonSprite.graphics.lineStyle(1, 0x555555);
myButtonSprite.graphics.beginFill(0xff000,1);
myButtonSprite.graphics.drawRect(0,0,200,30);
myButtonSprite.graphics.endFill();
goButton.overState = goButton.downState = goButton.upState = goButton.hitTestState = myButtonSprite;
addChild(goButton);
You can have different display objects for each state of the button or you can attach bitmaps instead of sprites.

Frame labels & function parameters

Is it possible to change a frame label within a gotoAndStop('label') with the parameters in a function?
I'm playing around with updating code as I learn more and more techniques, and at the moment the code is a basic click-a-button to select the object shape, and on press the button disappears:
// Change the object into a circle.
circle_btn.addEventListener(MouseEvent.CLICK,function(){changeShape_fun(circle_btn,circle);});
// Change the object into a square.
square_btn.addEventListener(MouseEvent.CLICK,function(){changeShape_fun(square_btn,square);});
// Change the object into a star.
star_btn.addEventListener(MouseEvent.CLICK,function(){changeShape_fun(star_btn,star);});
function changeShape_fun(shape_btn,frame){
shape_btn.visible = false;
main_mc.gotoAndStop('frame');
}
However I can't/don't seem to know how to change a frame label through function parameters, or if what I'm trying to do is even possible.
Also to note, while I'm all ears for any more efficient ways of doing what I'm trying to do, I would still like to know how/if you can change frame labels through function parmeters.
Thanks! :)
You're very close, but you're trying to go to a frame called 'frame' and not the string contained within the frame variable. Try this instead:
// Change the object into a circle.
circle_btn.addEventListener(MouseEvent.CLICK,function(event:MouseEvent){changeShape_fun(circle_btn, 'circle');});
// Change the object into a square.
square_btn.addEventListener(MouseEvent.CLICK,function(event:MouseEvent){changeShape_fun(square_btn, 'square');});
// Change the object into a star.
star_btn.addEventListener(MouseEvent.CLICK,function(event:MouseEvent){changeShape_fun(star_btn, 'star');});
function changeShape_fun(shape_btn,frame){
shape_btn.visible = false;
main_mc.gotoAndStop(frame);
}
This will go to a frame within main_mc called 'circle' when you click the circle or 'square' if you click the square, etc.