body要素内での再度CSS記述の必要性(ミニゲーム制作)
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 555
前提・実現したいこと
JavaScriptでケイブ(洞窟)の壁に当たらないように進んでいくゲームを作っています。
(「ゲームを作りながら楽しく学べるHTML5+CSS+JavaScriptプログラミング[改訂版]」のサンプルプログラムです)
発生している問題・エラーメッセージ
body内のimg#shipに
style="height:97px;"
という記述がありますが、この記述を外すと洞窟下側の当たり判定(hitTest)が上手く機能しなくなってしまいます。
styleはhead内で記述されているにも関わらずこのような事が起こる理由を教えていただけませんか?
該当のソースコード
<!DOCTYPE html>
<html>
<head>
<title>Cave</title>
<meta charset="utf-8" />
<style>
#main {
width: 800px;
height: 600px;
background-color: #00cc00;
position: absolute;
overflow: hidden;
}
#ship {
top: 250px;
left: 0px;
width: 150px;
height: 97px;
position: absolute;
z-index: 100;
}
#bang {
width: 200px;
height: 200px;
position: absolute;
z-index: 101;
visibility: hidden;
}
</style>
<script type="text/javascript">
"use strict";
var y = 250, v = 0, keyDown = false, WALLS = 80, score = 0;
var walls = [], slope = 0, timer, ship, main;
function init() {
main = document.getElementById('main');
ship = document.getElementById('ship');
for (var i = 0 ; i < WALLS ; i++) {
walls[i] = document.createElement("div");
walls[i].style.position = "absolute";
walls[i].style.top = "100px";
walls[i].style.left = i * 10 + "px";
walls[i].style.width = "10px";
walls[i].style.height = "400px";
walls[i].style.backgroundColor = "#333333";
main.appendChild(walls[i]);
}
slope = Math.floor(Math.random() * 5) + 1;
timer = setInterval(mainloop, 50);
window.addEventListener('keydown', function () { keyDown = true; });
window.addEventListener('keyup', function () { keyDown = false; });
}
function hitTest(){
var st = parseInt(ship.style.top) + 10;
var sh = parseInt(ship.style.height);
var sb = st + sh - 20;
var wt = parseInt(walls[14].style.top);
var wh = parseInt(walls[14].style.height);
var wb = wh + wt;
return (st < wt) || (sb > wb );
}
function mainloop() {
if (hitTest()) {
clearInterval(timer);
document.getElementById('bang').style.top = (y - 40) + "px";
document.getElementById('bang').style.visibility = "visible";
return;
}
score += 10;
document.getElementById('score').innerHTML = score.toString();
v += keyDown ? -3 : 3;
y += v;
ship.style.top = y + 'px';
var edge = walls[WALLS - 1].style;
var t = parseInt(edge.top);
var h = parseInt(edge.height);
var b = h + t;
t += slope;
b += slope;
if ((t < 0) && (slope < 0) || (b > 600) && (slope > 0)) {
slope = (Math.floor(Math.random() * 5) + 1) * (slope < 0 ? 1 : -1);
edge.top = (t + 10) + "px";
edge.height = (h - 20) + "px";
} else {
edge.top = t + "px";
}
for (var i = 0 ; i < WALLS - 1 ; i++) {
walls[i].style.top = walls[i + 1].style.top;
walls[i].style.height = walls[i + 1].style.height;
}
}
</script>
</head>
<body onload="init()">
<h1>Score:<span id="score"></span></h1>
<div id="main">
<img id="ship" src="ship.png" style="height:97px;" />
<img id="bang" src="bang.png" />
</div>
</body>
</html>
補足情報(FW/ツールのバージョンなど)
ブラウザはGoogle Chromeを使用しています。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
関係ありそうなのはhitTest()の下記の記述ですね。
var sh = parseInt(ship.style.height);
{element}.style.{css指定}で実際に指定されているCSSの値が取得できます。
例えば下記のようにデバッグ記述を入れてみるとわかりやすいです。
console.log(ship.style.height);
var sh = parseInt(ship.style.height);
直指定を入れた場合はその値を取得し、
直指定を抜いた時は何も取得しません。
そのため、sh を利用する当たり判定が効いていない状況になっているものと思われます。
もし、直指定をなくしたいのであればstyleから辿るのではなく、そのelement自体のheightを利用すれば、直指定を無効化できると思います。
var sh = parseInt(ship.height);
ただ。
様々なゲームにて「あたり判定」をというのは採用されているかと思いますが、
本当にその物体そのものの枠線にあるとき、つまり物体との距離0で「当たった」というのは現実的に違和感があります。
格闘ゲームで言えば「hit」は、やはりきちんとキャラクターに攻撃が「入った」ときです。
そのため「物体自体の大きさはある程度保持したいけど、”当たった”はきちんと”入った”ときにしたい」という、”あたり判定の幅”を持たせたいという要件を満たすために、styleで直指定して調整するというのはありだと思います。
提示の書籍を読んだことがあるわけではありませんが、CSSの指定とは別に直指定されているのはそのような意図があるように思います。
もちろんあたり判定に幅を持たせるやり方はこれだけではありませんが、複数のelementを扱うことになるため、入門書籍では、ひとまず容易に実現可能な方法をとっているのではないでしょうか。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.19%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
m.ts10806
2018/09/22 06:54
書籍に何も解説はついていないのでしょうか?
kopo
2018/09/22 09:17
読み返しましたが、この1行に関しては解説がありませんでした。
m.ts10806
2018/09/22 09:34
思うところで回答してみました。参考まで。