2

現在、大学向けの Xna ゲームに取り組んでいます。独自のテクスチャなどを入れる前に、まず何かをテストしています。

そのため、多くのチュートリアルを見て、多くのコードを実行しました。現在、この小さなプログラムを実行しています: http://www.konter.at/Konter_Game.rar

これが GameScreen で、ここでプレーヤーと背景、および使用するすべてのものをロードします。

namespace Casual_Game
{
    public class GameplayScreen : GameScreen
    {
        Player player;
        Camera camera;
        SpriteFont font;
        private List<Layer> layers;
        private SpriteBatch _spriteBatch;

    Rectangle recPlayer, recGround;
    bool colis = false;
    Collision collision;

    public override void LoadContent(ContentManager content, InputManager input)
    {
        camera = new Camera(Game1.reference.GraphicsDevice.Viewport) { Limits = new Rectangle(0, 0, 4800, 720) };

        collision = new Collision();
        _spriteBatch = new SpriteBatch(Game1.reference.GraphicsDevice);
        base.LoadContent(content, input);
        player = new Player();
        player.LoadContent(content, input);
        font = content.Load<SpriteFont>("Font1");

        layers = new List<Layer>
        {
            new Layer(camera) { Parallax = new Vector2(0.0f, 1.0f) },
            new Layer(camera) { Parallax = new Vector2(0.1f, 1.0f) },
            new Layer(camera) { Parallax = new Vector2(0.2f, 1.0f) },
            new Layer(camera) { Parallax = new Vector2(0.3f, 1.0f) },
            new Layer(camera) { Parallax = new Vector2(0.4f, 1.0f) },
            new Layer(camera) { Parallax = new Vector2(0.5f, 1.0f) },
            new Layer(camera) { Parallax = new Vector2(0.6f, 1.0f) },
            new Layer(camera) { Parallax = new Vector2(0.8f, 1.0f) },
            new Layer(camera) { Parallax = new Vector2(1.0f, 1.0f) }
        };

        // Add one sprite to each layer });
        layers[1].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer2") });
        layers[2].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer3") });
        layers[3].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer4") });
        layers[4].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer5") });
        layers[7].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer8") });
        layers[8].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer9") });

        // Add a few duplicates in different positions
        layers[7].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer8"), position = new Vector2(900, 0) });
        layers[7].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer8"), position = new Vector2(1400, 0) });
        layers[7].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer8"), position = new Vector2(2700, 0) });
        layers[8].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer9"), position = new Vector2(1600, 0) });
        layers[8].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer9"), position = new Vector2(3200, 0) });
        layers[8].Sprites.Add(new Sprite { texture = content.Load<Texture2D>("Textures/Layer9"), position = new Vector2(4800, 0) });

    }
    public override void UnloadContent()
    {
        base.UnloadContent();
    }
    public override void Update(GameTime gameTime)
    {
        player.Update(gameTime);


        recGround = new Rectangle((int)layers[8].Sprites[0].Position.X, (int)layers[8].Sprites[0].Position.Y, layers[8].Sprites[0].Texture.Width, layers[8].Sprites[0].Texture.Height);
        recPlayer = new Rectangle((int)player.Position.X, (int)player.Position.Y, player.Image.Width, player.Image.Height);
        float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
        KeyboardState keyboardState = Keyboard.GetState();

        if (keyboardState.IsKeyDown(Keys.Right))
            camera.Move(new Vector2(200.0f * (float)gameTime.ElapsedGameTime.TotalSeconds, 0.0f), true);

        if (keyboardState.IsKeyDown(Keys.Left))
            camera.Move(new Vector2(-200.0f * (float)gameTime.ElapsedGameTime.TotalSeconds, 0.0f), true);

        if (keyboardState.IsKeyDown(Keys.Down))
            camera.Move(new Vector2(0.0f, 400.0f * elapsedTime), true);

        if (keyboardState.IsKeyDown(Keys.Up))
            camera.Move(new Vector2(0.0f, -400.0f * elapsedTime), true);
        if (recPlayer.Intersects(recGround))
        {
            if (collision.PixelCollision(player.Image, layers[8].Sprites[0].Texture, recPlayer, recGround))
            {
                player.Collision = true;
                colis = true;
            }
            else
            {
                player.Collision = false;
                colis = false;
            }
        }
        else
        {
            player.Collision = false;
            colis = false;
        }

        camera.LookAt(player.Position);

        base.Update(gameTime);
    }
    public override void Draw(SpriteBatch spriteBatch)
    {
       Vector2 parallax = new Vector2(1.0f);
        _spriteBatch.Begin(SpriteSortMode.Deferred,null , null, null, null, null, camera.GetViewMatrix(parallax));
        foreach (Layer layer in layers)
            layer.Draw(_spriteBatch);
        player.Draw(_spriteBatch);
        spriteBatch.DrawString(font, "Player X : " + player.Position.X.ToString(),new Vector2(10, 10), Color.Black);
        spriteBatch.DrawString(font, "CameraX :" + camera._position.X.ToString(), new Vector2(10, 25), Color.Black);
        spriteBatch.DrawString(font, "CameraY :" + camera._position.Y.ToString(), new Vector2(10, 40), Color.Black);
        spriteBatch.DrawString(font, "Col : " + colis.ToString(), new Vector2(10, 55), Color.Black);
        _spriteBatch.End();

    }
}

異なるレイヤーを持つ視差背景であることがわかります。On Layer[8] は、プレイヤーが後で走る「地面」です。

問題は、衝突検出が正しく機能していないことです。検出が遅いか何かに読み込まれているようです。

プレイヤーが検出で地面にぶつかることを念頭に置いています。したがって、彼は地面に止まる場所には価値がありません。だからそれはexateでなければなりません。

これは衝突クラスです:

        public bool PixelCollision(Texture2D sprite1, Texture2D sprite2, Rectangle player, Rectangle enemy)
    {
        Color[] colorData1 = new Color[sprite1.Width * sprite1.Height];
        Color[] colorData2 = new Color[sprite2.Width * sprite2.Height];
        sprite1.GetData<Color>(colorData1);
        sprite2.GetData<Color>(colorData2);

        int top, bottom, left, right;

        top = Math.Max(player.Top, enemy.Top);
        bottom = Math.Min(player.Bottom, enemy.Bottom);
        left = Math.Max(player.Left, enemy.Left);
        right = Math.Min(player.Right, enemy.Right);

        for (int y = top; y < bottom; y++)
        {
            for (int x = left; x < right; x++)
            {
                Color A = colorData1[(y - player.Top) * (player.Width) + (x - player.Left)];
                Color B = colorData2[(y - enemy.Top) * (enemy.Width) + (x - enemy.Left)];

                if (A.A != 0 && B.A != 0)
                    return true;
            }
        }
        return false;
    }
}

誰かがそれを理解するのを手伝ってくれたら、とても幸せです. 私たちはそれほどプログラマーではありません。だから私たちは、尋ねても何も費用がかからないと考えました。:)

K.

編集: Player.Update と Draw:

public override void Update(GameTime gameTime)
    {
        moveAnimation.IsActive = true;
        inputManager.Update();


        if (inputManager.KeyDown(Keys.Right, Keys.A))
        {
            moveAnimation.currentFrame = new Vector2(moveAnimation.CurrentFrame.X, 2);
            velocity.X = moveSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
        }
        else if (inputManager.KeyDown(Keys.Left, Keys.A))
        {
            moveAnimation.currentFrame = new Vector2(moveAnimation.CurrentFrame.X, 1);
            velocity.X =  -moveSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
        }
        else
        {
            velocity.X = 0;
            moveAnimation.IsActive = false;
        }

        if (inputManager.KeyDown(Keys.Up, Keys.W) && jump)
        {
            velocity.Y = -jumpSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds; //Position += theDirection * theSpeed * (float)theGameTime.ElapsedGameTime.TotalSeconds;
            jump = false;
        }

        if (!jump)
            velocity.Y += gravity * (float)gameTime.ElapsedGameTime.TotalSeconds;
        else
            velocity.Y = 0;


        moveAnimation.Position = position += velocity;

        jump = moveAnimation.Position.Y >= 480;

        if (jump)
            position.Y = 480;


        base.Update(gameTime);
        moveAnimation.Update(gameTime);
    }
    public override void Draw(SpriteBatch spriteBatch)
    {
        moveAnimation.Draw(spriteBatch);
    }

Layer.Draw:

public class Layer
{
    SpriteBatch spr1teBatch;
    public Layer(Camera camera)
    {
        _camera = camera;
        Parallax = Vector2.One;
        Sprites = new List<Sprite>();
        spr1teBatch = new SpriteBatch(Game1.reference.GraphicsDevice );
    }

    public Vector2 Parallax { get; set; }

    public List<Sprite> Sprites { get; private set; }



    public void Draw(SpriteBatch spriteBatch)
    {
        spr1teBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, _camera.GetViewMatrix(Parallax));

        foreach(Sprite sprite in Sprites)
            sprite.Draw(spr1teBatch);

        spr1teBatch.End();
    }

    public Vector2 WorldToScreen(Vector2 worldPosition)
    {
        return Vector2.Transform(worldPosition, _camera.GetViewMatrix(Parallax));
    }

    public Vector2 ScreenToWorld(Vector2 screenPosition)
    {
        return Vector2.Transform(screenPosition, Matrix.Invert(_camera.GetViewMatrix(Parallax)));
    }

    private readonly Camera _camera;
}
4

1 に答える 1

2

あなたが描いているものを視覚化しましょう:

視覚化

画面上の recPlayer.x、recPlayer.y にプレーヤーを描画します。そして、recGround.x、recGround.y にレイヤーを描画します。しかし、この位置はビュー マトリックスによって変換されます。

ここで行うことは、2 つの長方形の交差するすべてのピクセルを反復処理することです。結果の x 値と y 値は画面空間にあります。x と y の位置の例を強調表示しました。まさにこの位置でボット テクスチャの色を取得する必要があります。

プレーヤーの色は、既に画面空間にあるため、非常に簡単に取得できます。テクスチャ内の位置はxTex = x - recPlayer.xyTex = y - recPlayer.yです。カラー配列のインデックスは で計算できますindex = yTex * width + xTex。色にアクセスするために、すでにこれを行っています。

地面の色を取得するのは、プレイヤーのように画面空間にないため、少しトリッキーです。おそらく翻訳され、少し拡大されています。レイヤーのスプライトが実際にどのように描画されるか、コードを投稿していません。recGround.x、recGround.yの位置に描画されていると思います(そして変換されます)。やらなければならないことは、地面のワールド空間での x/y の位置を計算することです。したがって、すでにお持ちの方法を使用します。

var screenPosition = new Vector2(x, y);
var groundPosition = ScreenToWorldPos(screenPos);

これにより、基本的にレイヤーの変換が反転します。右に 20 ピクセル移動すると、新しい groundPosition は元の位置から 20 ピクセル左になります (これが実際にこの位置にあるピクセルの位置であるため)。

プレーヤーの場合と同じように、色にアクセスできますxTex = x - recGround.x

私が気付いたもう 1 つの問題は、交差する四角形の計算です。もちろん、変換された長方形を使用して実際の位置を取得する必要があります。


古い投稿:

問題は、プレーヤーとレイヤーが同じ座標系で描画されていないことです。

プレーヤーは「デフォルト」システムで描画されます。レイヤーは、対応するビュー マトリックスで変換されて描画されるため、変換、スケーリングなどが行われます。

PixelCollision交差する可能性のあるすべての画面ピクセルを反復処理します。これらのピクセルは、プレーヤーのような「デフォルト」システムにあります。このため、次の方法でテクスチャの位置を計算できます。

texX = x - player.x
texY = y - player.y

ただし、これはレイヤーには機能しません。画面空間からレイヤーのワールド空間に変換する必要がxあります。y

layerPos = ScreenToWorld(new Vector2(x, y));

そして、 と で色にアクセスしlayerPos.x - enemy.xますlayerPos.y - enemy.y。システムでレイヤーを描画すると、これは機能enemy.x, enemy.yします。追加の変換がある場合、または別の場所に描画する場合は、これを考慮する必要があります。

于 2012-11-06T15:25:34.623 に答える