From: Joe Wreschnig Date: Thu, 18 Sep 2014 13:41:40 +0000 (+0200) Subject: Attach wings via physics engine (they're now... odd.) X-Git-Url: https://git.yukkurigames.com/?p=featherfall2.git;a=commitdiff_plain;h=5b22796116262ad2de3b7f6cd0fb635796362bbc;hp=54d3831fbc0e13801fc99cd17074f0d697593316 Attach wings via physics engine (they're now... odd.) New auto-wrapping approach. --- diff --git a/src/main.js b/src/main.js index debe1b5..ecff045 100644 --- a/src/main.js +++ b/src/main.js @@ -12,33 +12,47 @@ yf.ipairs(function (k, v) { Box2D[k] = Box2D[v]; }, { DYNAMIC_BODY: 'b2_dynamicBody' }); -function accessor (T, p) { - if (p[0].toLowerCase() === p[0]) - return { get: T.prototype['get_' + p], - set: T.prototype['set_' + p] }; - else - return { get: T.prototype['Get' + p], - set: T.prototype['Set' + p] }; +function camelizeCase (s) { + return s.replace(/_([a-z])/g, function (m) { + return m[1].toUpperCase(); + }); } +function wrapEmscriptenType (T) { + var P = T.prototype; + var keys = Object.keys(P); + var members = keys.filter(function (k) { return k.startsWith("get_"); }); + var accessors = keys.filter(function (k) { return k.startsWith("Get"); }); + members.forEach(function (k) { + var name = camelizeCase(k.slice(4)); + if (!name || name in P) return; + Object.defineProperty(P, name, { + get: P[k], set: P['s' + k.slice(1)] + }); + + }); + accessors.forEach(function (k) { + var name = k.slice(3); + name = name[0].toLowerCase() + name.slice(1); + if (!name || name in P) return; + Object.defineProperty(P, name, { + get: P[k], set: P['S' + k.slice(1)] + }); + + }); +} + +yf.each(wrapEmscriptenType, [ + Box2D.b2Vec2, Box2D.b2BodyDef, Box2D.b2Body, + Box2D.b2JointDef, Box2D.b2RevoluteJointDef, + Box2D.b2Joint, Box2D.b2DistanceJoint, Box2D.b2RevoluteJoint, +]); + yT.defineProperties(Box2D.b2Vec2.prototype, { - x: accessor(Box2D.b2Vec2, 'x'), - y: accessor(Box2D.b2Vec2, 'y'), 0: { alias: 'x' }, 1: { alias: 'y' }, }); -yT.defineProperties(Box2D.b2BodyDef.prototype, { - type: accessor(Box2D.b2BodyDef, 'type'), - position: accessor(Box2D.b2BodyDef, 'position'), -}); - -yT.defineProperties(Box2D.b2Body.prototype, { - position: accessor(Box2D.b2Body, 'Position'), - linearVelocity: accessor(Box2D.b2Body, 'LinearVelocity'), - angle: accessor(Box2D.b2Body, 'Angle'), -}); - var storage; @@ -46,29 +60,31 @@ var BodyC = yT(yuu.C, { SLOTS: ['transform'], constructor: function (body, size) { - this._body = body; + this.body = body; this._matrix = mat4.create(); }, - position: { alias: '_body.position' }, - linearVelocity: { alias: '_body.linearVelocity' }, - ApplyForce: { proxy: '_body.ApplyForce' }, + position: { alias: 'body.position' }, + linearVelocity: { alias: 'body.linearVelocity' }, + ApplyForce: { proxy: 'body.ApplyForce' }, matrix: { get: function () { var mat = this._matrix; mat4.identity(mat); - mat4.rotateZ(mat, mat, this._body.angle); - var pos = this._body.position; + var pos = this.body.position; mat4.translate(mat, mat, [pos.x, pos.y, 0]); + mat4.rotateZ(mat, mat, this.body.angle); return mat; } } }); var PlayerController = yT(yuu.C, { - constructor: function (body, left, right) { + constructor: function (body, left, right, leftJoint, rightJoint) { this.body = body; this.left = left; this.right = right; + this.leftJoint = leftJoint; + this.rightJoint = rightJoint; this.dleftLeft = this.dleftRight = this.drightLeft = this.drightRight = 0; this.up = 0; @@ -94,8 +110,13 @@ var PlayerController = yT(yuu.C, { }, _updateTransforms: function () { - this.left.yaw = -this.leftPivot * Math.PI / 2; - this.right.yaw = this.rightPivot * Math.PI / 2; + var gain = 1.0; + var leftTarget = this.leftPivot * Math.PI / 2; + var rightTarget = -this.rightPivot * Math.PI / 2; + var leftError = this.leftJoint.jointAngle - leftTarget; + var rightError = this.rightJoint.jointAngle - rightTarget; + this.leftJoint.motorSpeed = -gain * leftError; + this.rightJoint.motorSpeed = -gain * rightError; }, tick: function () { @@ -137,7 +158,7 @@ var PlayerController = yT(yuu.C, { function bodyFromAABB (world, position, aabb, density) { var bd = new Box2D.b2BodyDef(); var shape = new Box2D.b2PolygonShape(); - shape.SetAsBox(aabb.w / 2, aabb.h / 2); + shape.SetAsBox(aabb.hw, aabb.hh); if (density) bd.type = Box2D.DYNAMIC_BODY; bd.position = new b2Vec2(position[0], position[1]); @@ -155,6 +176,15 @@ function bodyFromLine (world, p0, p1) { return body; } +function pinJoint (world, bodyA, bodyB, anchor) { + var dfn = new Box2D.b2RevoluteJointDef(); + dfn.Initialize(bodyA, bodyB, new b2Vec2(anchor)); + dfn.maxMotorTorque = 10.0; + dfn.motorSpeed = 0.0; + dfn.enableMotor = true; + return Box2D.castObject(world.CreateJoint(dfn), Box2D.b2RevoluteJoint); +} + var GameScene = yT(yuu.Scene, { constructor: function () { yuu.Scene.call(this); @@ -173,20 +203,18 @@ var GameScene = yT(yuu.Scene, { .setSize([0.89, 1.0]) ); - var leftWing = new yuu.E(left = new yuu.Transform() - .setPosition([-0.25, 0.15, 0]), - new yuu.QuadC('@left') - .setZ(-1) - .setAnchor("right") - .setSize([0.45, 0.22]) - .setPosition([0, 0])); - var rightWing = new yuu.E(right = new yuu.Transform() - .setPosition([0.25, 0.15, 0]), - new yuu.QuadC('@right') - .setZ(-1) - .setAnchor('left') - .setSize([0.45, 0.22]) - .setPosition([0, 0])); + var leftWing = new yuu.E(left = new BodyC( + bodyFromAABB(world, [-0.50, 5.15], new yuu.AABB(0.45, 0.22), 1.0)), + new yuu.QuadC('@left') + .setZ(-1) + .setSize([0.45, 0.22])); + var leftJoint = pinJoint(world, left.body, body.body, [-0.1, 5.15]); + var rightWing = new yuu.E(right = new BodyC( + bodyFromAABB(world, [0.50, 5.15], new yuu.AABB(0.45, 0.22), 1.0)), + new yuu.QuadC('@right') + .setZ(-1) + .setSize([0.45, 0.22])); + var rightJoint = pinJoint(world, right.body, body.body, [0.1, 5.15]); this.player.addChildren(leftWing, rightWing); this.entity0.addChild(this.player); @@ -199,11 +227,12 @@ var GameScene = yT(yuu.Scene, { this.entity0.addChild(ground); this.player.attach( - this.controller = new PlayerController(body, left, right)); + this.controller = new PlayerController(body, left, right, + leftJoint, rightJoint)); Object.assign(this.commands, this.controller.commands); this.entity0.attach(new yuu.Ticker(function () { - world.Step(1/60, 4, 4); + world.Step(1/60, 8, 8); return true; }, 1)); diff --git a/src/yuu/core.js b/src/yuu/core.js index b526131..1923d2c 100644 --- a/src/yuu/core.js +++ b/src/yuu/core.js @@ -740,6 +740,9 @@ size: { swizzle: "wh" }, + hw: { get: function () { return this.w / 2; } }, + hh: { get: function () { return this.h / 2; } }, + contains: yf.argcd( function (p) { return this.contains(p.x, p.y); }, function (x, y) {