UNPKG

jsx

Version:

a faster, safer, easier JavaScript

363 lines (311 loc) 11.4 kB
import 'js/web.jsx'; import 'mvq.jsx'; import 'webgl-util.jsx'; import 'game.jsx'; class _Part { static function createArrayBuffer(a:number[]) : WebGLBuffer { var gl = Kingyo.gl; var buf = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buf); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(a), gl.STATIC_DRAW); return buf; } static function createIndexBuffer(a:int[]) : WebGLBuffer { var gl = Kingyo.gl; var buf = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(a), gl.STATIC_DRAW); return buf; } var vbuf = null:WebGLBuffer; var nbuf = null:WebGLBuffer; var ibuf = null:WebGLBuffer; var numv:int = 0; var numi:int = 0; function setVertex(v:number[]) : _Part {this.vbuf = _Part.createArrayBuffer(v); this.numv = v.length / 3;return this;} function setNormal(n:number[]) : _Part {this.nbuf = _Part.createArrayBuffer(n); return this;} function setIndex(i:int[]) : _Part {this.ibuf = _Part.createIndexBuffer(i); this.numi = i.length; return this;} } class Kingyo { static const bound = 10; static var gl = null:WebGLRenderingContext; static var prog = null:WebGLProgram; static var ulocs = null:Map.<WebGLUniformLocation>; static var alocs = null:Map.<int>; static var body:_Part; static var lfin:_Part; // left fin static var rfin:_Part; // right fin static var bfin:_Part; // back fin static var tfin:_Part; // tail fin static var all = []:Kingyo[]; static var prevTime = 0; static var eyeProg = null:WebGLProgram; static var eyeULocs = null:Map.<WebGLUniformLocation>; static var eyeALocs = null:Map.<int>; static var eyes = null:_Part; static function initWithGL(gl:WebGLRenderingContext) : void { Kingyo.gl = gl; Kingyo.prog = Util.getProgram('kbody.vs', 'kbody.fs'); Kingyo.body = new _Part() .setVertex([0,0,1, 0.7,0,0, 0,1,0, -0.7,0,0, 0,-1,0, 0,0,-1]) .setNormal([0,0,1, 1,0,0, 0,1,0, -1,0,0, 0,-1,0, 0,0,-1]) .setIndex([0,1,2, 0,2,3, 0,3,4, 0,4,1, 5,2,1, 5,3,2, 5,4,3, 5,1,4]:int[]); Kingyo.lfin = new _Part() .setVertex([0,0,0, 0.5,-0.25,0, 0.8,0.25,0]) .setNormal([0,0,1, 0,0,1, 0,0,1]) .setIndex([0,1,2]:int[]); Kingyo.rfin = new _Part() .setVertex([0,0,0, -0.8,0.25,0, -0.5,-0.25,0]) .setNormal([0,0,1, 0,0,1, 0,0,1]) .setIndex([0,1,2]:int[]); Kingyo.bfin = new _Part() .setVertex([0,0,0, 0,-0.5,-1, 0,0.5,-0.8]) .setNormal([1,0,0, 1,0,0, 1,0,0]) .setIndex([0,1,2]:int[]); Kingyo.tfin = new _Part() .setVertex([0,0,0, 0.8,-0.5,-1, 0,0.4,-0.8, -0.8,-0.5,-1]) .setNormal([0,1,1, 1,1,1, 0,1,0, -1,1,1]) .setIndex([0,1,2, 0,2,3]:int[]); Kingyo.ulocs = Util.getUniformLocations(Kingyo.prog); Kingyo.alocs = Util.getAttribLocations(Kingyo.prog); Kingyo.eyeProg = Util.getProgram('keye.vs', 'keye.fs'); Kingyo.eyeULocs = Util.getUniformLocations(Kingyo.eyeProg); Kingyo.eyeALocs = Util.getAttribLocations(Kingyo.eyeProg); var ex = 0.3, ey = 0.15, ez = 0.5; Kingyo.eyes = new _Part() .setVertex([-ex,ey,ez,0, -ex,ey,ez,1, -ex,ey,ez,2, -ex,ey,ez,3, ex,ey,ez,4, ex,ey,ez,5, ex,ey,ez,6, ex,ey,ez,7]) .setIndex([0,1,2, 0,2,3, 4,5,6, 4,6,7]:int[]); } static function init(num_kingyos:int) : void { for (var i = 0; i < num_kingyos; ++i) Kingyo.all.push(new Kingyo()); } static function reset() : void { for (var i = 0; i < Kingyo.all.length; ++i) Kingyo.all[i].init(); } static function numRests() : int { var r = 0; for (var i = 0; i < Kingyo.all.length; ++i) if (Kingyo.all[i]._state == 'swimming') ++r; return r; } static function update(t:number) : void { if (Kingyo.prevTime == 0) Kingyo.prevTime = t; var dt = t - Kingyo.prevTime; for (var i = 0; i < Kingyo.all.length; ++i) Kingyo.all[i]._update(dt); Kingyo.prevTime = t; } static function drawUnderWater(projMat:M44, viewMat:M44) : void { Kingyo.draw(projMat, viewMat, function(k:Kingyo):boolean{return k._state == 'swimming';}); } static function drawAboveWater(projMat:M44, viewMat:M44) : void { Kingyo.draw(projMat, viewMat, function(k:Kingyo):boolean{return k._state != 'swimming';}); } static function draw(projMat:M44, viewMat:M44, pred:(Kingyo)->boolean) : void { var gl = Kingyo.gl; var prog = Kingyo.prog; // draw bodies var ulocs = Kingyo.ulocs; var alocs = Kingyo.alocs; gl.useProgram(Kingyo.prog); gl.uniformMatrix4fv(ulocs['projectionMatrix'], false, projMat.array()); gl.uniformMatrix4fv(ulocs['viewMatrix'], false, viewMat.array()); gl.uniform4fv(ulocs['lightPosition'], [0, 1, 1, 0]); gl.enableVertexAttribArray(alocs['vertex']); gl.enableVertexAttribArray(alocs['normal']); for (var i = 0; i < Kingyo.all.length; ++i) { var k = Kingyo.all[i]; if (pred(k)) k._draw(); } gl.disableVertexAttribArray(alocs['vertex']); gl.disableVertexAttribArray(alocs['normal']); // draw eyes var eulocs = Kingyo.eyeULocs; var ealocs = Kingyo.eyeALocs; gl.useProgram(Kingyo.eyeProg); gl.uniformMatrix4fv(eulocs['projectionMatrix'], false, projMat.array()); gl.uniformMatrix4fv(eulocs['viewMatrix'], false, viewMat.array()); gl.uniform4fv(eulocs['lightPosition'], [0, 1, 1, 0]); gl.uniform1f(eulocs['radius'], 0.2); gl.bindBuffer(gl.ARRAY_BUFFER, Kingyo.eyes.vbuf); gl.vertexAttribPointer(ealocs['position'], 4, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(ealocs['position']); for (var i = 0; i < Kingyo.all.length; ++i) { var k = Kingyo.all[i]; if (pred(k)) k._drawEyes(); } gl.disableVertexAttribArray(ealocs['position']); } static function hit(x:number, y:number) : Kingyo[] { var h = []:Kingyo[]; for (var i = 0; i < Kingyo.all.length; ++i) { var k = Kingyo.all[i]; if (k._state != 'swimming') continue; var dx = k._pos.x - x; var dy = k._pos.y - y; var r = Math.sqrt(dx*dx + dy*dy); if (r < 2) h.push(k); } return h; } static function fish(kingyos:Kingyo[]) : void { for (var i = 0; i < kingyos.length; ++i) { kingyos[i]._fished(); } } var _pos = new V3(); var _vangle = 0; var _velo = 0; var _anim = 0; var _state = ''; // 'swimming', 'flying' and 'listed' var _spinMat = new M44(); var _spinAxis = new V3(); var _spinSpeed = 0; var _vz = 0; var _color = [0.7, 0, 0]; // default color var _color2 = [0.7, 0, 0]; var _color2pos = [0, 0, 0, 0]; // center.xyz & radius function constructor() { this.init(); if (Math.random() < 0.3) { // red & white this._color2 = [0.7, 0.7, 0.8]; this._color2pos = [2*Math.random()-1, 2*Math.random()-1, 2*Math.random()-1, 0.5*Math.random()+0.5]; } else if (Math.random() < 0.5) { // black this._color = [0.15, 0.1, 0.2]; this._color2 = [0.15, 0.1, 0.2]; this._color2pos = [0, 0, 0, 0]; } } function init() : void { this._setRandom(); var r = 8 * Math.random(); var x = r * Math.cos(this._vangle); var y = r * Math.sin(this._vangle); this._pos.set(x, y, -2 - Math.random() * 3); this._anim = 0; this._state = 'swimming'; this._spinMat.setIdentity(); this._spinAxis.set(0, 0, 0); this._spinSpeed = 0; this._vz = 0; } function _setRandom() : void { this._vangle = Math.random() * 2 * Math.PI; this._velo = Math.random() * 15 + 1; } function _fished() : void { this._state = 'flying'; this._pos.z = 2; this._vz = 150 + Math.random() * 50; this._velo = 12; this._spinMat.setIdentity(); var a = 2 * Math.PI * Math.random(); this._spinAxis.set(Math.cos(a), Math.sin(a), Math.random()-0.5); this._spinSpeed = 10 * Math.random() + 2; } function _update(dt:number) : void { switch (this._state) { default: break; case 'swimming': var x = this._pos.x + Math.cos(this._vangle) * this._velo * dt; var y = this._pos.y + Math.sin(this._vangle) * this._velo * dt; var b = Kingyo.bound; if (x < -b) {x = -b; this._setRandom();} if (y < -b) {y = -b; this._setRandom();} if (x > b) {x = b; this._setRandom();} if (y > b) {y = b; this._setRandom();} this._pos.x = x; this._pos.y = y; break; case 'flying': this._vz -= 300 * dt; this._pos.z = this._pos.z + this._vz * dt; this._spinMat.mul(new M44().setRotation(dt * this._spinSpeed, this._spinAxis)); if (this._pos.z >= 2) break; var num_listed = 0; for (var i = 0; i < Kingyo.all.length; ++i) if (Kingyo.all[i]._state == 'listed') ++num_listed; this._pos.set(num_listed * 1.5 - Kingyo.bound - 4.25, 3 + Kingyo.bound, 2); this._vangle = Math.PI / 2; this._spinMat.setIdentity(); this._velo = 2; this._state = 'listed'; case 'listed': break; } this._anim += dt * this._velo; } function _draw() : void { var gl = Kingyo.gl; var prog = Kingyo.prog; gl.uniform3fv(Kingyo.ulocs['color'], this._color); gl.uniform3fv(Kingyo.ulocs['color2'], this._color2); gl.uniform4fv(Kingyo.ulocs['color2pos'], this._color2pos); var modelMatLoc = Kingyo.ulocs['modelMatrix']; var s = Math.sin(this._anim * 5); // swing var bodyMat = new M44().setTranslation(this._pos) .mul(this._spinMat) .mul(new M44().setRotationZ(this._vangle - s/10)) .mul(new M44().setRotationX(Math.PI/2)) // JSON kingyo model is +Z front and +Y up. .mul(new M44().setRotationY(Math.PI/2)); // These two lines transform model to +X front and +Z up. gl.uniformMatrix4fv(modelMatLoc, false, bodyMat.array()); this._drawPart(Kingyo.body); var lfinMat = bodyMat.clone() .mul(new M44().setTranslation(0.5, -0.3, 0)) .mul(new M44().setRotation(1+s/2, 0.2, 1, -0.5)); gl.uniformMatrix4fv(modelMatLoc, false, lfinMat.array()); this._drawPart(Kingyo.lfin); var rfinMat = bodyMat.clone() .mul(new M44().setTranslation(-0.5, -0.3, 0)) .mul(new M44().setRotation(-1-s/2, -0.2, 1, -0.5)); gl.uniformMatrix4fv(modelMatLoc, false, rfinMat.array()); this._drawPart(Kingyo.rfin); var bfinMat = bodyMat.clone() .mul(new M44().setTranslation(0, 0.7, 0)) .mul(new M44().setRotation(s/2, 0, 1, 1)); gl.uniformMatrix4fv(modelMatLoc, false, bfinMat.array()); this._drawPart(Kingyo.bfin); var tfinMat = bodyMat.clone() .mul(new M44().setTranslation(0,0,-0.7)) .mul(new M44().setRotation(s/2, 0, 1, 0)); gl.uniformMatrix4fv(modelMatLoc, false, tfinMat.array()); this._drawPart(Kingyo.tfin); } function _drawPart(p:_Part) : void { var gl = Kingyo.gl; var prog = Kingyo.prog; gl.bindBuffer(gl.ARRAY_BUFFER, p.vbuf); gl.vertexAttribPointer(Kingyo.alocs['vertex'], 3, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, p.nbuf); gl.vertexAttribPointer(Kingyo.alocs['normal'], 3, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, p.ibuf); gl.drawElements(gl.TRIANGLES, p.numi, gl.UNSIGNED_SHORT, 0); } function _drawEyes() : void { var gl = Kingyo.gl; var prog = Kingyo.eyeProg; var ulocs = Kingyo.eyeULocs; var alocs = Kingyo.eyeALocs; gl.uniform3fv(ulocs['color'], this._color); var s = Math.sin(this._anim * 5); // swing var bodyMat = new M44().setTranslation(this._pos) .mul(this._spinMat) .mul(new M44().setRotationZ(this._vangle - s/10)) .mul(new M44().setRotationX(Math.PI/2)) // JSON kingyo model is +Z front and +Y up. .mul(new M44().setRotationY(Math.PI/2)); // These two lines transform model to +X front and +Z up. gl.uniformMatrix4fv(ulocs['modelMatrix'], false, bodyMat.array()); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Kingyo.eyes.ibuf); gl.drawElements(gl.TRIANGLES, 12, gl.UNSIGNED_SHORT, 0); } }