CreateJS / EaselJS

The Easel Javascript library provides a full, hierarchical display list, a core interaction model, and helper classes to make working with the HTML5 Canvas element much easier.
http://createjs.com/
MIT License
8.12k stars 1.97k forks source link

Select mouse events not firing #214

Closed dnldd closed 11 years ago

dnldd commented 11 years ago

Hi, I've noticed select mouse events do not trigger - onClick, onPress, drag/drop. OnDoubleClick works however. I'm running my example on a local server and using easeljs-0.5.0.min.js. This is what I'm doing:

.js file

var b2Vec2 = Box2D.Common.Math.b2Vec2;
var b2DebugDraw = Box2D.Dynamics.b2DebugDraw;
var b2BodyDef = Box2D.Dynamics.b2BodyDef;
var b2Body = Box2D.Dynamics.b2Body;
var b2FixtureDef = Box2D.Dynamics.b2FixtureDef;
var b2Fixture = Box2D.Dynamics.b2Fixture;
var b2World = Box2D.Dynamics.b2World;
var b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape;
var b2CircleShape = Box2D.Collision.Shapes.b2CircleShape;
var b2DebugDraw = Box2D.Dynamics.b2DebugDraw;
var b2AABB = Box2D.Collision.b2AABB;
var b2ContactListener = Box2D.Dynamics.b2ContactListener;

window.onblur = function(){ Ticker.setPaused(true); PAUSED = true; console.log("paused"); }
window.onfocus = function(){ Ticker.setPaused(false); PAUSED = false; console.log("unpaused"); }

var PAUSED = false;

var Type = {
    WALL : 1,
    BOULDER : 2
};

var CategoryBits = {
    WALL : 0x0001,
    BOULDER : 0x0002
};

function Boundary(density, restitution, friction, angularDamping, linearDamping, position, size, scale, categoryBits, maskBits, type, world){
    var boundaryFixture = new b2FixtureDef;
    boundaryFixture.density = density;
    boundaryFixture.restitution = restitution;
    boundaryFixture.friction = friction;
    boundaryFixture.filter.categoryBits = categoryBits;
    boundaryFixture.filter.maskBits = maskBits;
    boundaryFixture.shape = new b2PolygonShape;
    boundaryFixture.shape.SetAsBox(size.length/scale, size.height/scale);
    var boundaryBodyDef = new b2BodyDef;
    boundaryBodyDef.type = b2Body.b2_staticBody;
    boundaryBodyDef.angularDamping =  angularDamping;
    boundaryBodyDef.linearDamping = linearDamping;
    boundaryBodyDef.position.x = position.x/ scale; 
    boundaryBodyDef.position.y = position.y/scale; 
    this.boundary = world.CreateBody(boundaryBodyDef);
    this.boundary.CreateFixture(boundaryFixture);
    this.boundary.SetUserData(this);
    this.type = type;
};

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

function Size(length, height){
    this.length = length;
    this.height = height;
};

function Noir(size, scale, step, debug){
    this.GRAVITY = new b2Vec2(0, 10/(scale/5));
    this.FPS = 30;
    this.SCALE = scale; 
    this.STEP = step;
    this.TIMESTEP = 1/this.STEP;
    this.DEBUG = debug;
    this.LENGTH = size.length;
    this.LENGTH_OFFSET = 20;
    this.HEIGHT = size.height;
    this.HEIGHT_OFFSET = 10;
    this.BOUNDARY_WIDTH = 2;
    this.VELOCITY_ITERATIONS = 10;
    this.POSITION_ITERATIONS = 10;

    this.world;
    this.contactListener;
    this.canvas;
    this.debugCanvas;
    this.debugDraw;
    this.context;
    this.debugContext;
    this.stage;
    this.previousTime = Date.now();
    this.game;
};

Noir.prototype.initCanvas = function(){
    this.canvas = document.getElementById('canvas');
    this.context = canvas.getContext('2d');
    this.stage = new Stage(canvas);
    this.stage.snapPixelsEnabled = true;
    this.stage.mouseEventsEnabled = true;
    //this.stage.onDoubleClick = function(event){ console.log("moving.."); }

    this.stage.enableMouseOver();
    if(this.DEBUG){
        this.debugCanvas = document.getElementById('debugCanvas');
        this.debugContext = debugCanvas.getContext('2d');
        console.log('Debug on');
    } 
};

Noir.prototype.initDebug = function(){
    this.debugDraw = new b2DebugDraw();
    this.debugDraw.SetSprite(this.debugContext);
    this.debugDraw.SetDrawScale(this.SCALE);
    this.debugDraw.SetFillAlpha(0.7);
    this.debugDraw.SetLineThickness(1.0);
    this.debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
    this.world.SetDebugDraw(this.debugDraw);
};

Noir.prototype.setContactListener = function(){
    this.contactListener = new b2ContactListener;
    this.contactListener.events = this;
    this.contactListener.BeginContact = function(contact, manifold){
        var bodyAUser = contact.GetFixtureA().GetBody().GetUserData();
        var bodyBUser = contact.GetFixtureB().GetBody().GetUserData();
        /* console.log(bodyAUser.type + " , " + bodyBUser.type); */
        if((bodyAUser.type == Type.BOULDER) && (bodyBUser.type == Type.WALL)){ this.events.boulderWallContact(bodyAUser, bodyBUser); }
        else if((bodyAUser.type == Type.WALL) && (bodyBUser.type == Type.BOULDER)){ this.events.boulderWallContact(bodyBUser, bodyAUser); }
    }
    this.world.SetContactListener(this.contactListener);
};

Noir.prototype.boulderWallContact = function(boulder, wall){ boulder.flagToDestroy(); };

Noir.prototype.initPhysics = function(){
    this.lastTimestamp = Date.now();
    this.world = new b2World(this.GRAVITY, true);
    this.setContactListener();
    if(this.DEBUG){ this.initDebug(); console.log('Debug initialized'); } 
    var floor = new Boundary(1, 1, 0.6, 0.6, 0.6, new Position(-(this.LENGTH_OFFSET/2), (this.HEIGHT+ (this.HEIGHT_OFFSET - (this.HEIGHT_OFFSET - 1)))), 
            new Size((this.LENGTH + this.LENGTH_OFFSET), this.BOUNDARY_WIDTH), this.SCALE, CategoryBits.WALL, CategoryBits.BOULDER, Type.WALL, this.world);
    /* var ceiling = new Boundary(1, 1, 0.6, 0.6, 0.6, new Position(-(this.LENGTH_OFFSET/2), (this.HEIGHT_OFFSET - (this.HEIGHT_OFFSET - 1))), 
            new Size((this.LENGTH + this.LENGTH_OFFSET), this.BOUNDARY_WIDTH), this.SCALE, CategoryBits.WALL, CategoryBits.BOULDER, Type.WALL, this.world); */
    var leftFixture = new Boundary(1,1, 0.6, 0.6, 0.6, new Position(-(this.BOUNDARY_WIDTH - (this.BOUNDARY_WIDTH - 1)), -(this.LENGTH_OFFSET/2)),
        new Size(this.BOUNDARY_WIDTH, (this.HEIGHT + this.HEIGHT_OFFSET)), this. SCALE, CategoryBits.WALL, CategoryBits.BOULDER, Type.WALL, this.world);
    var rightFixture = new Boundary(1,1, 0.6, 0.6, 0.6, new Position((this.LENGTH + (this.LENGTH_OFFSET - (this.LENGTH_OFFSET - 1))),  -(this.LENGTH_OFFSET/2)),
        new Size(this.BOUNDARY_WIDTH,  (this.HEIGHT+ this.HEIGHT_OFFSET)), this.SCALE, CategoryBits.WALL, CategoryBits.BOULDER, Type.WALL, this.world);
};

Noir.prototype.tick = function(){
    this.updatePhysics();
    this.stage.update();
};

Noir.prototype.initTicker = function(){
    Ticker.setFPS(this.FPS);
    Ticker.useRAF = true;
    Ticker.addListener(this, true);
};

Noir.prototype.init = function(){
    this.initCanvas();
    this.initTicker();
    this.initPhysics();
    this.initGame(this.stage, this.world);
    var debug = document.getElementById('debug');
};

Noir.prototype.initOnLoadDocument = function(){
    console.log('running');
    if(document.loaded){ this.init(); }
    else{
        if(window.addEventListener){ window.addEventListener('load', this.init(), false); }
        else { window.attachEvent('onLoad', this.init); }
    }
}

Noir.prototype.updatePhysics = function(){
        /* remove flagged objects for destruction */
        /* update non-flagged objects */
        if(!PAUSED){
            this.updateGame();
            this.world.Step(this.TIMESTEP, this.VELOCITY_ITERATIONS, this.POSITION_ITERATIONS);
        this.world.ClearForces();
        if(this.DEBUG){
            this.world.m_debugDraw.m_sprite.graphics.clear();
            this.world.DrawDebugData();
        }
    }
};

Noir.prototype.initGame = function(){
    this.game = new Game(this.stage, this.SCALE, this.world);
    this.game.start();
};

Noir.prototype.updateGame = function(){ this.game.update(); }

function Actor(density, restitution, friction, angularDamping, linearDamping, path, position, size, stage, scale, categoryBits, maskBits, type, world){
    this.skin = new Bitmap(path);
    this.skin.x = position.x;
    this.skin.y = position.y;
    this.skin.regX = (size.length/2);
    this.skin.regY = (size.height/2); 
    this.skin.snapToPixel = true;
    this.skin.mouseEnabled = false;
    stage.addChild(this.skin);

    var actorFixture = new b2FixtureDef;
    actorFixture.density = density;
    actorFixture.restitution = restitution;
    actorFixture.friction = friction;
    actorFixture.filter.categoryBits = categoryBits;
    actorFixture.filter.maskBits = maskBits;
    actorFixture.shape = new b2PolygonShape;
    actorFixture.shape.SetAsBox((size.length/2)/scale, (size.height/2)/scale);
    var actorBodyDef = new b2BodyDef;
    actorBodyDef.type = b2Body.b2_dynamicBody;
    actorBodyDef.angularDamping = angularDamping;
    actorBodyDef.linearDamping = linearDamping;
    actorBodyDef.position.x = this.skin.x/scale;
    actorBodyDef.position.y = this.skin.y/scale;
    this.body = world.CreateBody(actorBodyDef);
    this.body.CreateFixture(actorFixture);
    this.body.SetUserData(this);
    this.type = type;
    this.destroy = false;
};

Actor.prototype.flagToDestroy = function(){ this.destroy = true; };

Actor.prototype.remove = function(game){
    game.stage.removeChild(this.skin);
    game.world.DestroyBody(this.body);
    game.actors.splice(game.actors.indexOf(this),1);
};

Actor.prototype.update = function(scale){  
    this.skin.rotation = this.body.GetAngle() * (180/Math.PI);
    this.skin.x = this.body.GetWorldCenter().x * scale;
    this.skin.y = this.body.GetWorldCenter().y * scale;
};

function Icon(path, position, size, stage){
    this.skin = new Bitmap(path);
    this.skin.x = position.x;
    this.skin.y = position.y;
    this.skin.regX = (size.length/2);
    this.skin.regY = (size.height/2); 
    stage.addChild(this.skin);
    //this.skin.onDoubleClick = function(event){ alert("click click"); }
    this.skin.onClick = function(event){ alert("click"); }
    this.skin.onPress = function(event){ console.log("pressing"); }
};

function Game(stage, scale, world){ 
    this.scale = scale;
    this.stage = stage;
    this.world = world;
    this.boulderSpawnDelayCounter = 0;
    this.actors = [];
    this.icon;
};

Game.prototype.start = function(){
    var  position = new Position(400, 200);
    var size = new Size(50, 50);
    console.log(this);
    this.icon = new Icon("images/bird.png", position, size, this.stage);
};

Game.prototype.controlledSpawn = function(stage, scale, world){
    var spawnInterval = (50 + Math.round(Math.random() * 10));
    this.boulderSpawnDelayCounter++;
    if(this.boulderSpawnDelayCounter % spawnInterval === 0){  
        this.boulderSpawnDelayCounter = 0;
        this.boulderSpawn();
    }
};

Game.prototype.boulderSpawn = function(stage, scale, world){
    var  position = new Position((100 + Math.round(Math.random() * 250)), -20);
    var size = new Size(50, 50);
    this.actors.push(new Actor(0.2, 0.6, 0.3, 0.3, 0.3, "images/bird.png", position, size, this.stage, this.scale, CategoryBits.BOULDER, CategoryBits.WALL, Type.BOULDER, this.world));
};

Game.prototype.update = function(){ 
    this.controlledSpawn();
    for(idx = 0; idx < this.actors.length; ++idx){
     if(this.actors[idx].destroy == true){ this.actors[idx].remove(this); }}
    for(idx = 0; idx < this.actors.length; ++idx){ this.actors[idx].update(this.scale); }
};

.html file

<!doctype html>
    <html xmlns:og="http://ogp.me/ns#">
        <head>
            <meta charset="utf-8">
            <title>Noir test</title>
            <link href="css/style.css" rel="stylesheet" type="text/css" />
        </head>
        <body>
            <canvas width="500" height="500" id="canvas"></canvas>
            <canvas width="500" height="500" id="debugCanvas"></canvas>
            <script> var createjs = window </script>
            <script type="text/javascript" src="libs/easeljs-0.5.0.min.js"></script>
            <script type="text/javascript" src="libs/Box2dWeb-2.1.a.3.min.js"></script>
            <script type="text/javascript" src="js/noir.js"></script>
            <script> var noir = new Noir(new Size(500, 500), 30, 20, false);  noir.initOnLoadDocument()</script>
        </body>
    </html>

Thanks.

gskinner commented 11 years ago

Can you isolate what isn't working as expected? Thanks!

dnldd commented 11 years ago

This is what isn't working correctly:

function Icon(path, position, size, stage){
    this.skin = new Bitmap(path);
    this.skin.x = position.x;
    this.skin.y = position.y;
    this.skin.regX = (size.length/2);
    this.skin.regY = (size.height/2); 
    stage.addChild(this.skin);
    //this.skin.onDoubleClick = function(event){ alert("click click"); }
    this.skin.onClick = function(event){ alert("click"); }
    this.skin.onPress = function(event){ console.log("pressing"); }
};

The commented-out onDoubleClick event works, onClick and onPress do not.

gskinner commented 11 years ago

any chance you could set up a jsfiddle or similar? I'm unable to reproduce your issue, and I can't see an immediate issue glancing at your code.

Thanks!

dnldd commented 11 years ago

I tried setting up a jsfiddle, didn't work out so well so I went ahead and hosted the game remotely for you to check out. it's over here: http://mobcont-pi.appspot.com/assets/bd/index.html. You'll notice that when a falling bird collides with the bird at the mouse pointer's position and it resets, clicking it does not fire the onClick event. The onClick event is set here:

function Shield(path, position, size, type, game){
    this.skin = new Bitmap(path);
    this.skin.x = position.x;
    this.skin.y = position.y;
    this.skin.regX = (size.length/2);
    this.skin.regY = (size.height/2); 
    this.type = type;
    game.stage.addChild(this.skin);
    this.skin.onClick = function(event){ game.activeShield = type; console.log("selected"); }
    /*this.skin.addEventListener("press", function(event){
        this.parent.addChild(this);
        var offset = { x : this.x - event.stageX, y : this.y - event.stageY};
        event.addEventListener("mouseMove", function(event) {
            console.log("moving");
            this.x = event.stageX + offset.x ;
            this.y = event.stageY + offset.y ;
        }, this)
    });  */
};

I know this setup is not ideal, sorry about that. Please do inspect with the js console. Noir.js is the file with all the easeljs code. Thanks.

sebastianderossi commented 11 years ago

@dnldd

Have you ever got the mouse events to work? After having a look at your code... I noticed that you have 2 canvases "canvas" and "debugCanvas" If you remove the debugCanvas will get those events just fine.

dnldd commented 11 years ago

@sebastianderossi Nope, I haven't gotten it to work yet. I'll try what you've suggested. So that means I have to sacrifice the debug renderer for box2d to get easelJS to work properly? Is there a work-around that let's me have both?

sebastianderossi commented 11 years ago

@dnldd

Here's an easier way to deal with displaying the debug draw and the EaselJS graphics:

var DEBUG = true;

world.Step(1/24, 2, 2); world.ClearForces(); if (DEBUG) { world.DrawDebugData(); }

// ... do all your work here (updating positions, etc)

stage.autoClear = !DEBUG; // prevents EaselJS from clearing the canvas. stage.alpha = 1-DEBUG*0.6; // draws the stage graphics with appropriate alpha. stage.update();

gskinner commented 11 years ago

Check out my first comment on this tutorial for one approach to handle this: http://gotoandlearn.com/play.php?id=177

Hope it helps. Grant.

On 2013-02-05, at 04:06 , Donald Adu-Poku notifications@github.com wrote:

@sebastianderossi Nope, I haven't gotten it to work yet. I'll try what you've suggested. So that means I have to sacrifice the debug renderer for box2d to get easelJS to work properly? Is there a work-around that let's me have both?

— Reply to this email directly or view it on GitHub.