Почему этот индексный html не отображает игру на моем столе?

#javascript #canvas

#javascript #холст

Вопрос:

Я нашел эту игру в Интернете и пытаюсь запустить ее со своего рабочего стола. Есть ли что-то особенное, что человек должен сделать с URL-адресом или изображениями, чтобы файл распознал, где все запущено и находится. У меня есть все файлы и .png-файлы в одной папке и на одном уровне.

Я бы подумал, что я должен видеть игру на экране. Это похоже на горизонтальную прокрутку слева направо с вражескими кораблями, которые выходят из правой части экрана, а главный корабль находится в правой части экрана. (Аналогично игре defender в старом стиле)

index.html

 <!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">

    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width">

    <link rel="stylesheet" href="app.css">
  </head>

  <body>
    <div id="game-over-overlay"></div>

    <div id="game-over">
      <h1>GAME OVER</h1>
      <button id="play-again">Play Again</button>
    </div>

    <div class="wrapper">
      <div id="instructions">
        <div>
          move with <span class="key">arrows</span> or <span class="key">wasd</span>
        </div>
        <div>
          shoot with <span class="key">space</span>
        </div>
      </div>
      <div id="score"></div>
    </div>

    <script type="text/javascript" src="resources.js"></script>
    <script type="text/javascript" src="input.js"></script>
    <script type="text/javascript" src="sprite.js"></script>
    <script type="text/javascript" src="app.js"></script>
  </body>
</html>
  

sprite.js

 (function() {
    function Sprite(url, pos, size, speed, frames, dir, once) {
        this.pos  = pos;
        this.size = size;
        this.speed  = typeof speed === 'number' ? speed : 0;
        this.frames = frames;
        this._index = 0;
        this.url = url;
        this.dir = dir || 'horizontal';
        this.once = once;
    };

    Sprite.prototype = {
        update: function(dt) {
            this._index  = this.speed*dt;
        },

        render: function(ctx) {
            var frame;

            if(this.speed > 0) {
                var max = this.frames.length;
                var idx = Math.floor(this._index);
                frame = this.frames[idx % max];

                if(this.once amp;amp; idx >= max) {
                    this.done = true;
                    return;
                }
            }
            else {
                frame = 0;
            }

            var x = this.pos[0];
            var y = this.pos[1];

            if(this.dir == 'vertical') {
                y  = frame * this.size[1];
            }
            else {
                x  = frame * this.size[0];
            }

            ctx.drawImage(resources.get(this.url),
                          x, y,
                          this.size[0], this.size[1],
                          0, 0,
                          this.size[0], this.size[1]);
        }
    };

    window.Sprite = Sprite;
  

resources.js

 (function() {
    var resourceCache = {};
    var loading = [];
    var readyCallbacks = [];

    // Load an image url or an array of image urls
    function load(urlOrArr) {
        if(urlOrArr instanceof Array) {
            urlOrArr.forEach(function(url) {
                _load(url);
            });
        }
        else {
            _load(urlOrArr);
        }
    }

    function _load(url) {
        if(resourceCache[url]) {
            return resourceCache[url];
        }
        else {
            var img = new Image();
            img.onload = function() {
                resourceCache[url] = img;

                if(isReady()) {
                    readyCallbacks.forEach(function(func) { func(); });
                }
            };
            resourceCache[url] = false;
            img.src = url;
        }
    }

    function get(url) {
        return resourceCache[url];
    }

    function isReady() {
        var ready = true;
        for(var k in resourceCache) {
            if(resourceCache.hasOwnProperty(k) amp;amp;
               !resourceCache[k]) {
                ready = false;
            }
        }
        return ready;
    }

    function onReady(func) {
        readyCallbacks.push(func);
    }

    window.resources = { 
        load: load,
        get: get,
        onReady: onReady,
        isReady: isReady
    };
  

input.js

 (function() {
    var pressedKeys = {};

    function setKey(event, status) {
        var code = event.keyCode;
        var key;

        switch(code) {
        case 32:
            key = 'SPACE'; break;
        case 37:
            key = 'LEFT'; break;
        case 38:
            key = 'UP'; break;
        case 39:
            key = 'RIGHT'; break;
        case 40:
            key = 'DOWN'; break;
        default:
            key = String.fromCharCode(code);
        }

        pressedKeys[key] = status;
    }

    document.addEventListener('keydown', function(e) {
        setKey(e, true);
    });

    document.addEventListener('keyup', function(e) {
        setKey(e, false);
    });

    window.addEventListener('blur', function() {
        pressedKeys = {};
    });

    window.input = {
        isDown: function(key) {
            return pressedKeys[key.toUpperCase()];
        }
    };
  

apps.js

 // A cross-browser requestAnimationFrame
// See https://hacks.mozilla.org/2011/08/animating-with-javascript-from-setinterval-to-requestanimationframe/
var requestAnimFrame = (function(){
    return window.requestAnimationFrame    ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame    ||
        window.oRequestAnimationFrame      ||
        window.msRequestAnimationFrame     ||
        function(callback){
            window.setTimeout(callback, 1000 / 60);
        };
})();

// Create the canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width  = 512;
canvas.height = 480;
document.body.appendChild(canvas);

// The main game loop
var lastTime;
function main() {
    var now = Date.now();
    var dt = (now - lastTime) / 1000.0;

    update(dt);
    render();

    lastTime = now;
    requestAnimFrame(main);
};

function init() {
    terrainPattern = ctx.createPattern(resources.get('terrain.png'), 'repeat');

    document.getElementById('play-again').addEventListener('click', function() {
        reset();
    });

    reset();
    lastTime = Date.now();
    main();
}

resources.load([
    'sprites.png',
    'terrain.png'
]);
resources.onReady(init);

// Game state
var player = {
    pos: [0, 0],
    sprite: new Sprite('sprites.png', [0, 0], [39, 39], 16, [0, 1])
};

var bullets = [];
var enemies = [];
var explosions = [];

var lastFire = Date.now();
var gameTime = 0;
var isGameOver;
var terrainPattern;

var score = 0;
var scoreEl = document.getElementById('score');

// Speed in pixels per second
var playerSpeed = 200;
var bulletSpeed = 500;
var enemySpeed = 100;

// Update game objects
function update(dt) {
    gameTime  = dt;

    handleInput(dt);
    updateEntities(dt);

    // It gets harder over time by adding enemies using this
    // equation: 1-.993^gameTime
    if(Math.random() < 1 - Math.pow(.993, gameTime)) {
        enemies.push({
            pos: [canvas.width,
                  Math.random() * (canvas.height - 39)],
            sprite: new Sprite('sprites.png', [0, 78], [80, 39],
                               6, [0, 1, 2, 3, 2, 1])
        });
    }

    checkCollisions();

    scoreEl.innerHTML = score;
};

function handleInput(dt) {
    if(input.isDown('DOWN') || input.isDown('s')) {
        player.pos[1]  = playerSpeed * dt;
    }

    if(input.isDown('UP') || input.isDown('w')) {
        player.pos[1] -= playerSpeed * dt;
    }

    if(input.isDown('LEFT') || input.isDown('a')) {
        player.pos[0] -= playerSpeed * dt;
    }

    if(input.isDown('RIGHT') || input.isDown('d')) {
        player.pos[0]  = playerSpeed * dt;
    }

    if(input.isDown('SPACE') amp;amp; !isGameOver amp;amp; Date.now() - lastFire > 100) {
        var x = player.pos[0]   player.sprite.size[0] / 2;
        var y = player.pos[1]   player.sprite.size[1] / 2;

        bullets.push({ pos: [x, y],
                       dir: 'forward',
                       sprite: new Sprite('sprites.png', [0, 39], [18, 8]) });
        bullets.push({ pos: [x, y],
                       dir: 'up',
                       sprite: new Sprite('sprites.png', [0, 50], [9, 5]) });
        bullets.push({ pos: [x, y],
                       dir: 'down',
                       sprite: new Sprite('sprites.png', [0, 60], [9, 5]) });

        lastFire = Date.now();
    }
}

function updateEntities(dt) {
    // Update the player sprite animation
    player.sprite.update(dt);

    // Update all the bullets
    for(var i=0; i<bullets.length; i  ) {
        var bullet = bullets[i];

        switch(bullet.dir) {
        case 'up': bullet.pos[1] -= bulletSpeed * dt; break;
        case 'down': bullet.pos[1]  = bulletSpeed * dt; break;
        default:
            bullet.pos[0]  = bulletSpeed * dt;
        }

        // Remove the bullet if it goes offscreen
        if(bullet.pos[1] < 0 || bullet.pos[1] > canvas.height ||
           bullet.pos[0] > canvas.width) {
            bullets.splice(i, 1);
            i--;
        }
    }

    // Update all the enemies
    for(var i=0; i<enemies.length; i  ) {
        enemies[i].pos[0] -= enemySpeed * dt;
        enemies[i].sprite.update(dt);

        // Remove if offscreen
        if(enemies[i].pos[0]   enemies[i].sprite.size[0] < 0) {
            enemies.splice(i, 1);
            i--;
        }
    }

    // Update all the explosions
    for(var i=0; i<explosions.length; i  ) {
        explosions[i].sprite.update(dt);

        // Remove if animation is done
        if(explosions[i].sprite.done) {
            explosions.splice(i, 1);
            i--;
        }
    }
}

// Collisions

function collides(x, y, r, b, x2, y2, r2, b2) {
    return !(r <= x2 || x > r2 ||
             b <= y2 || y > b2);
}

function boxCollides(pos, size, pos2, size2) {
    return collides(pos[0], pos[1],
                    pos[0]   size[0], pos[1]   size[1],
                    pos2[0], pos2[1],
                    pos2[0]   size2[0], pos2[1]   size2[1]);
}

function checkCollisions() {
    checkPlayerBounds();

    // Run collision detection for all enemies and bullets
    for(var i=0; i<enemies.length; i  ) {
        var pos = enemies[i].pos;
        var size = enemies[i].sprite.size;

        for(var j=0; j<bullets.length; j  ) {
            var pos2 = bullets[j].pos;
            var size2 = bullets[j].sprite.size;

            if(boxCollides(pos, size, pos2, size2)) {
                // Remove the enemy
                enemies.splice(i, 1);
                i--;

                // Add score
                score  = 100;

                // Add an explosion
                explosions.push({
                    pos: pos,
                    sprite: new Sprite('sprites.png',
                                       [0, 117],
                                       [39, 39],
                                       16,
                                       [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
                                       null,
                                       true)
                });

                // Remove the bullet and stop this iteration
                bullets.splice(j, 1);
                break;
            }
        }

        if(boxCollides(pos, size, player.pos, player.sprite.size)) {
            gameOver();
        }
    }
}

function checkPlayerBounds() {
    // Check bounds
    if(player.pos[0] < 0) {
        player.pos[0] = 0;
    }
    else if(player.pos[0] > canvas.width - player.sprite.size[0]) {
        player.pos[0] = canvas.width - player.sprite.size[0];
    }

    if(player.pos[1] < 0) {
        player.pos[1] = 0;
    }
    else if(player.pos[1] > canvas.height - player.sprite.size[1]) {
        player.pos[1] = canvas.height - player.sprite.size[1];
    }
}

// Draw everything
function render() {
    ctx.fillStyle = terrainPattern;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Render the player if the game isn't over
    if(!isGameOver) {
        renderEntity(player);
    }

    renderEntities(bullets);
    renderEntities(enemies);
    renderEntities(explosions);
};

function renderEntities(list) {
    for(var i=0; i<list.length; i  ) {
        renderEntity(list[i]);
    }    
}

function renderEntity(entity) {
    ctx.save();
    ctx.translate(entity.pos[0], entity.pos[1]);
    entity.sprite.render(ctx);
    ctx.restore();
}

// Game over
function gameOver() {
    document.getElementById('game-over').style.display = 'block';
    document.getElementById('game-over-overlay').style.display = 'block';
    isGameOver = true;
}

// Reset game to original state
function reset() {
    document.getElementById('game-over').style.display = 'none';
    document.getElementById('game-over-overlay').style.display = 'none';
    isGameOver = false;
    gameTime = 0;
    score = 0;

    enemies = [];
    bullets = [];

    player.pos = [50, canvas.height / 2];
  

app.css

 html, body {
    margin: 0;
    padding: 0;
    background-color: #151515;
}

canvas {
    display: block;
    margin: auto;

    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

.wrapper {
    width: 512px;
    margin: 0 auto;
    margin-top: 2em;
}

#instructions {
    float: left;
    font-family: sans-serif;
    color: #757575;
}

#score {
    float: right;
    color: white;
    font-size: 2em;
}

.key {
    color: #aaffdd;
}

#game-over, #game-over-overlay {
    margin: auto;
    width: 512px;
    height: 480px;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1;
    display: none;
}

#game-over-overlay {
    background-color: black;
    opacity: .5;
}

#game-over {
    height: 200px;
    text-align: center;
    color: white;
}

#game-over h1 {
    font-size: 3em;
    font-family: sans-serif;
}

#game-over button {
    font-size: 1.5em;
}
  

введите описание изображения здесь

введите описание изображения здесь

введите описание изображения здесь

Вот оригинальная ссылка на игру

   http://jlongster.com/Making-Sprite-based-Games-with-Canvas
  

Если бы кто-нибудь мог установить скрипку, чтобы узнать, почему она не работает, это было бы очень ценно.

Ошибки с консоли

  Uncaught SyntaxError: Unexpected end of input resources.js:61
 Uncaught SyntaxError: Unexpected end of input input.js:43
 Uncaught SyntaxError: Unexpected end of input sprite.js:54
 Uncaught SyntaxError: Unexpected end of input app.js:302
  

Комментарии:

1. Я бы не ожидал, что кто-то, кроме меня, отладит проблему. И первое, что я бы сделал, это проверил консоль ошибок браузера. Я уверен, что вы увидите ошибки безопасности HTML5 canvas.

2. Ваш HTML ищет «app.css», затем вы вставили «apps.css». Проверьте консоль на наличие ошибок.

3. Я проверил это, и все было в порядке в index.html файл. Он искал правильный файл.

4. Ну, я это исправил, мне не хватало }()); пространство имен закрывается в конце всех файлов .js.

Ответ №1:

Вы запускаете это на веб-сервере? То, как вы это сформулировали, заставляет меня думать, что вы скачали эти файлы и просто дважды щелкнули index.html.

Вам нужно загрузить что-то вродеhttps://www.apachefriends.org/index.html и запустите службу Apache, затем поместите ваши файлы в папку /xampp / htdocs /… тогда переходим

 http://localhost/index.html 
  

чтобы заставить ее загрузиться.

Комментарии:

1. Вот как я это делаю. Именно так я бы предпочел протестировать ее, просто запустив со своего рабочего стола.