0

プレイヤー ボックスが壁を通り抜けて望ましくない形で続いています。プレイヤーが一度に 0.1f(u) ずつ移動するようにしようとしましたが、これはゲームのパフォーマンスを著しく低下させます。プレイヤーが壁にぶつかったかどうか、どちら側にぶつかったか、壁にぶつからないようにするにはどうすればよいかを検出する方法はありますか?

これが私が実行しているコードです(これはもちろん最小限です)

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 Platformer
{

    public class Player
    {
        double terminalVelocity;
        //AnimatedTexture texture;
        public Texture2D texture;
        public Vector2 Position, Velocity;
        public Rectangle boundingBox;
        public Player(Texture2D tex, Vector2 pos, Vector2 vel, Rectangle bb)
        {
            texture = tex;
            Position = pos;
            Velocity = vel;
            boundingBox = bb;
            terminalVelocity = Math.Sqrt((2*bb.Width*bb.Height*Game1.gravity)/-9.8*2);
        }

        public void updateBoundingBoxes()
        {
            boundingBox.X = (int)Position.X;
            boundingBox.Y = (int)Position.Y;
        }

        public void onUpdate()  
        {
            updateBoundingBoxes();
            Position.X += Velocity.X;
            Position.Y += Velocity.Y;
            //Velocity = Vector2.Zero;
            Velocity.Y += Game1.gravity / 60;
            Velocity.X /= 1.2f;
        }

        public void Draw(SpriteBatch sb)
        {
            updateBoundingBoxes();
            sb.Begin();
                sb.Draw(texture,boundingBox,GameLighting.currentColour());
            sb.End();
        }

    }

    public enum GameLightingState
    {
        Red, Dark, Orange, Blue, White
    }

    public class Platform : Object
    {

        Texture2D text;
        public Rectangle rect;
        public Platform(Texture2D t, Vector2 p, int sizeX, int sizeY)
        {

            text = t;
            rect = new Rectangle((int)p.X, (int)p.Y, sizeX, sizeY);


        }

        public void onPlayerCollision(Player p)
        {
            p.Velocity.X = -p.Velocity.X / 2;
            p.Velocity.Y = -p.Velocity.Y / 2;
        }

        public void Draw(SpriteBatch sb)
        {
            sb.Begin();
               sb.Draw(text, rect, GameLighting.currentColour());
            sb.End();
        }

        public void onUpdate()
        {

        }

    }

    public class GameLighting
    {
        public static Color currentColour()
        {
            return eToColour(Game1.currentLightingState);
        }

        public static Color eToColour(GameLightingState gls)
        {
            switch (gls)
            {
                case(GameLightingState.Red):
                    return Color.Red;
                case (GameLightingState.Blue):
                    return Color.Blue;
                case (GameLightingState.Orange):
                    return Color.Orange;
                case (GameLightingState.Dark):
                    return Color.DarkGray;
                case (GameLightingState.White):
                    return Color.White;
            }
            return Color.White;
        }
    }


    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        public static float gravity = 9.80665f;
        public static GameLightingState currentLightingState;
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        List<Platform> platforms;
        List<Player> players;
        int controlledPlayerIndex = 0;
        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
            currentLightingState = GameLightingState.White;
            platforms = new List<Platform>();
            players = new List<Player>();
            players.Add(new Player(this.Content.Load<Texture2D>("Images/dirt"), new Vector2(300,0), new Vector2(0,0), new Rectangle(300,0,20,20)));
            platforms.Add(new Platform(this.Content.Load<Texture2D>("Images/dirt"),new Vector2(300,450),200,20));
            platforms.Add(new Platform(this.Content.Load<Texture2D>("Images/dirt"), new Vector2(20,20), 20, 200));
            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);

            // TODO: use this.Content to load your game content here
        }

        /// <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();
            foreach (Player p in players)
            {
                Boolean intersects = false;
                Rectangle tempRectangle = new Rectangle((int)(p.Position.X + p.Velocity.X),(int) (p.Position.Y + p.Velocity.Y), p.boundingBox.Width, p.boundingBox.Height);
                foreach (Platform pl in platforms)
                {
                    intersects = intersects || tempRectangle.Intersects(pl.rect);
                }
                if (!intersects)
                {
                    p.onUpdate();


                }
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Space))
            {
                players[controlledPlayerIndex].Velocity.Y -= 0.75f;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.A)) 
            {
                players[controlledPlayerIndex].Velocity.X -= 0.75f;
            }
            if (Keyboard.GetState().IsKeyDown(Keys.D))
            {
                players[controlledPlayerIndex].Velocity.X += 0.75f;
            }

            // TODO: Add your update logic here

            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);

            // TODO: Add your drawing code here

            foreach (Platform p in platforms)
            {
                p.Draw(spriteBatch);
            }
            foreach (Player p in players)
            {
               p.Draw(spriteBatch);
            }
            base.Draw(gameTime);
        }
    }
}

*最初のコメントに基づいてソースコードを更新

このコードに関する 1 つの注意点として、XNA で実行し、Images というフォルダーにあるdirt.png というアイコンを使用する必要があります。画像がどのように見えるかは関係ありません。何が起こっているのかを完全に理解するために必要なだけです。

4

1 に答える 1

1

最近、私自身も同様の問題を抱えていました。これが私がしたことです。

//variables needed
public bool follow = true;
public Vector2D startpoint;

//puts the startpoint value equal
//to the inital location of the player
public Player()
{
    startpoint.X = rectangle.X;
    startpoint.Y = rectangle.Y;
}

//if any of the collision tests fail
if(collision occurs)
{
    collision();
}
//else update startpoint to new valid location
else 
{
    startpoint.X = rectangle.X;
    startpoint.Y = rectangle.Y;
    follow = true;
}
if(follow == true)
{
    //movement commands occur
}
else
{
    follow = true;
}

//if a condition fails set player
//too last valid location
public void collision()
{
    rectangle.X = startpoint.X;
    rectangle.Y = startpoint.Y;
    follow = false;
}

これは私にとっては十分にうまくいきました。

于 2013-04-23T18:38:05.547 に答える