質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

1回答

301閲覧

body要素内での再度CSS記述の必要性(ミニゲーム制作)

kopo

総合スコア16

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

0クリップ

投稿2018/09/21 17:46

前提・実現したいこと

JavaScriptでケイブ(洞窟)の壁に当たらないように進んでいくゲームを作っています。
(「ゲームを作りながら楽しく学べるHTML5+CSS+JavaScriptプログラミング[改訂版]」のサンプルプログラムです)

発生している問題・エラーメッセージ

body内のimg#shipに
style="height:97px;"
という記述がありますが、この記述を外すと洞窟下側の当たり判定(hitTest)が上手く機能しなくなってしまいます。
styleはhead内で記述されているにも関わらずこのような事が起こる理由を教えていただけませんか?

該当のソースコード

JavaScript

1<!DOCTYPE html> 2<html> 3<head> 4 <title>Cave</title> 5 <meta charset="utf-8" /> 6 <style> 7 #main { 8 width: 800px; 9 height: 600px; 10 background-color: #00cc00; 11 position: absolute; 12 overflow: hidden; 13 } 14 15 #ship { 16 top: 250px; 17 left: 0px; 18 width: 150px; 19 height: 97px; 20 position: absolute; 21 z-index: 100; 22 } 23 24 #bang { 25 width: 200px; 26 height: 200px; 27 position: absolute; 28 z-index: 101; 29 visibility: hidden; 30 } 31 </style> 32 <script type="text/javascript"> 33 "use strict"; 34 var y = 250, v = 0, keyDown = false, WALLS = 80, score = 0; 35 var walls = [], slope = 0, timer, ship, main; 36 37 function init() { 38 main = document.getElementById('main'); 39 ship = document.getElementById('ship'); 40 41 for (var i = 0 ; i < WALLS ; i++) { 42 walls[i] = document.createElement("div"); 43 walls[i].style.position = "absolute"; 44 walls[i].style.top = "100px"; 45 walls[i].style.left = i * 10 + "px"; 46 walls[i].style.width = "10px"; 47 walls[i].style.height = "400px"; 48 walls[i].style.backgroundColor = "#333333"; 49 main.appendChild(walls[i]); 50 } 51 52 slope = Math.floor(Math.random() * 5) + 1; 53 timer = setInterval(mainloop, 50); 54 window.addEventListener('keydown', function () { keyDown = true; }); 55 window.addEventListener('keyup', function () { keyDown = false; }); 56 } 57 58 function hitTest(){ 59 var st = parseInt(ship.style.top) + 10; 60 var sh = parseInt(ship.style.height); 61 var sb = st + sh - 20; 62 63 var wt = parseInt(walls[14].style.top); 64 var wh = parseInt(walls[14].style.height); 65 var wb = wh + wt; 66 67 return (st < wt) || (sb > wb ); 68 } 69 70 function mainloop() { 71 if (hitTest()) { 72 clearInterval(timer); 73 document.getElementById('bang').style.top = (y - 40) + "px"; 74 document.getElementById('bang').style.visibility = "visible"; 75 return; 76 } 77 78 score += 10; 79 document.getElementById('score').innerHTML = score.toString(); 80 81 v += keyDown ? -3 : 3; 82 y += v; 83 ship.style.top = y + 'px'; 84 85 var edge = walls[WALLS - 1].style; 86 var t = parseInt(edge.top); 87 var h = parseInt(edge.height); 88 var b = h + t; 89 t += slope; 90 b += slope; 91 if ((t < 0) && (slope < 0) || (b > 600) && (slope > 0)) { 92 slope = (Math.floor(Math.random() * 5) + 1) * (slope < 0 ? 1 : -1); 93 edge.top = (t + 10) + "px"; 94 edge.height = (h - 20) + "px"; 95 } else { 96 edge.top = t + "px"; 97 } 98 99 for (var i = 0 ; i < WALLS - 1 ; i++) { 100 walls[i].style.top = walls[i + 1].style.top; 101 walls[i].style.height = walls[i + 1].style.height; 102 } 103 } 104 105 </script> 106</head> 107 108<body onload="init()"> 109 <h1>Score:<span id="score"></span></h1> 110 <div id="main"> 111 <img id="ship" src="ship.png" style="height:97px;" /> 112 <img id="bang" src="bang.png" /> 113 </div> 114</body> 115</html>

補足情報(FW/ツールのバージョンなど)

ブラウザはGoogle Chromeを使用しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/09/21 21:54

書籍に何も解説はついていないのでしょうか?
kopo

2018/09/22 00:17

読み返しましたが、この1行に関しては解説がありませんでした。
m.ts10806

2018/09/22 00:34

思うところで回答してみました。参考まで。
guest

回答1

0

ベストアンサー

関係ありそうなのはhitTest()の下記の記述ですね。

js

1var sh = parseInt(ship.style.height);

{element}.style.{css指定}で実際に指定されているCSSの値が取得できます。
例えば下記のようにデバッグ記述を入れてみるとわかりやすいです。

js

1console.log(ship.style.height); 2var sh = parseInt(ship.style.height);

直指定を入れた場合はその値を取得し、
直指定を抜いた時は何も取得しません。

そのため、sh を利用する当たり判定が効いていない状況になっているものと思われます。
もし、直指定をなくしたいのであればstyleから辿るのではなく、そのelement自体のheightを利用すれば、直指定を無効化できると思います。

js

1var sh = parseInt(ship.height);

ただ。
様々なゲームにて「あたり判定」をというのは採用されているかと思いますが、
本当にその物体そのものの枠線にあるとき、つまり物体との距離0で「当たった」というのは現実的に違和感があります。
格闘ゲームで言えば「hit」は、やはりきちんとキャラクターに攻撃が「入った」ときです。
そのため「物体自体の大きさはある程度保持したいけど、”当たった”はきちんと”入った”ときにしたい」という、”あたり判定の幅”を持たせたいという要件を満たすために、styleで直指定して調整するというのはありだと思います。
提示の書籍を読んだことがあるわけではありませんが、CSSの指定とは別に直指定されているのはそのような意図があるように思います。

もちろんあたり判定に幅を持たせるやり方はこれだけではありませんが、複数のelementを扱うことになるため、入門書籍では、ひとまず容易に実現可能な方法をとっているのではないでしょうか。

投稿2018/09/22 00:34

m.ts10806

総合スコア80731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kopo

2018/09/22 00:47

ありがとうございます。おっしゃる通りship.style.height=""となっていました。 ちなみに何故直指定するとship.style.heightが取得できるのでしょうか? head要素に記述したcssの読み込みはbodyのonloadより後に適用されるのでしょうか?
kopo

2018/09/22 01:06

ありがとうございます。 なぜship.style.topは取得できるのだろうと考えていましたが、1回目のhitTestではship.style.height同様に取得できていないことが確認できました。 リファレンスまで教えてくださりありがとうございます。 とてもすっきりしました。
m.ts10806

2018/09/22 01:11

そうですね。理論は同じです。 「あれ?」と思った時にはリファレンスの仕様を確認すると良いです。 確かに色々やっているとロジックが間違っているのか仕様なのかわからなくなることは多いですが、問題切り分けのためにリファレンスで仕様を確認してからデバッグをしていくというのは非常に有用です。
kopo

2018/09/22 01:19

ありがとうございます。 デバッグの仕方、リファレンスの大切さを学べてとても面白かったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問