Issue when setting Game Screen upon BACK button pressed - libgdx

I have 3 game screens, saying A, B and C, each extending the Screen class. The game normally goes from A to B, and B to C, triggered by click events.
For quick debug purpose, I put the following codes in ScreenC 's render method, so that when BACKSPACE or BACK key are pressed I can go back to ScreenB from ScreenC, and it works fine.
if (Gdx.input.isKeyPressed(Input.Keys.BACK) || Gdx.input.isKeyPressed(Input.Keys.BACKSPACE)) {
game.setScreen(new ScreenB(game));
dispose();
}
Now I want to go back from ScreenB to ScreenA, so I put the following in ScreenB's render method, and it works fine, too.
if (Gdx.input.isKeyPressed(Input.Keys.BACK) || Gdx.input.isKeyPressed(Input.Keys.BACKSPACE)) {
game.setScreen(new ScreenA(game));
dispose();
}
However, the problem is, now if I press BACKSPACE or BACK key on ScreenC, I will go back to ScreenA directly. Seems to me the keyPressed event propagated to ScreenB from ScreenC, so that ScreenB detected the event then set to ScreenA directly. I am wondering if this is the expected behavior and how do I avoid this? Thanks!

Try this
Gdx.input.isKeyJustPressed(Input.Keys.Back)
and the state isn't maintained just a single consumed event.
isKeyPressed is more for character movement i.e. "a" to move left etc

Related

SmartGWT TabSet.destroy() and recreation

I was having ID collision of tab IDs when trying to recreate the same TabSet.
My case is the following : I have 3 Tabs in general, then some action creates a 4th one, some action happens in this 4th tab which is then closed, and I need to relaunch my app and redraw again the 3 general Tabs fetching new info from the database. Everything was working well, except this warning of collision which was not a blocking one anyway.
In order to clean it, I followed Isomorphic's advice from this thread
and tried destroying the TabSet in order to recreate it.
I do:
if (myTabSet != null) {
myTabSet.destroy();
}
myTabSet = new TabSet();
// setting TabSet properties
// creating Tabs and adding them to the TabSet
I noticed, however, in debug, that the TabSet is not being desroyed completely, just some of its properties, and that a new ID is being given to it. As a result, there are no more warnings, the tabs are created, but they're not populated.
My question is : why the TabSet is not becoming null upon destruction, and how can I recreate it with no collision of IDs?
Thanks in advance
I used to have the same problem and fixed it with:
myTabSet.addCloseClickHandler(new CloseClickHandler() {
#Override
public void onCloseClick(TabCloseClickEvent event) {
event.getTab().getPane().destroy();
}
});
Apparently the tabset is not completely destroyed unless you destroy its pane.
Maybe it will work for you !

Applying action to a button in one frame makes it apply to whole movieclip in Flash CS6

I have a movieclip with several layers and frames. Some of those contain buttons. When I click button 1 I want it to go to the next frame. When I click button 2 I want it to go to frame 23. This is the code I'm using for button 1:
this.addEventListener(MouseEvent.CLICK, convnext);
function convnext(evt:MouseEvent):void
{
MovieClip(parent).gesprekkencivcen.nextFrame();
}
and this is the code for button 2:
this.addEventListener(MouseEvent.CLICK, convend1);
function convend1(evt:MouseEvent):void
{
MovieClip(parent).gesprekkencivcen.gotoAndStop(23);
}
What happens now is that when I click either of the buttons, or in fact anywhere inside the movieclip (even layers I haven't applied actions to) it executes both functions at the same time so I end up going to frame 24. Can somebody provide an answer to this problem?
Obviously this in both cases refers to the same object, and not to the buttons in particular. Record the names of those buttons as you've named their instances on the timeline, say button1 and button2 and write the code employing those names.
button1.addEventListener(MouseEvent.CLICK, convnext);
function convnext(evt:MouseEvent):void
{
parent.parent.gesprekkencivcen.nextFrame();
}
button2.addEventListener(MouseEvent.CLICK, convend1);
function convend1(evt:MouseEvent):void
{
parent.parent.gesprekkencivcen.gotoAndStop(23);
}
With this, however, you will need to update the link to gesprekkencivcen in both listeners, as those buttons will have this as parent, and their target apparently is not a child of this. I have tried to plainly set a call to parent.parent.gesprekkencivcen, which might not work.

flex setFocus on creation complete

Normally, forms and pop Ups don't have the focus set when they are just displayed. The obvious solution was to set the focus to the first input in the creation complete event of the component, so the keyboard short Cuts like tab and space start working.
The problem is that, creation complete is not the panacea, sometimes the element is not focus-able at that point, and i am not sure why that happens.
The render event would ensure the focus, but it dispatches too much for a very simple purpose.
In which point a component is always ready to be focus-able?
Edit: The component giving me trouble to get start up focus, is a TitleWindow, which can be poped in 2 ways, a Mouse click event and a keyboard event.
When the tite window is displayed by a click, the first input gets focus in the creation complete event, but when displayed by a keyboard event, it doesnt...
By now i got it working with the following code:
private function titlewindow_creationCompleteHandler(e:FlexEvent):void{
callLater( setTextInputFocus);
}
private function setTextInputFocus():void{
txtPregunta.setFocus();
}
But doubt the way is shown has anything to do with this... because, some other TitleWindow are displayed this way too and they're fine.
So what could it be?
The render event would ensure the focus, but it dispatches too much for a very simple purpose.
If this is true then why not try this:
private function titlewindow_creationCompleteHandler(e:FlexEvent):void{
var callback : Function = function(re : Event) : void {
titlewindow.removeEventHandler(RenderEvent.orsomething, callback);
setTextInputFocus();
};
titlewindow.addEventHandler(RenderEvent.orsomething, callback);
}
Might be kind of a hack since it should be focusable on creationComplete but it would probably work.

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!

Flash AS3 button eventlistener array bug

this is my first time posting a question here.
I have an array of 12 buttons on a timeline that when first visiting that part of the timeline, get a CLICK eventlistener added to them using a for loop. All of them work perfectly at that point.
When you click one it plays a frame label inside the specific movieClip and reveals a bio on the corresponding person with a close button and removes the CLICK eventlisteners for each button, again using a for loop. The close button plays a closing animation, and then the timeline goes back to the first frame (the one with the 12 buttons on it) and the CLICK eventlisteners are re-added, but now only the first 9 buttons of the array work. There are no output errors and the code to re-add the eventlisteners is exactly the same as the first time that works. I am completely at a loss and am wondering if anyone else has run into this problem.
All of my buttons are named correctly, there are absolutely no output errors (I've used the debug module) and I made sure the array with the buttons in it is outputting all 12 at the moment the close button is clicked to add the eventlisteners back.
for (var q = 0; q < ackBoDBtnArray.length; q++){
contentArea_mc.acknowledgements_mc.BoD_mc[ackBoDBtnArray[q]].addEventListener(MouseEvent.CLICK, showBio);
}
private function showBio(eo:MouseEvent):void {
trace("show the bio");
bodVar = ackBoDBtnArray.getIndex(eo.target.name);
contentArea_mc.acknowledgements_mc.BoD_mc.gotoAndPlay(ackBoDPgArray[bodVar]);
contentArea_mc.acknowledgements_mc.BoD_mc.closeBio_btn.addEventListener(MouseEvent.CLICK, hideBio);
for (var r = 0; r < ackBoDBtnArray.length; r++){
contentArea_mc.acknowledgements_mc.BoD_mc[ackBoDBtnArray[r]].mouseEnabled = false;
contentArea_mc.acknowledgements_mc.BoD_mc[ackBoDBtnArray[r]].removeEventListener(MouseEvent.CLICK, showBio);
}
}
private function hideBio(eo:MouseEvent):void {
trace("hide it!");
contentArea_mc.acknowledgements_mc.BoD_mc.closeBio_btn.removeEventListener(MouseEvent.CLICK, hideBio);
contentArea_mc.acknowledgements_mc.BoD_mc.gotoAndPlay(ackBoDClosePgArray[bodVar]);
for (var s = 0; s < ackBoDBtnArray.length; s++){
trace(ackBoDBtnArray[s]);
contentArea_mc.acknowledgements_mc.BoD_mc[ackBoDBtnArray[s]].mouseEnabled = true;
contentArea_mc.acknowledgements_mc.BoD_mc[ackBoDBtnArray[s]].addEventListener(MouseEvent.CLICK, showBio);
}
Thanks in advance for any help and insight you can provide...I have a slight feeling that its something that may be obvious to another set of eyes...haha.
Something that looks suspicious to me is that you're removing the event listener from closeBio_btn at the start of the hideBio(). Try placing that line after the for loop.
I'm having trouble justifying this hunch, but a couple of wild theories that have crossed my mind are:
This is a race condition. You're removing the listener for the handler from inside the handler itself, and since the handler was added dynamically, the runtime marks the handler for garbage collection. On the next sweep, the handler is deleted — but since gotoAndPlay probably takes a non-significant amount of time, the handler is still in the for loop adding click handlers when it gets killed, and has only added the first 9 at this point.
This is a data-corruption problem. Since the hide button and the array of 12 buttons are at least tangentially related through BoD_mc, the runtime is doing some strange optimization behind the scenes that makes accessing items through Bod_mc[with indexes] unreliable after closeBio_btn has been touched.
This is an interesting problem, I hope you find a solution :)
It seems to fix it I had to just add every btn dynamically instead of just having them on the timeline. Still strange though, thanks everyone