質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.61%

[Dxlib]素早く動かすと当たり判定がおかしくなる原因が知りたい。GitHub全ソースあり

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 684
退会済みユーザー

退会済みユーザー

提示コードの///コメント部内部のコードですが当たり判定が以下の画像のような挙動をしてしまい上手く実装出来ません。これはどうしたらいいのでしょうか?
「左側に衝突して補正されて左キーを離してすぐに下キーを押押すと二枚目のように少しめり込み、キーを離すと上に補正されてしまいます。」
これはどうしたらいいのでしょうか?おそらくコメント内部のコードが悪いと思うのですが何度見ても正しいです。どうすればいいのでしょうか?

試したこと
キー入力は問題りませんでした。

その他
ゆっくりと動かすと問題なのですが。 素早くキーを押し変えると問題が発生します。

Github: https://github.com/Shigurechan/ActionGame

イメージ説明
イメージ説明
イメージ説明

2Dアクションゲーム
#define CELL ((int)48)

#include "Input.hpp"

// コンストラクタ
Input::Input()
{
    //キー状態配列を初期化
    for (int i = 0; i < 256; i++)
    {
        Key[i] = 0;
    }
}

//キー入力状態を更新
void Input::Update()
{    
    char tmpKey[256];   // 現在のキーの入力状態を格納する
    GetHitKeyStateAll(tmpKey);  // 全てのキーの入力状態を得る
    for (int i = 0; i < 256; i++) {
        if (tmpKey[i] != 0) {   // i番のキーコードに対応するキーが押されていたら
            Key[i]++;   // 加算
        }
        else {              
            // 押されていなければ
            Key[i] = 0;   // 0にする
        }
    } 
}

//キーを押した時だけ
bool Input::getKeyDown(unsigned char KeyCode)
{
    if (Key[KeyCode] == 1)
    {
        return true;
    }
    else
    {
        return false;
    }
}

//キーを押している時
int Input::getKeyDownHold(unsigned char KeyCode)
{
    //printf("あああ\n");
    return Key[KeyCode];
}
#include "Player.hpp"

//コンストラクタ
Player::Player(Entry* e) : Actor(e)
{

}

//座標を修正
void Player::FixPos(glm::ivec2 pos)
{
    if (mVector == VECTOR_UP)
    {
        printf("UP\n");
        mPosition.y = pos.y + CELL + CELL / 2;
    }
    else if (mVector == VECTOR_DOWN)
    {
        printf("DOWN\n");

        mPosition.y = pos.y - (CELL / 2);
    }
    else if (mVector == VECTOR_LEFT)
    {
        printf("LEFT\n");

        mPosition.x = pos.x + (CELL + CELL / 2);
    }
    else if (mVector == VECTOR_RIGHT)
    {
        printf("RIGHT\n");

        mPosition.x = pos.x - (CELL / 2);
    }
    else {
        printf("None\n");
    }

}




//更新
void Player::Update()
{
    DrawFormatString(0,0,GetColor(0,255,0),"Position: %d , %d ",mPosition.x,mPosition.y);



    //printf("%d\n",mSpeed_Max);
    Bullet_Update();    //バレットを更新
    Player_Update();    //プレイヤー更新
}

//ステータスを設定
void Player::set_Bulid(ItemData data)
{

    mSpeed_Max += data.mSpeed_Max;

    HP_Max += data.HP_Max;
    HP += data.HP_Rec;            
    HP_autoRec += data.HP_autoRec;

    Attack += data.Attack;

    Coin += data.Coin;

}



//キー入力部
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//プレイヤー 更新
void Player::Player_Update()
{
    //printf("いいいい\n");


    mSpeed = mSpeed_Max;
    //キー入力
    if (Owner->InputKey->getKeyDownHold(KEY_INPUT_LEFT) > 0)
    {
        mVector = VECTOR_LEFT;    //方向
    }
    else if (Owner->InputKey->getKeyDownHold(KEY_INPUT_RIGHT) > 0)
    {
        mVector = VECTOR_RIGHT;    //方向
    }
    else if (Owner->InputKey->getKeyDownHold(KEY_INPUT_UP) > 0)
    {
        mVector = VECTOR_UP;    //方向
    }
    else if (Owner->InputKey->getKeyDownHold(KEY_INPUT_DOWN) > 0)
    {
        mVector = VECTOR_DOWN;    //方向
    }
    else {
        mSpeed = 0;
    }






    //当たり判定

    //スプライトの中心からのため修正
    glm::ivec2 pos = mPosition;
    pos.x += -(CELL / 2);
    pos.y += -(CELL / 2);
    mCol.setPosition(pos);
    mCol.setSize(mSize);
    mCol.setTrigger(false);
    mCol.setVector(mVector);


}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//描画
void Player::Draw()
{
    Bullet_Draw();    //バレット描画
    Player_Draw();    //プレイヤー描画
}


//プレイヤー 描画
void Player::Player_Draw()
{
    //方向
    if (mVector == VECTOR_UP)
    {
        DrawRotaGraph(mPosition.x, mPosition.y, 1.0, 0, mSprite, true, false);
    }
    else if (mVector == VECTOR_DOWN)
    {
        DrawRotaGraph(mPosition.x, mPosition.y, 1.0, PI, mSprite, true, false);
    }
    else if (mVector == VECTOR_LEFT)
    {
        DrawRotaGraph(mPosition.x, mPosition.y, 1.0, -(PI * 2) / 4, mSprite, true, false);
    }
    else if (mVector == VECTOR_RIGHT)
    {
        DrawRotaGraph(mPosition.x, mPosition.y, 1.0, (PI * 2) / 4, mSprite, true, false);
    }

    DrawPixel(mPosition.x, mPosition.y,GetColor(0,255,0));
}


//バレット 描画
void Player::Bullet_Draw()
{
    for (std::vector<Bullet>::iterator itr = mBullet->begin(); itr != mBullet->end(); itr++)
    {        
        itr->Draw();    //バレット描画        
    }
}



//デストラクタ
Player::~Player()
{

}
#include "Stage.hpp"

//コンストラクタ
Stage::Stage(Entry* e)
{

}

//更新

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//プレイヤーとの当たり判定
void Stage::ColPlayer(Player &player)
{
    for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++)
    {
        if (Box_Collision::Intersect(itr->mCol,player.mCol) == true)
        {
            switch (itr->mCol.getObjectType())
            {
                //ショップ
                case StageObjectType::Shop:
                {
                    if (Owner->InputKey->getKeyDown(KEY_INPUT_P) == true)
                    {
                        player.setIsMenu(true);
                        player.FixPos(itr->mCol.getPosition());
                    }
                }
                break;

                //レンガとの当たり判定
                case StageObjectType::Brick:
                {                    
                    player.FixPos(itr->mCol.getPosition());
                }
                break;

                //ブロックとの当たり判定
                case StageObjectType::Block:
                {

                    player.FixPos(itr->mCol.getPosition());
                }
                break;
            }
        }
    }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//画面スクロール
void Stage::ScrollMap(Player& player)
{
    //左右移動
    if (player.getPosition().x > (SCREEN_WIDTH - 100) + player.getSpeed() && player.getVector() == VECTOR_RIGHT) {
        printf("Right\n");

        for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++)
        {

            glm::ivec2 pos;
            pos = itr->getPosition();
            pos.x += -player.getSpeed();

            itr->setPosition(pos);
        }
    }
    else if (player.getPosition().x < ( 100 ) + player.getSpeed() && player.getVector() == VECTOR_LEFT)
    {
        printf("Left\n");
        for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++)
        {
            glm::ivec2 pos;
            pos = itr->getPosition();
            pos.x += player.getSpeed();

            itr->setPosition(pos);
        }

        //上下移動
    }else if (player.getPosition().y > (SCREEN_HEIGHT - 100) + player.getSpeed() && player.getVector() == VECTOR_DOWN) {
        printf("Dwon\n");

        for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++)
        {

            glm::ivec2 pos;
            pos = itr->getPosition();
            pos.y += -player.getSpeed();

            itr->setPosition(pos);
        }
    }
    else if (player.getPosition().y < (100) + player.getSpeed() && player.getVector() == VECTOR_UP)
    {
        printf("Up\n");
        for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++)
        {
            glm::ivec2 pos;
            pos = itr->getPosition();
            pos.y += player.getSpeed();

            itr->setPosition(pos);
        }
    }
    else {


        //移動
        int speed = player.getSpeed();
        glm::ivec2 vec = player.getVector();
        glm::ivec2 pos = player.getPosition();
        pos.x += vec.x * speed;
        pos.y += vec.y * speed;

        player.setPosition(pos);
    }
}

//エネミーとの当たり判定
void Stage::ColEnemy(std::shared_ptr<std::vector<Enemy>> enemy)
{
    for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++)
    {
        MapChip chip = *itr;
        for (std::vector<Enemy>::iterator itr = enemy->begin(); itr != enemy->end(); itr++)
        {
            //交差判定
            if (Box_Collision::Intersect(chip.mCol, itr->mCol) == true )
            {
                switch (chip.mCol.getObjectType())
                {

                    //ブロック
                case StageObjectType::Block:
                {
                    itr->FixPos(chip.mCol.getPosition());
                    itr->setMove_Rand();
                }


                }
            }
        }
    }

}






//デストラクタ
Stage::~Stage()
{

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    退会済みユーザー

    2021/02/23 08:30

    そうですか。キー入力は確認したのですが...

    キャンセル

  • stdio

    2021/02/23 10:46

    突然すみません。私の予想では、やはりBox_Collision::Intersectの使い方が間違っているように思えます。衝突判定の方法を今一度ご検討しなおして下さい。

    確かに私もDxLibでキーの入力やったことありますが、専用のクラスを作って、外部コントローラとキーボードの設定合わせたりとか色々面倒なこと多かった記憶あります...

    キャンセル

  • fana

    2021/02/23 11:21

    キー入力の実装がどれだけ面倒か知らんけども,
    「各処理の妥当な処理結果がどうあるべきか」が定まっているのであれば,
    問題の現象が発生する状況からスタートさせてデバッグ実行していくとか
    各所に適当なログ出力でも仕込むとかすればすぐに原因を絞り込んでいける話なんじゃないの?

    「その状況においてはこうあるべき」という話と反する結果を生じている場所を見つけるだけの作業だと思うのだが.

    キャンセル

回答 1

check解決した方法

-1

下記の提示コードですが以下の画面スクロール部でプレイヤーが移動するコードを書いている為でした。自己解決です。

動いてめり込み 離して動きが止まり 当たり判定を行う(めり込みしている状態)
という順序でおかしくなっていました。

#include "Game_Scene.hpp"

//コンストラクタ
Game_Scene::Game_Scene(Scene_Type t,Entry *e) : Scene_base(t,e)
{
    Owner = e;


    flag = false;    //ショップ中かどうか?
    player = std::make_shared<Player>(e);                    //プレイヤー
    stage = std::make_shared<Stage>(e);                        //ステージ
    shop = std::make_shared<Shop>(e);                        //ショップメニュー
    enemy_mng = std::make_shared<Enemy_Mng>();                //エネミー管理



}

//更新
void Game_Scene::Update()
{
    //バトル
    if (player->getIsMenu() == false)
    {    

        stage->ScrollMap(*player);                //画面スクロール
        stage->Update();                        //ステージ更新

        player->Update();                        //プレイヤー更新
        stage->ColPlayer(*player);                //プレイヤーとマップとの当たり判定

        enemy_mng->Update();                    //エネミー更新

        stage->ColBullet(player->getBullet());    //バレットとマップとの当たり判定
        stage->ColEnemy(enemy_mng->getEnemy());
    }
    else
    {
        //ショップ画面
        if (shop->getState() == true)
        {
            shop->Update(*player);
        }
        else {
            player->setIsMenu(false);
            shop = std::make_shared <Shop>(Owner);
        }
    }



}

//描画
void Game_Scene::Draw()
{

    player->Draw();    //プレイヤー描画
    stage->Draw();    //ステージ描画
    //enemy_mng->Draw();

    //ショップ画面
    if (player->getIsMenu() == true)
    {
        shop->Draw();
    }



}

//デストラクタ
Game_Scene::~Game_Scene()
{

}
//画面スクロール
void Stage::ScrollMap(Player& player)
{
    //左右移動
    if (player.getPosition().x > (SCREEN_WIDTH - 100) + player.getSpeed() && player.getVector() == VECTOR_RIGHT) 
    {
        for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++)
        {
            glm::ivec2 pos;
            pos = itr->getPosition();
            pos.x += -player.getSpeed();
            itr->setPosition(pos);
        }

        glm::ivec2 pos = player.getPosition();
        pos.x = player.getPosition().x - player.getSpeed();
        player.setPosition(pos);
    }
    else if (player.getPosition().x < ( 100 ) + player.getSpeed() && player.getVector() == VECTOR_LEFT)
    {
        for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++)
        {
            glm::ivec2 pos;
            pos = itr->getPosition();
            pos.x += player.getSpeed();
            itr->setPosition(pos);
        }

        glm::ivec2 pos = player.getPosition();
        pos.x = player.getPosition().x + player.getSpeed();
        player.setPosition(pos);

        //上下移動
    }else if (player.getPosition().y > (SCREEN_HEIGHT - 100) + player.getSpeed() && player.getVector() == VECTOR_DOWN) 
    {

        for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++)
        {    
            glm::ivec2 pos;
            pos = itr->getPosition();
            pos.y += -player.getSpeed();
            itr->setPosition(pos);
        }

        glm::ivec2 pos = player.getPosition();
        pos.y = player.getPosition().y - player.getSpeed();
        player.setPosition(pos);
    }
    else if (player.getPosition().y < (100) + player.getSpeed() && player.getVector() == VECTOR_UP)
    {
        for (std::vector<MapChip>::iterator itr = mStage.begin(); itr != mStage.end(); itr++)
        {    
            glm::ivec2 pos;
            pos = itr->getPosition();
            pos.y += player.getSpeed();
            itr->setPosition(pos);
        }

        glm::ivec2 pos = player.getPosition();
        pos.y = player.getPosition().y + player.getSpeed();
        player.setPosition(pos);
    }    
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る