44838


斜め移動するとピタゴラスの定理の関係で少し多めに移動してしまう現象を調整したプログラムなのですが、下記のものは正しいのでしょうか？  
間違ってるもしくはもっと綺麗な正しいプログラムの組み方ある場合は例を教えていただきたいです。  
※角度についても学習していたため無駄にコードが変更されたます。

[code]

    #include "DxLib.h"
    #include "math.h"
    
    int Key[256];
    
    int gpUpdateKey() {
        char tmpKey[256];
        GetHitKeyStateAll(tmpKey);
    
        for (int i = 0; i < 256; i++) {
            if (tmpKey[i] != 0) {
                Key[i]++;
            }
            else {
                Key[i] = 0;
            }
        }
    
        return 0;
    }
    
    //斜めは0.71,
    float m = 5.0;
    float move = 5.0;//移動量
    #define IP 3.14159265359;
    float angle = 0.0;
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);//画面モード
    
        float x= 320; float y = 240;
        int Handle = LoadGraph("mario.png");
    
        while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdateKey() == 0) {
    
            if (Key[KEY_INPUT_LEFT] >= 1 || Key[KEY_INPUT_RIGHT] >= 1) {
                if (Key[KEY_INPUT_DOWN] >= 1 || Key[KEY_INPUT_UP] >= 1) {
                    move = 0.71f * m;
                }
            }
            else {
                move = 1.0f * m;
            }
    
            if (Key[KEY_INPUT_RIGHT] >= 1) {
                if (Key[KEY_INPUT_A] >= 1) {
                    angle += 0.01f;
                }
                else {
                    x += move;
                }
            }
    
            if (Key[KEY_INPUT_LEFT] >= 1) {
                if (Key[KEY_INPUT_A] >= 1) {
                    angle -= 0.01f;
                }
                else {
                    x -= move;
                }
            }
    
            if (Key[KEY_INPUT_UP] >= 1) {
                y-= move;
            }
    
            if (Key[KEY_INPUT_DOWN] >= 1) {
                y+=move;
            }
    
            DrawRotaGraph((int)x,(int)y,1.0,angle,Handle,TRUE);
        }
    
        DxLib_End();                // ＤＸライブラリ使用の終了処理
        return 0;               // ソフトの終了 
    }
    
[/code]


CC BY-SA 4.0
2018-06-17T12:23:56.467
44826
2018-06-18T03:57:36.110
2018-06-17T16:22:30.737
3060
question
c++
「DXライブラリ」斜め移動の移動量を調整するプログラムの組み方


ある物体を１回の操作で距離 `r` を移動させる、ただし任意の角度 `th`
で。という設問に対してどのようなコードを書くと理解しやすいか、という話であると解釈することにして

単純に高校数学ですね。半径 `r` の円の円周上の点は原点 O （物体の現在位置）に対して

[code]

    (x,y) = (r*cos(th), r*sin(th));
    
[/code]

ですから、擬似コードを書くなら

[code]

    object.location.x += r*cos(th);
    object.location.y += r*sin(th);
    
[/code]

なだけです。 `th` が 45度なら `cos(45degree)=sin(45degree)=0.707` なので提示コード上書かれている `0.71`
と同じ値が現れるという寸法です（元コードにおいては `r=5` 固定）。  
# ほとんどの処理系では角度をラジアンで記述することに注意。  
# 数学的座標軸の方向と、グラフィック画面上の座標軸の方向が違うことにも注意。

ただし、実際の画面上の座標は整数値しか使えないわけで、計算結果に対して表示位置は丸めにより必ずズレます。そのズレを容認するとかしないとかは設計方針というか仕様というか、設計者が決める話で「何が正しい」かはその方針次第ってことになります。

あとは浮動小数点数演算を是とするか否とするか、とか（昔のゲーム機のマイコンには浮動小数点数演算回路は無かった。でも今のパソコンの CPU
だと整数演算より浮動小数点数演算のほうが高速なことがあったりする）

このコードだと物体は瞬間移動してしまうので見た目は不自然になるから、移動途中の様子も描画する必要がありそうだけど、その「移動途中」の座標をどう求めるかとか

整数演算限定で、一定方向（`th` が固定）のときに最も滑らかで美しい軌跡計算するには DDA の知識があるとよいとか（ブレゼンハムのアルゴリズム）

ゲームを作るうえではこの手の数学的知識がほぼ必須です。そしてコンピュータの浮動小数点数は数学でいう「実数」とはまったく異なるものなので、そういう知識も必要です。

浮動小数点数の丸め方式が違うのでうんぬん・・・  
<https://it.srad.jp/story/18/06/11/0838212/>

メモリ容量とか演算速度とかいろいろと制約がある中で「自然な動き」を実現するために今までのゲームプログラマはかなり苦労してきたと思います。そして今からも苦労するのは変わらないでしょうね。勉強あるのみ、ぢゃないでしょうか。


CC BY-SA 4.0
2018-06-18T03:57:36.110
44838
2018-06-18T03:57:36.110
8589
44826
answer