3

私は Javascript を初めて使用するので、単純な SnakeGame を作成して HTML に埋め込むことにしました。ただし、ヘビの方向を変更するコードは、数ターン後にフリーズします。

注: これは HTML Canvas で実行しています。

ソース:

var Canvas;
var ctx;

var fps = 60;

var x = 0;
var seconds = 0;

var lastLoop;
var thisLoop;
var tempFPS = 0;
var blockList = [];
var DEFAULT_DIRECTION = "Right";

var pendingDirections = [];

function update() {
    x += 1;

    thisLoop = new Date();
    tempFPS = 1000 / (thisLoop - lastLoop);
    lastLoop = thisLoop;
    tempFPS = Math.round(tempFPS*10)/10;

    if (x==10){
        document.getElementById("FPS").innerHTML = ("FPS: " + tempFPS);
    }

    //Rendering
    for (var i = 0; i<blockList.length; i++){
        var block = blockList[i];
        draw(block.x, block.y);
    }

    if (x==5){
        x=0;
        seconds+=1;

        //Updates once per x frames
        moveBlocks();
    }
}

function moveBlocks(){
    if(blockList.length === 0){
        return;
    }


    for (var j = 0; j<pendingDirections.length; j++){
        if (b >= blockList.length -1){
            pendingDirections.shift();

        }else {
            //Iterates through each direction that is pending
            var b = pendingDirections[j].block;
            try{
                blockList[b].direction = pendingDirections[j].direction;
            } catch(err){
                alert(err);
            }
            pendingDirections[j].block++;
        }
    }

    for (var i = 0; i<blockList.length; i++){
        var block = blockList[i];
        clear(block.x, block.y);
        if (block.direction == "Down"){
            block.y += BLOCK_SIZE;
        } else if (block.direction == "Up"){
            block.y -= BLOCK_SIZE;
        } else if (block.direction == "Left"){
            block.x -= BLOCK_SIZE;
        } else if (block.direction == "Right"){
            block.x += BLOCK_SIZE;
        } else {
            alert(block.direction);
        }
        draw(block.x, block.y);
    }
}

function init(){
    lastLoop = new Date();
    window.setInterval(update, 1000/fps);
    Canvas = document.getElementById("Canvas");
    ctx = Canvas.getContext("2d");
}

//The width/height of each block
var BLOCK_SIZE = 30;

//Draws a block
function draw(x, y) {

    ctx.fillStyle = "#000000";
    ctx.fillRect(x,y,BLOCK_SIZE,BLOCK_SIZE);
}

function clear(x,y){
    ctx.fillStyle = "#FFFFFF";
    ctx.fillRect(x,y,BLOCK_SIZE,BLOCK_SIZE);
}

function processInput(key){
    if (key == 110){
        //n (new)
        newBlock(BLOCK_SIZE*4,0);
        newBlock(BLOCK_SIZE*3,0);
        newBlock(BLOCK_SIZE*2,0);
        newBlock(BLOCK_SIZE*1,0);
        newBlock(0,0);

    } else if (key == 119){
        changeDirection("Up");
    } else if (key == 115){
        changeDirection("Down");
    } else if (key == 97){
        changeDirection("Left");
    } else if (key == 100){
        changeDirection("Right");
    } else if (key==122){
        var pDir = "Pending Directions: ";
        for (var i = 0; i<pendingDirections.length; i++){
            pDir += pendingDirections[i].direction + ", ";
        }
        alert(pDir);
    } else if (key == 120){
        var dir = "Directions: ";   
        for (var j = 0; j<blockList.length; j++){
            dir += blockList[j].direction + ", ";
        }
        alert(dir);
    } else {
        alert("KEY: " +key);
    }
}

function changeDirection(d){
    var LD = blockList[0].direction;
    var valid = false;

    if (d == "Up"){
        if(LD != "Down"){
            valid = true;
        }
    } else if (d == "Down"){
        if(LD != "Up"){
            valid = true;
        }
    } else if (d == "Left"){
        if(LD != "Right"){
            valid = true;
        }
    } else if (d == "Right"){
        if(LD != "Left"){
            valid = true;
        }
    }  

    if (d == LD) { valid = false;}

    if (valid){     
        var dir = {'direction' : d, 'block' : 0};
        pendingDirections.unshift(dir);
    }
}
function newBlock(x, y){
    var block = {'x': x, 'y' : y, 'direction' : DEFAULT_DIRECTION};
    //This works: alert(block['x']);
    draw(x,y);
    blockList.push(block);
}

ありがとう

4

1 に答える 1

2

Evan が言ったように、主な問題は保留中の指示をどのように処理するかです。

この問題は、立て続けに 2 回向きを変えると発生します。これにより、同じブロックに保留中の 2 つの方向が追加されます。これらが正しい順序で処理されない場合、ブロックは間違った方向に移動する可能性があります。更新ごとに、ブロックごとに保留中の方向が 1 つだけ必要なので、1 回の更新中に 1 つのブロックで複数の方向が回避されるように、これを処理する方法を再設計しました。

これへのリンクは次のとおりです。http://jsbin.com/EkOSOre/5/edit

方向が変更されると、最初のブロックの保留中の方向が更新され、既存の保留中の方向が上書きされることに注意してください。

if (valid) {
    blockList[0].pendingDirection = direction;
}

次に、更新が発生すると、ブロックのリストがループされ、次のブロックの保留中の方向が現在のブロックの現在の方向に設定されます。

if(!!nextBlock) {
    nextBlock.pendingDirection = block.direction;
}

現在のブロックに保留中の方向がある場合は、方向を保留中の方向に設定します。

if(block.pendingDirection !== null) {
    block.direction = block.pendingDirection;
}

次に、通常どおりブロックの場所を更新します。

また、変数 (b) を初期化する前に使用したり、null/undefined エラーをどのようにキャッチしたか (その状況をチェックして適切に処理する必要があります) など、他にもさまざまな問題がありましたが、これが主な問題でした。あなたのアルゴリズムの問​​題。

また、ユーザーが 'n' を押したときに古いブロックを削除する必要があります。これは、古いブロックが残され、存在するブロックの速度と合計数が増加するためです。

ゲームの残りの部分も頑張ってください。JavaScript の学習も頑張ってください。

于 2013-11-08T16:35:32.197 に答える