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

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

新作アプリ「隣の田所さん」制作第12週目の作業予定です。

78日目:ブロック削除時のアニメーション その1
79日目:ブロック削除時のアニメーション その2
80日目:カメラアングルの調整 その1
81日目:カメラアングルの調整 その2
82日目:カメラ距離の調整 その1
83日目:カメラ距離の調整 その2
84日目:予備日(次の週の予定を立てる)

昨日の動画の通り、”動き”の部分に関してほぼほぼ出来てきたのですが、詰めの甘い部分があるため今週はその詰めの作業を行う予定です。

“動き”の部分が終われば残りは単純にブロック/アイテム種類を増やしたり、サーバへのブロックの保存/読み込みや、”対人戦”に関わる部分を作り込んでいく予定です。

デアゴ管理アプリ制作 第2弾 71-76日目

今週の作業でブロックの追加や削除が可能になりました。

ブロックの追加/削除位置はプレーヤーの向いている方向や角度で決定するようにしました。この方が連続してブロックを追加/削除し易いです。

長押しタップでブロック削除、ちょっとだけ画面に触れるとブロックを追加します。

思ったよりもスムーズに実装することが出来ました。

ヾ(。>﹏<。)ノ゙✧*。 

デアゴ管理アプリ制作 第2弾 隣の田所さん 70日目

新作アプリ「隣の田所さん」制作第11週目の作業予定です。

71日目:地面抜け対策
72日目:ブロックの追加 その1
73日目:ブロックの追加 その2
74日目:ブロックの削除 その1
75日目:ブロックの削除 その2
76日目:ブロック追加/削除の効果音追加
77日目:予備日(次の週の予定を立てる)

まず71日目はバグ対策を行います。田所さん(プレーヤー)は、ジャンプ後稀に地面をすり抜けて永遠の彼方に落ちてしまうことがあります。これはこれで面白いのですがバグなので直します。

72日目からはいよいよブロックの追加や削除を可能にします。

今週も面白そうな作業が続きます。

デアゴ管理アプリ制作 第2弾 64-69日目

今週は移動やカメラ操作、落下中のアニメーション作業を行いました。

前後移動時は手や足を振り、体を少し左右に捻るようにしました。左右同時も手足を振り、体をわずかに移動方向へ傾けるようにしました。

カメラでの視点移動が速い場合は、体の向きの追従を少しずらしました。

今週の作業予定には無かったのですが、ジャンプ後の落下中は手足がだんだん開くようにしました!

全体的に、そこそこ良い感じになったと思います。

デアゴ管理アプリ制作 第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座標位置はマイナスにならないように制限をかけました。

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

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