Javascript 删除或隐藏前一帧中的图像-HTML5画布

Javascript 删除或隐藏前一帧中的图像-HTML5画布,javascript,html,canvas,html5-canvas,Javascript,Html,Canvas,Html5 Canvas,我正在尝试使用htlm5和js编辑pacman实现()。问题是,当我使背景透明时,幽灵和吃豆人图像会保留预览帧 我的js代码: Pacman.FPS = 30; Pacman.Ghost = function (game, map, colour) { function getColour() { if (eatable) { if (secondsAgo(eatable) > 5) {

我正在尝试使用htlm5和js编辑pacman实现()。问题是,当我使背景透明时,幽灵和吃豆人图像会保留预览帧

我的js代码:

    Pacman.FPS = 30;

    Pacman.Ghost = function (game, map, colour) {



    function getColour() { 
        if (eatable) { 
            if (secondsAgo(eatable) > 5) { 
                return game.getTick() % 20 > 10 ? "rgba(0, 0, 0, 0.1)" : "rgba(0, 0, 0, 0.1)";
            } else { 

                return "rgba(0, 0, 0, 0.1)";
            }
        } else if(eaten) { 
            return "#222";
        } 
        return colour;
    };

    function draw(ctx) {

        var s    = map.blockSize, 
            top  = (position.y/10) * s,
            left = (position.x/10) * s;

        if (eatable && secondsAgo(eatable) > 8) {
            eatable = null;
        }

        if (eaten && secondsAgo(eaten) > 3) { 
            eaten = null;
        }

        var tl = left + s;
        var base = top + s - 3;
        var inc = s / 10;

        var high = game.getTick() % 10 > 5 ? 3  : -3;
        var low  = game.getTick() % 10 > 5 ? -3 : 3;

        ctx.fillStyle = getColour();
        ctx.beginPath();

        ctx.moveTo(left, base);

        ctx.quadraticCurveTo(left, top, left + (s/2),  top);
        ctx.quadraticCurveTo(left + s, top, left+s,  base);

        // Wavy things at the bottom
        ctx.quadraticCurveTo(tl-(inc*1), base+high, tl - (inc * 2),  base);
        ctx.quadraticCurveTo(tl-(inc*3), base+low, tl - (inc * 4),  base);
        ctx.quadraticCurveTo(tl-(inc*5), base+high, tl - (inc * 6),  base);
        ctx.quadraticCurveTo(tl-(inc*7), base+low, tl - (inc * 8),  base); 
        ctx.quadraticCurveTo(tl-(inc*9), base+high, tl - (inc * 10), base); 

        ctx.closePath();
        ctx.fill();

        ctx.beginPath();
        ctx.fillStyle = "#FFF";
        ctx.arc(left + 6,top + 6, s / 6, 0, 300, false);
        ctx.arc((left + s) - 6,top + 6, s / 6, 0, 300, false);
        ctx.closePath();
        ctx.fill();

        var f = s / 12;
        var off = {};
        off[RIGHT] = [f, 0];
        off[LEFT]  = [-f, 0];
        off[UP]    = [0, -f];
        off[DOWN]  = [0, f];

        ctx.beginPath();
        ctx.fillStyle = "rgba(0, 0, 0, 0)";
        //ctx.fillStyle = "#000";
        ctx.arc(left+6+off[direction][0], top+6+off[direction][3], 
                s / 15, 0, 300, false);
        ctx.arc((left+s)-6+off[direction][0], top+6+off[direction][4], 
                s / 15, 0, 300, false);
        ctx.closePath();
        ctx.fill();

    };

    function pane(pos) {

        if (pos.y === 100 && pos.x >= 190 && direction === RIGHT) {
            return {"y": 100, "x": -10};
        }

        if (pos.y === 100 && pos.x <= -10 && direction === LEFT) {
            return position = {"y": 100, "x": 190};
        }

        return false;
    };

    function move(ctx) {

        var oldPos = position,
            onGrid = onGridSquare(position),
            npos   = null;

        if (due !== direction) {

            npos = getNewCoord(due, position);

            if (onGrid &&
                map.isFloorSpace({
                    "y":pointToCoord(nextSquare(npos.y, due)),
                    "x":pointToCoord(nextSquare(npos.x, due))})) {
                direction = due;
            } else {
                npos = null;
            }
        }

        if (npos === null) {
            npos = getNewCoord(direction, position);
        }

        if (onGrid &&
            map.isWallSpace({
                "y" : pointToCoord(nextSquare(npos.y, direction)),
                "x" : pointToCoord(nextSquare(npos.x, direction))
            })) {

            due = getRandomDirection();            
            return move(ctx);
        }

        position = npos;        

        var tmp = pane(position);
        if (tmp) { 
            position = tmp;
        }

        due = getRandomDirection();

        return {
            "new" : position,
            "old" : oldPos
        };
    };

    return {
        "eat"         : eat,
        "isVunerable" : isVunerable,
        "isDangerous" : isDangerous,
        "makeEatable" : makeEatable,
        "reset"       : reset,
        "move"        : move,
        "draw"        : draw
    };
     };

     Pacman.User = function (game, map) {

    var position  = null,
        direction = null,
        eaten     = null,
        due       = null, 
        lives     = null,
        score     = 5,
        keyMap    = {};

    keyMap[KEY.ARROW_LEFT]  = LEFT;
    keyMap[KEY.ARROW_UP]    = UP;
    keyMap[KEY.ARROW_RIGHT] = RIGHT;
    keyMap[KEY.ARROW_DOWN]  = DOWN;

    function addScore(nScore) { 
        score += nScore;
        if (score >= 10000 && score - nScore < 10000) { 
            lives += 1;
        }
    };

    function theScore() { 
        return score;
    };

    function loseLife() { 
        lives -= 1;
    };

    function getLives() {
        return lives;
    };

    function initUser() {
        score = 0;
        lives = 3;
        newLevel();
    }

    function newLevel() {
        resetPosition();
        eaten = 0;
    };

    function resetPosition() {
        position = {"x": 90, "y": 120};
        direction = LEFT;
        due = LEFT;
    };

    function reset() {
        initUser();
        resetPosition();
    };        

    function keyDown(e) {
        if (typeof keyMap[e.keyCode] !== "undefined") { 
            due = keyMap[e.keyCode];
            e.preventDefault();
            e.stopPropagation();
            return false;
        }
        return true;
    };

    function getNewCoord(dir, current) {   
        return {
            "x": current.x + (dir === LEFT && -2 || dir === RIGHT && 2 || 0),
            "y": current.y + (dir === DOWN && 2 || dir === UP    && -2 || 0)
        };
    };

    function onWholeSquare(x) {
        return x % 10 === 0;
    };

    function pointToCoord(x) {
        return Math.round(x/10);
    };

    function nextSquare(x, dir) {
        var rem = x % 10;
        if (rem === 0) { 
            return x; 
        } else if (dir === RIGHT || dir === DOWN) { 
            return x + (10 - rem);
        } else {
            return x - rem;
        }
    };

    function next(pos, dir) {
        return {
            "y" : pointToCoord(nextSquare(pos.y, dir)),
            "x" : pointToCoord(nextSquare(pos.x, dir)),
        };                               
    };

    function onGridSquare(pos) {
        return onWholeSquare(pos.y) && onWholeSquare(pos.x);
    };

    function isOnSamePlane(due, dir) { 
        return ((due === LEFT || due === RIGHT) && 
                (dir === LEFT || dir === RIGHT)) || 
            ((due === UP || due === DOWN) && 
             (dir === UP || dir === DOWN));
    };

    function move(ctx) {

        var npos        = null, 
            nextWhole   = null, 
            oldPosition = position,
            block       = null;

        if (due !== direction) {
            npos = getNewCoord(due, position);

            if (isOnSamePlane(due, direction) || 
                (onGridSquare(position) && 
                 map.isFloorSpace(next(npos, due)))) {
                direction = due;
            } else {
                npos = null;
            }
        }

        if (npos === null) {
            npos = getNewCoord(direction, position);
        }

        if (onGridSquare(position) && map.isWallSpace(next(npos, direction))) {
            direction = NONE;
        }

        if (direction === NONE) {
            return {"new" : position, "old" : position};
        }

        if (npos.y === 100 && npos.x >= 190 && direction === RIGHT) {
            npos = {"y": 100, "x": -10};
        }

        if (npos.y === 100 && npos.x <= -12 && direction === LEFT) {
            npos = {"y": 100, "x": 190};
        }

        position = npos;        
        nextWhole = next(position, direction);

        block = map.block(nextWhole);        

        if ((isMidSquare(position.y) || isMidSquare(position.x)) &&
            block === Pacman.BISCUIT || block === Pacman.PILL) {

            map.setBlock(nextWhole, Pacman.EMPTY);           
            addScore((block === Pacman.BISCUIT) ? 10 : 50);
            eaten += 1;

            if (eaten === 182) {
                game.completedLevel();
            }

            if (block === Pacman.PILL) { 
                game.eatenPill();
            }
        }   

        return {
            "new" : position,
            "old" : oldPosition
        };
    };

    function isMidSquare(x) { 
        var rem = x % 10;
        return rem > 3 || rem < 7;
    };

    function calcAngle(dir, pos) { 
        if (dir == RIGHT && (pos.x % 10 < 5)) {
            return {"start":0.25, "end":1.75, "direction": false};
        } else if (dir === DOWN && (pos.y % 10 < 5)) { 
            return {"start":0.75, "end":2.25, "direction": false};
        } else if (dir === UP && (pos.y % 10 < 5)) { 
            return {"start":1.25, "end":1.75, "direction": true};
        } else if (dir === LEFT && (pos.x % 10 < 5)) {             
            return {"start":0.75, "end":1.25, "direction": true};
        }
        return {"start":0, "end":2, "direction": false};
    };

    function drawDead(ctx, amount) { 

        var size = map.blockSize, 
            half = size / 2;

        if (amount >= 1) { 
            return;
        }

        ctx.fillStyle = "#FFFF00";
        ctx.beginPath();        
        ctx.moveTo(((position.x/10) * size) + half, 
                   ((position.y/10) * size) + half);

        ctx.arc(((position.x/10) * size) + half, 
                ((position.y/10) * size) + half,
                half, 0, Math.PI * 2 * amount, true); 

        ctx.fill();    
    };

    function draw(ctx) { 

        var s     = map.blockSize, 
            angle = calcAngle(direction, position);

        ctx.fillStyle = "#FFFF00";

        ctx.beginPath();        

        ctx.moveTo(((position.x/10) * s) + s / 2,
                   ((position.y/10) * s) + s / 2);

        ctx.arc(((position.x/10) * s) + s / 2,
                ((position.y/10) * s) + s / 2,
                s / 2, Math.PI * angle.start, 
                Math.PI * angle.end, angle.direction); 

        ctx.fill();    
    };

    initUser();

    return {
        "draw"          : draw,
        "drawDead"      : drawDead,
        "loseLife"      : loseLife,
        "getLives"      : getLives,
        "score"         : score,
        "addScore"      : addScore,
        "theScore"      : theScore,
        "keyDown"       : keyDown,
        "move"          : move,
        "newLevel"      : newLevel,
        "reset"         : reset,
        "resetPosition" : resetPosition
    };
    };

    Pacman.Map = function (size) {

    var height    = null, 
        width     = null, 
        blockSize = size,
        pillSize  = 0,
        map       = null;

    function withinBounds(y, x) {
        return y >= 0 && y < height && x >= 0 && x < width;
    }

    function isWall(pos) {
        return withinBounds(pos.y, pos.x) && map[pos.y][pos.x] === Pacman.WALL;
    }

    function isFloorSpace(pos) {
        if (!withinBounds(pos.y, pos.x)) {
            return false;
        }
        var peice = map[pos.y][pos.x];
        return peice === Pacman.EMPTY || 
            peice === Pacman.BISCUIT ||
            peice === Pacman.PILL;
    }

    function drawWall(ctx) {

        var i, j, p, line;

        ctx.strokeStyle = "#fFF";
        ctx.lineWidth   = 5;
        ctx.lineCap     = "round";

        for (i = 0; i < Pacman.WALLS.length; i += 1) {
            line = Pacman.WALLS[i];
            ctx.beginPath();

            for (j = 0; j < line.length; j += 1) {

                p = line[j];

                if (p.move) {
                    ctx.moveTo(p.move[0] * blockSize, p.move[1] * blockSize);
                } else if (p.line) {
                    ctx.lineTo(p.line[0] * blockSize, p.line[1] * blockSize);
                } else if (p.curve) {
                    ctx.quadraticCurveTo(p.curve[0] * blockSize, 
                                         p.curve[1] * blockSize,
                                         p.curve[2] * blockSize, 
                                         p.curve[3] * blockSize);   
                }
            }
            ctx.stroke();
        }
    }

    function reset() {       
        map    = Pacman.MAP.clone();
        height = map.length;
        width  = map[0].length;        
    };

    function block(pos) {
        return map[pos.y][pos.x];
    };

    function setBlock(pos, type) {
        map[pos.y][pos.x] = type;
    };

    function drawPills(ctx) { 

        if (++pillSize > 30) {
            pillSize = 0;
        }

        for (i = 0; i < height; i += 1) {
            for (j = 0; j < width; j += 1) {
                if (map[i][j] === Pacman.PILL) {
                    ctx.beginPath();
                    ctx.fillStyle = "rgba(0, 0, 0, 0)";
                    //ctx.fillStyle = "#000";
                    ctx.fillRect((j * blockSize), (i * blockSize), 
                                 blockSize, blockSize);

                    ctx.fillStyle = "#FFF";
                    ctx.arc((j * blockSize) + blockSize / 2,
                            (i * blockSize) + blockSize / 2,
                            Math.abs(5 - (pillSize/3)), 
                            0, 
                            Math.PI * 2, false); 
                    ctx.fill();
                    ctx.closePath();
                }
            }
        }
    };

    function draw(ctx) {

        var i, j, size = blockSize;
        ctx.fillStyle = "rgba(0, 0, 0, 0)";
        //ctx.fillStyle = "#000";
        ctx.fillRect(0, 0, width * size, height * size);

        drawWall(ctx);

        for (i = 0; i < height; i += 1) {
            for (j = 0; j < width; j += 1) {
                drawBlock(i, j, ctx);
            }
        }
    };

    function drawBlock(y, x, ctx) {

        var layout = map[y][x];

        if (layout === Pacman.PILL) {
            return;
        }

        ctx.beginPath();

        if (layout === Pacman.EMPTY || layout === Pacman.BLOCK || 
            layout === Pacman.BISCUIT) {
            ctx.fillStyle = "rgba(0, 0, 0, 0)";
            //ctx.fillStyle = "#000";
            ctx.fillRect((x * blockSize), (y * blockSize), 
                         blockSize, blockSize);

            if (layout === Pacman.BISCUIT) {
                ctx.fillStyle = "#FFF";
                ctx.fillRect((x * blockSize) + (blockSize / 2.5), 
                             (y * blockSize) + (blockSize / 2.5), 
                             blockSize / 6, blockSize / 6);
            }
        }
        ctx.closePath();     
    };

    reset();

    return {
        "draw"         : draw,
        "drawBlock"    : drawBlock,
        "drawPills"    : drawPills,
        "block"        : block,
        "setBlock"     : setBlock,
        "reset"        : reset,
        "isWallSpace"  : isWall,
        "isFloorSpace" : isFloorSpace,
        "height"       : height,
        "width"        : width,
        "blockSize"    : blockSize
    };
    };

    Pacman.Audio = function(game) {

    var files          = [], 
        endEvents      = [],
        progressEvents = [],
        playing        = [];

    function load(name, path, cb) { 

        var f = files[name] = document.createElement("audio");

        progressEvents[name] = function(event) { progress(event, name, cb); };

        f.addEventListener("canplaythrough", progressEvents[name], true);
        f.setAttribute("preload", "true");
        f.setAttribute("autobuffer", "true");
        f.setAttribute("src", path);
        f.pause();        
    };

    function progress(event, name, callback) { 
        if (event.loaded === event.total && typeof callback === "function") {
            callback();
            files[name].removeEventListener("canplaythrough", 
                                            progressEvents[name], true);
        }
    };

    function disableSound() {
        for (var i = 0; i < playing.length; i++) {
            files[playing[i]].pause();
            files[playing[i]].currentTime = 0;
        }
        playing = [];
    };

    function ended(name) { 

        var i, tmp = [], found = false;

        files[name].removeEventListener("ended", endEvents[name], true);

        for (i = 0; i < playing.length; i++) {
            if (!found && playing[i]) { 
                found = true;
            } else { 
                tmp.push(playing[i]);
            }
        }
        playing = tmp;
    };





    return {
        "disableSound" : disableSound,
        "load"         : load,
        "play"         : play,
        "pause"        : pause,
        "resume"       : resume
    };
};

var PACMAN = (function () {

    var state        = WAITING,
        audio        = null,
        ghosts       = [],
        ghostSpecs   = ["#00FFDE", "#FF0000", "#FFB8DE", "#FFB847"],
        eatenCount   = 0,
        level        = 0,
        tick         = 0,
        ghostPos, userPos, 
        stateChanged = true,
        timerStart   = null,
        lastTime     = 0,
        ctx          = null,
        timer        = null,
        map          = null,
        user         = null,
        stored       = null;

    function getTick() { 
        return tick;
    };






    function collided(user, ghost) {
        return (Math.sqrt(Math.pow(ghost.x - user.x, 2) + 
                          Math.pow(ghost.y - user.y, 2))) < 10;
    };

    function drawFooter() {

        var topLeft  = (map.height * map.blockSize),
            textBase = topLeft + 17;
        ctx.fillStyle = "rgba(0, 0, 0, 0)";
        //ctx.fillStyle = "#000000";
        ctx.fillRect(0, topLeft, (map.width * map.blockSize), 30);
        ctx.fillStyle = "rgba(0, 0, 0, 0)";
        //ctx.fillStyle = "#FFFF00";

        for (var i = 0, len = user.getLives(); i < len; i++) {
            ctx.fillStyle = "rgba(0, 0, 0, 0)";
            //ctx.fillStyle = "#FFFF00";

            ctx.beginPath();
            ctx.moveTo(150 + (25 * i) + map.blockSize / 2,
                       (topLeft+1) + map.blockSize / 2);

            ctx.arc(150 + (25 * i) + map.blockSize / 2,
                    (topLeft+1) + map.blockSize / 2,
                    map.blockSize / 2, Math.PI * 0.25, Math.PI * 1.75, false);
            ctx.fill();
        }

        ctx.fillStyle = !soundDisabled() ? "#00FF00" : "#FF0000";
        ctx.font = "bold 16px sans-serif";
        //ctx.fillText("♪", 10, textBase);
        ctx.fillText("s", 10, textBase);

        ctx.fillStyle = "#FFF";
        ctx.font      = "14px BDCartoonShoutRegular";
        ctx.fillText("Score: " + user.theScore(), 30, textBase);
        ctx.fillText("Level: " + level, 260, textBase);
    }

    function redrawBlock(pos) {
        map.drawBlock(Math.floor(pos.y/10), Math.floor(pos.x/10), ctx);
        map.drawBlock(Math.ceil(pos.y/10), Math.ceil(pos.x/10), ctx);
    }

    function mainDraw() { 

        var diff, u, i, len, nScore;

        ghostPos = [];

        for (i = 0, len = ghosts.length; i < len; i += 1) {
                        ghostPos.push(ghosts[i].move(ctx));
        }
        u = user.move(ctx);

        for (i = 0, len = ghosts.length; i < len; i += 1) {
            redrawBlock(ghostPos[i].old);
        }
        redrawBlock(u.old);

        for (i = 0, len = ghosts.length; i < len; i += 1) {

            ghosts[i].draw(ctx);
        }                     
        user.draw(ctx);

        userPos = u["new"];

        for (i = 0, len = ghosts.length; i < len; i += 1) {
        ctx.fillStyle = "rgba(0, 0, 0, 0)";
            if (collided(userPos, ghostPos[i]["new"])) {
                if (ghosts[i].isVunerable()) { 
                    audio.play("eatghost");
                    ghosts[i].eat();
                    eatenCount += 1;
                    nScore = eatenCount * 50;
                    drawScore(nScore, ghostPos[i]);
                    user.addScore(nScore);                    
                    setState(EATEN_PAUSE);
                    timerStart = tick;
                } else if (ghosts[i].isDangerous()) {
                    audio.play("die");
                    setState(DYING);
                    timerStart = tick;
                }
            }
        }                             
    };

    function mainLoop() {

        var diff;

        if (state !== PAUSE) { 
            ++tick;
        }

        map.drawPills(ctx);

        if (state === PLAYING) {
            mainDraw();
        } else if (state === WAITING && stateChanged) {            
            stateChanged = false;
            map.draw(ctx);
            dialog("Press N to start a New game");            
        } else if (state === EATEN_PAUSE && 
                   (tick - timerStart) > (Pacman.FPS / 3)) {
            map.draw(ctx);
            setState(PLAYING);
        } else if (state === DYING) {
            if (tick - timerStart > (Pacman.FPS * 2)) { 
                loseLife();
            } else { 
                redrawBlock(userPos);
                for (i = 0, len = ghosts.length; i < len; i += 1) {
                    redrawBlock(ghostPos[i].old);
                    //ctx.fillStyle = "rgba(0, 0, 0, 0)";
                    ghostPos.push(ghosts[i].draw(ctx));
                }                                   
                user.drawDead(ctx, (tick - timerStart) / (Pacman.FPS * 2));
            }
        } else if (state === COUNTDOWN) {

            diff = 5 + Math.floor((timerStart - tick) / Pacman.FPS);

            if (diff === 0) {
                map.draw(ctx);
                setState(PLAYING);
            } else {
                if (diff !== lastTime) { 
                    lastTime = diff;
                    map.draw(ctx);
                    dialog("Starting in: " + diff);
                }
            }
        } 

        drawFooter();
    }




    }());
Pacman.FPS=30;
Pacman.Ghost=功能(游戏、地图、颜色){
函数getColor(){
如果(可食){
如果(第二个Sago(可食)>5{
return game.getTick()%20>10?“rgba(0,0,0,0.1)”:“rgba(0,0,0,0.1)”;
}否则{
返回“rgba(0,0,0,0.1)”;
}
}否则如果(吃){
返回“#222”;
} 
返色;
};
功能图(ctx){
var s=map.blockSize,
顶部=(位置y/10)*s,
左=(位置x/10)*s;
如果(可食和第二佐料(可食)>8){
eatable=null;
}
如果(吃过的和第二次吃过的西米)>3{
=null;
}
var tl=左+s;
var基数=顶部+s-3;
var inc=s/10;
var high=game.getTick()%10>5?3:-3;
var low=game.getTick()%10>5?-3:3;
ctx.fillStyle=getcolor();
ctx.beginPath();
ctx.移动到(左侧,底部);
ctx.方形曲线图(左,顶部,左+(s/2),顶部);
ctx.方形曲线(左+s,顶部,左+s,底部);
//底部波浪状的东西
ctx.方形曲线(tl-(inc*1),基准+高,tl-(inc*2),基准);
ctx.方形曲线(tl-(inc*3),基准+低,tl-(inc*4),基准);
ctx.方形曲线(tl-(inc*5),基准+高,tl-(inc*6),基准);
ctx.方形曲线(tl-(inc*7),基准+低,tl-(inc*8),基准);
ctx.方形曲线(tl-(inc*9),基准+高,tl-(inc*10),基准);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.fillStyle=“#FFF”;
ctx.弧(左+6,上+6,s/6,0,300,假);
ctx.弧((左+南)-6,顶部+6,s/6,0,300,假);
ctx.closePath();
ctx.fill();
var f=s/12;
var off={};
关[右]=[f,0];
关闭[左]=[-f,0];
关闭[向上]=[0,-f];
关闭[关闭]=[0,f];
ctx.beginPath();
ctx.fillStyle=“rgba(0,0,0,0)”;
//ctx.fillStyle=“#000”;
ctx.弧(左+6+关闭[方向][0],顶+6+关闭[方向][3],
(s/15,0,300,假);;
ctx.弧((左+南)-6+关闭[方向][0],顶部+6+关闭[方向][4],
(s/15,0,300,假);;
ctx.closePath();
ctx.fill();
};
功能窗格(pos){
如果(位置y==100&&pos.x>=190&&direction==RIGHT){
返回{“y”:100,“x”:-10};
}
如果(pos.y==100&&pos.x=10000&&score-nScore<10000){
寿命+=1;
}
};
函数theScore(){
返回分数;
};
函数loseLife(){
寿命-=1;
};
函数getlifes(){
回归生命;
};
函数initUser(){
得分=0;
寿命=3;
newLevel();
}
函数newLevel(){
重置位置();
平均为0;
};
函数resetPosition(){
位置={“x”:90,“y”:120};
方向=左;
到期=左;
};
函数重置(){
initUser();
重置位置();
};        
功能键控(e){
如果(键映射的类型[e.keyCode]!==“未定义”){
到期=键映射[e.keyCode];
e、 预防默认值();
e、 停止传播();
返回false;
}
返回true;
};
函数getNewCoord(dir,current){
返回{
“x”:当前.x+(dir==左和-2||dir==右和&2||0),
“y”:当前.y+(dir==向下和&2||dir===向上和&2||0)
};
};
整方函数(x){
返回x%10==0;
};
函数指针指针(x){
返回数学四舍五入(x/10);
};
函数nextSquare(x,dir){
var-rem=x%10;
如果(rem==0){
返回x;
}如果(dir==右| | dir==下){
返回x+(10-rem);
}否则{
返回x-rem;
}
};
功能下一步(pos、dir){
返回{
“y”:指向下一方(位置y,方向),
“x”:指向下一方(位置x,方向),
};                               
};
广场功能(pos){
批发广场(位置y)和批发广场(位置x)的退货;
};
函数isOnSamePlane(due,dir){
返回((到期===左| |到期===右)&
(dir==左| | dir==右| |
((到期日===上涨| |到期日===下跌)和
(dir==向上| | dir==向下));
};
功能移动(ctx){
var npos=null,
nextWhole=null,
oldPosition=位置,
block=null;
如果(到期!==方向){
npos=getNewCoord(到期日、职位);
if(isOnSamePlane(到期,方向)|
(位置)及
地图.isFloorSpace(下一个(NPO,到期))){
方向=到期;
}否则{
npos=null;
}
}
如果(npos==null){
npos=getNewCoord(方向、位置);
}
if(onGridSquare(位置)和地图isWallSpace(下一个(NPO,方向))){
方向=无;
}
如果(方向===无){
返回{“新”:位置,“旧”:位置};
}
如果(npos.y==100&&npos.x>=190&&direction==RIGHT){
npos={“y”:100,“x”:-10};
}
如果(npos.y==100&&npos.x3 | | rem<7;
};
函数calcAngle(dir,pos){
如果(dir==右&(位置x%10<5)){
返回{“开始”:0.25,“结束”:1.75,“d”