Created
March 19, 2015 03:46
-
-
Save darkoverlordofdata/084530da8b8b7896e26e to your computer and use it in GitHub Desktop.
Box2D MouseJoint
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### | |
* Set up the environment | |
### | |
do -> | |
### | |
* Polyfil the requestAnimationFrame method | |
### | |
unless window.requestAnimationFrame | |
window.requestAnimationFrame = do -> | |
window.webkitRequestAnimationFrame or window.mozRequestAnimationFrame or window.oRequestAnimationFrame or window.msRequestAnimationFrame or (callback) -> | |
window.setTimeout callback, 1000 / 60 | |
return | |
window.addEventListener 'load', -> | |
### | |
* If desktop, use stats | |
### | |
unless navigator.isCocoonJS | |
container = document.createElement('div') | |
document.body.appendChild container | |
stats = new Stats() | |
container.appendChild stats.domElement | |
stats.domElement.style.position = 'absolute' | |
### | |
* configure the canvas element | |
### | |
canvas = document.createElement((if navigator.isCocoonJS then 'screencanvas' else 'canvas')) | |
canvas.width = window.innerWidth * window.devicePixelRatio | |
canvas.height = window.innerHeight * window.devicePixelRatio | |
canvas.style.width = '100%' | |
canvas.style.height = '100%' | |
document.body.appendChild canvas | |
new MouseJoint(canvas, stats) | |
return | |
, true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MathUtil = -> | |
MathUtil.RADIANS = Math.PI / 180 | |
MathUtil.DEGREES = 180 / Math.PI | |
MathUtil.rndRange = (min, max) -> | |
min + (Math.random() * (max - min)) | |
MathUtil.rndIntRange = (min, max) -> | |
Math.round MathUtil.rndRange(min, max) | |
MathUtil.toRadians = (degrees) -> | |
degrees * MathUtil.RADIANS | |
MathUtil.toDegrees = (radians) -> | |
radians * MathUtil.DEGREES | |
MathUtil.hitTest = (x1, y1, w1, h1, x2, y2, w2, h2) -> | |
return true if y1 < y2 + h2 if y1 + h1 > y2 if x1 < x2 + w2 if x1 + w1 > x2 | |
false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MouseJoint | |
METER = 100 | |
width: 0 | |
height: 0 | |
bodies: null | |
actors: null | |
stage: null | |
renderer: null | |
world: null | |
mouseJoint: null | |
touchX: null | |
touchY: null | |
isBegin: false | |
stats: null | |
listener: null | |
assets: [ | |
"assets/ball.png" | |
"assets/box.jpg" | |
] | |
### | |
* Initialize the game | |
### | |
constructor: (canvas, @stats) -> | |
@bodies = [] | |
@actors = [] | |
@width = canvas.width | |
@height = canvas.height | |
@stage = new PIXI.Stage(0xDDDDDD, true) | |
@renderer = PIXI.autoDetectRenderer(@width, @height, canvas, false) | |
loader = new PIXI.AssetLoader(@assets) | |
loader.onComplete = @start | |
loader.load() | |
### Events ### | |
if typeof window.ontouchstart is 'undefined' | |
events = ['mousedown', 'mouseup'] | |
@listener = document | |
else | |
events = ['touchstart', 'touchend'] | |
@listener = if navigator.isCocoonJS then document else canvas | |
for event in events | |
@listener.addEventListener event, @[event], true | |
return | |
### | |
* Start up the level | |
### | |
start: => | |
### | |
* Elements | |
### | |
@world = new Box2D.Dynamics.b2World(new Box2D.Common.Math.b2Vec2(0, 10), true) | |
polyFixture = new Box2D.Dynamics.b2FixtureDef() | |
polyFixture.shape = new Box2D.Collision.Shapes.b2PolygonShape() | |
polyFixture.density = 1 | |
circleFixture = new Box2D.Dynamics.b2FixtureDef() | |
circleFixture.shape = new Box2D.Collision.Shapes.b2CircleShape() | |
circleFixture.density = 1 | |
circleFixture.restitution = 0.7 | |
bodyDef = new Box2D.Dynamics.b2BodyDef() | |
bodyDef.type = Box2D.Dynamics.b2Body.b2_staticBody | |
#down | |
polyFixture.shape.SetAsBox 10, 1 | |
bodyDef.position.Set 9, @height / METER + 1 | |
@world.CreateBody(bodyDef).CreateFixture polyFixture | |
#left | |
polyFixture.shape.SetAsBox 1, 100 | |
bodyDef.position.Set -1, 0 | |
@world.CreateBody(bodyDef).CreateFixture polyFixture | |
#right | |
bodyDef.position.Set @width / METER + 1, 0 | |
@world.CreateBody(bodyDef).CreateFixture polyFixture | |
bodyDef.type = Box2D.Dynamics.b2Body.b2_dynamicBody | |
i = 0 | |
while i < 10 | |
bodyDef.position.Set MathUtil.rndRange(0, @width) / METER, -MathUtil.rndRange(50, 5000) / METER | |
body = @world.CreateBody(bodyDef) | |
s = undefined | |
if Math.random() > 0.5 | |
s = MathUtil.rndRange(70, 100) | |
circleFixture.shape.SetRadius s / 2 / METER | |
body.CreateFixture circleFixture | |
@bodies.push body | |
ball = new PIXI.Sprite(PIXI.Texture.fromFrame("assets/ball.png")) | |
@stage.addChild ball | |
ball.i = i | |
ball.anchor.x = ball.anchor.y = 0.5 | |
ball.scale.x = ball.scale.y = s / 100 | |
@actors.push ball | |
# | |
else | |
s = MathUtil.rndRange(50, 100) | |
polyFixture.shape.SetAsBox s / 2 / METER, s / 2 / METER | |
body.CreateFixture polyFixture | |
@bodies.push body | |
box = new PIXI.Sprite(PIXI.Texture.fromFrame("assets/box.jpg")) | |
@stage.addChild box | |
box.i = i | |
box.anchor.x = box.anchor.y = 0.5 | |
box.scale.x = s / 100 | |
box.scale.y = s / 100 | |
@actors.push box | |
i++ | |
@update() | |
return | |
### | |
* The Game Loop | |
### | |
update: => | |
requestAnimationFrame @update | |
if @isBegin and not @mouseJoint | |
dragBody = @getBodyAtMouse() | |
if dragBody | |
jointDef = new Box2D.Dynamics.Joints.b2MouseJointDef() | |
jointDef.bodyA = @world.GetGroundBody() | |
jointDef.bodyB = dragBody | |
jointDef.target.Set @touchX, @touchY | |
jointDef.collideConnected = true | |
jointDef.maxForce = 300.0 * dragBody.GetMass() | |
@mouseJoint = @world.CreateJoint(jointDef) | |
dragBody.SetAwake true | |
if @mouseJoint | |
if @isBegin | |
@mouseJoint.SetTarget new Box2D.Common.Math.b2Vec2(@touchX, @touchY) | |
else | |
@world.DestroyJoint @mouseJoint | |
@mouseJoint = null | |
@world.Step 1 / 60, 3, 3 | |
@world.ClearForces() | |
n = @actors.length | |
i = 0 | |
while i < n | |
body = @bodies[i] | |
actor = @actors[i] | |
position = body.GetPosition() | |
actor.position.x = position.x * 100 | |
actor.position.y = position.y * 100 | |
actor.rotation = body.GetAngle() | |
i++ | |
@renderer.render @stage | |
@stats?.update() | |
return | |
getBodyAtMouse: => | |
mousePos = new Box2D.Common.Math.b2Vec2(@touchX, @touchY) | |
aabb = new Box2D.Collision.b2AABB() | |
aabb.lowerBound.Set @touchX - 0.001, @touchY - 0.001 | |
aabb.upperBound.Set @touchX + 0.001, @touchY + 0.001 | |
body = undefined | |
@world.QueryAABB ((fixture) -> | |
unless fixture.GetBody().GetType() is Box2D.Dynamics.b2BodyDef.b2_staticBody | |
if fixture.GetShape().TestPoint(fixture.GetBody().GetTransform(), mousePos) | |
body = fixture.GetBody() | |
return false | |
true | |
), aabb | |
body | |
### | |
* Events | |
### | |
mousedown: (event) => | |
@isBegin = true | |
@mousemove event | |
@listener.addEventListener 'mousemove', @mousemove, true | |
return | |
mouseup: (event) => | |
@listener.removeEventListener 'mousemove', @mousemove, true | |
@isBegin = false | |
@touchX = undefined | |
@touchY = undefined | |
return | |
mousemove: (event) => | |
@touchX = event.clientX / METER | |
@touchY = event.clientY / METER | |
return | |
touchstart: (event) => | |
@isBegin = true | |
@touchmove event | |
@listener.addEventListener 'touchmove', @touchmove, true | |
return | |
touchend: (event) => | |
@listener.removeEventListener 'touchmove', @touchmove, true | |
@isBegin = false | |
@touchX = undefined | |
@touchY = undefined | |
return | |
touchmove: (event) => | |
touche = event.changedTouches[0] | |
@touchX = (touche.pageX*window.devicePixelRatio) / METER | |
@touchY = (touche.pageY*window.devicePixelRatio) / METER | |
return | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment