1 decade ago by Chema
Howdy,
I'm trying to implement the amusing Box2DWeb demo (https://code.google.com/p/box2dweb/ -- you'll have to download it if you have a paranoid browser) in Impact, but I've been stuck in a loop for a while... perhaps someone could break me out. So, I grabbed the physics demo and adapted the Box2DWeb's one to it. It works like this: when you click anywhere, it triggers an ig.input.state in update, which calls getBodyAtMouse, which in turn creates a small collision box around the cursor and does an ig.world.QueryAABB to check if there are any bodies beneath it. So far so good, but the query never calls getBodyCB, the callback, and being new to Box2D I'm completely stumped. I suspect the problem resides in the click coordinates I'm feeding Box2D, but after many hours I've not made any progress. Any takers?
You need only replace the main.js from the latest physics demo with this one:
I'm trying to implement the amusing Box2DWeb demo (https://code.google.com/p/box2dweb/ -- you'll have to download it if you have a paranoid browser) in Impact, but I've been stuck in a loop for a while... perhaps someone could break me out. So, I grabbed the physics demo and adapted the Box2DWeb's one to it. It works like this: when you click anywhere, it triggers an ig.input.state in update, which calls getBodyAtMouse, which in turn creates a small collision box around the cursor and does an ig.world.QueryAABB to check if there are any bodies beneath it. So far so good, but the query never calls getBodyCB, the callback, and being new to Box2D I'm completely stumped. I suspect the problem resides in the click coordinates I'm feeding Box2D, but after many hours I've not made any progress. Any takers?
You need only replace the main.js from the latest physics demo with this one:
DBG_ALL = 0xFFFFF; DBG_ERROR = 0x1; DBG_WARN = 0x2; DBG_NOTICE = 0x4; DBG_DEBUG = 0x8; DBG_DEBUG_SPAM = 0x10; DBG_IMPACT_DBG = 0x20 DBG_BOX2D = 0x30; DBG_NOSPAM = DBG_ALL ^ DBG_DEBUG_SPAM; debug = DBG_NOSPAM; //debug = false; ig.module( 'game.main' ) .requires( 'impact.game', 'impact.font', 'game.entities.player', 'game.entities.crate', 'game.levels.test', 'plugins.box2d.game', 'plugins.box2d.debug' ) .defines(function(){ MyGame = ig.Box2DGame.extend({ gravity: 0, // All entities are affected by this // Load a font font: new ig.Font( 'media/04b03.font.png' ), clearColor: '#1b2026', mouseJoint: false, init: function() { // Bind keys ig.input.bind( ig.KEY.LEFT_ARROW, 'left' ); ig.input.bind( ig.KEY.RIGHT_ARROW, 'right' ); ig.input.bind( ig.KEY.UP_ARROW, 'jump' ); ig.input.bind( ig.KEY.DOWN_ARROW, 'down' ); ig.input.bind( ig.KEY.SPACE, 'shoot' ); // Bind mouse clicks and touch ig.input.bind( ig.KEY.MOUSE1, 'MouseDown' ); if( ig.ua.mobile ) { ig.input.bindTouch( '#buttonLeft', 'left' ); ig.input.bindTouch( '#buttonRight', 'right' ); ig.input.bindTouch( '#buttonShoot', 'shoot' ); ig.input.bindTouch( '#buttonJump', 'jump' ); } // Load the LevelTest as required above ('game.level.test') this.loadLevel( LevelTest); if ( debug & DBG_BOX2D ) this.debugDrawer = new ig.Box2DDebug( ig.world ); if ( debug & DBG_DEBUG ) document.addEventListener("mousedown", function(e) { console.log("Event mousedown at: "+ e.clientX +", "+ e.clientY); }, true); }, loadLevel: function( data ) { this.parent( data ); for( var i = 0; i < this.backgroundMaps.length; i++ ) { this.backgroundMaps[i].preRender = true; } }, update: function() { var click = this.ClickCoordinates(ig.input.mouse.x, ig.input.mouse.y); // .state and .pressed both activate on click if( ig.input.pressed("MouseDown") ) { if (debug & DBG_DEBUG) console.log("ig.input.pressed MouseDown at: "+ JSON.stringify(click) + " (ig.input.mouse: "+ ig.input.mouse.x +", "+ ig.input.mouse.y +")."); } if( ig.input.state("MouseDown") ) { if (debug & DBG_DEBUG_SPAM) console.log("ig.input.state MouseDown at: "+ JSON.stringify(click) + " (ig.input.mouse: "+ ig.input.mouse.x +", "+ ig.input.mouse.y +")."); if(!this.mouseJoint) { var body = this.getBodyAtMouse(); if(body) { var md = new Box2D.Dynamics.Joints.b2MouseJointDef(); md.bodyA = ig.world.GetGroundBody(); md.bodyB = body; md.target.Set(click.x, click.y); md.collideConnected = true; md.maxForce = 300.0 * body.GetMass(); this.mouseJoint = ig.world.CreateJoint(md); body.SetAwake(true); } } } if(this.mouseJoint) { if(ig.input.state("MouseDown")) { this.mouseJoint.SetTarget( new Box2D.Common.Math.b2Vec2(click.x, click.y)); } else { ig.world.DestroyJoint(this.mouseJoint); this.mouseJoint = null; } } // .state and .released both activate on release if( ig.input.released("MouseDown") ) { if (debug & DBG_DEBUG_SPAM) console.log("ig.input.released MouseDown at: "+ JSON.stringify(click) + " (ig.input.mouse: "+ ig.input.mouse.x +", "+ ig.input.mouse.y +")."); } // Update all entities and BackgroundMaps, call Step and ClearForces this.parent(); // screen follows the player var player = this.getEntitiesByType( EntityPlayer )[0]; if( player ) { this.screen.x = player.pos.x - ig.system.width/2; this.screen.y = player.pos.y - ig.system.height/2; } }, draw: function() { // Draw all entities and BackgroundMaps this.parent(); if ( debug & DBG_BOX2D ) this.debugDrawer.draw(); if( !ig.ua.mobile ) { this.font.draw( 'Arrow Keys + Space', 2, 2 ); } }, getBodyAtMouse: function() { // Box2D requires window coordinates var click = this.ClickCoordinates(ig.input.mouse.x, ig.input.mouse.y); var aabb = new Box2D.Collision.b2AABB(); aabb.lowerBound.Set(click.x - 0.001, click.y - 0.001); aabb.upperBound.Set(click.x + 0.001, click.y + 0.001); // Query the world for overlapping shapes. this.selectedBody = null; ig.world.QueryAABB(this.getBodyCB, aabb); return this.selectedBody; }, getBodyCB: function(fixture) { var click = this.ClickCoordinates(ig.input.mouse.x, ig.input.mouse.y); this.mousePVec = new b2Vec2(click.x, click.y); if (debug & DBG_DEBUG) console.log("getBodyCB: Called with fixture "+ fixture); if(fixture.GetBody().GetType() != Box2D.Dynamics.b2Body.b2_staticBody) { if(fixture.GetShape().TestPoint(fixture.GetBody().GetTransform(), mousePVec)) { this.selectedBody = fixture.GetBody(); return false; } } return true; }, ClickCoordinates: function(localX, localY) { return { x: localX, y: localY }; }, // http://js-tut.aardon.de/js-tut/tutorial/position.html getElementPosition: function(element) { var elem=element, tagname="", x=0, y=0; while((typeof(elem) == "object") && (typeof(elem.tagName) != "undefined")) { y += elem.offsetTop; x += elem.offsetLeft; tagname = elem.tagName.toUpperCase(); if(tagname == "BODY") elem=0; if(typeof(elem) == "object") { if(typeof(elem.offsetParent) == "object") elem = elem.offsetParent; } } return {x: x, y: y}; } }); if( ig.ua.iPad ) { ig.Sound.enabled = false; ig.main('#canvas', MyGame, 60, 240, 160, 2); } else if( ig.ua.mobile ) { ig.Sound.enabled = false; ig.main('#canvas', MyGame, 60, 160, 160, 2); } else { ig.main('#canvas', MyGame, 60, 320, 240, 2); } });