├── README
├── dots
├── csg.js
├── dev.js
├── favicon.ico
├── game.js
├── glMatrix-0.9.5.min.js
├── index.html
├── meshes.js
├── package.json
├── particles.js
├── physics.js
├── reference.txt
├── server.js
├── shaders.js
├── tedge.js
├── textures.js
├── thick.png
└── thin.png
├── ducks
├── convert.html
├── converth.html
├── duck.js
├── duck.zip
├── game.js
├── glMatrix-0.9.5.min.js
├── gun.h
├── index.html
├── meshes.js
├── node_modules
│ └── socket.io
│ │ ├── .gitignore
│ │ ├── .npmignore
│ │ ├── History.md
│ │ ├── Makefile
│ │ ├── Readme.md
│ │ ├── index.js
│ │ ├── lib
│ │ ├── logger.js
│ │ ├── manager.js
│ │ ├── namespace.js
│ │ ├── parser.js
│ │ ├── socket.io.js
│ │ ├── socket.js
│ │ ├── store.js
│ │ ├── stores
│ │ │ ├── memory.js
│ │ │ └── redis.js
│ │ ├── transport.js
│ │ ├── transports
│ │ │ ├── flashsocket.js
│ │ │ ├── htmlfile.js
│ │ │ ├── http-polling.js
│ │ │ ├── http.js
│ │ │ ├── index.js
│ │ │ ├── jsonp-polling.js
│ │ │ ├── websocket.js
│ │ │ └── xhr-polling.js
│ │ └── util.js
│ │ └── package.json
├── physics.js
├── server.js
├── tedge.js
└── thick.png
├── rift
├── build-docs.bat
├── csg.js
├── dev.js
├── game.js
├── glMatrix-0.9.5.min.js
├── ideas.txt
├── index.html
├── meshes.js
├── model.html
├── particles.js
├── physics.js
├── reference.txt
├── release
│ ├── compiled.js
│ ├── index.html
│ └── introspection.mp3
├── shaders.js
├── tedge notes.txt
├── tedge.js
├── texture.html
├── textures.js
└── tools
│ └── documentation.js
├── space
├── dev.js
├── game.js
├── glMatrix-0.9.5.min.js
├── lab
│ ├── advanced.html
│ ├── compiled.html
│ ├── dev.js
│ ├── game.js
│ ├── glMatrix-0.9.5.min.js
│ ├── index.html
│ ├── meshes.js
│ ├── noise.txt
│ ├── physics.js
│ ├── print.html
│ ├── shaders.js
│ ├── tedge.js
│ ├── tedge.js.bak
│ └── tunnel.html
├── meshes.js
├── physics.js
├── shaders.js
├── stars.html
└── tedge.js
└── tanks
├── favicon.ico
├── game.js
├── glMatrix-0.9.5.min.js
├── index.html
├── link
├── meshes.js
├── package.json
├── server.js
├── singleplayer.html
├── tedge.js
├── thick.png
└── thin.png
/README:
--------------------------------------------------------------------------------
1 | A collection of 3D JavaScript games using WebGL.
2 |
3 | Developed by Team Duck.
--------------------------------------------------------------------------------
/dots/csg.js:
--------------------------------------------------------------------------------
1 | // constructive solid geometry -- needs some work
2 | // todo: support UVs
3 | // check intersection direction
4 |
5 | function LineIntersection(lineVertex, lineVector, pointA, pointB)
6 | {
7 | debugger;
8 | var c = VecSub(lineVertex, pointA);
9 | var v = VecSub(pointB, pointA);
10 | var d = VecLength(v);
11 | var t = VecDot(v, c);
12 | var q = VecAdd(pointA, VecScale(v, t/d));
13 | var vq = VecSub(q, lineVertex);
14 | var r = VecLength(vq) / VecDot(q, vq);
15 | var F = VecAdd(lineVertex, VecScale(lineVector, r));
16 | return F;
17 | //var r = VecDot(v, q);
18 | //t = (t + r) / d;
19 | // if 0 <= t <= d, then it's on the segment; otherwise it's off in space
20 | //if (t >= 0 && t <= d)
21 | // return VecAdd(pointA, VecScale(v, t / d));
22 | return;
23 | }
24 |
25 | function LineOverlap(segmentA, segmentB, lineVector)
26 | {
27 | var aVector = VecSub(segmentA[1], segmentA[0]);
28 | var bVector = VecSub(segmentB[1], segmentB[0]);
29 | if (VecDot(aVector, lineVector) < 0) {
30 | var swap = segmentA[0];
31 | segmentA[0] = segmentA[1];
32 | segmentA[1] = swap;
33 | }
34 | if (VecDot(bVector, lineVector) < 0) {
35 | var swap = segmentB[0];
36 | segmentB[0] = segmentB[1];
37 | segmentB[1] = swap;
38 | }
39 | // a and b are both facing the same direction
40 | var q;
41 | if (VecDot(segmentA[0], lineVector) >= VecDot(segmentB[0], lineVector)) {
42 | q = segmentA[0];
43 | } else {
44 | q = segmentB[0];
45 | }
46 |
47 | var r;
48 | if (VecDot(segmentA[1], lineVector) <= VecDot(segmentB[1], lineVector)) {
49 | r = segmentA[1];
50 | } else {
51 | r = segmentB[1];
52 | }
53 |
54 | if (VecDot(VecSub(r, q), lineVector) > 0)
55 | return [q, r];
56 | return;
57 | }
58 |
59 | function CSG() {
60 | var csg = {
61 | mesh: {vertices: [], normals: [], uvs: [], count: 0},
62 |
63 | append: function(subMesh, transform, uvTransform) {
64 | if (transform) {
65 | subMesh = CloneMesh(subMesh);
66 | subMesh = TransformMesh(subMesh, transform);
67 | if (uvTransform)
68 | TransformMeshUVs(subMesh, uvTransform);
69 | }
70 |
71 | csg.mesh.count += subMesh.count;
72 | csg.mesh.vertices = csg.mesh.vertices.concat(subMesh.vertices);
73 | if (subMesh.normals)
74 | csg.mesh.normals = csg.mesh.normals.concat(subMesh.normals);
75 | if (subMesh.uvs)
76 | csg.mesh.uvs = csg.mesh.uvs.concat(subMesh.uvs);
77 | },
78 |
79 | subtract: function(subMesh, transform) {
80 | if (transform) {
81 | subMesh = CloneMesh(subMesh);
82 | subMesh = TransformMesh(subMesh, transform);
83 | }
84 |
85 | var mesh = csg.mesh;
86 | var culled = {count: 0, vertices: [], normals: [], uvs: []}
87 | var intersection = false;
88 |
89 | // go through each triangle in the mesh
90 | for (var i = 0; i < mesh.vertices.length; i+=9)
91 | {
92 | var segments = []; var linkedVertices = [];
93 | var linkedNormals = [];
94 | // go through each triangle of the subtrahend
95 | for (var j = 0; j < subMesh.vertices.length; j+=9)
96 | {
97 | // check if the triangles collide and find the overlapping segment
98 |
99 | // find the line of the intersection of the planes
100 | var mNormal = [mesh.normals[i], mesh.normals[i+1], mesh.normals[i+2]];
101 | var sNormal = [subMesh.normals[j], subMesh.normals[j+1], subMesh.normals[j+2]];
102 | var lineVector = VecCross(mNormal, sNormal);
103 | if (VecLengthSqr(lineVector) < 0.5) continue;
104 |
105 | var lineVertex;
106 | var mAnchor = Vector3(mesh.vertices[i], mesh.vertices[i+1], mesh.vertices[i+2]);
107 | var sAnchor = Vector3(subMesh.vertices[j], subMesh.vertices[j+1], subMesh.vertices[j+2]);
108 | lineVertex = VecDot(VecSub(mAnchor, sAnchor), mNormal);
109 | lineVertex = VecAdd(VecScale(mNormal, lineVertex), sAnchor);
110 |
111 | // clip segment along mTriangle
112 | var mSegment = []; var mK;
113 | for (var k = 0; k < 3; k++) {
114 | var m0 = Vector3(mesh.vertices[i+k*3], mesh.vertices[i+k*3+1], mesh.vertices[i+k*3+2]);
115 | var m1 = Vector3(mesh.vertices[i+((k+1)%3)*3],
116 | mesh.vertices[i+((k+1)%3)*3+1],
117 | mesh.vertices[i+((k+1)%3)*3+2]);
118 | var mV = LineIntersection(lineVertex, lineVector, m0, m1);
119 | if (mV) {
120 | mSegment.push(mV);
121 | } else {
122 | mK = k;
123 | }
124 | }
125 | if (mSegment.length < 2) continue;
126 |
127 | // clip segment along sTriangle
128 | var sSegment = [];
129 | for (var k = 0; k < 3; k++) {
130 | var s0 = Vector3(subMesh.vertices[j+k*3], subMesh.vertices[j+k*3+1], subMesh.vertices[j+k*3+2]);
131 | var s1 = Vector3(subMesh.vertices[j+((k+1)%3)*3],
132 | subMesh.vertices[j+((k+1)%3)*3+1],
133 | subMesh.vertices[j+((k+1)%3)*3+2]);
134 | var sV = LineIntersection(lineVertex, lineVector, s0, s1);
135 | if (sV) {
136 | sSegment.push(sV);
137 | }
138 | }
139 | if (sSegment.length < 2) continue;
140 |
141 | var segment = LineOverlap(mSegment, sSegment, lineVector);
142 | if (segment) {
143 | segments.push(segment);
144 | linkedVertices.push([
145 | Vector3(mesh.vertices[i+mK*3],
146 | mesh.vertices[i+mK*3+1],
147 | mesh.vertices[i+mK*3+2]),
148 | Vector3(mesh.vertices[i+((mK+1)%3)*3],
149 | mesh.vertices[i+((mK+1)%3)*3+1],
150 | mesh.vertices[i+((mK+1)%3)*3+2])
151 | ]);
152 | linkedNormals.push(mNormal);
153 | }
154 | }
155 | if (segments.length > 0) {
156 | // create new faces
157 | intersection = true;
158 | for (var k = 0; k < segments.length; k++) {
159 | culled.count += 2;
160 | culled.vertices = culled.vertices.concat(segments[k][0]);
161 | culled.vertices = culled.vertices.concat(segments[k][1]);
162 | culled.vertices = culled.vertices.concat(linkedVertices[k][0]);
163 | culled.vertices = culled.vertices.concat(segments[k][1]);
164 | culled.vertices = culled.vertices.concat(linkedVertices[k][1]);
165 | culled.vertices = culled.vertices.concat(linkedVertices[k][0]);
166 | for (var q = 0; q < 6; q++)
167 | culled.normals = culled.normals.concat(linkedNormals[k]);
168 | }
169 | } else {
170 | // no intersection, so keep this triangle
171 | culled.count++;
172 | for (var k = 0; k < 9; k++) {
173 | culled.vertices.push(mesh.vertices[i+k]);
174 | culled.normals.push(mesh.normals[i+k]);
175 | }
176 | if (mesh.uvs) {
177 | var ui = i*2/3;
178 | for (var k = 0; k < 6; k++) {
179 | culled.uvs.push(mesh.uvs[ui+k]);
180 | }
181 | }
182 | }
183 | }
184 |
185 | csg.mesh = culled;
186 | csg.mesh.uvs = [];
187 | },
188 |
189 | compile: function(transform) {
190 | var mesh = {vertices: csg.mesh.vertices, count: csg.mesh.count};
191 | if (csg.mesh.normals.length) mesh.normals = csg.mesh.normals;
192 | if (csg.mesh.uvs.length) mesh.uvs = csg.mesh.uvs;
193 | if (transform)
194 | mesh = TransformMesh(mesh, transform);
195 | return BufferMesh(mesh);
196 | }
197 | };
198 | return csg;
199 | }
200 |
--------------------------------------------------------------------------------
/dots/dev.js:
--------------------------------------------------------------------------------
1 | function TextSprite(text, style, font, x, y) {
2 | if (style === undefined) style = "white";
3 | if (font === undefined) font = "32px lucida console";
4 | if (x === undefined) x = 0;
5 | if (y === undefined) y = 0;
6 |
7 | var t = {"x": x, "y": y};
8 | var bitmap;
9 | var size;
10 | var texture = gl.createTexture();
11 | var mesh = BufferMesh(SQUARE_MESH);
12 |
13 |
14 | context.clearRect(0, 0, canvas2D.width, canvas2D.height);
15 | context.fillStyle = style;
16 | context.font = font;
17 | context.textBaseline = "top";
18 | context.fillText(text, 0, 0);
19 | size = context.measureText(text);
20 | t.size = size;
21 | var width = 1; while (width < size.width) width *= 2;
22 | bitmap = context.getImageData(0, 0, width, width);
23 | StoreTexture(texture, bitmap);
24 |
25 | var identity = Mat4List(Matrix4());
26 | var screen = Matrix4();
27 | screen = Mat4Mult(screen, Mat4Translate([1, -1, 0]));
28 | screen = Mat4Mult(screen, Mat4Scale(width/2, width/2, 1));
29 | screen = Mat4Mult(screen, Mat4Translate([-canvas.width/2, -canvas.height/2, 0]));
30 | screen = Mat4Mult(screen, Mat4Scale(2/canvas.width, 2/canvas.height, 1));
31 | screen = Mat4List(screen);
32 |
33 | if (x < 0) t.x = canvas.width - size.width + t.x;
34 |
35 | t.render = function (mtx) {
36 | // set up texture shader
37 | TEX_SHADER.enable();
38 |
39 | // orthogonal
40 | gl.uniformMatrix4fv(TEX_SHADER.pMatrix, false, identity);
41 | gl.uniformMatrix4fv(TEX_SHADER.vMatrix, false, screen);
42 |
43 | // blending for transparency
44 | gl.enable(gl.BLEND);
45 | gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
46 | gl.depthMask(false);
47 |
48 | // bind texture
49 | gl.activeTexture(gl.TEXTURE0);
50 | gl.bindTexture(gl.TEXTURE_2D, texture);
51 | gl.uniform1i(TEX_SHADER.samplerUniform, 0);
52 | DrawMesh(mesh, Mat4List(Mat4Translate([2*t.x/width, 2*(canvas.height - t.y)/width, 0])), TEX_SHADER);
53 |
54 | gl.disable(gl.BLEND);
55 | gl.depthMask(true);
56 |
57 | // draw
58 | gl.uniformMatrix4fv(TEX_SHADER.pMatrix, false, pMatrix);
59 | gl.uniformMatrix4fv(TEX_SHADER.vMatrix, false, vMatrix);
60 | TEX_SHADER.disable();
61 | STD_SHADER.enable();
62 | }
63 | return t;
64 | }
65 |
--------------------------------------------------------------------------------
/dots/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/teamduck/gametube/40e8ea4b963148dadadea1f7d28f6d10e0a07953/dots/favicon.ico
--------------------------------------------------------------------------------
/dots/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | DOTS
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
24 |
25 |
26 |
28 |