ページ 11

自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 12:32
by ああ、北の国から

コード:

public class Game1 : Microsoft.Xna.Framework.Game
    {
        // メンバー変数の宣言
        GraphicsDeviceManager graphics;
        private Renderer renderer;
        private Chara chara;
        private InputState input;
        int[,] map = new int[16, 24]
            {
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
            };

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);

            graphics.PreferredBackBufferWidth = Screen.Width;
            graphics.PreferredBackBufferHeight = Screen.Height;
        }

        /// <summary>
        /// 初期化
        /// </summary>
        protected override void Initialize()
        {
            base.Window.Title = "アクション";

            // インスタンスの生成
            renderer = new Renderer(Content, GraphicsDevice);
            input = new InputState();
            chara = new Chara(input);
            
            chara.Initialize();
            base.Initialize();
        }

        /// <summary>
        /// 読み込み
        /// </summary>
        protected override void LoadContent()
        {
            renderer.LoadTexture("stage");
            renderer.LoadTexture("map");
            renderer.LoadTexture("chara");
        }

        /// <summary>
        /// 解放
        /// </summary>
        protected override void UnloadContent()
        {
            renderer.Unload();
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="gameTime"></param>
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed
                || Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();

            input.Update();
            chara.Update();
            base.Update(gameTime);
        }

        /// <summary>
        /// 表示
        /// </summary>
        /// <param name="gameTime"></param>
        protected override void Draw(GameTime gameTime)
        {
            renderer.Begin();

            renderer.DrawTexture("stage", new Vector2(0, 0));

            for (int i = 0; i < 24; i++)
            {
                for (int j = 0; j < 16; j++)
                {
                    renderer.DrawTexture("map", new Vector2(i * 32, j * 32), new Vector2(32, 32), new Vector2((float)map[j, i], 0));
                }
            }

            chara.Draw(renderer);

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

コード:

class Renderer
    {
        // メンバー変数の宣言
        private ContentManager contentManager;
        private SpriteBatch spriteBatch;
        private GraphicsDevice graphicsDevice;
        private Dictionary<string, Texture2D>
            textures = new Dictionary<string, Texture2D>();

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="content"></param>
        /// <param name="graphics"></param>
        public Renderer(ContentManager content, GraphicsDevice graphics)
        {
            contentManager = content;
            contentManager.RootDirectory = "Content";
            graphicsDevice = graphics;
            spriteBatch = new SpriteBatch(graphics);
        }

        /// <summary>
        /// 読み込み
        /// </summary>
        /// <param name="name"></param>
        public void LoadTexture(string name)
        {
            textures[name] = contentManager.Load<Texture2D>(name);
        }

        /// <summary>
        /// 解放
        /// </summary>
        public void Unload()
        {
            textures.Clear();
            contentManager.Unload();
        }

        /// <summary>
        /// 描画の開始
        /// </summary>
        public void Begin()
        {
            spriteBatch.Begin();
        }

        /// <summary>
        /// 描画の終了
        /// </summary>
        public void End()
        {
            spriteBatch.End();
        }

        /// <summary>
        /// 表示
        /// </summary>
        /// <param name="name"></param>
        /// <param name="position"></param>
        public void DrawTexture(string name, Vector2 position)
        {
            spriteBatch.Draw(textures[name], position, Color.White);
        }

        /// <summary>
        /// 表示
        /// </summary>
        /// <param name="name"></param>
        /// <param name="position"></param>
        /// <param name="bmp"></param>
        public void DrawTexture(string name, Vector2 position, Vector2 size, Vector2 bmp)
        {
            spriteBatch.Draw(textures[name], position,
                            new Rectangle((int)bmp.X * (int)size.X, (int)bmp.Y * (int)size.Y, (int)size.X, (int)size.Y), Color.White);
        }
    }

コード:

class InputState
    {
        // メンバー変数の宣言
        private Vector2 velocity = Vector2.Zero;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public InputState()
        {

        }

        /// <summary>
        /// 移動量の獲得
        /// </summary>
        /// <returns></returns>
        public Vector2 Velocity
        {
            get
            {
                return velocity;
            }
        }

        /// <summary>
        /// 更新
        /// </summary>
        public void Update()
        {
            var keyState = Keyboard.GetState();
            UpdateVelocity(keyState);
        }

        /// <summary>
        /// 移動速度の更新
        /// </summary>
        public void UpdateVelocity(KeyboardState keyState)
        {
            velocity = Vector2.Zero;

            if (keyState.IsKeyDown(Keys.Right))
            {
                velocity.X = 1.0f;
            }
            if (keyState.IsKeyDown(Keys.Left))
            {
                velocity.X = -1.0f;
            }
            if (keyState.IsKeyDown(Keys.Down))
            {
                velocity.Y = 1.0f;
            }
            if (keyState.IsKeyDown(Keys.Up))
            {
                velocity.Y = -1.0f;
            }
            if (velocity.Length() != 0)
            {
                velocity.Normalize();
            }
        }
    }

コード:

class Chara : Actor
    {
        // メンバー変数の宣言
        private InputState input;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public Chara(InputState input)
        {
            this.input = input;

            Radius = 16;
            Name = "chara";
        }

        /// <summary>
        /// 初期化
        /// </summary>
        public override void Initialize()
        {
            Position = new Vector2(144, 464);
        }

        /// <summary>
        /// 更新
        /// </summary>
        public override void Update()
        {
            Position += input.Velocity * 8;

            var min = new Vector2(Radius, Radius);
            var max = new Vector2(Screen.Width - Radius, Screen.Height - 48);
            Position = Vector2.Clamp(Position, min, max);
        }
    }

コード:

abstract class Actor
    {
        // メンバー変数の宣言
        protected Vector2 Position { get; set; }
        protected int Radius { get; set; }
        protected string Name { get; set; }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        protected Actor()
        {

        }

        /// <summary>
        /// 初期化抽象メソッド
        /// </summary>
        public abstract void Initialize();

        /// <summary>
        /// 更新抽象メソッド
        /// </summary>
        public abstract void Update();

        /// <summary>
        /// 表示
        /// </summary>
        /// <param name="renderer"></param>
        public void Draw(Renderer renderer)
        {
            renderer.DrawTexture(Name, Position - new Vector2(Radius, Radius));
        }
    }

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 12:33
by ああ、北の国から
自機とマップの当たり判定がわかりません。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 12:47
by softya(ソフト屋)
ここまで書けていて当たり判定がわからないということは学校の課題だと思いますが自分で書いたコードは何処の部分でしょうか?
それと当たり判定を行うクラスなどを新設しなくてはいけないのとmapの情報を当たり判定クラスに引き渡す必要があります。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 18:16
by ああ、北の国から
一応全部自分で書いたんですが・・・

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 18:28
by softya(ソフト屋)
ああ、北の国から さんが書きました:一応全部自分で書いたんですが・・・
失礼しました。
方法の1つとして情報が各クラスに分散しているので、当たり判定のクラスを作って、このクラスがプレーヤーの情報とマップの情報を得て当たり判定をする方法を提案させていただきましたが実装できそうでしょうか?

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 18:59
by ああ、北の国から
できれば、C#のコードを教えてほしいです。
何分初心者なもので

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 19:17
by softya(ソフト屋)
ああ、北の国から さんが書きました:できれば、C#のコードを教えてほしいです。
何分初心者なもので
出来るだけ自分で実装していただきたいのですが、何処がわからない点でしょうか?
今までの話からクラスを自分で作ることは問題ないと認識しているのですが。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 19:35
by ああ、北の国から
全部わかりません。
最初は自機のx、y座標とマップチップが重なったら、その分マイナスをするようにプログラミングしたのですが、
そうすると、配列で表示した背景のブロックと、当たり判定がずれていて、半分入って半分入れない感じになってしまい、
画面外に行くと強制終了するようになってしまいました。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 19:37
by softya(ソフト屋)
ああ、北の国から さんが書きました:全部わかりません。
最初は自機のx、y座標とマップチップが重なったら、その分マイナスをするようにプログラミングしたのですが、
そうすると、配列で表示した背景のブロックと、当たり判定がずれていて、半分入って半分入れない感じになってしまい、
画面外に行くと強制終了するようになってしまいました。
そのコードを掲載してもらえませんか?

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 21:51
by ああ、北の国から
すみません。
消してしまいました。
覚えてもいないです。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 21:55
by softya(ソフト屋)
ああ、北の国から さんが書きました:すみません。
消してしまいました。
覚えてもいないです。
もう一度、分かる範囲で組んでみて下さい。
再現はしなくてよいので、自分で正しいと思う物を作ってみて下さいね。
ここまで自力で組めたのなら、問題があっても何らかの物は組めると思います。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 22:08
by ああ、北の国から
すみません。
思いつきません。
教えていただけませんか。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月12日(木) 22:18
by softya(ソフト屋)
ああ、北の国から さんが書きました:すみません。
思いつきません。
教えていただけませんか。
堂々巡りですし、提示されたコードは全部自分で組んだんですよね?
それだけの実力はあると考えてはいけないのでしょうか?

では、新たなクラスを作成しmap情報を設定するメソッドを作ってみて下さい。
名前で困ると行けませんからclass HitJudgeとさせて頂きます。
わからない場合は、具体的に何処がわからないか書いて下さい。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月13日(金) 17:59
by ああ、北の国から
もう少し詳しくお願いします。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月13日(金) 19:02
by softya(ソフト屋)
ああ、北の国から さんが書きました:もう少し詳しくお願いします。
ほんとにクラスの書き方を理解されているのでしょうか?
map変数を受け取り保存するメソッドを持つclass HitJudge定義してみて下さい。
これが出来ないとC#の基本の基本が理解できていない事になります。

※申し訳ないですが出来るレベルと出来たものを明確に示して頂かない限りこちらからコードを書くこと無いと思って下さい。
今のままでは丸写しのコードを書いてくれの依頼でしかありません。
ベースと成るものを書いて頂けたら、それの修正案などは提示させて頂きます。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月14日(土) 01:13
by へにっくす
ああ、北の国から さんが書きました:最初は自機のx、y座標とマップチップが重なったら、その分マイナスをするようにプログラミングしたのですが、
そうすると、配列で表示した背景のブロックと、当たり判定がずれていて、半分入って半分入れない感じになってしまい、
画面外に行くと強制終了するようになってしまいました。
本当に分からないなら、こんな説明できませんけど。
よくあるミスは左上座標を判定の基準にしている間違い。
ブロック一つ一つの中心座標とのオフセットを考慮しないといけないのでは?
マップは16 x 24、ブロックの大きさは32 x 32。
単純に x * 32, y * 32とやったんではだめ
中心にするには x * 32 + 16, x * 32 + 16。

・・・しかし本当に覚えてないの?
プログラマで仕事したいと思ってるなら、それじゃダメだよ?
アマでいいなら別にいいけどさ。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月14日(土) 23:52
by aあ
渡せはしましたがそのあとどうすれば

Re: 自機とマップの当たり判定ga

Posted: 2012年7月15日(日) 08:30
by へにっくす
aあ さんが書きました:渡せはしましたがそのあとどうすれば
だれ?
ユーザー名が違いますけど。

ああ、北の国からさんなのでしたら
だからコード貼り付けろと言うところですけど。
言葉だけじゃ限界があるんですよ?

Re: 自機とマップの当たり判定ga

Posted: 2012年7月15日(日) 11:34
by softya(ソフト屋)
ああ、北の国からさん。フォーラムルールにあります通り名前の統一をお願いします。
熟読をお願いします。 http://dixq.net/board/board.html

ああ、北の国からさん。
問題のあるソースコードを貼り付けてくださいね。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月17日(火) 19:19
by ああ、北の国から
最初は

コード:

if (左が押されたら)
if (map[(int)player.Y, (int)player.X - 1] != 2)
                {
                    player.X--;                    
                }
という風に4方向やっていたんですが、
今、Collisionクラスを作り、CollisionMainメソッドにActorクラスで新たに作ったGetSizeプロパティを使い、
Sizeとmapを引数で持ってきたのですが、
この場合は、上のコードをどのように書き換えればよろしいのでしょうか?
player.Xやplayer.YはVector2でキャラクターの座標を定義したものです。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月17日(火) 20:43
by ookami
こんにちは、ookamiです。横からすいません。
まず、自機とマップの当たり判定について、できるだけ詳しく、言葉を尽くして、説明してもらえますか?
単に当たり判定と言っても、プレーヤーを点と見ていいのか、四角と見るのかでもぜんぜん変わってきますし、
マップも、四角いマップチップが縦横に並んでいるのか、それともマップチップではなく、一枚絵のようなもので、ドット単位で判定しなければいけないのか、など、いろいろあります。

Re: 自機とマップの当たり判定ga

Posted: 2012年7月17日(火) 20:48
by softya(ソフト屋)
とりあえずCollisionクラス全部を見せてくださいね。出来れば関連するもの全てを提示して下さい。
それがここのルールでもあります。

それとPlayerの座標系とマップの座標系は1:1ではなく32:1では無いのでしょうか?
あとmapの値の意味を説明して下さい。2以外は障害物では無いのでしょうか?

Re: 自機とマップの当たり判定ga

Posted: 2012年7月17日(火) 23:01
by へにっくす
ああ、北の国から さんが書きました:今、Collisionクラスを作り、CollisionMainメソッドにActorクラスで新たに作ったGetSizeプロパティを使い、
Sizeとmapを引数で持ってきたのですが、
この場合は、上のコードをどのように書き換えればよろしいのでしょうか?
player.Xやplayer.YはVector2でキャラクターの座標を定義したものです。
CollisionクラスとActionクラスのソースは?
player.Xやplayer.YはVector2で、というよりソース貼り付けた方が一発で分かるんだけどなあ。。
言葉だけじゃ限界があるんだよ?