1
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 WindowsGame3
{
    public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    Texture2D ship, bullet, alien;

    Texture2D[] aliens = new Texture2D[20];
    Texture2D[] bullets = new Texture2D[10];

    Vector2 shipPos = new Vector2(200, 540);
    Vector2 alienPos = new Vector2(200, 400);
    Vector2 bulletPos = new Vector2(200, 450);

    Vector2[] aliensPos = new Vector2[20];
    Vector2[] bulletsPos = new Vector2[10];

    int alienCount = 0;
    int bulletCount = 0;

    KeyboardState state = Keyboard.GetState();

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";

        graphics.PreferredBackBufferWidth = 400;
        graphics.PreferredBackBufferHeight = 600;
    }

    protected override void Initialize()
    {
        base.Initialize();
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);

        alien = Content.Load<Texture2D>("alien");
        ship = Content.Load<Texture2D>("ship");

        for (int x = 0; x < 5; x++)
        {
            for (int y = 0; y < 4; y++)
            {
                aliens[alienCount] = Content.Load<Texture2D>("alien");
                aliensPos[alienCount].X = 100 + (x * 40);
                aliensPos[alienCount].Y = 20 + (y * 40);
                alienCount++;
            }  
        }
    }

    protected override void UnloadContent()
    {

    }

    protected override void Update(GameTime gameTime)
    {
        if (state.IsKeyDown(Keys.Right) && shipPos.X < 360)
        {
            shipPos.X += 5;
        }

        if (state.IsKeyDown(Keys.Left) && shipPos.X > 0)
        {
            shipPos.X -= 5;
        }

        if (state.IsKeyDown(Keys.Space))
        {
                bullets[bulletCount] = Content.Load<Texture2D>("bullet");
                bulletsPos[bulletCount].X = shipPos.X;
                bulletsPos[bulletCount].Y = shipPos.Y;
                bulletCount++;
        }

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.Black);

        spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);

        spriteBatch.Draw(ship, shipPos, Color.White);
        spriteBatch.Draw(alien, alienPos, Color.White);

        for (int alienCount = 0; alienCount < 20; alienCount++)
        {
            spriteBatch.Draw(aliens[alienCount], aliensPos[alienCount], Color.White);
        }

        for (int bulletCount = 0; bulletCount < 10; bulletCount++)
        {
            spriteBatch.Draw(bullets[bulletCount], bulletsPos[bulletCount], Color.White);
        }

        spriteBatch.End();
        base.Draw(gameTime);
    }
}
}

我想在船舶位置创建一个子弹并将该子弹存储在一个数组中,但是在我的 draw 方法中,当我从数组中绘制子弹时,我收到错误消息 This method does not accept null for this parameter。参数名称:纹理

4

2 回答 2

3

在 XNA 中,最好在需要之前加载所有资源,这就是 LoadContent() 方法的用途。您应该在其中加载子弹纹理,然后在必要时在 Update() 中使用它。

每个图像只需要一个 Texture2D 对象,即使您想多次绘制它。您不需要完全相同图像的 Texture2D 数组。

因此,对于您的示例:

protected override void LoadContent()
{
    spriteBatch = new SpriteBatch(GraphicsDevice);

    alien = Content.Load<Texture2D>("alien"); //only one texture needed
    ship = Content.Load<Texture2D>("ship");
    bullet = Content.Load<Texture2D>("bullet"); //only one texture needed

    //set initial positions as before
    for (int x = 0; x < 5; x++)
    {
        for (int y = 0; y < 4; y++)
        {
            aliensPos[alienCount].X = 100 + (x * 40);
            aliensPos[alienCount].Y = 20 + (y * 40);
            alienCount++;
        }  
    }
}

当你想制作新的外星人或子弹时,你只需设置它们的位置,因为图像已经加载:

if (state.IsKeyDown(Keys.Space))
{
        bulletsPos[bulletCount].X = shipPos.X;
        bulletsPos[bulletCount].Y = shipPos.Y;
        bulletCount++;
}

然后,当您加载并准备好所有纹理时,您可以绘制它:

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.Black);

    spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);

    spriteBatch.Draw(ship, shipPos, Color.White);

    for (int alienCount = 0; alienCount < 20; alienCount++)
    {
        //draw alien texture for every aliensPos
        spriteBatch.Draw(alien, aliensPos[alienCount], Color.White);
    }

    for (int bulletCount = 0; bulletCount < 10; bulletCount++)
    {
        //draw bullet texture for every bulletsPos
        spriteBatch.Draw(bullet, bulletsPos[bulletCount], Color.White);
    }

    spriteBatch.End();
    base.Draw(gameTime);
}

最后,为了让你的船动起来,你应该每一帧都读键盘。您只调用一次 Keyboard.GetState() 。当您阅读它时,它会返回当前按下的键,因此您需要每帧刷新它。

您应该将其添加到 Update() 方法的开头:

state = Keyboard.GetState();
于 2012-10-31T10:18:58.457 回答
0

那是因为您试图在制作子弹之前画出子弹。解决方案是在制作子弹之前不要画子弹。

有很多方法可以做到这一点,但这是最快和最肮脏的方法:

改变

    for (int bulletCount = 0; bulletCount < 10; bulletCount++)
    {
        spriteBatch.Draw(bullets[bulletCount], bulletsPos[bulletCount], Color.White);
    }

    for (int bulletCount = 0; bulletCount < 10; bulletCount++)
    {
        if(bullets[bulletCount] != null)
            spriteBatch.Draw(bullets[bulletCount], bulletsPos[bulletCount], Color.White);
    }
于 2012-10-30T20:20:18.090 回答