LWJGL Mouse carrying out command multiple times randomly - lwjgl

Im trying to set my LWJGL Mouse to grabbed and not grabbed when i push the left mouse button.
However this has proven to become a tricky matter since the LWJGL mouse for some matter executes the command multiple times randomly. For an example:
if (Mouse.isButtonDown(0)){
Mouse.setGrabbed( !Mouse.isGrabbed() );
System.out.println("Pushed");
}
if(Mouse.isGrabbed()){
camera.processMouse(1, 80, -80);
If i run this code it will print "Pushed" several times randomly per push. As you can imagine that becomes a problem when i try to set my Mouse to grabbed true or false from each click. the times i have tried this code it has printed "Pushed" 4 - 7 times per click
is there any way to make the Mouse only carry out the command once per click?
many thanks in advance to everyone who will take time to help me solve this problem.
Thomas

An easy way is to check a boolean field which you flip on the first iteration of the block after the mouse is clicked or released to tell you if this is the first time since the click that the if block has been executed. Here's an example:
private boolean alreadyClicked;
void someMethod(){
if(Mouse.isButtonDown(0)){
if(!alreadyClicked){
alreadyClicked = true;
// do what you want to do when the mouse is clicked
}
}
else{
alreadyClicked = false;
}
}
Alternatively you could use the event buffer of the Mouse class to detect clicks like this:
while(Mouse.next()) {
if(Mouse.getEventButton() == 0) {
if(Mouse.getEventButtonState()) {
// clicked
}
else{
// released
}
}
}

Related

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.

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!

Reload or update Info on stage with phone app

I have an phone app that displays certain text info, on stage, based on the day (e.g. Sunday, Monday...). When the day changes, Sunday to Monday, it should display Monday's info but it doesn't update when I test in the phone. I think this is because the phone holds the memory of where the user was. So, I need to make the app reload somehow, so it gets the correct info matching the day. I was thinking to do this with a user button (see below) but have not been successful with the reload. Any ideas please? Thank you in advance.
myButton.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler);
function fl_MouseClickHandler(event:MouseEvent):void {
if (myText1.stage) {
removeChild(myText1);
}
else {
addChild(myText1);
}
}
That piece of code just removes the text from it's parent or adds it back.
What you probably want to do is to update the text property of it using the current day.
Something like :
myButton.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler);
function fl_MouseClickHandler(event:MouseEvent):void {
var days:Object = {
0:"Sunday",1:"Monday",2:"Tuesday",
3:"Wednesday",4:"Thursday",5:"Friday",6:"Saturday"};
myText1.text = days[new Date().getDay()];
}
I was able to put the function that gets the information, within a button function, which updates when the user clicks.

currentFrame identifiers [AS3]

I'm completely new to Flash and AS3, and I'd have thought this would be a simple question, but I've been unable to find an answer online or in the documentation. I'm trying to use addEventListener (Event.ENTER_FRAME) and (.currentFrame) to disable a button for part of an animation sequence. While the animation sequence fades in, the Button Hand cursor is visible and people can select it before the sequence is completed. I want this button disabled for the first 213frames of the main timeline, which is when the button becomes visible.
Earlier, I was successfully able to disable a Rewind button for parts of a different movie scene using the code below with a few insignificant things changed.
Skip_btn.addEventListener(MouseEvent.CLICK, SkipToGoToScene);
function SkipToGoToScene(event:MouseEvent):void
{
MovieClip(this.root).gotoAndPlay(1, "Opening");
}
//Skip_btn functions
Skip_btn.addEventListener(Event.ENTER_FRAME, skipDisable);
function skipDisable(event:Event) {
if (this.currentFrame < 213)
{ Skip_btn.mouseEnabled = false;
} else {
Skip_btn.mouseEnabled = true;
}
if (this.currentFrame > 213) {
Skip_btn.removeEventListener(Event.ENTER_FRAME, skipDisable);
}
}
The problem is that before I could just use "this.currentFrame" as the button was on the same timeline that it controlled, whereas now it's embedded in a MovieClip that is on the main timeline. What can I swap "this" for so I can reference this main timeline? Also, could someone fill me in on what the other "identifiers" are for ".currentFrame", as I'm not too sure how it works. The documentation examples ask for Movieclips such as "MyMovie_mc.currentFrame", but what if you just want to reference a main timeline?
If the button is on main timeline you could just use
this.root.getChildByName("Skip_btn").mouseEnabled = true;
And if you start playing animation on main timeline use
MovieClip(this.root).currentFrame

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