0

シンプルなプラットフォームゲームを作ろうとしています。プレーヤーは正方形で、プラットフォームはすべて正方形です。私は XNA の初心者ですが、C# 4.0 の経験はわずかです。

私のコードの問題は、キャラクターがプラットフォームの下側を通過するとき、通過しないように設定しているにもかかわらず、通過し続けることです。

これを修正できないため、事前に誰かが私を助けてくれるかどうか尋ねたいと思います.

コードのさまざまな部分がどのように連携するかを次に示します。

  • platform 構造体では、画像が読み込まれ、次の 3 つの値のいずれかを保持できる列挙型が格納されます。
  • 修正が必要な衝突検出方法 (交差点をチェックし、その特定のプラットフォームの列挙型をチェックし、通過できるかどうかを判断し、以下を含む配列を返します: {isabove, isbelow, isleft, isright} のプラットフォーム)
    • プレイヤーがプラットフォームの上にいる場合は true を返しますが、プラットフォームの下にぶつかっても何も起こりません。
  • 重力と垂直方向の動きを扱う私のプレーヤーの垂直方向の動き、それが原因かもしれませんが、私にはわかりません。更新ループの最初に衝突チェックが実行され、その後垂直方向のモーション メソッドが実行されます。

衝突のコードは次のとおりです。

    public bool[] environmentCollisionDetect(Charachter thing, ScreenObjects sreenobjectlist, bool[] platformstatus)
    {
        //Defaults the collision to false
        platformstatus[0] = false;  //Above platform
        platformstatus[1] = false;  //Below Platform
        platformstatus[2] = false;  //Left
        platformstatus[3] = false;  //Right

        //Store the player in boxA
        boxA.Height = thing.image.Height;
        boxA.Width = thing.image.Width;
        boxA.X = (int)thing.position.X;
        boxA.Y = (int)thing.position.Y;

        //Find a collision
        foreach (Platform platform in screenobjectlist)
        {
            //Makes sure the platform cannot be passed through
            if (platform.platformCollisionProperty != platformCollision.passable)
            {
                //Store the platform's rectangle
                boxB = platform.destinationrectangle;
                boxB.Height = platform.image.Height;
                boxB.Width = platform.image.Width;
                boxB.X = (int)platform.destinationrectangle.X;
                boxB.Y = (int)platform.destinationrectangle.Y;

                //Collision Check
                if (boxA.Intersects(boxB))
                {
                    switch (platform.platformCollisionProperty)
                    {
                        //Platform is Solid
                        case platformCollision.impassible:

                            //Player is below it
                            if (boxA.Top > boxB.Bottom)
                            {
                                platformstatus[1] = true;
                            }

                            //Player is above it
                            if (boxA.Bottom > boxB.Top)
                            {
                                platformstatus[0] = true;
                            }
                            break;

                        //Platform can be passed through bottom
                        case platformCollision.platform:
                            if (boxA.Bottom > boxB.Top)
                            {
                                platformstatus[0] = true;
                            }
                            break;
                    }

                    break;
                }
            }
        }
      return platformstatus;
    }

垂直モーションコードは次のとおりです。

  • ジャンプボタンがアクティブになると、 isJumping bool が true に設定されます
  • isinair bool は、このループ内でのみ使用され、プレイヤーがまだ空中を滑空しているかどうかを判断します
  • 最後に、タイマーを機能させることができなかったため、カウンターとして使用されます

    public void verticalMotionI(GameTime gametime)
    {
        //Resets the bools if not standing on platform
        if ((this.isJumping == true) && (this.platformstatus[0] == false))
        {
            this.i = 0;
            this.isJumping = false;
            this.isinair = false;
        }
    
        //Jumps if A button is activated and standing on a platform
        else if ((this.isJumping == true) && (this.platformstatus[0] == true))
        {
            //Set up bools to jump
            this.isJumping = false;
            this.isinair = true;
    
            //Overwrites the start time
            this.starttime = currentime;
    
            //Move up
            this.position.Y -= this.playermovementspeed * 1.5f;
    
            //Increase counter
            this.i++;
        }
    
        //Pulls stops moving player if jumptimer had elapsed
        else if ((this.isinair == true) && (i == this.jumptime))
        {
            this.isinair = false;
    
            //Apply gravity
            Gravity.forceofGravity(this);
        }
    
        //Stops the jump if bottom of a platform is hit
        else if ((this.isinair == true) && (this.platformstatus[1] == true))
        {
            //Reset bools
            this.isinair = false;
    
            //reset I
            this.i = 0;
    
            //Apply gravity
            Gravity.forceofGravity(this);
        }
    
        //Continues the jump if in air
        else if ((this.isinair == true) && (this.platformstatus[1] == false))
        {
            //Move up
            this.position.Y -= this.playermovementspeed * 1.5f;
    
            //Increase counter
            this.i++;
        }
    
        //Apply Gravity
        else if ((this.isinair == false) && (this.platformstatus[0] == false))
        {
            //reset I
            this.i = 0;
    
            Gravity.forceofGravity(this);
        }
    }
    
4

2 に答える 2

0

if (boxA.Top > boxB.Bottom)- の場合、この条件は決して真であってはなりませんboxA.Intersects(boxB)。ということif (boxA.Top < boxB.Bottom && boxA.Top > boxB.Center.Y)ですか?

今後の参考のための回答として、コメントの調査を再投稿するだけです。コメントではなく回答に余裕があるので、いくつか説明することもできます。

明らかに、Rectangle.Intersects(Rectangle)それらが何らかの形で重なっている場合にのみ真になります。トリックは、それを解釈する際に、画面上の Y 座標が実際には上から下に移動することを覚えておく必要があるということです。Y = 0 は画面の上部にあり、Y = は下部にあります。2D ゲーム プログラミングに慣れていない場合、これは逆に思えるかもしれませんが、これがグラフィックス アダプターの仕組みです。

したがって、boxA の上部が boxB の下部であると言うと、実際には、画面上で boxA の上部が boxB の下部よりも下にあるということになります。必要な機能を提供するために、条件を変更し、ロジックのポイントを追加しました。boxA が boxB の下boxA.Top > boxB.Center.Yで具体的に交差していることを意味します。そのままにしておけば、boxA が boxBの上から落ちてきた場合にも条件は true になります。これは、タイルの下のプレーヤーを含むロジックのプラットフォームと固体ブロックを区別する必要があることを考えると、あなたが望んでいないと思います。コードでこの区別を行う必要があります。また、もちろん、あなたのコメントは言った.boxA.Top < boxB.Bottom//player is below it

最後に、デバッグに関するアドバイスです。特定の動作が発生していないことに気付いた場合は、その動作を指示する行 (この場合はplatformstatus[1] = true) にブレークポイントを配置してください。そのブレークポイントに到達したことがない場合は、なぜそれが発生していないかがわかります。ここで、囲んでいる条件にブレークポイントを配置するだけです。そのブレークポイントに到達したら、手動で値を確認し、期待値と比較して、適切なロジックを使用したかどうかを確認します。誰もが条件文で間違いを犯すことがあります。個人的には、それが私の最初の弱点の 1 つです。

于 2012-06-20T13:12:22.847 に答える
0

重力が私が想定していることを行う場合、プラットフォームに当たったときにプレイヤーの位置を明示的に設定しているようには見えません。私が見ているのは、isInAirフラグを切り替えて重力を適用することです...テスト目的で問題を解決するために、この擬似コードのようなものを試してください:

if(dude is jumping & dude collides with platform){
   set the top of dudes head to be at position under the platform;
}

これが役立つことを願っています。:)

死んだ馬を打ち負かしたり、ろばになったりするのではなく、車輪を再発明しています. そこにあるいくつかの物理エンジンをチェックしてください。私は Farseer 3+ をいじっていますが、素晴らしいです。World Body Fixture パターンを最初に理解するときは、わずかな学習曲線がありますが、ひらめきがあれば、ボディ/フィクスチャにいくつかのプロパティを設定し、OnCollision メソッドを起動するのは簡単です。

Farseer は .NET への Box2D 物理エンジン ポートであり、オープン ソースであり、学習曲線を突き抜ければ驚くべきものです。

この farseer docをざっと見てみると、きっと気に入っていただけると思います。:) 気に入らなくても、これはオープン ソースであり、機能の一部を独自のひねりを加えて実装する *咳*コピー* する方法についていくつかのアイデアを提供できます。

単純なジャンプ、オブジェクトの状態、および対話機能だけが必要な場合は、エンジンのすべての楽しい複雑さを実装する必要はありません。これらはすべて Farseer にうまくラップされています。

于 2012-06-19T17:21:49.880 に答える