JavaScript游戏无法正常工作,初始化后冻结

时间:2013-10-24 20:24:43

标签: javascript oop game-engine

我有以下问题:我试图在JavaScript中制作一个简单的游戏。游戏的想法是有一个画布,一个球在里面弹跳,小垫从左到右击球。我这样做了,它工作正常:

var canvasBg;
var contextBg;

var canvasBall;
var contextBall;


function Drawable() {

    this.initialize = function(x,y) {
        this.x = x;
        this.y = y;
    };

    this.draw = function() {

    };
}

function Ball() {

    var dx = 2;
    var dy = 2;

    var radius = 5;

    this.draw = function() {

        contextBall.beginPath();
        contextBall.clearRect(0,0,canvasBall.width,canvasBall.height);
        contextBall.closePath();

        contextBall.beginPath();
        contextBall.fillStyle = "#0000ff";
        contextBall.arc(this.x, this.y, radius, 0, Math.PI*2, true);
        contextBall.closePath();
        contextBall.fill();

        // the code seems to stop here
        if(this.x<0 || this.x>300)
            dx = -dx;
        if(this.y<0 || this.y>150)
            dy = -dy;

        if((this.x+radius)>pad.x && (this.x-radius)<(pad.x+50) && (this.y+radius)>pad.y && (this.y-radius)<(pad.y+10)) {
            dy = -dy;
        } 

        if(this.y>(pad.y-2) && this.y<(pad.y+12) && (this.x+radius)>pad.x && (this.x-radius)<(pad.x+50)) {
            dx = -dx;
        }

        this.x += dx;
        this.y += dy;
    };

}

Ball.prototype = new Drawable();

KEY_CODES = {

    37: 'left',
    39: 'right',
};

KEY_STATUS = {};

for (code in KEY_CODES) {

    KEY_STATUS[ KEY_CODES[ code ]] = false;
}

document.onkeydown = function(e) {
    var keyCode = (e.keyCode) ? e.keyCode : e.charCode;
    if (KEY_CODES[keyCode]) {
        e.preventDefault();
        KEY_STATUS[KEY_CODES[keyCode]] = true;
    }
};

document.onkeyup = function(e) {
    var keyCode = (e.keyCode) ? e.keyCode : e.charCode;
        if (KEY_CODES[keyCode]) {
        e.preventDefault();
        KEY_STATUS[KEY_CODES[keyCode]] = false;
    }
};

function Pad() {

    var hSpeed = 5;
    this.padWidth = 50;
    this.padHeight = 10;

    this.draw = function() {

        contextBg.clearRect(0,0,canvasBg.width,canvasBg.height);
        contextBg.fillStyle = "#ffffff";
        contextBg.fillRect(this.x,this.y,this.padWidth,this.padHeight);

    };

    this.move = function() {
        if(KEY_STATUS.left || KEY_STATUS.right) {
            contextBg.clearRect(0,0,canvasBg.width,canvasBg.height);

            if(KEY_STATUS.left) {
                this.x -= hSpeed;
            if (this.x <= 0)
                this.x = 0;
            } else if (KEY_STATUS.right) {
                this.x += hSpeed;
            if (this.x >= 300-this.padWidth)
                this.x = 300 - this.padWidth;
            }
            this.draw();
        }
    };
}

Pad.prototype = new Drawable();


function init() {

        canvasBg = document.getElementById('display');
        contextBg = this.canvasBg.getContext('2d');

        canvasBall = document.getElementById('ball');
        contextBall = this.canvasBall.getContext('2d');

        ball = new Ball();
        ball.initialize(10,10);

        pad = new Pad();
        pad.initialize(120,80);

        setInterval(function(){animate();},30);

}

function animate() {
        ball.draw();
        pad.draw();
        pad.move();
};

但是,我决定尝试改进我的代码,然后我制作了一个类GamePlay:

var game = new GamePlay();

function Drawable() {

    this.initialize = function(x,y) {
        this.x = x;
        this.y = y;
    };

    this.draw = function() {

    };
}

function Ball() {

    var dx = 2;
    var dy = 2;

    var radius = 5;

    this.draw = function() {

        this.context.beginPath();
        this.context.clearRect(0,0,this.canvas.width,this.canvas.height);
        this.context.closePath();

        this.context.beginPath();
        this.context.fillStyle = "#0000ff";
        this.context.arc(this.x, this.y, radius, 0, Math.PI*2, true);
        this.context.closePath();
        this.context.fill();



        if(this.x<0 || this.x>300)
            dx = -dx;
        if(this.y<0 || this.y>150)
            dy = -dy;

        if((this.x+radius)>pad.x && (this.x-radius)<(pad.x+50) && (this.y+radius)>pad.y && (this.y-radius)<(pad.y+10)) {
            dy = -dy;
        } 

        if(this.y>(pad.y-2) && this.y<(pad.y+12) && (this.x+radius)>pad.x && (this.x-radius)<(pad.x+50)) {
            dx = -dx;
        }


        this.x += dx;
        this.y += dy;
    };

}

Ball.prototype = new Drawable();

KEY_CODES = {

    37: 'left',
    39: 'right',
};

KEY_STATUS = {};

for (code in KEY_CODES) {

    KEY_STATUS[ KEY_CODES[ code ]] = false;
}

document.onkeydown = function(e) {
    var keyCode = (e.keyCode) ? e.keyCode : e.charCode;
    if (KEY_CODES[keyCode]) {
        e.preventDefault();
        KEY_STATUS[KEY_CODES[keyCode]] = true;
    }
};

document.onkeyup = function(e) {
    var keyCode = (e.keyCode) ? e.keyCode : e.charCode;
        if (KEY_CODES[keyCode]) {
        e.preventDefault();
        KEY_STATUS[KEY_CODES[keyCode]] = false;
    }
};

function Pad() {

    var hSpeed = 5;
    this.padWidth = 50;
    this.padHeight = 10;

    this.draw = function() {

        this.context.clearRect(0,0,this.canvas.width,this.canvas.height);
        this.context.fillStyle = "#ffffff";
        this.context.fillRect(this.x,this.y,this.padWidth,this.padHeight);

    };

    this.move = function() {
        if(KEY_STATUS.left || KEY_STATUS.right) {
            this.context.clearRect(0,0,this.canvas.width,this.canvas.height);

            if(KEY_STATUS.left) {
                this.x -= hSpeed;
            if (this.x <= 0)
                this.x = 0;
            } else if (KEY_STATUS.right) {
                this.x += hSpeed;
            if (this.x >= 300-this.padWidth)
                this.x = 300 - this.padWidth;
            }
            this.draw();
        }
    };
}

Pad.prototype = new Drawable();

function GamePlay() {

    var ball;
    var pad;

    this.setUpGame = function() {

        this.canvasBg = document.getElementById('display');
        this.contextBg = this.canvasBg.getContext('2d');

        this.canvasBall = document.getElementById('ball');
        this.contextBall = this.canvasBall.getContext('2d');

        Ball.prototype.canvas = this.canvasBall;
        Ball.prototype.context = this.contextBall;

        Pad.prototype.canvas = this.canvasBg;
        Pad.prototype.context = this.contextBg;

        ball = new Ball();
        ball.initialize(10,10);

        pad = new Pad();
        pad.initialize(120,80);

    };


    var animate = function() {
        ball.draw();
        pad.draw();
        pad.move();
    };

    this.startGame = function() {
        setInterval(function(){animate();},30);
    };

}

function init() {
    game.setUpGame();
    game.startGame();
}

但是,它只在其初始化坐标上绘制一个球,然后似乎停在那里。我尝试通过在代码中的某些点上放置alert()进行一些手动测试,我发现它似乎停止在ball的draw方法中间并且跳过在动画中调用pad.draw()和pad.move()( )。我不知道出了什么问题,我的猜测就是原型。我是JavaScript新手,这个基于原型的OOP对我来说仍然有点混乱。感谢。

2 个答案:

答案 0 :(得分:1)

我尝试了代码并发现了下一个问题:

  1. function init - 希望在html完全加载后调用它
  2. Ball.draw函数引用对象pad,在其上下文中未定义,使用game.pad
  3. var animate = function创建本地“私有”变量,将其更改为this.animate = function
  4. setInterval中的
  5. 调用适当的函数setInterval(function(){game.animate();},30);
  6. 在定义var game = new GamePlay();之前调用
  7. GamePlay,将此字符串移到
  8. 下面

    在这些更改后,它在控制台中无错误地工作

答案 1 :(得分:0)

我相信这是因为您在绘制方法中错过了路径。

首先,您不需要使用.clearRect.beginPath包裹.closePath

其次,可能导致您的脚本出错的原因是您在绘制圆圈后.fill之后使用.closePath.fill应该在.closePath之前使用,实际上在使用.fill之后,您不需要使用.closePath,因为它已经为您关闭了路径。