C#XNA-背景音乐逻辑
本文关键字:背景音乐 C#XNA- | 更新日期: 2023-09-27 18:26:27
所以我正在处理XNA游戏状态示例。我有两首不同的歌曲在游戏状态下播放和循环。这意味着:
mainMenu.mp3 goes to the mainMenu game state
backgroundMusic.mp3 goes to the Playing game state
所以这是有效的。但我也有Escape
键逻辑,它会将您从任何状态返回到mainMenu状态(当按下Esc
时)。来自Playing
的歌曲停止并且来自mainMenu
的歌曲开始播放。但是,如果我单击"开始游戏"按钮,将转到Playing
,则不会播放背景音乐。问题出在哪里?
这是我的代码:
// Main Menu game state
if (Game1.g_CurrentGameState == Game1.g_GameStates.g_MainMenu && !m_SongStart)
{
MediaPlayer.Play(m_MainMenuTheme);
m_SongStart = true; // bool
}
if (Game1.g_CurrentGameState != Game1.g_GameStates.g_MainMenu)
{
MediaPlayer.Stop();
m_SongStart = false; // bool
}
// Playing game state
if (Game1.g_CurrentGameState == Game1.g_GameStates.g_GamePlaying && !m_SongStart)
{
MediaPlayer.Play(m_GamePlayingMainTheme);
m_SongStart = true;
}
if (Game1.g_CurrentGameState != Game1.g_GameStates.g_GamePlaying)
{
MediaPlayer.Stop();
m_SongStart = false;
}
以下代码将根据当前游戏状态播放歌曲:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace WindowsGame1
{
public class Game1 : Game
{
private GameState _gameState;
private GraphicsDeviceManager _graphicsDeviceManager;
private KeyboardState _keyboardState;
private Song _song1;
private Song _song2;
public Game1() {
_graphicsDeviceManager = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void LoadContent() {
_song1 = Content.Load<Song>("song1");
_song2 = Content.Load<Song>("song2");
}
protected override void UnloadContent() {
if (_song1 != null) _song1.Dispose();
if (_song2 != null) _song2.Dispose();
}
protected override void Update(GameTime gameTime) {
GameState gameState = _gameState;
var keyboardState = Keyboard.GetState();
if (keyboardState.IsKeyDown(Keys.A) && _keyboardState.IsKeyUp(Keys.A)) {
gameState = GameState.Menu;
}
else if (keyboardState.IsKeyDown(Keys.B) && _keyboardState.IsKeyUp(Keys.B)) {
gameState = GameState.InGame;
}
else if (keyboardState.IsKeyDown(Keys.C) && _keyboardState.IsKeyUp(Keys.C)) {
gameState = GameState.Undefined;
}
_keyboardState = keyboardState;
if (gameState != _gameState) {
switch (gameState) {
case GameState.Undefined:
MediaPlayer.Stop();
break;
case GameState.Menu:
MediaPlayer.Stop();
MediaPlayer.Play(_song1);
break;
case GameState.InGame:
MediaPlayer.Stop();
MediaPlayer.Play(_song2);
break;
default:
throw new ArgumentOutOfRangeException();
}
_gameState = gameState;
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime) {
GraphicsDevice.Clear(Color.CornflowerBlue);
base.Draw(gameTime);
}
}
internal enum GameState
{
Undefined,
Menu,
InGame
}
}
为什么不写一个包装类来包装歌曲和游戏状态成员,并在当前游戏状态等于该状态时播放歌曲?@Aybe答案的oop版本。这要归功于他!
以下是我的想法。应该易于使用和管理。很简单。
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Collections.Generic;
namespace WindowsGame1
{
public class GameStateManager
{
private static List<GameState> GameStates = new List<GameState>();
private static GameState CurrentGameState = null;
public static void AddState(GameState gameState)
{
GameStates.Add(gameState);
}
public static GameState GetState(string name)
{
return GameStates.Find(gameState => gameState.Name == name);
}
public static void SwitchStates(GameState gameState)
{
if (CurrentGameState != null)
{
if (MediaPlayer.State == MediaState.Playing)
MediaPlayer.Stop();
}
CurrentGameState = gameState;
if (CurrentGameState != null)
MediaPlayer.Play(CurrentGameState.Song);
}
public static void SwitchStates(string gameState)
{
SwitchStates(GetState(gameState));
}
public static void Dispose()
{
foreach (var gameState in GameStates)
{
gameState.Song.Dispose();
}
GameStates.Clear();
}
}
public class GameState
{
public Song Song;
public string Name;
public GameState(string name, Song song)
{
Name = name;
Song = song;
}
}
public class Game1 : Game
{
private GraphicsDeviceManager _graphicsDeviceManager;
private KeyboardState _keyboardState;
public Game1()
{
_graphicsDeviceManager = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void LoadContent()
{
GameStateManager.AddState(new GameState("InGame", Content.Load<Song>("song1")));
GameStateManager.AddState(new GameState("Menu", Content.Load<Song>("song2")));
}
protected override void UnloadContent()
{
GameStateManager.Dispose();
}
protected override void Update(GameTime gameTime)
{
var keyboardState = Keyboard.GetState();
if (keyboardState.IsKeyDown(Keys.A) && _keyboardState.IsKeyUp(Keys.A))
{
GameStateManager.SwitchStates("Menu");
}
else if (keyboardState.IsKeyDown(Keys.B) && _keyboardState.IsKeyUp(Keys.B))
{
GameStateManager.SwitchStates("InGame");
}
else if (keyboardState.IsKeyDown(Keys.C) && _keyboardState.IsKeyUp(Keys.C))
{
GameStateManager.SwitchStates("Undefined");
}
_keyboardState = keyboardState;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
base.Draw(gameTime);
}
}
}