cocos2dx/coco2d layer transition - cocos2d-x

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

Related

How to create a MenuItemImage with a callback function in stead of selected image?

I have a MenuItemImage here:
auto myImage = MenuItemImage::create("image.png","image_selected.png",
CC_CALLBACK_1(HelloWorld::onImageClicked,this));
It allow me to input a image.png, which will be changed to image_selected.png on selected when I navigate between items in my menu with keyboard. However, I want to perform some actions when select it with myImage->selected(); (NOT activate it by clicking/touching or calling for myImage->activate(); function), not just a boring image_selected.png.
Now, I'm thinking about set up all of those action in:
keyBoardListener->onKeyPressed = [&](cocos2d::EventKeyboard::KeyCode keycode, Event* event)
{ // Setting up actions on KEY_RIGHT_ARROW or KEY_LEFT_ARROW pressed};
However this way makes things complicated. Therefore, I want to ask if there's any way that I could set up all of my actions as myImage being creating so I could call all of those action with a simple myImage->selected() or stop them with myImage->unselected() later?
Your attention and help is very much appreciated :D
Simply do this:
auto myImage = MenuItemImage::create("image.png", "image_selected.png", [&](Ref* ref){
//your code here
//by ref you can access "myImage" object
});
edit:
I'm not sure what are you trying to achieve. Do you want to have a few buttons in menu, which always one of the is selected and change them using arrows? (so menu navigation is like on console games).
edit2:
After watch a sample yt video I don't think you can achieve this relying only on MenuItemImage. Instead I'd create a ui::Button (if you need clicking/touching as well) or Sprite. Then I'd handle button states by myself. As for glowing frame you probably need some fancy shader or create it in photoshop and add to it an action with constantly fading out and in.

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

Stop MouseEvent-propagation of displayList views to starling views

I'm creating a game that uses the starling-layer (the game itself) and the classic display list which contains several Popups and Stuff like that.
I have one thing that troubles me:
If MouseEvents are generated on displayList-elements they always go through to the starling layer and produce TouchEvents etc. which is quite annoying.
I was wondering there is some general (and easy to use) approach to handle that.
One possibility was to listen on all displayList-Elements for the following Events:
interfaceElement.addEventListener(MouseEvent.MOUSE_MOVE, stopPropagationHandler);
interfaceElement.addEventListener(MouseEvent.MOUSE_DOWN, stopPropagationHandler);
interfaceElement.addEventListener(MouseEvent.MOUSE_UP, stopPropagationHandler);
private function stopPropagationHandler(e:MouseEvent):void {
e.stopPropagation();
}
But this looks quite nasty to me.
And even if I did it like that, I have one more issue:
If a starling-element is below that display-list-element and if it has a TouchEvent.TOUCH for rollover-behavior >> the rollover-appearance will not be removed from the starling if you hover over the display-list-element.
I also thought about putting a dummy-starling element behind every display-list-element,... to stop the events.. but that all sounds a bit "over-complicated" for such a "simple" task.
Or am I missing something?
A hint would be much appreciated.
Thanks.
You could create 1 main container in the displaylist (not the stage) and listen for ROLL_OVER and ROLL_OUT, and set somekind of global flag there, that your mouse is over the display-list container. Then in your starling events, check for this flag. This isn't the nicest solution out there i guess, but it should work
var isOverDisplayList:Boolean = false;
container.addEventListener(MouseEvent.ROLL_OVER, onRollOver);
container.addEventListener(MouseEvent.ROLL_OUT, onRollOut);
function onRollOver(e:MouseEvent) {
isOverDisplayList = true;
}
function onRollOut(e:MouseEvent) {
isOverDisplayList = false;
}

Tweening with actionscript 3

I have been working on this one a while. I have an object in this case a movieClip called "mcBall". I set up two buttons "btnLeft" and "btnRight"with a tween so that the mcBall will ease between the two points smoothly.
Works fine, but where it gets glitchy is the the two buttons are still active an if the user clicks on either button of course the ball goes back to the starting point like it's supposed to.
My question is this ... What is the best way to have the buttons be de-activated while the "mcBall" object is moving. Would it be best to use a removeEventListener for the buttons and then have it added again. Would it be better to use an if statement like "If (mcBall.x = >=81 || <=469) removeEventListener"? Maybe use the tweenEvent.MOTION_FINISH to set up the eventListener again.
Any help would be greatly appreciated. Thanks
using Flash cs3
In this code I managed to turn off one button so that while the ball is moving it remains inactive but the other is still active. I'm not sure of the placement of the removeEventListener.
import fl.transitions.Tween;
import fl.transitions.easing.*;
function moveBallRight(evt:MouseEvent):void {
var moveBall:Tween=new Tween(mcBall,"x",Regular.easeOut,80,470,4,true);
btnRight.removeEventListener(MouseEvent.CLICK,moveBallRight);
btnLeft.addEventListener(MouseEvent.CLICK,moveBallLeft);
}
btnRight.addEventListener(MouseEvent.CLICK,moveBallRight);
function moveBallLeft(evt:MouseEvent) {
var moveBall:Tween=new Tween(mcBall,"x",Regular.easeOut,470,80,4,true);
btnRight.addEventListener(MouseEvent.CLICK,moveBallRight);
btnLeft.removeEventListener(MouseEvent.CLICK,moveBallLeft);
}
btnLeft.addEventListener(MouseEvent.CLICK,moveBallLeft);
Personally, I would recommend using the Actuate tween library. Unlike TweenLite/Max, it is fully opensource, and has most of the features, and is faster, with no pro/pay version.
I also like Actuate's interface much better than TweenLite. It is very similar so easy for people to start using it, but I like how tween modifiers are added in a more explicit way.
Simple example:
Actuate.tween(mySprite, 1, { alpha:1 });
Then is you want to specify an easing equation, just chain it on the end:
Actuate.tween(mySprite, 1, { alpha:1 }).ease(Quad.easeOut);
Want a delay as well? Add that to the chain:
Actuate.tween(mySprite, 1, { alpha:1 }).delay(1).ease(Quad.easeOut);
Of course you can also call a function onComplete, even with parameters:
Actuate.tween(mySprite, 1, { alpha:1 }).onComplete(trace, 'Tween finished');
Check out the Actuate Google Code page linked above for the full list of methods with examples.
I would recommend not using the native Tween class from fl.transitions.Tween. Its not very good. The industry standard is TweenMax from greensock.
Using TweenMax it is trivially easy to respond to end-of-tween events. You simply add an onComplete:myhandlerfunction to your tween.
An example from your above code would look like this:
Instead of
var moveBall:Tween=new Tween(mcBall,"x",Regular.easeOut,80,470,4,true);
You would have:
TweenMax.to(mcBall, 4, {x:470, ease:Expo.easeOut, onComplete:onBallMovedLeftComplete};
Hope that helps. And I hope you never have to use those native tween classes again. They are the pits.
I agree that you should use TweenLite or TweenMax as the other answers suggests.
From what I gather though, the question is the best approach in activating/deactivating your event listeners for the buttons.
I'd say the best approach is to have a function for adding your button listeners and another function for removing them.
Then, whenever you call a tween, you first call the removal function before executing the tween.
Then upon completion, you call the function to add them again. You can use the onComplete parameter with Tweenlite to specify the function to add the button listeners.
for example :
function moveBallRight(evt:MouseEvent):void
{
removeButtonListeners();
TweenLite.to(mcBall, 4, {x:470, ease:Expo.easeOut, onComplete:addButtonListeners};
}
function moveBallLeft(evt:MouseEvent):void
{
removeButtonListeners();
// do your tween
TweenLite.to(mcBall, 4, {x:80, ease:Expo.easeOut, onComplete:addButtonListeners};
}
function addButtonListeners():void
{
// add both listeners here
}
function removebuttonListeners():void
{
// remove both listeners here
}
Also, you'd obviously want to call addButtonListeners at the beginning of your program as well, so that the listeners are initially active when the program runs.

Set a button to invisible once clicked

I'm trying to set a button to invisible in AS3 however when the I leave the frame and come back to it the button is visible again. This is for a jeopardy game I make making for comm tech class.
Here is what I currently have:
a1.addEventListener(MouseEvent.CLICK, a1mouseClick);
function a1mouseClick(mouse:MouseEvent) {
a1.visible = false;
gotoAndStop("A1");
trace("Going to A1");
}
however when it comes back to the frame with the a1 button it is visible again.
Here is my current animation: https://dl.dropbox.com/u/23938245/jeporady.fla
While moving through the timeline flash player can recreates sprites, movie clips and text fields, so your buttons appears visible again. To prevent recreation move all controls to separate level without key frames. If key frames are required try to set the same instance name for this button in all keyframes.
#fsbmain and #prototypical they are right.
While moving through the timeline flash player can recreates sprites, movie clips and text fields, so your buttons appears visible again. To prevent recreation move all controls to separate level without key frames. If key frames are required try to set the same instance name for this button in all keyframes.
I was looking at your project, and offer a quick fix, you need to do the following:
Create a new layer on top to manage a few of actions availables for all frames with the following actions:
import flash.display.DisplayObject;
// Manages the buttons visible state
var buttonsStates:Object = {
"a1":true, "b1":true, "c1":true, "d1":true, "e1":true,
"a2":true, "b2":true, "c2":true, "d2":true, "e2":true,
"a3":true, "b3":true, "c3":true, "d3":true, "e3":true,
"a4":true, "b4":true, "c4":true, "d4":true, "e4":true,
"a5":true, "b5":true, "c5":true, "d5":true, "e5":true
};
// Checks the buttons visibility
function checkVisibility () {
for (var buttonName:String in buttonsStates)
{
var child:DisplayObject = this.getChildByName(buttonName);
child.visible = buttonsStates[buttonName];
}
}
// Saves the visible satatus to false
function setVisibilityToFalse(target:*) {
buttonsStates[target.name] = false;
target.visible = false;
}
Every time you want to check the visibility of the buttons you must call the checkVisibility() function. For example, every time you return to the button list.
Finally the event handler for each button must be like this:
function a1mouseClick(mouse:MouseEvent) {
setVisibilityToFalse(mouse.currentTarget); // Saves the visible state to false
gotoAndStop("A1");
trace("Going to A1");
}
You can download the edited file here http://cl.ly/Lt6X
You are missing a fundamental aspect of how the flash timeline and keyframes function. Once you move away from that frame, the stage instance of the content of that frame and it's properties/states are gone. When you return to that frame, the instance is created again based on the keyframe contents.
I think the best solution given your current approach is to put the main board persistent throughout all the frames. You can do that by creating a layer for it, and have it's keyframe extend from frame 2 to frame 27. However, your next issue will be adjusting visibility of all the elements on that screen when you don't want them visible.
My suggestion would be to put all the elements of that screen into a movieclip symbol of it's own and add that movieclip, and all code for it's listeners, to this new layer you created. For example you might name that instance - main_board and therefore you could modify it's visibility with main_board.visible property. If you did choose that solution, you would need to modify all the code on that frame to use that instance name as well ie :
main_board.a1.visible = false;
Also, you'd need to modify all you addEventListener lines as well :
main_board.a1.addEventListener(MouseEvent.CLICK, a1mouseClick);
Your approach for this game could be greatly simplified, but even further beyond the scope of this question than I have already gone!