「独創アプリ開発日記」カテゴリーアーカイブ

デアゴ管理アプリ制作 第2弾 63日目

デアゴ管理とは、デアゴスティーニに習って1日(1回)のアプリ制作作業量を少なくすることによって、恐ろしいほど飽き性のアプリ制作者(私です)の作業を毎日継続させ易くするプロジェクト管理手法です。

デアゴ管理による10週目の作業予定です。

64日目:移動方向キーの操作性向上
65日目:前後移動時のアニメーション その1
66日目:前後移動時のアニメーション その2
67日目:左右移動時のアニメーション その1
68日目:左右移動時のアニメーション その2
69日目:カメラ移動時のアニメーション
70日目:予備日(次の週の予定を立てる)

先週までで以下動画のように自由自在にフィールドを動き回れるようになりましたが、プレーヤーが突っ立ったまま動きがありません。

今週は移動やカメラ操作に合わせてプレーヤーにアニメーションを付けていきます。

デアゴスティーニ商法作業管理第2弾 57-59日目

この3日間で、iPadでの動作不正対策とマルチタッチ対応を完璧に対処できました!

iPadでの動作不正の原因は、iPadOSになってからブラウザのユーザーエージェント情報がPCに近いものになっていたためでした。

以下のような判定で問題なくPCとそれ以外を判定することが出来ました。

const ua = navigator.userAgent;
const isIOS = ua.indexOf("iPhone") >= 0 || ua.indexOf("iPad") >= 0 || navigator.userAgent.indexOf("iPod") >= 0;
const isIPadOS = (navigator.platform == "MacIntel" && 
                  navigator.userAgent.indexOf("Safari") != -1 &&
                  navigator.userAgent.indexOf("Chrome") == -1 &&
                  navigator.standalone !== undefined);
const isAndroid = ua.indexOf("Android") >= 0;
const isPC = !(isIOS || isIPadOS || isAndroid);

マルチタッチ対応は上記のisPCフラグを利用して、PCとそれ以外(スマホやタブレット)で処理を分岐し、マウスポイントやタップ情報を共通の配列に流し込んでうまく処理することが出来るようになりました。

function changedTouches(event) {
    let touches = [];
    if (isPC) {
        // PCはマウスポイント1点だけ
        touches.push({id:0, x:event.pageX - _canvasOffsetX, y:event.pageY - _canvasOffsetY});
    } else {
        // スマホやタブレットは複数
        for (let i = 0; i < event.changedTouches.length; i++) {
            touches.push({id:event.changedTouches[i].identifier, x:event.changedTouches[i].pageX - _canvasOffsetX, y:event.changedTouches[i].pageY - _canvasOffsetY});
        }
    }
    return touches;
}

これで懸念事項が全て解決し、明日からの垂直方向の障害物判定にスッキリした気分で進めます!

(⋈◍>◡<◍)。✧♡

デアゴスティーニ商法作業管理第2弾 56日目

デアゴスティーニ商法作業管理とは、1日のアプリ制作作業量を少なくすることによって、恐ろしいほど飽き性のアプリ制作者(私です)の作業を毎日継続させ易くする手法です。

デアゴスティーニ商法作業管理による9週目の作業予定です。

57日目:マルチタッチ対応
58日目:iPadでアプリが動作しない原因の特定
59日目:iPadでアプリが動作しない原因を解消
60日目:垂直方向の障害物判定 その1 接触判定用変数用意
61日目:垂直方向の障害物判定 その2 下方向の移動制限
62日目:垂直方向の障害物判定 その3 上方向の移動制限
63日目:予備日(次の週の予定を立てる)

今作っているアプリはベースがWebGLなので、PCでもスマホでもタブレットでも動きます。

スマホで動かそうとしたらマルチタッチに対応しておらず、移動とジャンプが同時に出来なかったためその対処をまず行います。また、なぜかiPadで動作しなかったため原因の特定と解決を行います。

それらを終えてから、いよいよ垂直方向の障害物判定を行なっていく予定です。

はやくブロックに乗ったり、ジャンプで飛び越えたりしてみたい!

o(゚ー゚*o)ワクワク

デアゴスティーニ商法作業管理第2弾 53-55日目

ブロックにめり込まないようになりました。

とりあえず水平方向のみの判定です。今後、垂直方向も判定を入れていきます。

垂直方向を判定出来れば、ジャンプでブロックを超えることが可能になるので楽しみです。

ちなみに衝突判定処理は以下のコードのようになりました。斜め方向にぶつかった際、移動が止まらずにブロックを避ける方向にプレーヤーがうまくずれて動き続けるようにしています。

ブロックの1辺の長さは 1.0 です。_land.isBlockはx/y/z軸方向の位置を整数で指定すると、その位置にブロックがあるか判定してくれる関数です。見ての通り垂直方向のy軸には0しか指定していません。

ちょっと長いな・・・もう少し短くしたいな・・・


// 衝突判定
const DISTANCE_TO_BLOCK = 0.45;
const BOUND_DIFF = 0.0001;
if (moveX < 1.0 && moveZ < 1.0) {   // ←ラグでのブロック抜けを防ぐ
    // x方向のチェック
    if (0 != moveX) {
        let nextBX = Math.floor(0.5 + _objs.player.basePos.x + moveX + DISTANCE_TO_BLOCK * (0 < moveX ? 1 : -1));
        let nextBZ = Math.floor(0.5 + _objs.player.basePos.z);
        let posOfBlock = _objs.player.basePos.z - Math.floor(_objs.player.basePos.z);
        if (0.5 <= posOfBlock && posOfBlock <= 0.5 + DISTANCE_TO_BLOCK) {
            // 1個奥もチェック
            if (_land.isBlock(nextBX, 0, nextBZ) || _land.isBlock(nextBX, 0, nextBZ - 1)) {
                _objs.player.basePos.x = nextBX + (0.5 + DISTANCE_TO_BLOCK + BOUND_DIFF) * (0 < moveX ? -1 : 1);
                moveX = 0;
            }
        } else if (0.5 - DISTANCE_TO_BLOCK <= posOfBlock && posOfBlock <= 0.5) {
            // 1個手前もチェック
            if (_land.isBlock(nextBX, 0, nextBZ) || _land.isBlock(nextBX, 0, nextBZ + 1)) {
                _objs.player.basePos.x = nextBX + (0.5 + DISTANCE_TO_BLOCK + BOUND_DIFF) * (0 < moveX ? -1 : 1);
                moveX = 0;
            }
        } else {
            if (_land.isBlock(nextBX, 0, nextBZ)) {
                _objs.player.basePos.x = nextBX + (0.5 + DISTANCE_TO_BLOCK + BOUND_DIFF) * (0 < moveX ? -1 : 1);
                moveX = 0;
            }
        }
    }
    // z方向のチェック
    if (0 != moveZ) {
        let nextBX = Math.floor(0.5 + _objs.player.basePos.x);
        let nextBZ = Math.floor(0.5 + _objs.player.basePos.z + moveZ + DISTANCE_TO_BLOCK * (0 < moveZ ? 1 : -1));
        let posOfBlock = _objs.player.basePos.x - Math.floor(_objs.player.basePos.x);
        if (0.5 <= posOfBlock && posOfBlock <= 0.5 + DISTANCE_TO_BLOCK) {
            // 1個左もチェック
            if (_land.isBlock(nextBX, 0, nextBZ) || _land.isBlock(nextBX - 1, 0, nextBZ)) {
                _objs.player.basePos.z = nextBZ + (0.5 + DISTANCE_TO_BLOCK + BOUND_DIFF) * (0 < moveZ ? -1 : 1);
                moveZ = 0;
            }
        } else if (0.5 - DISTANCE_TO_BLOCK <= posOfBlock && posOfBlock <= 0.5) {
            // 1個右もチェック
            if (_land.isBlock(nextBX, 0, nextBZ) || _land.isBlock(nextBX + 1, 0, nextBZ)) {
                _objs.player.basePos.z = nextBZ + (0.5 + DISTANCE_TO_BLOCK + BOUND_DIFF) * (0 < moveZ ? -1 : 1);
                moveZ = 0;
            }
        } else {       
            if (_land.isBlock(nextBX, 0, nextBZ)) {
                _objs.player.basePos.z = nextBZ + (0.5 + DISTANCE_TO_BLOCK + BOUND_DIFF) * (0 < moveZ ? -1 : 1);
                moveZ = 0;
            }
        }
    }
} else {
    moveX = 0;
    moveZ = 0;
}
// 加算
_objs.player.basePos.x += moveX;
_objs.player.basePos.z += moveZ;

デアゴスティーニ商法作業管理第2弾 50-52日目

いやー面白くなってきました。

この3日間で画面の上下左右ドラッグによる視点変更と視点に合わせての移動方向修正を実装完了しました。

これで世界を自由自在に動いたり、見たい方向を見渡せるようになりました。

カメラ位置はプレーヤーを中心として球面座標系で動きます。

openGLは垂直方向がy、奥行きがzなので、プレーヤーとカメラの距離をrとすると、

x = r * sinθ * cosφ
y = r * cosθ
z = r * sinθ * cosφ

となります。θはx軸周りの傾き、φはy軸周りの傾きとなります。

尚、地面にめり込まないよう、カメラのy座標位置はマイナスにならないように制限をかけました。

ゲームプレイするより作る方が面白いですね。

特定の部分を作っている時だけかもしれないけど・・・

デアゴスティーニ商法作業管理第2弾 49日目

デアゴスティーニ商法作業管理とは、1日のアプリ制作作業量を少なくすることによって、恐ろしいほど飽き性のアプリ制作者(私です)の作業を毎日継続させ易くする手法です。

デアゴスティーニ商法作業管理による第8号(8週目)の作業予定です。

50日目:画面ドラッグによる視点変更 その1 上下
51日目:画面ドラッグによる視点変更 その2 左右
52日目:画面ドラッグによる視点変更 その3 視点に合わせて移動方向修正
53日目:移動による障害物判定 その1 接触判定用変数用意
54日目:移動による障害物判定 その2 ブロック接触判定
55日目:移動による障害物判定 その3 移動制限
56日目:予備日(次の週の予定を立てる)

ここら辺の処理が山場な気がします。ここを越えればあとは比較的単純作業だと思われるので頑張ります!

‹‹(´ω` )/››

デアゴスティーニ商法作業管理第2弾 46-47日目

1mジャンプ出来るようになりました。

背面飛びしてみました。

ジャンプするためのy座標を求める式は以下の通りです。

y = v0 * t – g * t * t / 2;

ここで、tは時間、gは重力加速度(9.80665m/s2)、v0は初速で、1m飛ぶため4.42869m/sをセットしています。

初速の計算は

√2gh / sinθ (※ルートは2ghの全体にかかります。)

で可能です。hが高さ(m)です。真上なのでsinθは1です。

1m飛びたいならば、2 * 9.80665 * 1 のルートです。

数学大好きです。

(⋈◍>◡<◍)。✧♡

デアゴスティーニ商法作業管理第2弾 43-45日目

十字キーによる移動が可能になりました。前方向に移動して、レンガの家の跡地?から脱出出来ました。

内部的にはglBufferSubDataにより、インスタンシングを利用して描画した立方体の位置情報のみを更新して移動を実現しています。

この画像内に見える物体は、元々は全て立方体です。

OpenGLのインスタンシングを使って、位置やテクスチャ、角度や拡大率を変えた立方体を描画して構成しているので超省メモリなんです。

まあ、だからと言って

ゲームが面白くなるわけではないんですが。