WedX - журнал о программировании и компьютерных науках

HTML5 Canvas + js игра | Сброс игры при смерти меняет скорость игры?

Я пытаюсь сделать игру, используя холст HTML5 и javascript. Я считаю, что делал все хорошо до того момента, когда мне нужно было сбросить игру после смерти. Я не совсем уверен, что вызывает неожиданное поведение, но у меня есть мысли.

В значительной степени игра работает на скорости «х», а затем, когда она сбрасывается, все движется намного быстрее. Я не менял ни одну из переменных для какой-либо скорости чего бы то ни было, и при отладке и проверке моего кода скорости вновь созданных объектов такие же, как и при первом запуске игры, но они движутся намного быстрее. Если вы снова умрете, он снова сбрасывается и работает еще быстрее. Умереть, промыть, повторить, и он продолжает ускоряться до тех пор, пока страница, вероятно, не перейдет в состояние «не отвечает».

Я не знаю точно, что я делаю неправильно, что вызывает разницу в скорости или, по крайней мере, иллюзию разницы в скорости. У меня есть идея, что это как-то связано с тем, что мой игровой цикл запускается несколько раз навсегда каждый раз, когда он сбрасывается, но я не понимаю, как/почему это происходит. любая обратная связь приветствуется.

Кроме того, вы можете посетить мою страницу тестирования, чтобы увидеть весь код, если вам нужно больше, чем я разместил ниже: игровая тестовая площадка< /а>

var windowx,
windowy,
canvas,
player,
quadTree,
ctx;

var drawObjects;
var keyState;

var mainloop;
var animFrame;
var ONE_FRAME_TIME;

var reset = function () {

//get canvas and set height and width
canvas = document.getElementById('canvas');
canvas.setAttribute('width', windowx / 2);
canvas.setAttribute('height', windowy / 2);
ctx = canvas.getContext("2d");
drawObjects = [];
keyState = {};
quadTree = new Quadtree(quadTreeBounds);


//make the friendly square
player = new Rectangle(20, 20, 40, 40, 0, 0, XPhysicsBehaviorNormal, YPhysicsBehaviorNormal, XBoundaryBehaviorInCanvas, YBoundaryBehaviorInCanvas, playerObjectType, '#580000', null);
drawObjects.push(player);
drawObjects.push(new Rectangle(40, 100, canvas.width + (distanceOutsideCanvasBeforeDie / 2), canvas.clientHeight - 100, defaultEnemyRectangleVelocity, 0, null, YPhysicsBehaviorNormal, null, YBoundaryBehaviorInCanvas, enemyObjectType, null, OutOfCanvasDieBehavior));


backgroundMusicAudio.play();

//define main loop
mainloop = function () {
    buildQuadTree();
    updateGame();
    drawGame();
};

//define the windowanimationframeobject
animFrame = window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    null;

if (animFrame !== null) {
    var recursiveAnim = function () {
        mainloop();
        animFrame(recursiveAnim, canvas);
    };

    // start the mainloop
    animFrame(recursiveAnim, canvas);
} else {
    // fallback to setInterval if the browser doesn't support requestAnimationFrame
    ONE_FRAME_TIME = 1000.0 / 60.0;
    setInterval(mainloop, ONE_FRAME_TIME);
}
}

$(function () {
//get window width and height;
windowx = window.innerWidth;
windowy = window.innerHeight;

reset();

$(document).on('change', '#sound-enabled-toggle', function() {
    var isChecked = $(this).is(':checked');
    $('#sound-enabled-toggle').blur();
    if (isChecked) {
        backgroundMusicAudio.play();
        playerJumpAudio = playerJumpMusicAudioSetup();
        playerBlinkAudio = playerBlinkMusicAudioSetup();
    } else {
        backgroundMusicAudio.pause();
        playerJumpAudio = new Audio('');
        playerBlinkAudio = new Audio('');
    }
});
});

//left the function here in case I need to do anything else but for now it's  just clearing.
function buildQuadTree() {
    quadTree.clear();
}

function updateGame() {

//determine if there are any keys pushed at the current point
keyPressActions();

//loop for calculating and updating all objects positions/values.
for (var i = 0; i < drawObjects.length; i++) {
    var object = drawObjects[i];
    quadTree.insert(new SimpleRectangle(object.x, object.y, object.width || (object.radius * 2), object.height || (object.radius * 2), object.name));
    object.update();

    //roundFloatingPoints Numbers to 2 decimal places
    roundObjectVelocitiesAndPoints(object);
}
PlayerDeathTrigger(player);
}

function drawGame() {
//clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.font = "20px Verdana";
ctx.fillText("100,000", (canvas.width * .8), (canvas.clientHeight * .1));
ctx.font = "15px Verdana";
ctx.fillText("Temp Score", (canvas.width * .8), (canvas.clientHeight * .05));

//draw all objects in drawObjects
for (var i = 0; i < drawObjects.length; i++) {
    var object = drawObjects[i];
    object.draw();
}
}

Ответы:


1

В целом, я бы рекомендовал реорганизовать этот код, чтобы ваша функция сброса не создавала заново так много объектов. По сути, функция сброса просто воссоздает большую часть игровой логики.

Выявленная вами конкретная проблема, по-видимому, связана с тем, что вы вызываете setInterval при каждом сбросе без очистки предыдущего интервала. См. приведенный ниже код с минимальными изменениями, чтобы предотвратить эту проблему.

var windowx,
    windowy,
    canvas,
    player,
    quadTree,
    ctx,
    gameLoop;

var drawObjects;
var keyState;

var mainloop;
var animFrame;
var ONE_FRAME_TIME;

var reset = function() {

    // Remove our old game loop
    clearInterval(gameLoop);

    //get canvas and set height and width
    canvas = document.getElementById('canvas');
    canvas.setAttribute('width', windowx / 2);
    canvas.setAttribute('height', windowy / 2);
    ctx = canvas.getContext("2d");
    drawObjects = [];
    keyState = {};
    quadTree = new Quadtree(quadTreeBounds);


    //make the friendly square
    player = new Rectangle(20, 20, 40, 40, 0, 0, XPhysicsBehaviorNormal, YPhysicsBehaviorNormal, XBoundaryBehaviorInCanvas, YBoundaryBehaviorInCanvas, playerObjectType, '#580000', null);
    drawObjects.push(player);
    drawObjects.push(new Rectangle(40, 100, canvas.width + (distanceOutsideCanvasBeforeDie / 2), canvas.clientHeight - 100, defaultEnemyRectangleVelocity, 0, null, YPhysicsBehaviorNormal, null, YBoundaryBehaviorInCanvas, enemyObjectType, null, OutOfCanvasDieBehavior));


    backgroundMusicAudio.play();

    //define main loop
    mainloop = function() {
        buildQuadTree();
        updateGame();
        drawGame();
    };

    //define the windowanimationframeobject
    animFrame = window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        null;

    if (animFrame !== null) {
        var recursiveAnim = function() {
            mainloop();
            animFrame(recursiveAnim, canvas);
        };

        // start the mainloop
        animFrame(recursiveAnim, canvas);
    } else {
        // fallback to setInterval if the browser doesn't support requestAnimationFrame
        ONE_FRAME_TIME = 1000.0 / 60.0;
        gameLoop = setInterval(mainloop, ONE_FRAME_TIME);
    }
}

$(function() {
    //get window width and height;
    windowx = window.innerWidth;
    windowy = window.innerHeight;

    reset();

    $(document).on('change', '#sound-enabled-toggle', function() {
        var isChecked = $(this).is(':checked');
        $('#sound-enabled-toggle').blur();
        if (isChecked) {
            backgroundMusicAudio.play();
            playerJumpAudio = playerJumpMusicAudioSetup();
            playerBlinkAudio = playerBlinkMusicAudioSetup();
        } else {
            backgroundMusicAudio.pause();
            playerJumpAudio = new Audio('');
            playerBlinkAudio = new Audio('');
        }
    });
});

//left the function here in case I need to do anything else but for now it's  just clearing.
function buildQuadTree() {
    quadTree.clear();
}

function updateGame() {

    //determine if there are any keys pushed at the current point
    keyPressActions();

    //loop for calculating and updating all objects positions/values.
    for (var i = 0; i < drawObjects.length; i++) {
        var object = drawObjects[i];
        quadTree.insert(new SimpleRectangle(object.x, object.y, object.width || (object.radius * 2), object.height || (object.radius * 2), object.name));
        object.update();

        //roundFloatingPoints Numbers to 2 decimal places
        roundObjectVelocitiesAndPoints(object);
    }
    PlayerDeathTrigger(player);
}

function drawGame() {
    //clear the canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.font = "20px Verdana";
    ctx.fillText("100,000", (canvas.width * .8), (canvas.clientHeight * .1));
    ctx.font = "15px Verdana";
    ctx.fillText("Temp Score", (canvas.width * .8), (canvas.clientHeight * .05));

    //draw all objects in drawObjects
    for (var i = 0; i < drawObjects.length; i++) {
        var object = drawObjects[i];
        object.draw();
    }
}
18.03.2015
  • Спасибо. Я попробовал этот интервал сброса и отмену анимации, но они не сработали, поэтому я воспользовался вашим советом по рефакторингу. Я думал, что цикл никогда не должен останавливаться, но мои игровые объекты должны просто очищаться и сбрасываться, поэтому единственное, что сейчас есть в моей функции сброса, — это очистка объектов рисования и ключей. затем создание игрока и блока. Это прекрасно работает. Спасибо. 18.03.2015
  • Потрясающий. Я рад, что у вас все получилось. Я бы предложил внести изменения в ваш пост и поделиться рабочим кодом со всеми, кто захочет сослаться на этот вопрос в будущем. Ваше здоровье! 18.03.2015
  • Новые материалы

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]