显然我必须展示研究工作(并且更清楚)?!?......
我一直在尝试使用XNA从头开始制作一个自上而下的太空射击游戏。我过去曾经这样做过很多次,但是还没有编写一段时间,这让我再次陷入困境。我有问题让子弹发射我想要的方式(我想在任何时候在屏幕上最多指定数量的子弹,例如。)
我已经阅读了很多关于使用数组的文章但由于某种原因我无法理解为什么它们只出现在一个子弹中。我已尽最大努力调试并看到它们似乎都被创造并且当空间被推动时被“触发”,但是看起来它们都被绘制在相同的位置,因此看起来像一颗子弹。有趣的是,我设置的'maxBullets'变量越高,子弹移动的速度越快,就好像每当我创建一个新的Bullet1时,位置 - =速度被应用于所有这些变量。
任何人都可以帮我找到解决方案。如果您需要任何信息,如果我遗漏了什么,请告诉我。所有帮助赞赏。谢谢:))
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace AlienAttacks
{
public class Player
{
Texture2D texture, bulletTexture1;
KeyboardState kbState;
public Vector2 position;
public int turnSpeed = 15, backSpeed = 2, forwardSpeed = 3;
Rectangle gameScreenBounds;
public int frameWidth, frameHeight, currentFrameX, currentFrameY;
Rectangle drawnRect;
Bullet[] bullets;
Bullet bullet1;
public int maxBullets = 3; // this will actually allow one extra bullet due to array starting at zero
public int bulletSpeed = 4;
public float FireTimer = 0.0f, FireRate = 0.8f;
public Player(Texture2D Texture, int FrameWidth, int FrameHeight, Rectangle GameScreenBounds, Texture2D BulletTexture1)
{
texture = Texture;
frameWidth = FrameWidth;
frameHeight = FrameHeight;
gameScreenBounds = GameScreenBounds;
bulletTexture1 = BulletTexture1;
bullet1 = new Bullet(bulletTexture1, bulletSpeed);
bullets = new Bullet[maxBullets];
for (int i = 0; i < maxBullets; i++)
{
bullets[i] = bullet1;
}
}
public void Update(GameTime gameTime)
{
drawnRect = new Rectangle(currentFrameX * frameWidth, currentFrameY * frameHeight, frameWidth, frameHeight);
kbState = Keyboard.GetState();
// Keyboard Controls
if (kbState.IsKeyDown(Keys.A) && position.X > gameScreenBounds.Left)
{
position.X -= turnSpeed;
}
if (kbState.IsKeyDown(Keys.D) && position.X + frameWidth < gameScreenBounds.Right)
{
position.X += turnSpeed;
}
if (kbState.IsKeyDown(Keys.W) && position.Y > gameScreenBounds.Top)
{
currentFrameX = 1;
position.Y -= forwardSpeed;
}
else
currentFrameX = 0;
if (kbState.IsKeyDown(Keys.S) && position.Y + frameHeight < gameScreenBounds.Bottom)
{
position.Y += backSpeed;
}
for (int i = 0; i < maxBullets; i++)
{
bullets[i] = bullet1;
bullets[i].Update(gameTime);
}
FireTimer += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (kbState.IsKeyDown(Keys.Space))
{
for (int i = 0; i < maxBullets; i++)
{
if (FireTimer >= FireRate)
{
if (!bullets[i].IsAlive)
{
bullets[i].IsAlive = true;
bullets[i].position = position;
FireTimer = 0.0f;
}
}
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, drawnRect, Color.White);
for (int i = 0; i < maxBullets; i++)
{
bullets[i].Draw(spriteBatch);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace AlienAttacks
{
public class Bullet
{
public Texture2D texture;
public Vector2 position;
public int speed;
public bool IsAlive = false;
public Bullet(Texture2D Texture, int Speed)
{
texture = Texture;
speed = Speed;
}
public void Update(GameTime gameTime)
{
if (IsAlive)
{
position.Y -= speed;
// if bullet goes off top of screen...
if (position.Y - texture.Height < 0)
{
BulletDead();
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
if (IsAlive)
spriteBatch.Draw(texture, position, Color.White);
}
public void BulletDead()
{
IsAlive = false;
}
}
}
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.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace AlienAttacks
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Rectangle gameScreenBounds;
Texture2D hudBGTexture;
Rectangle hudRect;
int hudPositionY;
Texture2D p1Texture, p1bulletTexture1;
Player player1;
Vector2 player1StartPosition;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
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()
{
// TODO: Add your initialization logic here
graphics.PreferredBackBufferWidth = 1600;
graphics.PreferredBackBufferHeight = 900;
//graphics.IsFullScreen = true;
graphics.ApplyChanges();
hudRect = new Rectangle(0, 0, graphics.PreferredBackBufferWidth, 100);
hudPositionY = graphics.PreferredBackBufferHeight - hudRect.Height;
gameScreenBounds = new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight - hudRect.Height);
base.Initialize();
}
/// <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);
hudBGTexture = Content.Load<Texture2D>("hud");
p1bulletTexture1 = Content.Load<Texture2D>("shot");
p1Texture = Content.Load<Texture2D>("red");
player1 = new Player(p1Texture, 144, 104, gameScreenBounds, p1bulletTexture1);
player1StartPosition = new Vector2(graphics.PreferredBackBufferWidth / 2 - player1.frameWidth / 2, graphics.PreferredBackBufferHeight - hudRect.Height - player1.frameHeight);
player1.position = player1StartPosition;
}
/// <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 || Keyboard.GetState().IsKeyDown(Keys.Escape))
this.Exit();
player1.Update(gameTime);
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.Black);
SpriteBatch targetBatch = new SpriteBatch(GraphicsDevice);
RenderTarget2D target = new RenderTarget2D(GraphicsDevice, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight);
GraphicsDevice.SetRenderTarget(target);
spriteBatch.Begin();
player1.Draw(spriteBatch);
spriteBatch.Draw(hudBGTexture, new Vector2(0, hudPositionY), Color.WhiteSmoke);
spriteBatch.End();
GraphicsDevice.SetRenderTarget(null);
targetBatch.Begin();
targetBatch.Draw(target, new Rectangle(0, 0, GraphicsDevice.DisplayMode.Width, GraphicsDevice.DisplayMode.Height), Color.White);
targetBatch.End();
base.Draw(gameTime);
}
}
}
答案 0 :(得分:1)
看起来数组中的每个项目都指向一个实例。
bullet1 = new Bullet(bulletTexture1, bulletSpeed);
bullets = new Bullet[maxBullets];
for (int i = 0; i < maxBullets; i++)
{
bullets[i] = bullet1;
}
应该是这样的:
bullets = new Bullet[maxBullets];
for (int i = 0; i < maxBullets; i++)
{
bullets[i] = new Bullet(bulletTexture1, bulletSpeed);
}