这个奇怪的画架行为是什么?

时间:2014-05-04 21:09:19

标签: javascript canvas easeljs createjs html4

我对javascript和easelJS / createJS很新,但我认为我理解它们足以完成简单的任务。我开始尝试画布,并且卡在一个地方。

这个小项目使用canvas和easelJS来渲染带有2个引擎的简单穿梭,以及简单的物理移动它。 (伪)物理工作正常:对于两个引擎,都会采取单独的操作,但渲染失败。每当我打开引擎(按键' q'或者' w')两个引擎的火灾都会出现。

我试图找到这个代码的最简单的子集来重现那个问题,但是我失败了,所以我提供了这个简单项目的完整代码。

<!DOCTYPE HTML>
<html>
<head>
<title></title>

<style>
    /*#myCanvas{
        width: 1200px;
        height: 600px;
    }*/
</style>

<script src="createjs-2013.12.12.min.js"></script>
<script>


/* Keyboard */
var Key = {
    _pressed: {},

    /*LEFT: 37,
    UP: 38,
    RIGHT: 39,
    DOWN: 40,*/
    Q: 81, W: 87, E: 69, R:82, T:84, Y: 89,


    isDown: function(keyCode) {
        return this._pressed[keyCode];
    },

    onKeydown: function(event) {
        this._pressed[event.keyCode] = true;
    },

    onKeyup: function(event) {
        delete this._pressed[event.keyCode];
    },

    getThrottles: function () {
        var resObj = {};
        for(var code in this._pressed){
            resObj[String.fromCharCode(code)] = 1;
        }
        return resObj;
    }
};

/* Vector2 */
function Vector2 (x, y, dx, dy){
    this.x = x ? x : 0;
    this.y = y ? y : 0;
    this.dx = dx ? dx : 0;
    this.dy = dy ? dy : 0;
}

/* Physics */
var Physics = {
    objects: [],

    update: function(){
        for(ind in this.objects){
            var obj = this.objects[ind];

            for(ind2 in obj.forces){
                var f = obj.forces[ind2];


                // velocities calculations
                if(f.x == obj.x && f.y == obj.y){
                    obj.velocity.dx += f.dx/obj.mass;
                    obj.velocity.dy += f.dy/obj.mass;
                }
                else{
                    var len = Math.sqrt((f.x-obj.x)*(f.x-obj.x) + (f.y-obj.y)*(f.y-obj.y));
                    var fpar = new Vector2(0, 0, (obj.x-f.x)/len, (obj.y-f.y)/len);
                    var fper = new Vector2(0, 0, (obj.y-f.y)/len, -(obj.x-f.x)/len);
                    var factorpar = f.dx*fpar.dx + f.dy*fpar.dy;
                    var factorper = f.dx*fper.dx + f.dy*fper.dy;

                    obj.velocity.dx += f.dx/obj.mass;
                    obj.velocity.dy += f.dy/obj.mass;

                    // TODO: here radius should be considered in equation
                    obj.avelocity += factorper/obj.imoment;

                }


            }

            obj.forces.length = 0;

            // rotations and translations
            obj.x += obj.velocity.dx;
            obj.y += obj.velocity.dy;
            obj.rotation += obj.avelocity;

            // dumping
            var dumping = 0.95;
            var adumping = 0.95;
            var minvel = 0.0001;
            var minavel = 0.0001;

            obj.velocity.dx = dumping * obj.velocity.dx;
            obj.velocity.dy = dumping * obj.velocity.dy;
            obj.avelocity = adumping * obj.avelocity;

        }

    }

};



var myStage;

createjs.DisplayObject.prototype.mass =0.5;
createjs.DisplayObject.prototype.imoment = 0.1;
createjs.DisplayObject.prototype.forces = [];
createjs.DisplayObject.prototype.velocity = new Vector2();
createjs.DisplayObject.prototype.avelocity = 0;

function Engine(width, height){
    var that = this;
    this.width = width;
    this.height = height;
    this.innerThrottle = 0;

    this.throttle = function(value){
        if(value!==null)
            that.innerThrottle = value;

        that.flame.graphics.clear();
        that.flame.graphics.beginFill("#ff0000").drawRoundRect(
                        -that.width*that.innerThrottle/2,
                        that.height+that.margin,
                        that.width*that.innerThrottle,
                        that.width*that.innerThrottle,
                that.margin);

        return that.innerThrottle;
    };



    //drawing
    this.margin = 0.1 * this.width;
    this.body = new createjs.Shape();
    this.body.graphics.beginFill("#999999").drawRect(-this.width/2, 0, this.width, this.height);
    this.addChild(this.body);

    this.flame = new createjs.Shape();
    this.flame.graphics.beginFill("#ff0000").drawRoundRect(
                    -this.width*this.throttle()/2,
                    this.height+this.margin,
                    this.width*this.throttle(),
                    this.width*this.throttle(),
            this.margin);
    this.addChild(this.flame);
}
Engine.prototype = new createjs.Container();

function Shuttle(radius){
    var that = this;
    this.engineNames = ['Q','W','E','R','T','Y'];
    this.engines = {};
    this.addEngine = function (x,y,rotation){
        var tmpEn = new Engine(radius/2, radius/1);
        tmpEn.x = x;
        tmpEn.y = y;
        tmpEn.rotation = rotation;
        that.addChild(tmpEn);

        that.engines[that.engineNames[Object.keys(that.engines).length]] = tmpEn;
    };

    this.steering = null;

    this.shuttleTick = function(){
        var throttles = that.steering.getThrottles();
        var engines = that.engines;

        for(var key in engines)
            engines[key].throttle(0);

        for(var key2 in throttles){
            if(engines[key2]){
                engines[key2].throttle(throttles[key2]);

                var end = engines[key2].localToGlobal(0,-0.1);
                var start = engines[key2].localToGlobal(0,0);

                that.forces.push(new Vector2(start.x, start.y, (end.x-start.x)*throttles[key2], (end.y-start.y)*throttles[key2]));
            }
        }


    };



    // drawing
    var core = new createjs.Shape();
    core.graphics.beginFill("#000000").drawCircle(0,0,radius);
    this.addChild(core);
}
Shuttle.prototype = new createjs.Container();

var shuttle;
function init(){

    // Key object initialization
    window.addEventListener('keyup', function(event) { Key.onKeyup(event); }, false);
    window.addEventListener('keydown', function(event) { Key.onKeydown(event); }, false);


    myStage = new createjs.Stage("myCanvas");

    //var engine = new Engine(200,300);
    var r = 10;
    shuttle = new Shuttle(r);
    shuttle.steering = Key;
    shuttle.addEngine(-r,0,0);
    shuttle.addEngine(r,0,0);
    shuttle.x = 500;
    shuttle.y = 200;
    //shuttle.velocity.dx = 1;
    //shuttle.avelocity = 1;

    myStage.addChild(shuttle);

    Physics.objects = [shuttle];

    createjs.Ticker.setFPS(60);
    createjs.Ticker.addEventListener('tick', tick);

}

function tick(){
    shuttle.shuttleTick();
    Physics.update();
    myStage.update();
}
</script>


</head>
<body onload="init()">
<canvas id="myCanvas" width="1200" height="600">

</canvas>
</body>
</html>

1 个答案:

答案 0 :(得分:0)

您的具体问题是您正在扩展Container类,但在创建Engine实例时不会对其进行初始化。如果您将其插入Engine(width, height)函数的顶部,它应该可以工作:

this.initialize();

更一般地说,您应该研究Javascript的原型继承是如何工作的 - 您的代码很难阅读并且不必要地复杂化。

在JS中实现“经典”OOP继承模式有很多不同的方法,但是由于你正在使用CreateJS,在你的情况下最有用的方法可能是首先学习他们的方法,调整你的类遵循相同的模式,从那里开始工作 - 见例如this question