我在Monogame中制作了一个平台游戏,在那里我有敌人可以制造攻击框架但是如果我试图杀死它,它会卡在框架中而不能死亡。
这是我的Game1代码:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace TreasureHunt
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
int enemyLives = 2;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
SoundEffect aj;
SoundEffect collect;
Texture2D coinCount;
int screenWidth = 1024;
int screenHeight = 768;
//int enemyLives = 2;
//Vector2 temp = new Vector2 (1000, 600);
Pirate player;
List<EnemyPirate> argh = new List<EnemyPirate>();
List<Coin> coin = new List<Coin>();
bool firstPirateArmy = true;
Level map;
Vector2 dist;
Vector2 coindist;
Background backGround;
int collectedCoins;
SpriteFont inGameFont;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferWidth = screenWidth;
graphics.PreferredBackBufferHeight = screenHeight;
graphics.IsFullScreen = false;
Window.Title = "TreasureHunt";
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()
{
map = new Level (screenWidth, screenHeight);
map.LoadMap (Content, 1);
backGround = new Background(screenWidth, (int)(Level.GetWorldSize().X * Level.GetTileSize()), 1, Content);
player = new Pirate(screenWidth, screenHeight, Content, graphics.GraphicsDevice);
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(400, 400), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(1600, 420), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(3800, 600), enemyLives));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (505, 278)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (1100, 25)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (890, 660)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (1720, 660)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (2348, 410)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (2850, 150)));
coin.Add (new Coin (screenWidth, screenHeight, Content, new Vector2 (2950, 660)));
base.Initialize();
}
private void ResetPirates()
{
if(firstPirateArmy)
{
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(1000, 500), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(1500, 50), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(3700, 200), enemyLives));
firstPirateArmy = false;
}
else
{
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(400, 400), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(1600, 420), enemyLives));
argh.Add(new EnemyPirate(screenWidth, screenHeight, Content, new Vector2(3800, 600), enemyLives));
firstPirateArmy = true;
}
}
/// <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);
inGameFont = Content.Load<SpriteFont>("inGameFont");
aj = Content.Load<SoundEffect> ("AjLjud");
collect = Content.Load<SoundEffect> ("Collecting1");
coinCount = Content.Load<Texture2D> ("Coin");
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all 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)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
player.Update (gameTime);
for (int i = 0; i < coin.Count (); i++) {
coin [i].Update (gameTime);
coindist = (coin [i].GetPosition () - player.GetPosition ());
if (coindist.Length () < 60) {
collect.Play ();
coin.RemoveAt (i);
collectedCoins++;
}
}
for (int i = 0; i < argh.Count (); i++) {
dist = (argh [i].GetPosition () - player.GetPosition ());
if (dist.Length () < 100) {
argh [i].Attack ();//.currentState = EnemyPirate.figureState.hitting;
player.playerLives--;
}
}
for (int i = 0; i < argh.Count(); i++)
{
argh[i].Update(gameTime);
if (player.HasHitEnemy(argh[i].GetBoundingBox()))
{
argh [i].enemyLives--;
aj.Play ();
argh [i].hurt = true;
if (argh [i].enemyLives <= 0) {
argh [i].currentState = EnemyPirate.figureState.predie;
argh [i].EnemyIsDead ();
//if(argh[i].dead)
//argh.RemoveAt (i);
}
if (argh.Count() == 0)
ResetPirates();
}
if (argh [i].currentState == EnemyPirate.figureState.died)
argh.RemoveAt (i);
}
map.UpdateCamera(player.GetPosition());
backGround.Update ();
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.Clear(Color.CornflowerBlue);
spriteBatch.Begin (SpriteSortMode.Deferred,
null,
SamplerState.PointClamp,
null,
null);
backGround.Draw (spriteBatch);
map.Draw (spriteBatch);
foreach (EnemyPirate c in argh)
c.Draw (spriteBatch);
foreach (Coin c in coin)
c.Draw (spriteBatch);
player.Draw (spriteBatch);
//spriteBatch.DrawString(inGameFont, "speed.Y:" + player.position.Y, new Vector2(20, 20), Color.White);
spriteBatch.DrawString(inGameFont, "R = Reset", new Vector2(20, 20), Color.White);
spriteBatch.DrawString(inGameFont, "dist: "+dist.Length()+" "+player.playerLives, new Vector2(20, 40), Color.White);
spriteBatch.DrawString(inGameFont, ": " + collectedCoins, new Vector2(55, 70), Color.White);
spriteBatch.Draw (coinCount, new Vector2 (20, 60), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
这是我的敌人代码:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace TreasureHunt
{
public class EnemyPirate : PlatformerFigure
{
public int enemyLives = 2;
int animWalk = 0;
int animHit = 6;
int animPreDie = 9;
// int animDie = 10;
public figureState currentState;
public bool dead;
public bool hurt;
public const float _delay = 3; // seconds
public float _remainingDelay = _delay;
public enum figureState // Alla olika stadier figuren kan befinna sig i
{
standing,
walking,
jumping,
predie,
die,
died,
hitting
}
public EnemyPirate (int screenWidth, int screenHeight, ContentManager contMan, Vector2 position, int Lives)
{
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
LoadMedia(contMan);
enemyLives = Lives;
animSequence = new int[]{ 1, 2, 3, 4, 5, 0, 7, 8, 0, 10, 11, 11 };
SetBoundingBox (new Rectangle (10, 15, 63, 81));
Reset ();
this.position = position;
}
public void Reset()
{
Facing = AnimatedObject.direction.left;
SetFrame(animWalk);
currentState = figureState.standing;
maxSpeed = new Vector2(1f, 6);
//position = new Vector2(1600, 400); // Behövs inte när man skickar in en position till konstruktorn.
speed = Vector2.Zero;
slipperyK = 1;
acc = Vector2.Zero; // Från början står figuren still.
walkAcc = 1f;
primaryColor = Color.White;
alpha = 1;
}
private void LoadMedia(ContentManager content)
{
gfx = content.Load<Texture2D>("EnemyPirate2");
AnimationSettings(96, 96, 110, direction.right, 12);
}
public override bool Update(GameTime gameTime)
{
var timer = (float) gameTime.ElapsedGameTime.TotalSeconds;
Think();
Move(gameTime);
UpdateAnimation(gameTime);
GroundCollision();
if (currentState == figureState.hitting && currentFrame == 0)
currentState = figureState.standing;
// else if (enemyLives <= 0)
// currentState = figureState.predie;
if (currentState == figureState.predie) {
_remainingDelay -= timer;
if (_remainingDelay < 2) {
alpha -= 0.04f;
if (alpha < 0)
alpha = 0;
}
}
if (_remainingDelay <= 0)
currentState = figureState.died;
return true;
}
private void Think()
{
if (Facing == direction.left)
{
acc.X = -walkAcc;
if (WallCollision(new Vector2(-10,0)) || !GroundAhead())
{
Facing = direction.right;
acc.X = walkAcc;
}
}
else
{
acc.X = walkAcc;
if (WallCollision(new Vector2(10,0)) || !GroundAhead())
{
Facing = direction.left;
acc.X = -walkAcc;
}
}
}
private bool GroundAhead()
{
Vector2 ahead = position + pos_feet; // Vart finns figurens fötter?
if (Facing == direction.left)
ahead += new Vector2(-10, 0); // Tittar lite till vänster om figuren
else
ahead += new Vector2(10, 0); // Tittar lite till höger om figuren
int tile = Level.GetTile(ahead);
if (tile > 44 && tile < 77 || tile > 84 && tile < 104)
return true;
return false;
}
public void EnemyIsDead ()
{
if (currentState == figureState.predie)
SetFrame (animPreDie);
acc = Vector2.Zero;
walkAcc = 0;
dead = true;
}
public void Hurted()
{
if (hurt) {
var pos = position.X;
while(position.X < pos-5){
position = new Vector2 (position.X, 0);
}
}
}
public void Attack()
{
if (currentState != figureState.hitting) {
SetFrame (animHit);
currentState = figureState.hitting;
}
}
}
}
答案 0 :(得分:1)
代码太多了。您没有Asserts或Exceptions。使你的代码变得非常脆弱,这样如果出现错误,它将停止并提醒你修复它。
例如。在Argh.Attack()内部,断言currentState尚未死亡。