X-Git-Url: https://git.yukkurigames.com/?p=featherfall2.git;a=blobdiff_plain;f=src%2Fmain.js;h=debe1b5b6343b888f8ebabf4594b946f55241a31;hp=36f874e4c456985c00572cb26719ed337872bab4;hb=defed78331d2f353b582608cbd9ad367920322be;hpb=6a662cfe7cd27e67c4457feceda67a966ca75f09 diff --git a/src/main.js b/src/main.js index 36f874e..debe1b5 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,70 @@ "use strict"; +var b2Vec2 = yf.argcd( + function (a) { + return b2Vec2.call(this, a[0] || a.x || 0.0, a[1] || a.y || 0.0); + }, + Box2D.b2Vec2 +); + + +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] }; +} + +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; -var PlayerController = new yT(yuu.C, { +var BodyC = yT(yuu.C, { + SLOTS: ['transform'], + + constructor: function (body, size) { + this._body = body; + this._matrix = mat4.create(); + }, + + 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; + mat4.translate(mat, mat, [pos.x, pos.y, 0]); + return mat; + } } +}); + +var PlayerController = yT(yuu.C, { constructor: function (body, left, right) { this.body = body; this.left = left; @@ -10,21 +72,21 @@ var PlayerController = new yT(yuu.C, { this.dleftLeft = this.dleftRight = this.drightLeft = this.drightRight = 0; this.up = 0; + this.free = 0; this.leftPivot = 0; this.rightPivot = 0; - this.x = this.lastX = body.x; - this.y = this.lastY = body.y; this.commands = { dleftLeft: yuu.propcmd(this, 'dleftLeft'), dleftRight: yuu.propcmd(this, 'dleftRight'), drightLeft: yuu.propcmd(this, 'drightLeft'), drightRight: yuu.propcmd(this, 'drightRight'), up: yuu.propcmd(this, 'up'), + free: yuu.propcmd(this, 'free'), }; }, _updatePivots: function () { - var PIVOT_SPEED = 0.03; + var PIVOT_SPEED = 0.05; var leftSpeed = (this.dleftRight - this.dleftLeft) * PIVOT_SPEED; var rightSpeed = (this.drightLeft - this.drightRight) * PIVOT_SPEED; this.leftPivot = yf.clamp(this.leftPivot + leftSpeed, 0, 1); @@ -34,120 +96,117 @@ var PlayerController = new yT(yuu.C, { _updateTransforms: function () { this.left.yaw = -this.leftPivot * Math.PI / 2; this.right.yaw = this.rightPivot * Math.PI / 2; - this.body.x = this.x; - this.body.y = this.y; }, tick: function () { this._updatePivots(); - var dt = 0.016; - var GRAVITY = 1; - var DRAG_MAX = 1; - var LIFT_MAX = 1; - - - var left = (1 - this.leftPivot) * Math.PI / 2; - var right = (1 - this.rightPivot) * Math.PI / 2; - - var vx = (this.x - this.lastX) / dt; - var vy = (this.y - this.lastY) / dt; - - var rotor = 1 * this.up; - - var cleft = Math.cos(left); - var cright = Math.cos(right); - var sleft = Math.sin(left); - var sright = Math.sin(right); - - var dvyleft = sleft * rotor; - var dvyright = sright * rotor; - var dvxleft = cleft * rotor; - var dvxright = cright * rotor; - - var dvx = (dvxleft - dvxright); - var dvy = (dvyleft + dvyright) - GRAVITY; - - var leftarea = DRAG_MAX * Math.abs(sleft); - var rightarea = DRAG_MAX * Math.abs(sright); - var dragy = vy * vy * (leftarea + rightarea); - - leftarea = DRAG_MAX * Math.abs(cleft); - rightarea = DRAG_MAX * Math.abs(cright); - var dragx = vx * vx * (leftarea + rightarea); - - leftarea = LIFT_MAX * Math.abs(cleft); - rightarea = LIFT_MAX * Math.abs(cright); - var liftx = vy * vy * (rightarea - leftarea); - - leftarea = LIFT_MAX * Math.abs(sleft); - rightarea = LIFT_MAX * Math.abs(sright); - var lifty = vx * vx * (rightarea - leftarea); - - if (vy > 0) { - dragy = -dragy; - liftx = -liftx; - } - if (vx > 0) { - dragx = -dragx; - lifty = -lifty; - } - - var ax = dvx + liftx + dragx; - var ay = dvy + lifty + dragy; - - var origX = this.x; - var origY = this.y; - this.x += (this.x - this.lastX) + ax * dt * dt; - this.y += (this.y - this.lastY) + ay * dt * dt; - this.y = Math.max(0, this.y); - this.lastX = origX; - this.lastY = origY; + var THRUST = 3.5; + var DRAG_FREE = 0.01; + var DRAG_OPEN = 0.5; + var DRAG_LOCK = 1; + var CORRECTION = 1; + + var leftAngle = (1 - this.leftPivot) * Math.PI / 2; + var rightAngle = (1 - this.rightPivot) * Math.PI / 2; + + var cleft = Math.cos(leftAngle); + var cright = Math.cos(rightAngle); + var sleft = Math.sin(leftAngle); + var sright = Math.sin(rightAngle); + + var thrust = +!this.free * +this.up * THRUST; + var ax = thrust * (cleft - cright); + var ay = thrust * (sright + sleft); + + var v = this.body.linearVelocity; + var drag = this.up ? DRAG_OPEN : this.free ? DRAG_FREE : DRAG_LOCK; + ax += drag * Math.max(cleft, cright) * v.x * v.x * -Math.sign(v.x); + ay += drag * (sleft + sright) * v.y * v.y * -Math.sign(v.y); + + if (!this.up || this.free) + ax += CORRECTION * (cleft - cright) * v.y * v.y * Math.sign(v.y); + + this.body.ApplyForce(new b2Vec2(ax, ay), this.body.position); + this._updateTransforms(); }, TAPS: ['tick'], }); +function bodyFromAABB (world, position, aabb, density) { + var bd = new Box2D.b2BodyDef(); + var shape = new Box2D.b2PolygonShape(); + shape.SetAsBox(aabb.w / 2, aabb.h / 2); + if (density) + bd.type = Box2D.DYNAMIC_BODY; + bd.position = new b2Vec2(position[0], position[1]); + var body = world.CreateBody(bd); + body.CreateFixture(shape, density || 0); + return body; +} + +function bodyFromLine (world, p0, p1) { + var bd = new Box2D.b2BodyDef(); + var shape = new Box2D.b2EdgeShape(); + shape.Set(new b2Vec2(p0), new b2Vec2(p1)); + var body = world.CreateBody(bd); + body.CreateFixture(shape, 0); + return body; +} + var GameScene = yT(yuu.Scene, { constructor: function () { yuu.Scene.call(this); - this.layer0.resize(-1.3333333333/2, -0.2, 1.3333333333, 1); + var zoom = 10; + this.layer0.resize( + zoom * -1.3333333333/2, zoom * -0.2, zoom * 1.3333333333, zoom * 1); + + var world = new Box2D.b2World(new b2Vec2(0, -5)); var body, left, right; - this.player = new yuu.E(body = new yuu.Transform() - .setScale([0.081, 0.091, 1]), - new yuu.QuadC('@player') - .setAnchor('bottom') - .setPosition([0, 0])); + this.player = new yuu.E( + body = new BodyC(bodyFromAABB( + world, [0, 5], new yuu.AABB(0.89, 1.0), 1.0)), + new yuu.QuadC('@player') + .setSize([0.89, 1.0]) + ); + var leftWing = new yuu.E(left = new yuu.Transform() - .setPosition([-0.3, 0.65, 0]) - .setScale([0.45, 0.22, 1]), + .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.3, 0.65, 0]) - .setScale([0.45, 0.22, 1]), + .setPosition([0.25, 0.15, 0]), new yuu.QuadC('@right') .setZ(-1) .setAnchor('left') + .setSize([0.45, 0.22]) .setPosition([0, 0])); this.player.addChildren(leftWing, rightWing); this.entity0.addChild(this.player); - var ground = new yuu.E(new yuu.Transform() - .setPosition([0, -10, 1]) - .setScale([100, 20, 1]), - new yuu.QuadC() - .setColor([0, 0.5, 0, 1])); + var ground = new yuu.E( + new BodyC(bodyFromLine(world, [-100, 0], [100, 0])), + new yuu.QuadC() + .setAnchorAtPosition('top') + .setSize([100, 1]) + .setColor([0, 0.5, 0, 1])); this.entity0.addChild(ground); this.player.attach( this.controller = new PlayerController(body, left, right)); Object.assign(this.commands, this.controller.commands); + this.entity0.attach(new yuu.Ticker(function () { + world.Step(1/60, 4, 4); + return true; + }, 1)); + this.ready = yuu.ready([ new yuu.Material('@player'), new yuu.Material('@left'), @@ -173,6 +232,8 @@ var GameScene = yT(yuu.Scene, { w: '+dleftRight', o: '+drightLeft', p: '+drightRight', + z: '+free', + x: '+up', } });