Cocos2D: Play Sound on Touches Moved - cocos2d-iphone

I currently have a dial that rotates on touch. I would like to include a "click" sound effect when the dial is moving. I have the click sound working, but it is a bit chaotic.
I currently put this in my touches moved:
[[SimpleAudioEngine sharedEngine] playEffect:#"ButtonClick.m4a"];
But when I rotate the dial the sound effects goes crazy (i.e. CLICKCLICKLICKCLICKCLICK...) when i would like to to do this: Click..Click..Click..Click..Click..
Instead of the "click" sound restarting at each movement of the dial, how can I achieve a "click" sound that finishes the full sound file and starts over each time (i.e. loop)?

Related

How to Halt Sound Effect in SDL2

How would I halt the playing of a sound effect in SDL2?
Currently I'm playing sound effects using the SDL2 Mixer with this code.
Mix_PlayChannel(-1, soundEffect, 0);
However I want the play to be able to not have to listen to the entire sound effect and when they leave the menu the sound effect should stop.
I've tried Mix_HaltMusic(); however that doesn't seem to apply to Mix_Chunk.
How would I do so?
To stop the Mix_Chunk started with Mix_PlayChannel, you have to use Mix_HaltChannel as explained in this answer for the opposite problem.

Get cursor position in a game before it is re-centered

I am trying to record my in-game mouse movement so I can play it back. The game is Call of Duty 4, although that isn't relevant to this question. What is relevant is that most First Person Shooter games re-center the mouse cursor when you move it, so that you never hit any borders. I can't find anything about this online after searching for a while. I am currently using a mouse hook (WH_MOUSE) in order to keep track of the mouse movements (WM_MOUSEMOVE). When I list these messages, I can see that the cursor is pulled back to screenResolutionX / 2, screenResolutionY / 2 (the center of the screen).
My first attempt at figuring this out was to ignore the messages if they are equal to the center of the screen, so that when I play back these mouse movements, the re-centering is ignored. I assumed this would solve the problem, but now when I play back the mouse movements the mouse goes too far (way off from what I recorded). When I do the same recording/playing back in the main menu of the game (where the cursor isn't re-centered), the playback is incredibly accurate. My question is: what can I do to record mouse movements in the game accurately, given that the game re-centers my cursor?
Thanks in advance.
Edit: let me clarify what I'm asking. I want to only record actual user mouse input, not the game re-centering the mouse cursor.
In order to intercept those mouse messages you'd have to make a filter driver or a hook. Here's a nice article (with code) on the subject:
http://www.oblita.com/interception.html
That article is based on this Windows API: SetWindowsHookEx and shold be a good starting point for you.
Have you considered Low Level Mouse Hook? It intercepts mouse messages earlier than just mouse hook.

OpenAL sound stops OpenGL from drawing

I have a scene that is modified when mouse left button is clicked.
My problem is: this modified scene was supposed to appear with a sound, but the scene waits the sounds to finish before it renders itself.
I'm using this function:
do {
alGetSourcei(source, AL_SOURCE_STATE, &state);
} while (state == AL_PLAYING);
Of course, this function tells the program to wait. But what alternative could I use? if I remove this function, the sound isnt played
I even tried to create a function sound(), that is called after glutPostRedisplay but it still waits the sound complete to render
I think your problem, that the sounds stop, is somewhere else. alGetSourcei is not required to keep the sound playing.
Anyway you can't do that in a while loop because it will block the update of the windows messages and OpenGL and will prevent the scene from redrawing.
To play it you just need to call alSourcePlay, after this you could check each frame if the source is still playing ( if you need to do this for some reason ).

Is it possible to "reset" any existing touches?

Cocos2d-iphone 1.0.1.
My main game scene requires the player to have a finger pressing the screen for the character to move.
While the character moves (thus the finger pressing the screen), a battle might occur. Such battle triggers a new CCScene which is pushed into the CCDirector (so the main game scene still exists within memory).
During the battle, naturally, the player will probably release his finger at some point.
When the battle is over, this CCScene is popped. Thus, the main game scene returns.
Now here is a problem: the main game scene still thinks that the finger that was initially pressing the screen before the battle is still pressing it at the same point, thus the joystick is still "functioning" and the player is still moving despite the fact that the finger is no longer pressing the screen.
Is there a way to "reset" the screen touches? I'd like to do so in the onEnter method of the main game scene. I tried something like
self.isTouchEnabled = NO;
self.isTouchEnabled = YES;
Hoping that such would re-register the touch dispatcher and thus causing some kind of reset. It did not work.
Basically, I need a way to tell the main game scene "dude, no one's touching the screen despite whatever you think".
Edit
Note that, if you press the screen again, it is fixed.
To make sure I understand the problem:
After you pop the battle scene, the character continues moving around as if the user never released his finger from the joystick?
My initial thought is that you have a deeper underlying design flaw somewhere in the code. It is my understanding that you want to use at least one layer to handle input. Try shifting everything in that 'game' CCScene to a 'game' CCLayer and add the layer as a child of the scene. Then register the layer to receive touch input.
If that doesn't work, you could always use a flag. Compare the scene you are in to the scene you want to be in, and if not, don't activate the joystick controller. Kind of hack-y but it works.
I've run into this kind of problem myself.
How i've fixed it:
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches){
[touchesOnScreen addObject:touch];
}
}
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches){
[touchesOnScreen removeObject:touch];
}}
- (void)ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[touchesOnScreen removeAllObjects];
}
So basically iOS keeps a pointer to every touch on the screen. What you do is manage those touches yourself with an NSSet. When you push the scene just set every UITouch from the set to nil. That is equivalent to UITouchPhaseCancelled. This will cancel all your touches on the screen. If the user still has his finger on the screen that touch wont be registered anymore...even if he moves it or something.
Note : you need to remove all objects in ccTouchesCancelled (it's called when the user has 6 or more touches on the screen) or else when he touches again the app crashes. If your app needs more than 5 touches you need to find a way around that.
Possibly the simplest solution is to have your CCDirector, on completion of popping your battle scene, call first resignFirstResponder then 'becomeFirstResponder` on the offending view; off the top of my head anyway it seems that ought to forward on the touches to another responder, hopefully letting it fizzle out when no one else handles it.
A more complicated dive into the UIView methods provides this private call cancelTouchTracking. Most likely it does something similar to what #skytz has put together. Warning: That last will mostly likely get you rejected in the app store process, but for your info there it is.
I'd opt for the simpler solution and hope it works. O_o

Posting MouseEvents to applications in OSX

I am trying to send mouse events to a (I think SDL/OpenGL) game that doesn't support a gamepad. I know I could just use one of the many Gamepad to Keyboard/Mouse applications available, but I thought it would be fun to write my own. The following code works fine except when the game is running:
// point is a CGPoint that is set earlier on...
CGEventRef event = CGEventCreateMouseEvent(NULL,kCGEventMouseMoved , point, 0);
CGEventSetType(event, kCGEventMouseMoved);// apparently there is a apple bug that requires this...
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
With this, I can move the cursor on my desktop, and even in the games menu's, however the only time the game gets it while in the actual game is when I move my physical mouse. Sending keyboard events works fine in the game, so I don't know what the problem is
I found out what the problem was, I had to use:
CGEventSetIntegerValueField(event, kCGMouseEventDeltaX, dX);
CGEventSetIntegerValueField(event, kCGMouseEventDeltaY, dY);
to set the relative coordinates of the mouse move. I think this is because the game was warping the mouse to the center of the game window, and my application wasn't getting the mouse move events from that.