我正在使用C#和monogame框架在Visual Studio中构建此游戏。游戏的目的是让你使用埃里克躲避随着时间的推移而变得更快的堕落敌人,如果你击中了敌人,那么游戏结束了。
有一个主菜单在游戏开始之前加载,要求你按Enter键开始游戏,如果你按下这个游戏加载,如果你击中一个敌人就会出现一个屏幕上的游戏,你返回到主菜单按A.
但是,目前我的游戏并未首先打开主菜单或在屏幕上显示游戏。这些屏幕使用与主游戏本身相同的背景图像,但文本采用深红色字体,以使状态易于区分。
这是我的代码,请有人建议
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Collections.Generic;
using System;
using System.Media;
using Microsoft.Xna.Framework.Audio;
namespace AttackOfTheUnknown
{
/// <summary>
/// Constructor for Game.
/// This is called when the Game object is created.
/// </summary>
public class SuperAlianorRescue : Game
{
// --- GAME STATE ---
enum GameState
{
GameMenu = 0,
GamePlay = 1,
GameOver = 2,
}
GameState currentGameState;
// --- GRAPHICS ---
// Manages the graphics
GraphicsDeviceManager graphics;
// Used to draw sprite images (textures)
SpriteBatch spriteBatch;
// Area which should be visible on all TVs (OK to draw inside)
Rectangle safeBounds;
// Percentage of the screen on every side is the safe area
const float safeAreaPortion = 0.05f;
// --- CHARACTER ---
// Used for character sprite
Texture2D characterTexture;
// Used to store current character position
Vector2 characterPosition;
// Used to calculate next position of character given user input
const int characterSpeed = 10;
// Used to state character has collided with enemy
bool characterHit = false;
//--- ENEMIES ---
// Used for enemy sprite
Texture2D enemyTexture;
// The list of enemies currently in the game
List<Vector2> enemyPositions = new List<Vector2>();
// Probability that an enemy will be spawned
float enemySpawnProbability = 0.05f;
// Speed of enemy
public float speedIncrement = 0.01f;
public float enemySpeed = 0.005f;
public float speed = 0;
// Used to generate random colours
Random random = new Random();
// Current enemy colour
Color enemyColor = Color.White;
// IMPORT GAME BACKGROUND
Texture2D backgroundTexture;
// SOUND
// enemy spawn sound
SoundEffect enemySpawnSound;
SoundEffectInstance enemySpawnSoundInstance;
// --- IN_GAME INFORMATION ---
// Player score
long score;
// Highest score
long highScore;
// Font used to display score
SpriteFont scoreFont;
// Used to hold current on-screen information
string scoreText = "SCORE: 0";
string highScoreText = "HI: 0";
string gameName = "Super Alianor Rescue";
string aimText = "Aim: Move Eric with WASD keys to dodge the enemies.";
string menuWelcome = "Welcome to Super Alianor Rescue.";
string menuHowToPlay = "Press ENTER To Start New Game.";
string GameOverText = "Game Over";
string GameOverClose = "Press Escape To Quit Game";
Song theSong;
public SuperAlianorRescue()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferHeight = 600;
graphics.PreferredBackBufferWidth = 650;
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
base.Initialize();
// Calculate safe bounds based on current resolution
Viewport viewport = graphics.GraphicsDevice.Viewport;
safeBounds = new Rectangle(
(int)(viewport.Width * safeAreaPortion),
(int)(viewport.Height * safeAreaPortion),
(int)(viewport.Width * (1 - 2 * safeAreaPortion)),
(int)(viewport.Height * (1 - 2 * safeAreaPortion)));
// Start the player in the centre along the bottom of the screen
characterPosition.X = (safeBounds.Width - characterTexture.Width) / 2;
characterPosition.Y = safeBounds.Height - characterTexture.Height;
// Reset score
score = 0;
highScore = 0;
MediaPlayer.IsRepeating = true;
MediaPlayer.Play(theSong);
MediaPlayer.Volume = 0.01f;
// Set the initial game state
currentGameState = GameState.GameMenu;
// Reset score
score = 0;
highScore = 0;
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// Load textures
enemyTexture = Content.Load<Texture2D>("enemy");
characterTexture = Content.Load<Texture2D>("eric2");
backgroundTexture = Content.Load<Texture2D>("gameback");
// create the font
scoreFont = Content.Load<SpriteFont>("GameFont");
theSong = Content.Load<Song>("Komiku_-_63_-_The_Zone");
// create the sound effect
enemySpawnSound = Content.Load<SoundEffect>("Zombie Demon");
enemySpawnSoundInstance = enemySpawnSound.CreateInstance();
enemySpawnSoundInstance.Volume = 1.0f;
enemySpawnSoundInstance.Pitch = 1.0f;
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// game-specific content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Get input
KeyboardState keyboard = Keyboard.GetState();
GamePadState gamePad = GamePad.GetState(PlayerIndex.One);
// use game state
switch (currentGameState)
{
case GameState.GameMenu:
// Allows the game to exit
if (gamePad.Buttons.Back == ButtonState.Pressed ||
keyboard.IsKeyDown(Keys.Escape))
{
this.Exit();
}
if (gamePad.Buttons.Start == ButtonState.Pressed ||
keyboard.IsKeyDown(Keys.Enter))
{
// Start the player in the center along the bottom of the screen
characterPosition.X = (safeBounds.Width - characterTexture.Width) / 2;
characterPosition.Y = (safeBounds.Height - characterTexture.Height);
// Set the game state to play
currentGameState = GameState.GamePlay;
// Reset score
score = 0;
}
break;
case GameState.GameOver:
// If game is over, the game allows return to main menu if key A is pressed
if (gamePad.Buttons.A == ButtonState.Pressed ||
keyboard.IsKeyDown(Keys.A))
{
currentGameState = GameState.GameMenu;
}
break;
case GameState.GamePlay:
// Press X during game play to return to main menu
if (gamePad.Buttons.X == ButtonState.Pressed ||
keyboard.IsKeyDown(Keys.X))
{
currentGameState = GameState.GameMenu;
}
// Press ESC to quit game during game play
if (gamePad.Buttons.Back == ButtonState.Pressed ||
keyboard.IsKeyDown(Keys.Escape))
{
this.Exit();
}
//Move the player left and right with arrow keys or d-pad
if (keyboard.IsKeyDown(Keys.Left) || gamePad.DPad.Left == ButtonState.Pressed)
{
characterPosition.X -= characterSpeed;
}
if (keyboard.IsKeyDown(Keys.Right) || gamePad.DPad.Right == ButtonState.Pressed)
{
characterPosition.X += characterSpeed;
}
// Prevent the character from moving off of the screen
characterPosition.X = MathHelper.Clamp(characterPosition.X,
safeBounds.Left, safeBounds.Right - characterTexture.Width);
// Get the bounding rectangle of the character
Rectangle characterRectangle =
new Rectangle((int)characterPosition.X, (int)characterPosition.Y,
characterTexture.Width, characterTexture.Height);
// Spawn new enemy
if (random.NextDouble() < enemySpawnProbability)
{
float x = (float)random.NextDouble() *
(Window.ClientBounds.Width - enemyTexture.Width);
enemyPositions.Add(new Vector2(x, -enemyTexture.Height));
// play the enemy spawn sound
enemySpawnSoundInstance.Play();
}
// Increase enemy speed as game progresses
enemySpeed += speedIncrement;
if (speed >= speedIncrement) speed = enemySpeed;
// Update each enemy
characterHit = false;
for (int i = 0; i < enemyPositions.Count; i++)
{
// Animate this enemy
enemyPositions[i] =
new Vector2(enemyPositions[i].X,
enemyPositions[i].Y + enemySpeed);
// Get the bounding rectangle of this enemy
Rectangle enemyRectangle =
new Rectangle((int)enemyPositions[i].X, (int)enemyPositions[i].Y,
enemyTexture.Width, enemyTexture.Height);
// Check collision with character
if (characterRectangle.Intersects(enemyRectangle))
characterHit = true;
// Remove this enemy if it has fallen off the screen
if (enemyPositions[i].Y > Window.ClientBounds.Height)
{
enemyPositions.RemoveAt(i);
// When removing an enemy, the next enemy will have the same index
// as the current enemy. Decrement i to prevent skipping an enemy.
i--;
}
}
// Reset game if character has been hit
if (characterHit)
{
// check for highscore
if (score > highScore)
highScore = score;
// reset score to zero
score = 0;
// empty the enemies list
enemyPositions = new List<Vector2>();
// change color of enemies to indicate a new game
enemyColor = new Color(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255));
// finish game by loading gameover screen
currentGameState = GameState.GameOver;
}
else
{
// update score (character has been hit)
score = score + 1;
}
// update on-screen information variables
scoreText = "SCORE: " + score.ToString();
highScoreText = "HIGH SCORE: " + highScore.ToString();
break;
}
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice device = graphics.GraphicsDevice;
// use game state
switch (currentGameState)
{
case GameState.GameMenu: // load game menu and clear once enter key is pressed
spriteBatch.Begin();
spriteBatch.Draw(backgroundTexture, Vector2.Zero, Color.White);
spriteBatch.DrawString(scoreFont, menuWelcome,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(menuWelcome).X / 3,
30), Color.DarkRed);
spriteBatch.DrawString(scoreFont, menuHowToPlay,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(menuHowToPlay).X / 4,
30), Color.DarkRed);
spriteBatch.End();
device.Clear(Color.DarkBlue);
break;
case GameState.GameOver: // load game menu and clear once escape is pressed
spriteBatch.Begin();
spriteBatch.Draw(backgroundTexture, Vector2.Zero, Color.White);
spriteBatch.DrawString(scoreFont, GameOverText,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(GameOverText).X / 3,
30), Color.DarkRed);
spriteBatch.DrawString(scoreFont, GameOverClose,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(GameOverClose).X / 4,
30), Color.DarkRed);
spriteBatch.End();
device.Clear(Color.DarkBlue);
break;
case GameState.GamePlay: // load the sprite batch for main game play
// Open sprite batch
spriteBatch.Begin();
spriteBatch.End();
break;
}
device.Clear(Color.CornflowerBlue);
// "Open" the sprite batch
spriteBatch.Begin();
// Clear game screen with background colour
device.Clear(Color.DarkBlue);
// Draw background
spriteBatch.Draw(backgroundTexture, Vector2.Zero, Color.White);
// Draw character
spriteBatch.Draw(characterTexture, characterPosition, Color.White);
// Draw enemies
foreach (Vector2 enemyPosition in enemyPositions)
spriteBatch.Draw(enemyTexture, enemyPosition, enemyColor);
// Draw on-screen game information
spriteBatch.DrawString(scoreFont, scoreText, new Vector2(30, 30), Color.Black);
spriteBatch.DrawString(scoreFont, highScoreText,
new Vector2((float)safeBounds.Right - scoreFont.MeasureString(highScoreText).X,
30), Color.Black);
spriteBatch.DrawString(scoreFont, gameName,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(gameName).X / 2,
30), Color.Black);
spriteBatch.DrawString(scoreFont, aimText,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(gameName).X / 1,
60), Color.Black);
// "Close" the sprite batch
spriteBatch.End();
break;
base.Draw(gameTime);
}
}
}
答案 0 :(得分:1)
您的游戏状态的绘制代码在switch语句之外,因此在绘制的精灵上删除任何菜单或游戏,并在顶部绘制游戏精灵。这是由这段代码引起的:
case GameState.GamePlay: // load the sprite batch for main game play
// Open sprite batch
spriteBatch.Begin();
spriteBatch.End();
break;
}
要解决此问题,您需要将游戏状态绘制代码移至switch语句中,如下所示:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice device = graphics.GraphicsDevice;
// use game state
switch (currentGameState)
{
case GameState.GameMenu: // load game menu and clear once enter key is pressed
device.Clear(Color.DarkBlue);
spriteBatch.Begin();
spriteBatch.Draw(backgroundTexture, Vector2.Zero, Color.White);
spriteBatch.DrawString(scoreFont, menuWelcome,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(menuWelcome).X / 3,
30), Color.DarkRed);
spriteBatch.DrawString(scoreFont, menuHowToPlay,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(menuHowToPlay).X / 4,
30), Color.DarkRed);
spriteBatch.End();
break;
case GameState.GameOver: // load game menu and clear once escape is pressed
device.Clear(Color.DarkBlue);
spriteBatch.Begin();
spriteBatch.Draw(backgroundTexture, Vector2.Zero, Color.White);
spriteBatch.DrawString(scoreFont, GameOverText,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(GameOverText).X / 3,
30), Color.DarkRed);
spriteBatch.DrawString(scoreFont, GameOverClose,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(GameOverClose).X / 4,
30), Color.DarkRed);
spriteBatch.End();
device.Clear(Color.DarkBlue);
break;
case GameState.GamePlay: // load the sprite batch for main game play
device.Clear(Color.CornflowerBlue);
// Open sprite batch
spriteBatch.Begin();
// Draw background
spriteBatch.Draw(backgroundTexture, Vector2.Zero, Color.White);
// Draw character
spriteBatch.Draw(characterTexture, characterPosition, Color.White);
// Draw enemies
foreach (Vector2 enemyPosition in enemyPositions)
spriteBatch.Draw(enemyTexture, enemyPosition, enemyColor);
// Draw on-screen game information
spriteBatch.DrawString(scoreFont, scoreText, new Vector2(30, 30), Color.Black);
spriteBatch.DrawString(scoreFont, highScoreText,
new Vector2((float)safeBounds.Right - scoreFont.MeasureString(highScoreText).X,
30), Color.Black);
spriteBatch.DrawString(scoreFont, gameName,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(gameName).X / 2,
30), Color.Black);
spriteBatch.DrawString(scoreFont, aimText,
new Vector2((float)safeBounds.Right / 2 - scoreFont.MeasureString(gameName).X / 1,
60), Color.Black);
// "Close" the sprite batch
spriteBatch.End();
break;
}
base.Draw(gameTime);
}
以前你在switch语句中的游戏状态创建了一个空的sprite批处理并关闭了switch语句,然后是游戏绘制代码。
在上文中,我已将您的游戏绘制代码移至switch语句中(为了清晰起见,将device.clear()
语句移至每个开关块的顶部)