Skip to content

Commit

Permalink
Use only one global variable for all static objects.
Browse files Browse the repository at this point in the history
Rationale:
* Step on fewer toes if used as one library among many on a page.
* Closer to being suitable for loading into a more controlled
  module-using environment such as Node.js.
* Clarify dependencies among components.
* I think I heard non-global variables are slightly faster.
  • Loading branch information
kpreid committed Jun 11, 2012
1 parent 0ab2897 commit c9e2ba6
Show file tree
Hide file tree
Showing 30 changed files with 1,758 additions and 1,558 deletions.
15 changes: 9 additions & 6 deletions audio.js
@@ -1,12 +1,15 @@
// Copyright 2011-2012 Kevin Reid under the terms of the MIT License as detailed // Copyright 2011-2012 Kevin Reid under the terms of the MIT License as detailed
// in the accompanying file README.md or <http://opensource.org/licenses/MIT>. // in the accompanying file README.md or <http://opensource.org/licenses/MIT>.


var CubesAudio = (function () { (function () {
var ID_EMPTY = cubes.Blockset.ID_EMPTY;
var ID_LIMIT = cubes.Blockset.ID_LIMIT;

var lAudioContext = typeof AudioContext !== "undefined" ? AudioContext var lAudioContext = typeof AudioContext !== "undefined" ? AudioContext
: typeof webkitAudioContext !== "undefined" ? webkitAudioContext : null; : typeof webkitAudioContext !== "undefined" ? webkitAudioContext : null;
var supported = !!lAudioContext; var supported = !!lAudioContext;


function CubesAudio(config) { function Audio(config) {
var context; var context;
if (supported) { if (supported) {
context = new lAudioContext(); /* feature test point */ context = new lAudioContext(); /* feature test point */
Expand Down Expand Up @@ -41,7 +44,7 @@ var CubesAudio = (function () {
function readBlock() { function readBlock() {
// Find volumes of material in the block // Find volumes of material in the block
counts = []; counts = [];
for (var i = 0; i < Blockset.ID_LIMIT; i++) counts.push(0); for (var i = 0; i < ID_LIMIT; i++) counts.push(0);
var raw = blockWorld.raw; var raw = blockWorld.raw;
for (var i = raw.length - 1; i >= 0; i--) { for (var i = raw.length - 1; i >= 0; i--) {
counts[raw[i]]++; counts[raw[i]]++;
Expand All @@ -61,7 +64,7 @@ var CubesAudio = (function () {


var totalAmp = 0; var totalAmp = 0;
var color = []; var color = [];
for (var value = Blockset.ID_EMPTY + 1; value < Blockset.ID_LIMIT; value++) { for (var value = ID_EMPTY + 1; value < ID_LIMIT; value++) {
var count = counts[value]; var count = counts[value];
if (count == 0) continue; if (count == 0) continue;


Expand Down Expand Up @@ -176,7 +179,7 @@ var CubesAudio = (function () {
} }
}); });
} }
CubesAudio.supported = supported; Audio.supported = supported;


return CubesAudio; cubes.Audio = Object.freeze(Audio);
}()); }());
138 changes: 72 additions & 66 deletions block-render.js
Expand Up @@ -8,81 +8,87 @@
// believe that it is obviously the authors' intent to make this code free to // believe that it is obviously the authors' intent to make this code free to
// use. // use.


// Renders single blocks from a world. (function () {

function BlockRenderer(blockset, renderer, resolution) {
"use strict"; "use strict";


var gl = renderer.context; var World = cubes.World;

var WorldRenderer = cubes.WorldRenderer;
var singleBlockWorld = new World([1,1,1], blockset);
singleBlockWorld.s(0,0,0,1);
var singleBlockR = new WorldRenderer(singleBlockWorld, function () { return [0,0,0]; }, renderer, null, function (){}, false);

var rttFramebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);
rttFramebuffer.width = resolution;
rttFramebuffer.height = resolution;

var renderbuffer1 = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer1);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, rttFramebuffer.width, rttFramebuffer.height);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer1);

var renderbuffer2 = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer2);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, rttFramebuffer.width, rttFramebuffer.height);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer2);

gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);


function blockToImageData(blockID, context2d) { // Renders single blocks from a world.
gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer); function BlockRenderer(blockset, renderer, resolution) {

var gl = renderer.context;
gl.viewport(0, 0, rttFramebuffer.width, rttFramebuffer.height);
gl.clearColor(0,0,0,0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);


var restoreView = renderer.saveView(); var singleBlockWorld = new World([1,1,1], blockset);
renderer.setExposure(1.0); singleBlockWorld.s(0,0,0,1);
renderer.setViewToBlock(); var singleBlockR = new WorldRenderer(singleBlockWorld, function () { return [0,0,0]; }, renderer, null, function (){}, false);
singleBlockWorld.s(0,0,0,blockID);
singleBlockWorld.rawLighting[0] = singleBlockWorld.lightOutside;
singleBlockR.updateSomeChunks();
singleBlockR.draw();


// restore stuff (except for framebuffer which we're about to read) var rttFramebuffer = gl.createFramebuffer();
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);
restoreView(); rttFramebuffer.width = resolution;
rttFramebuffer.height = resolution;


var imageData = context2d.createImageData(rttFramebuffer.width, rttFramebuffer.height); var renderbuffer1 = gl.createRenderbuffer();
var arrayC = imageData.data; gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer1);
var arrayGL = new Uint8Array(rttFramebuffer.width * rttFramebuffer.height * 4); gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, rttFramebuffer.width, rttFramebuffer.height);
gl.readPixels(0, 0, rttFramebuffer.width, rttFramebuffer.height, gl.RGBA, gl.UNSIGNED_BYTE, arrayGL); gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer1);


// copy into canvas data and flip y var renderbuffer2 = gl.createRenderbuffer();
var h = rttFramebuffer.height; gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer2);
var w = rttFramebuffer.width * 4; // width in bytes gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, rttFramebuffer.width, rttFramebuffer.height);
for (var y = h; y--; y >= 0) { gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer2);
var nyl = (h - y) * w;
var pyl = y * w;
for (var i = w - 1; i >= 0; i--)
arrayC[nyl + i] = arrayGL[pyl + i];
}


gl.bindTexture(gl.TEXTURE_2D, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.bindFramebuffer(gl.FRAMEBUFFER, null);


return imageData; function blockToImageData(blockID, context2d) {
gl.bindFramebuffer(gl.FRAMEBUFFER, rttFramebuffer);

gl.viewport(0, 0, rttFramebuffer.width, rttFramebuffer.height);
gl.clearColor(0,0,0,0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

var restoreView = renderer.saveView();
renderer.setExposure(1.0);
renderer.setViewToBlock();
singleBlockWorld.s(0,0,0,blockID);
singleBlockWorld.rawLighting[0] = singleBlockWorld.lightOutside;
singleBlockR.updateSomeChunks();
singleBlockR.draw();

// restore stuff (except for framebuffer which we're about to read)
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
restoreView();

var imageData = context2d.createImageData(rttFramebuffer.width, rttFramebuffer.height);
var arrayC = imageData.data;
var arrayGL = new Uint8Array(rttFramebuffer.width * rttFramebuffer.height * 4);
gl.readPixels(0, 0, rttFramebuffer.width, rttFramebuffer.height, gl.RGBA, gl.UNSIGNED_BYTE, arrayGL);

// copy into canvas data and flip y
var h = rttFramebuffer.height;
var w = rttFramebuffer.width * 4; // width in bytes
for (var y = h; y--; y >= 0) {
var nyl = (h - y) * w;
var pyl = y * w;
for (var i = w - 1; i >= 0; i--)
arrayC[nyl + i] = arrayGL[pyl + i];
}

gl.bindFramebuffer(gl.FRAMEBUFFER, null);

return imageData;
}

this.blockToImageData = blockToImageData;
this.deleteResources = function () {
rttFramebuffer = null;
gl.deleteRenderbuffer(renderbuffer1);
gl.deleteRenderbuffer(renderbuffer2);
gl.deleteFramebuffer(rttFramebuffer);
singleBlockR.deleteResources();
};
} }


this.blockToImageData = blockToImageData; cubes.BlockRenderer = BlockRenderer;
this.deleteResources = function () { }());
rttFramebuffer = null;
gl.deleteRenderbuffer(renderbuffer1);
gl.deleteRenderbuffer(renderbuffer2);
gl.deleteFramebuffer(rttFramebuffer);
singleBlockR.deleteResources();
};
}
27 changes: 16 additions & 11 deletions blockset.js
@@ -1,9 +1,21 @@
// Copyright 2011-2012 Kevin Reid under the terms of the MIT License as detailed // Copyright 2011-2012 Kevin Reid under the terms of the MIT License as detailed
// in the accompanying file README.md or <http://opensource.org/licenses/MIT>. // in the accompanying file README.md or <http://opensource.org/licenses/MIT>.


var BlockType = (function () { (function () {
"use strict"; "use strict";


var CatchupQueue = cubes.util.CatchupQueue;
var Cell = cubes.storage.Cell;
var Circuit = cubes.Circuit;
var CubeRotation = cubes.util.CubeRotation;
var max = Math.max;
var min = Math.min;
var mod = cubes.util.mod;
var Notifier = cubes.util.Notifier;
var ObjectMap = cubes.util.ObjectMap;
var Persister = cubes.storage.Persister;
var World = cubes.World;

function noop() {} function noop() {}


// Global non-persistent serial numbers for block types, used in the sound render queue. // Global non-persistent serial numbers for block types, used in the sound render queue.
Expand Down Expand Up @@ -191,14 +203,7 @@ var BlockType = (function () {
return self; return self;
}; };


return Object.freeze(BlockType); cubes.BlockType = Object.freeze(BlockType);
}());

var Blockset = (function () {
"use strict";

var max = Math.max;
var min = Math.min;


// Texture parameters // Texture parameters
var TILE_MAPPINGS = [ var TILE_MAPPINGS = [
Expand Down Expand Up @@ -654,7 +659,7 @@ var Blockset = (function () {
var blockIconsW = []; var blockIconsW = [];
var blockIconsR = []; var blockIconsR = [];
var toRerenderIcon = appearanceChangedQueue.getHead(); var toRerenderIcon = appearanceChangedQueue.getHead();
var iconRenderer = new BlockRenderer(blockset, renderer, blockRenderRes); var iconRenderer = new cubes./* late lookup */BlockRenderer(blockset, renderer, blockRenderRes);
var iconCanvas = document.createElement("canvas"); var iconCanvas = document.createElement("canvas");
var iconCtx = iconCanvas.getContext('2d'); var iconCtx = iconCanvas.getContext('2d');
iconCanvas.width = iconCanvas.height = blockRenderRes; iconCanvas.width = iconCanvas.height = blockRenderRes;
Expand Down Expand Up @@ -958,5 +963,5 @@ var Blockset = (function () {
} }
} }


return Object.freeze(Blockset); cubes.Blockset = Object.freeze(Blockset);
}()); }());
9 changes: 7 additions & 2 deletions body.js
@@ -1,9 +1,14 @@
// Copyright 2011-2012 Kevin Reid under the terms of the MIT License as detailed // Copyright 2011-2012 Kevin Reid under the terms of the MIT License as detailed
// in the accompanying file README.md or <http://opensource.org/licenses/MIT>. // in the accompanying file README.md or <http://opensource.org/licenses/MIT>.


var Body = (function () { (function () {
"use strict"; "use strict";


var AAB = cubes.util.AAB;
var CubeRotation = cubes.util.CubeRotation;
var IntVectorMap = cubes.util.IntVectorMap;
var measuring = cubes.measuring;

// physics constants // physics constants
var GRAVITY = 20; // cubes/s^2 var GRAVITY = 20; // cubes/s^2
var MAX_STEP_UP = 0.57; // cubes var MAX_STEP_UP = 0.57; // cubes
Expand Down Expand Up @@ -214,5 +219,5 @@ var Body = (function () {
} }
} }


return Body; cubes.Body = Object.freeze(Body);
}()); }());
16 changes: 14 additions & 2 deletions circuit.js
@@ -1,8 +1,20 @@
// Copyright 2011-2012 Kevin Reid under the terms of the MIT License as detailed // Copyright 2011-2012 Kevin Reid under the terms of the MIT License as detailed
// in the accompanying file README.md or <http://opensource.org/licenses/MIT>. // in the accompanying file README.md or <http://opensource.org/licenses/MIT>.


var Circuit = (function () { (function () {
"use strict"; "use strict";

var AAB = cubes.util.AAB;
var CubeRotation = cubes.util.CubeRotation;
var mod = cubes.util.mod;
var UNIT_PX = cubes.util.UNIT_PX;
var UNIT_PY = cubes.util.UNIT_PY;
var UNIT_PZ = cubes.util.UNIT_PZ;
var UNIT_NX = cubes.util.UNIT_NX;
var UNIT_NY = cubes.util.UNIT_NY;
var UNIT_NZ = cubes.util.UNIT_NZ;
var ZEROVEC = cubes.util.ZEROVEC;

var DEBUG_WIRE = false; var DEBUG_WIRE = false;


// These are slice'd because the circuit code does foo[aDirection] a lot, so we want the toString() behavior of real JS arrays. TODO: Review whether it would be better to use symbol strings (e.g. "px", "py", ...) or numbers for directions. // These are slice'd because the circuit code does foo[aDirection] a lot, so we want the toString() behavior of real JS arrays. TODO: Review whether it would be better to use symbol strings (e.g. "px", "py", ...) or numbers for directions.
Expand Down Expand Up @@ -703,5 +715,5 @@ var Circuit = (function () {
}); });
}; };


return Object.freeze(Circuit); cubes.Circuit = Object.freeze(Circuit);
}());; }());;
7 changes: 5 additions & 2 deletions config.js
Expand Up @@ -3,9 +3,12 @@


// Global option structure. // Global option structure.


var CubesConfig = (function () { (function () {
"use strict"; "use strict";


var Input = cubes.Input;
var PersistentCell = cubes.storage.PersistentCell;

function Config(storage, storagePrefix) { function Config(storage, storagePrefix) {
var config = this; var config = this;


Expand Down Expand Up @@ -45,5 +48,5 @@ var CubesConfig = (function () {
defineOption("currentTopWorld", "string", "Untitled"); defineOption("currentTopWorld", "string", "Untitled");
} }


return Config; cubes.Config = Object.freeze(Config);
}()); }());
10 changes: 6 additions & 4 deletions cubes.html
Expand Up @@ -16,16 +16,18 @@
<script type="text/javascript" src="deps/gl-matrix/gl-matrix.js"></script> <script type="text/javascript" src="deps/gl-matrix/gl-matrix.js"></script>
<script type="text/javascript" src="deps/game-shim/game-shim.js"></script> <script type="text/javascript" src="deps/game-shim/game-shim.js"></script>


<script type="text/javascript" src="module-initial.js"></script>

<!-- Framework --> <!-- Framework -->
<script type="text/javascript" src="util.js"></script> <script type="text/javascript" src="util.js"></script>
<script type="text/javascript" src="storage.js"></script> <script type="text/javascript" src="storage.js"></script>
<script type="text/javascript" src="measuring.js"></script> <script type="text/javascript" src="measuring.js"></script>


<!-- Game components --> <!-- Game components -->
<script type="text/javascript" src="circuit.js"></script>
<script type="text/javascript" src="blockset.js"></script> <script type="text/javascript" src="blockset.js"></script>
<script type="text/javascript" src="world.js"></script> <script type="text/javascript" src="world.js"></script>
<script type="text/javascript" src="world-gen.js"></script> <script type="text/javascript" src="world-gen.js"></script>
<script type="text/javascript" src="circuit.js"></script>
<script type="text/javascript" src="renderer.js"></script> <script type="text/javascript" src="renderer.js"></script>
<script type="text/javascript" src="world-render.js"></script> <script type="text/javascript" src="world-render.js"></script>
<script type="text/javascript" src="block-render.js"></script> <script type="text/javascript" src="block-render.js"></script>
Expand All @@ -41,7 +43,7 @@
This does not actually hook up the game to the UI or load the world; that is done by main.start() which is done onload. This does not actually hook up the game to the UI or load the world; that is done by main.start() which is done onload.
--> -->
<script type="text/javascript"> <script type="text/javascript">
var main = new CubesMain("./", 1/60 /* timestep */, localStorage); var main = new cubes.Main("./", 1/60 /* timestep */, localStorage);
</script> </script>
</head> </head>
<body class="ui-mode-hidden" onload='(function () { <body class="ui-mode-hidden" onload='(function () {
Expand Down Expand Up @@ -250,7 +252,7 @@ <h2>Options</h2>
<script>main.config.cubeParticles.bindControl("cubeParticles");</script> <script>main.config.cubeParticles.bindControl("cubeParticles");</script>
<div class="optionline"><label><input type="checkbox" id="enableSound"> Sound</label></div> <div class="optionline"><label><input type="checkbox" id="enableSound"> Sound</label></div>
<script> <script>
document.getElementById("enableSound").disabled = !CubesAudio.supported; document.getElementById("enableSound").disabled = !cubes.Audio.supported;
main.config.sound.bindControl("enableSound"); main.config.sound.bindControl("enableSound");
</script> </script>
<div class="optionline"><label><input type="checkbox" id="fsaa"> Fake 2× FSAA (I have fillrate to burn)</label></div> <div class="optionline"><label><input type="checkbox" id="fsaa"> Fake 2× FSAA (I have fillrate to burn)</label></div>
Expand All @@ -268,7 +270,7 @@ <h3>Controls</h3>
</tbody> </tbody>
</table> </table>
<script type="text/javascript"> <script type="text/javascript">
new CubesControlBindingUI(main.config.controls, document.getElementById("controls-config")); new cubes.ControlBindingUI(main.config.controls, document.getElementById("controls-config"));
</script> </script>
<p>To change a control binding, click on the current one and then press the key or mouse button you wish to use instead. To add an additional binding, click the “…”. To remove a binding, click on it and click the “×” button.</p> <p>To change a control binding, click on the current one and then press the key or mouse button you wish to use instead. To add an additional binding, click the “…”. To remove a binding, click on it and click the “×” button.</p>


Expand Down
4 changes: 3 additions & 1 deletion devel/bindings-testbed.html
Expand Up @@ -19,6 +19,8 @@
<link rel="stylesheet" href="../style.css" type="text/css"> <link rel="stylesheet" href="../style.css" type="text/css">


<script type="text/javascript" src="../deps/gl-matrix/gl-matrix.js"></script> <script type="text/javascript" src="../deps/gl-matrix/gl-matrix.js"></script>
<script type="text/javascript" src="../deps/game-shim/game-shim.js"></script>
<script type="text/javascript" src="../module-initial.js"></script>
<script type="text/javascript" src="../util.js"></script> <script type="text/javascript" src="../util.js"></script>
<script type="text/javascript" src="../storage.js"></script> <script type="text/javascript" src="../storage.js"></script>
<script type="text/javascript" src="../input.js"></script> <script type="text/javascript" src="../input.js"></script>
Expand All @@ -36,7 +38,7 @@
</tbody> </tbody>
</table> </table>
<script type="text/javascript"> <script type="text/javascript">
new CubesControlBindingUI(new Cell("test", Input.defaultBindings), document.getElementById("controls-config")); new cubes.ControlBindingUI(new cubes.storage.Cell("test", cubes.Input.defaultBindings), document.getElementById("controls-config"));
</script> </script>
</div> </div>


Expand Down

0 comments on commit c9e2ba6

Please sign in to comment.