c# XNA使用数组发射子弹
本文关键字:发射 子弹 数组 XNA | 更新日期: 2023-09-27 18:07:50
显然我必须展示我的研究努力(并且更清楚)?
我一直在尝试使用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);
}
}
}
看起来数组中的每一项都指向一个实例。
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);
}