機能の説明:
ゲームでは、敵の攻撃を避けながら、3つの異なる鍵を集め、対応するドアを開け、最終的に目的地に到達する必要があります。
このゲームも自社開発のHTML5GameフレームワークcnGameJSに基づいています。
Chromeブラウザでの閲覧を推奨します。
エフェクトプレビュー:
方向キーで動きを制御し、スペースバーで射撃し、Shiftキーでドアを開けます。


実装分析:
前回の記事「3D MazeのHTML5実装」では、3Dシーンの効果を放射法によってシミュレートしましたが、この記事は3Dに基づいていますゲーム要素を追加して、より完全な一人称シューティング ゲームを構築します。
3Dシーンエフェクトをシミュレートする方法については上記で詳しく説明しましたが、この記事では主にゲームのインタラクティブ部分の実装方法を紹介します。
1. マップ上のゲーム要素と画面上のオブジェクトの対応関係は何ですか?
まず、各ゲーム要素は 2 つのゲーム オブジェクトに対応します。1 つは左側のマップ上のオブジェクトで、もう 1 つは右側の画面上のオブジェクトです。例えば、敵の位置、射撃の有無、ステータスなどの情報はすべて左側のマップオブジェクトで表現されており、その情報をもとに画面上の敵の表示が描画されます。左側の地図上のオブジェクト。 つまり、左側のマップ オブジェクトは、ゲーム要素の位置とステータスを決定する役割を果たし、実際にゲーム情報を保存します。右側の画面オブジェクトは、ゲーム要素の表示のみを担当します。
1 2 | <strong> newEnemy.relatedObj= enemy2({src:srcObj.enemy,context:screenContext});
newEnemy.relatedObj.relatedParent=newEnemy;</strong>
|
ログイン後にコピー
上記のように、マップ上のオブジェクトと画面上のオブジェクトは相互に
reference
関係を維持しているため、マップ オブジェクトを通じて画面オブジェクトに簡単にアクセスしたり、その逆を行うことができます。
2. プレイヤーを発見した後に敵に撃たせるにはどうすればいいですか?
この関数を実装するには、敵に対するプレーヤーの角度を知る必要があります。敵からプレーヤーまでの距離と、敵の x と y の差に基づいてこのパラメーターを見つけることができます。次に、敵オブジェクトの位置からその方向に光線を放射できます。光線が壁に触れずにプレイヤーに触れることができれば、敵がプレイヤーを認識していることがわかります。この時点で、敵はプレイヤーに向けて発砲することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | nextX = enemyCenter[0];
nextY = enemyCenter[1];
while (this.map.getPosValue(nextX, nextY) == 0) {
distant += 1;
x = nextX;
y = nextY;
if (cnGame.collision.col_Point_Rect(x, y, playerRect)&&!spriteList[i].relatedObj.isCurrentAnimation( "enemyDie" )) {
spriteList[i].isShooting = true;
if (spriteList[i].lastShootTime > spriteList[i].shootDuration) {
spriteList[i].shoot(player);
spriteList[i].relatedObj.setCurrentImage(srcObj.enemy1);
spriteList[i].lastShootTime = 0;
}
else {
if (spriteList[i].lastShootTime > 0.1) {
spriteList[i].relatedObj.setCurrentImage(srcObj.enemy);
}
spriteList[i].lastShootTime += duration;
}
break ;
}
else {
spriteList[i].isShooting = false;
}
nextX = distant * Math. cos (angle) + enemyCenter[0];
nextY = enemyCenter[1] - distant * Math.sin(angle);
}
}
|
ログイン後にコピー
3. キーを取得したかどうかを確認するにはどうすればよいですか?
キー取得の検出とは、実際にはプレイヤーオブジェクトとキーオブジェクトが衝突するかどうかを検出し、衝突した場合にはキーを取得するだけです。左側のマップ オブジェクトでも衝突検出が発生します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var checkGetKeys = function () {
var list = cnGame.spriteList;
var playerRect= this.player.getRect();
for ( var i = 0, len = list.length; i < len; i++) {
if (list[i] instanceof key) {
if (cnGame.collision.col_Between_Rects(list[i].getRect(),playerRect)) {
this.keysValue.push(list[i].keyValue);
list.remove(list[i]);
i--;
len--;
}
}
}
}
|
ログイン後にコピー
4. ゲーム要素とゲームシーンを画面上に同時に描画し、正しい順序を維持するにはどうすればよいですか?
CSSでは
z-Index
を使用して要素の正しい階層関係を維持できますが、今はcanvas上にグラフィックを描画する必要があるため、z-Index効果をシミュレートすることしかできません。 前の記事で述べたように、3D シーンは異なる長さのピクセル線で描画されます。そのため、他のゲーム要素を追加した後、正しい階層関係を維持したい場合は、要素ごとにピクセルを作成する必要があります。ピクセル行は zIndex 属性をカスタマイズし、それを配列に保存します。
描画するたびに、配列は zIndex に従ってソートされるため、描画順序が決まり、正しいレベルが保証されます
。 zIndex の値は、プレーヤーと要素またはピクセル ラインの間の距離に基づいて計算されます:
1 | <strong>zIndex= Math. floor (1 / distant * 10000)</strong>
|
ログイン後にコピー
その後、各描画は、遠い画像を覆う近い画像の効果を生み出すことができます:
並べ替え:
1 2 3 4 5 6 7 8 9 10 11 12 | colImgsArray.sort( function (obj1, obj2) {
if (obj1.zIndex > obj2.zIndex) {
return 1;
}
else if (obj1.zIndex < obj2.zIndex) {
return -1;
}
else {
return 0;
}
});
|
ログイン後にコピー
描画:
1 2 3 4 5 6 7 8 9 10 | for ( var i = 0, len = colImgsArray.length; i < len; i++) {
var obj = colImgsArray[i];
if (obj.draw){
obj.draw();
}
else {
context.drawImage(obj.img, obj.oriX, obj.oriY, obj.oriWidth, obj.oriHeight, obj.x, obj.y, obj.width, obj.height);
}
}
|
ログイン後にコピー
5. プレイヤーが敵に当たったかどうかを判断するには?
プレイヤーが敵に当たるかどうかの判定には実際には当たり判定を使用しますが、今回は画面上の要素のオブジェクトを用いて当たり判定を行っています。
十字線 (画面の中点) によって形成される四角形が敵オブジェクトと衝突するかどうかを検出するだけで、敵が当たったかどうかを検出できます。
1 2 3 4 5 6 7 8 9 10 | <strong> for ( var i = list2.length - 1; i >= 0; i--) {
if (list2[i] instanceof enemy2 && list2[i].relatedParent.isShooting) {
var obj = list2[i];
var enemyRect = obj.getRect();
if (cnGame.collision.col_Point_Rect(starPos[0], starPos[1], enemyRect)) {
obj.setCurrentAnimation( "enemyDie" );
break ;
}
}
}</strong>
|
ログイン後にコピー
敵を攻撃した後、ループから抜け出し、敵の背後にある敵を攻撃しないように検出を停止する必要があります。 以上がHTML5 一人称シューティング ゲーム実装のためのコード共有の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。