XNA MediaPlayer Issue - xna

I have the following code in Draw() in Game1. However, the Music only plays when I'm pressing the close button for the program. Where should I be putting MediaPlayer.Play() if not there? normS, fastS, slowS, and playing are all Song types. If you need me to clear anything up, just ask.
if (stateS == "normal")
{
if (!MediaPlayer.Equals(playing, normS))
{
playing = normS;
}
spriteBatch.Draw(norm, pos, Color.White);
}
else if (stateS == "fast")
{
if (!MediaPlayer.Equals(playing, fastS))
{
playing = fastS;
}
spriteBatch.Draw(fast, pos, Color.White);
}
else if (stateS == "slow")
{
if (!MediaPlayer.Equals(playing, slowS))
{
playing = slowS;
}
spriteBatch.Draw(slow, pos, Color.White);
}
MediaPlayer.Play(playing);

Is there a particular reason why you need to have the songs play out of the Draw method? Draw should be reserved for drawing things.
Like user1306322 said in the comment above, I would recommend moving the
MediaPlayer.Play(playing);
into the Update method, and wrap it in a conditional (so you dont just keep playing a new song every update, which I think is what is happening for you now since clicking and holding the Close Window x stops the updates. You could try this by dragging the window around as well):
if (!MediaPlayer.IsPlaying)
{
MediaPlayer.Play(playing);
}
If necessary, you can leave the rest of the code in Draw, but most likely this whole thing should go in Update.
edit I just realised you may not have a conditional on this because you want to be able to change the song at any time. In that case, you should set a variable to hold your "Last Song", so you can compare it in your conditional like this:
if (MediaPlayer.IsPlaying == false || playing != lastPlaying)
{
MediaPlayer.Play(playing);
}

Related

How to toggle two images to pause and play a game in SWIFT, SpriteKIT

I want to toggle between two images to pause and play my game. I tried using the code below but it doesn't work. I declared the pause and play as SKSpriteNodes().
Can anyone help?
func paused(){
self.scene?.view?.paused = true
pause.removeFromParent()
}
// PLAYING FUNCTION
func playing(){
self.scene?.view?.paused = false
play.removeFromParent()
}
As someone else told you, you aren't giving enough informations for us to give you a precise answer.
Anyway, the little part of your code that I can see doesn't seem to be right to me.
First of all you probably shouldn't use two nodes, nor delete any of them.
If your goal is simply to change the icon, you should use the same node and simply change its texture property.
If you'd like an example, I can give you one.
EDIT : Here is the example
// In this example, we will call playPauseNode the SKSpriteNode you are using as a button
var isPlaying = true
func buttonTouched() {
if isPlaying { // If the game is playing
playPauseNode.texture = SKTexture(imageNamed: "theNameOfYourPlayButtonImage")
isPlaying = false
}
else { // If the game is paused
playPauseNode.texture = SKTexture(imageNamed: "theNameOfYourPauseButtonImage")
isPlaying = true
}
}
I believe it should behave as you expect it to...

SpriteKit properly handling sounds

I have a SpriteKit game where I have a number of different Sprites Lasers, Planes, etc. A number of these Sprites have a sounds that will play whenever they are visible. Right now I play the sound in the SKSpriteNode itself. This probably isn't what I want because if I have I have 50 of the same sprites, they'll all be playing the same sound and gobbing resources. However, I'm not really sure where would be the best place to play the the sound, because for some of these sprites I would need to check if it should be playing or not. I suppose I could put the sounds in the the GameScene and loop through all sprites during every update to determine what sounds should and should not still be playing, that way there would only be one instance of every sound. I was hoping to keep all the sprite code within the sprite itself, but this would solve the issue with multiple instances of the same sound playing. Is this the correct way to handle sounds?
It is hard to give you a proper code example without seeing your code. You can however get the gist of what you can try with what I have below.
In MyScene add a property BOOL propSound.
Whenever you create a new plane and wonder about adding the prop sound do something like this:
if(propSound == false)
{
propSound = true;
// add your code to play prop sound
}
If you add every newly created plane sprite into a NSMutableArray like this [yourArrayName addObject:newPlane];, you can check the array count every time you remove a plane in order to know if the last plane was removed and the sound needs to be stopped.
if([yourArrayName count] == 0)
{
propSound = false;
// add your code to stop prop sound
}
Maybe you are looking for something like this?
NSMutableArray *coin = [[NSMutableArray alloc] initWithCapacity:1];
SKAction *_coinSound = [SKAction playSoundFileNamed:#"Pickup_Coin4.wav" waitForCompletion:NO];
[coin addObject:_coinSound];
SKAction *_playCoinSound = [SKAction sequence:coin];
Then I just check if the "character" in my case touched the coin. If so it will play the sound.
if([_adventurer intersectsNode:coin]){
[coin runAction:_playCoinSound];
}
Edit:
Saw your comment on your question. I guess you could check if there is at least 1 plane on the screen, if so then you could play a loop of the sound. If there is less than 1 no sound.
Do not play the same sound again if there already are playing. You could use a BOOL to see if the sound is already playing.
BOOL isPlaneSoundOn = false;
if(!isPlaneSoundOn && _planeNode.count > 0){
//play the sound
isPlaneSoundOn = true;
} else if(_plane.count == 0) {
//stop the sound
isPlaneSoundOn = false;
}
Something like that. Maybe you get the idea :)
I would personally play any community sounds off the scene using the SKAction playSoundWithFilename, and assign this sound a key.
Then I would check if the key exists, and if it does not, then play the sound

Strange behaviour with setCurrentPlaybackTime

I use: MPMoviePlayerController to show video.
Below I put list of thumbs from the video.
When pressing a thumb I want to jump to a specific place in the video using: setCurrentPlaybackTime.
I also have a timer updating the selected thumb according to the location of the video using: currentPlaybackTime.
My problem: when calling: setCurrentPlaybackTime, the player keeps giving the seconds before seeking to the specific second. It take few seconds to the player to reflect the new seconds. In the mean time the experience of the user is bad: Pressing a thumb shows it selected for a show time, then the timer updates to the previous thumb, then it jumps back to the thumb I selected.
I tried using (in the timer):
if (moviePlayer.playbackState != MPMoviePlaybackStatePlaying && !(moviePlayer.loadState & MPMovieLoadStatePlaythroughOK)) return;
In order to prevent from the timer to update the selected thumb as long the player is in a transition phase between showing the previous thumb and the new thumb, but it doesn't seem to work. The "playbackState" and "loadState" seems to be totally inconstant and unpredictable.
For solving this issue, this how I have implemented this nasty state coverage in one of my projects. This is nasty and fragile but worked good enough for me.
I used two flags and two time intervals;
BOOL seekInProgress_;
BOOL seekRecoveryInProgress_;
NSTimeInterval seekingTowards_;
NSTimeInterval seekingRecoverySince_;
All of the above should be defaulted to NO and 0.0.
When initiating the seek:
//are we supposed to seek?
if (movieController_.currentPlaybackTime != seekToTime)
{ //yes->
movieController_.currentPlaybackTime = seekToTime;
seekingTowards_ = seekToTime;
seekInProgress_ = YES;
}
Within the timer callback:
//are we currently seeking?
if (seekInProgress_)
{ //yes->did the playback-time change since the seeking has been triggered?
if (seekingTowards_ != movieController_.currentPlaybackTime)
{ //yes->we are now in seek-recovery state
seekingRecoverySince_ = movieController_.currentPlaybackTime;
seekRecoveryInProgress_ = YES;
seekInProgress_ = NO;
seekingTowards_ = 0.0;
}
}
//are we currently recovering from seeking?
else if (seekRecoveryInProgress_)
{ //yes->did the playback-time change since the seeking-recovery has been triggered?
if (seekingRecoverySince_ != movieController_.currentPlaybackTime)
{ //yes->seek recovery done!
seekRecoveryInProgress_ = NO;
seekingRecoverySince_ = 0.0;
}
}
In the end, MPMoviePlayerController simply is not really meant for such "micro-management". I had to throw in at least half a dozen flags for state coverage in all kinds of situations and I would never recommend to repeat this within other projects. Once you reach this level, it might be a great idea to think about using AVPlayer instead.

How to detect open/closed hand using Microsoft Kinect for Windows SDK ver 1.7 C#

I have recently started using Microsoft Kinect for Windows SDK to program some stuff using the Kinect the device.
I am busting my ass to find a way to detect whether a certain hand is closed or opened.
I saw the Kinect for Windows Toolkit but the documentation is none existent and I can't find a way to make it work.
Does anyone knows of a simple way to detect the hand's situation? even better if it doesn't involve the need to use the Kinect toolkit.
This is how I did it eventually:
First things first, we need a dummy class that looks somewhat like this:
public class DummyInteractionClient : IInteractionClient
{
public InteractionInfo GetInteractionInfoAtLocation(
int skeletonTrackingId,
InteractionHandType handType,
double x,
double y)
{
var result = new InteractionInfo();
result.IsGripTarget = true;
result.IsPressTarget = true;
result.PressAttractionPointX = 0.5;
result.PressAttractionPointY = 0.5;
result.PressTargetControlId = 1;
return result;
}
}
Then, in the main application code we need to announce about the interactions events handler like this:
this.interactionStream = new InteractionStream(args.NewSensor, new DummyInteractionClient());
this.interactionStream.InteractionFrameReady += InteractionStreamOnInteractionFrameReady;
Finally, the code to the handler itself:
private void InteractionStreamOnInteractionFrameReady(object sender, InteractionFrameReadyEventArgs e)
{
using (InteractionFrame frame = e.OpenInteractionFrame())
{
if (frame != null)
{
if (this.userInfos == null)
{
this.userInfos = new UserInfo[InteractionFrame.UserInfoArrayLength];
}
frame.CopyInteractionDataTo(this.userInfos);
}
else
{
return;
}
}
foreach (UserInfo userInfo in this.userInfos)
{
foreach (InteractionHandPointer handPointer in userInfo.HandPointers)
{
string action = null;
switch (handPointer.HandEventType)
{
case InteractionHandEventType.Grip:
action = "gripped";
break;
case InteractionHandEventType.GripRelease:
action = "released";
break;
}
if (action != null)
{
string handSide = "unknown";
switch (handPointer.HandType)
{
case InteractionHandType.Left:
handSide = "left";
break;
case InteractionHandType.Right:
handSide = "right";
break;
}
if (handSide == "left")
{
if (action == "released")
{
// left hand released code here
}
else
{
// left hand gripped code here
}
}
else
{
if (action == "released")
{
// right hand released code here
}
else
{
// right hand gripped code here
}
}
}
}
}
}
SDK 1.7 introduces the interaction concept called "grip". You read about all the KinectInteraction concepts at the following link: http://msdn.microsoft.com/en-us/library/dn188673.aspx
The way Microsoft has implemented this is via an event from an KinectRegion. Among the KinectRegion Events are HandPointerGrip and HandPointerGripRelease, which fire at the appropriate moments. Because the event is coming from the element the hand is over you can easily take appropriate action from the event handler.
Note that a KinectRegion can be anything. The base class is a ContentControl so you can place something as simple as an image to a complex Grid layout within the region to be acted on.
You can find an example of how to use this interaction in the ControlBasics-WPF example, provided with the SDK.
UPDATE:
KinectRegion is simply a fancy ContentControl, which in turn is just a container, which can have anything put inside. Have a look at the ControlBasics-WPF example, at the Kinect for Windows CodePlex, and do a search for KinectRegion in the MainWindow.xaml file. You'll see that there are several controls inside it which are acted upon.
To see how Grip and GripRelease are implemented in this example, it is best to open the solution in Visual Studio and do a search for "grip". They way they do it is a little odd, in my opinion, but it is a clean implementation that flows very well.
For what i know Microsoft kinect for windows SDK does not best to detect open and close hands. Microsoft provides tracking of 20 body parts and does not include the fingers of the hand. You can take advantage of the kinect interactions for that in an inderect way. This tutorial shows how:
http://dotneteers.net/blogs/vbandi/archive/2013/05/03/kinect-interactions-with-wpf-part-iii-demystifying-the-interaction-stream.aspx
But i think the best solution when tracking finger movements would be using OpenNI SDK.
Some of the MiddleWares of OpenNI allow finger tracking.
You can use something like this
private void OnHandleHandMove(object source, HandPointerEventArgs args)
{
HandPointer ptr = args.HandPointer;
if (ptr.HandEventType==HandEventType.Grip)
{
// TODO
}
}

Control sound to only play once in XNA

I use a sound each time a key is pressed to fire a missile. But it doesn't sound nice. I guess it's because the the sound is repeated so many times while the key is pressed down and that the code is within the Update method. I'm looking for a simple solution to just play the sound once when key is pressed? (I have tested to use a boolean variable to be true the first time and then false after det the sound has been played, but this didn't worked well because, when and where should I set it to true again) Help is preciated!
// Fire
if (keyboardState.IsKeyDown(Keys.Space))
{
missile.launchMissile(spaceship.spaceshipPosition, spaceship.spaceshipDirection);
soundExplosion.Play();
}
EDIT New code that isn't working!?
KeyboardState keyboardState = Keyboard.GetState();
KeyboardState prevKeyboardState;
prevKeyboardState = keyboardState;
keyboardState = Keyboard.GetState();
if (keyboardState.IsKeyDown(Keys.Space) && prevKeyboardState.IsKeyUp(Keys.Space))
{
missile.launchMissile(spaceship.spaceshipPosition, spaceship.spaceshipDirection);
soundExplosion.Play();
}
Store your previous keyboard state as well
KeyBoardState prevKeyboardState;
then in your update
prevKeyboardState = keyboardState;
keyboardState = Keyboard.GetState();
if (keyboardState.IsKeyDown(Keys.Space) && prevKeyboardState.IsKeyUp(Keys.Space))
{
//your code
}
You're basically just triggering the sound tons of times every second making it sound awful.

Resources