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

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

ただいまの
回答率

90.45%

  • JavaScript

    21025questions

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

  • CSS

    7812questions

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

  • HTML5

    5301questions

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

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

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 184

kopogaya

score 3

 前提・実現したいこと

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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mts10806

    2018/09/22 06:54

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

    キャンセル

  • kopogaya

    2018/09/22 09:17

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

    キャンセル

  • mts10806

    2018/09/22 09:34

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

    キャンセル

回答 1

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を扱うことになるため、入門書籍では、ひとまず容易に実現可能な方法をとっているのではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/22 09:47

    ありがとうございます。おっしゃる通りship.style.height=""となっていました。
    ちなみに何故直指定するとship.style.heightが取得できるのでしょうか?

    head要素に記述したcssの読み込みはbodyのonloadより後に適用されるのでしょうか?

    キャンセル

  • 2018/09/22 09:50

    リファレンスをご確認ください。
    https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/style
    > 取得時には要素のインライン style 属性で定義されたすべてのスタイルプロパティを表す

    インライン、つまり直指定のものしか取得しません。

    キャンセル

  • 2018/09/22 10:06

    ありがとうございます。
    なぜship.style.topは取得できるのだろうと考えていましたが、1回目のhitTestではship.style.height同様に取得できていないことが確認できました。

    リファレンスまで教えてくださりありがとうございます。
    とてもすっきりしました。

    キャンセル

  • 2018/09/22 10:11

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

    キャンセル

  • 2018/09/22 10:19

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

    キャンセル

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

  • ただいまの回答率 90.45%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • JavaScript

    21025questions

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

  • CSS

    7812questions

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

  • HTML5

    5301questions

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