· 8 years ago · Nov 26, 2017, 01:46 PM
1<html>
2 <head>
3 <meta charset=utf-8>
4 <style>
5 body { margin: 0; }
6 canvas { width: 100%; height: 100%; }
7 </style>
8 <script type="text/javascript" src="three.min.js"></script>
9 <script type="text/javascript" src="jquery.js"></script>
10 </head>
11 <body>
12 <table width="100%" height="100%">
13 <tr>
14 <td width="10%">
15 Ad block 1 goes here
16 </td>
17 <td width="80%" height="100%">
18 <div id="gamebox" class="canvas">
19 </div>
20 </td>
21 <td width="10%">
22 Ad block 2 goes here
23 </td>
24 </tr>
25 </table>
26 <script type="text/javascript">
27 var scene, camera, renderer = null;
28 var texmgr, blockmaterial, flagmaterial, blankmaterial, warntag, explodewall, explodetexture, tagset, pivot1, boomflash = null;
29 var matrixsize = 10;
30 var controlx = 0;
31 var controly = 0;
32 var raycaster, mousevector, pickablelist = null;
33 var gameoverstate = false;
34 var flashstate = 0;
35 var explodescale = 0.1;
36 var map = null;
37
38 $(document).ready(function() {
39 $("#gamebox").height($(window).height());
40
41 scene = new THREE.Scene();
42 camera = new THREE.PerspectiveCamera(75, $("#gamebox").offsetWidth / $("gamebox").offsetHeight, 0.1, 1000);
43 renderer = new THREE.WebGLRenderer({preserveDrawingBuffer: true});
44 var container = document.getElementById('gamebox');
45 var w = container.offsetWidth;
46 var h = container.offsetHeight;
47 renderer.setSize(w, h);
48 container.appendChild(renderer.domElement);
49 window.addEventListener('resize', onWindowResize, false );
50 window.addEventListener('keydown', myOnKeydown, false);
51 window.addEventListener('keyup', myOnKeyup, false);
52 window.addEventListener('mousedown', myOnMouseDown, false);
53 window.addEventListener('contextmenu', myOnRightClick, false);
54
55 texmgr = new THREE.TextureLoader();
56 blockmaterial = new THREE.MeshBasicMaterial({map: texmgr.load('img/ButtonBasic.png')});
57 flagmaterial = new THREE.MeshBasicMaterial({map: texmgr.load('img/mark.jpg')});
58 blankmaterial = new THREE.SpriteMaterial({color: 0xffffff}); blankmaterial.visible = false;
59 warntag = new THREE.SpriteMaterial({map: texmgr.load('img/FlagProb.png'), color:0xffffff});
60 warntag.transparent = true;
61 warntag.opacity = 0.3;
62 //var warntexture = texmgr.load('img/FlagProb.png');
63 raycaster = new THREE.Raycaster();
64 mousevector = new THREE.Vector2();
65 pickablelist = new Array();
66 explodetexture = texmgr.load('img/lava.jpg');
67
68 // Load all the tags
69 tagset = new Array();
70 for(var i=1;i<25;i++) {
71 // var imgpath = ;
72 // tagset[i] = texmgr.load('img/Flag'+ i +'.png');
73 //var tagtex = texmgr.load(imgpath);
74 tagset[i] = new THREE.SpriteMaterial({map: texmgr.load('img/Flag'+ i +'.png'), color: 0xffffff})
75 tagset[i].transparent = true;
76 tagset[i].opacity = 0.3;
77 }
78
79 // Step 1: create the emtpy array structure. We will add to this as we go
80 map = new Array();
81 for(x=0;x<=matrixsize;x++) {
82 map[x] = new Array();
83 for(y=0;y<=matrixsize;y++) {
84 map[x][y] = new Array();
85 for(z=0;z<=matrixsize;z++) {
86 map[x][y][z] = new Array();
87 } } }
88
89 // Step 2: build a shell of the map in the scene. This will be filled in as the user digs into the cube top & bottom
90 for(x=0;x<matrixsize;x++) {
91 for(z=0;z<matrixsize;z++) {
92 createblock(x,0,z);
93 createblock(x,matrixsize-1,z);
94 } }
95 // left & right (top & bottom already placed)
96 for(y=1;y<matrixsize-1;y++) {
97 for(z=0;z<matrixsize;z++) {
98 createblock(0,y,z);
99 createblock(matrixsize-1,y,z);
100 } }
101 //front & back (all edges already placed)
102 for(x=1;x<=matrixsize-2;x++) {
103 for(y=1;y<=matrixsize-2;y++) {
104 createblock(x,y,0);
105 createblock(x,y,matrixsize-1);
106 } }
107
108 // Now fill the map with bomb locations
109 var count = 280;
110 while(count>0) {
111 x = Math.floor(Math.random() * (matrixsize-1));
112 y = Math.floor(Math.random() * (matrixsize-1));
113 z = Math.floor(Math.random() * (matrixsize-1));
114// console.log('['+ x +','+ y +','+ z +']');
115 if(!(map[x][y][z]['mine']==1)) {
116 map[x][y][z]['mine'] = 1;
117 count--;
118 }
119 }
120
121 pivot1 = new THREE.Mesh(new THREE.PlaneGeometry(1,1), new THREE.MeshBasicMaterial({color:0x000000}));
122 pivot1.material.visible = false;
123 scene.add(pivot1);
124 pivot1.add(camera);
125 camera.position.z = matrixsize*1.41;
126
127 boomflash = new THREE.Mesh(new THREE.PlaneGeometry(5,5), new THREE.MeshBasicMaterial({color:0xffffff}));
128 camera.add(boomflash);
129 boomflash.position.z = -1;
130 boomflash.material.visible = false;
131
132 animate();
133 console.log('['+ $("#gamebox").width() +','+ $("#gamebox").height() +']');
134 });
135
136 function createblock(x,y,z) {
137 map[x][y][z]['entity'] = new THREE.Mesh(new THREE.BoxGeometry(1,1,1), blockmaterial);
138 map[x][y][z]['entity'].position.x = -(matrixsize-1)/2.0 +x;
139 map[x][y][z]['entity'].position.y = -(matrixsize-1)/2.0 +y;
140 map[x][y][z]['entity'].position.z = -(matrixsize-1)/2.0 +z;
141 scene.add(map[x][y][z]['entity']);
142 pickablelist.push(map[x][y][z]['entity']);
143 }
144
145
146 function animate() {
147 requestAnimationFrame(animate);
148
149 if(controlx==1) {
150 pivot1.rotateX(0.01);
151 }else if(controlx==-1) {
152 pivot1.rotateX(-0.01);
153 }
154 if(controly==1) {
155 pivot1.rotateY(0.01);
156 }else if(controly==-1) {
157 pivot1.rotateY(-0.01);
158 }
159
160 if(gameoverstate==true) {
161 if(flashstate>2) {
162 boomflash.material.visible = false;
163 flashstate = true;
164 }else{
165 flashstate++;
166 }
167 explodescale += 0.5;
168 explodewall.scale.set(explodescale, explodescale, explodescale);
169 explodewall.rotation.x += 0.019;
170 explodewall.rotation.y += 0.015;
171 }
172
173 renderer.render(scene, camera);
174 }
175
176 function gameover(x,y,z) {
177
178 gameoverstate = true;
179 flashstate = 1;
180 boomflash.material.visible = true;
181
182 explodewall = new THREE.Mesh(new THREE.SphereGeometry(0.1, 12,12),
183 new THREE.MeshBasicMaterial({map:explodetexture, color:0xffffff}));
184 explodewall.position.x = -(matrixsize-1)/2.0 +x;
185 explodewall.position.y = -(matrixsize-1)/2.0 +y;
186 explodewall.position.z = -(matrixsize-1)/2.0 +z;
187 explodewall.material.side = THREE.DoubleSide;
188 explodewall.material.transparent = true;
189 explodewall.material.opacity = 0.7;
190 scene.add(explodewall);
191
192 // now turn the blown square black, and disable the chance to click on it
193 map[tx][ty][tz]['entity'].material = new THREE.MeshBasicMaterial({color:0x000000});
194 pickablelist.splice(pickablelist.indexOf(map[tx][ty][tz]['entity']), 1);
195 }
196
197 function myOnRightClick(myevent) {
198 myevent.preventDefault();
199 }
200
201 function myOnMouseDown(myevent) {
202 mousevector.set( (event.clientX/window.innerWidth)*2-1, -(event.clientY/window.innerHeight)*2+1);
203 raycaster.setFromCamera(mousevector, camera);
204 var intersectslist = raycaster.intersectObjects(pickablelist);
205 if(intersectslist.length>0) {
206 tx = intersectslist[0].object.position.x +(matrixsize-1)/2;
207 ty = intersectslist[0].object.position.y +(matrixsize-1)/2;
208 tz = intersectslist[0].object.position.z +(matrixsize-1)/2;
209
210 if(myevent.which==3) { // this was a right mouse-click
211 myevent.preventDefault();
212
213 // With this block, determine if it has been flagged. If not, add a flag to it. If it has, remove the flag. Either way, update all the surrounding tags (if they exist)
214 var direction = 0;
215 if(map[tx][ty][tz]['flag']==1) {
216 direction = -1;
217 map[tx][ty][tz]['entity'].material = blockmaterial;
218 map[tx][ty][tz]['flag'] = 0;
219 }else{
220 console.log('Right-clicked!');
221 direction = 1;
222 map[tx][ty][tz]['entity'].material = flagmaterial;
223 map[tx][ty][tz]['flag'] = 1;
224 }
225 map[tx][ty][tz]['entity'].geometry.buffersNeedUpdate = true;
226 map[tx][ty][tz]['entity'].geometry.uvsNeedUpdate = true;
227
228 for(x=-1;x<=1;x++) {
229 if(tx+x>=0 && tx+x<matrixsize) {
230 for(y=-1;y<=1;y++) {
231 if(ty+y>=0 && ty+y<matrixsize) {
232 for(z=-1;z<=1;z++) {
233 if(tz+z>=0 && tz+z<matrixsize) {
234 if(!(x==0 && y==0 && z==0)) { // skip the center
235 if(map[tx+x] && map[tx+x][ty+y] && map[tx+x][ty+y][tz+z]) { // ensure this location exists
236 if(map[tx+x][ty+y][tz+z]['tag']) { // ensure this has a tag, not a block
237// if(map[tx+x][ty+y][tz+z]['tagvalue']==0) { // This is currently 0 (aka hidden). Show the tag
238 // map[tx+x][ty+y][tz+z]['tag'].material.visible = true;
239 // }
240 map[tx+x][ty+y][tz+z]['tagvalue'] -= direction;
241 if(map[tx+x][ty+y][tz+z]['tagvalue']==0) {
242 map[tx+x][ty+y][tz+z]['tag'].material = blankmaterial;
243 }else if(map[tx+x][ty+y][tz+z]['tagvalue']<0) {
244 map[tx+x][ty+y][tz+z]['tag'].material = warntag;
245 console.log('Updating ['+ (tx+x) +','+ (ty+y) +','+ (tz+z) +'] (value='+ map[tx+x][ty+y][tz+z]['tagvalue'] +')');
246 }else{
247 map[tx+x][ty+y][tz+z]['tag'].material = tagset[map[tx+x][ty+y][tz+z]['tagvalue']];
248 }
249 } } } } } } } } }
250 }else{
251 // Determine if this location is a bomb or not.
252 if(map[tx][ty][tz]['mine']==1) {
253 if(!(map[tx][ty][tz]['flag']==1)) { // ignore any clicks on already-flagged bombs
254 gameover(tx,ty,tz);
255 }
256 }else{
257
258 pickablelist.splice(pickablelist.indexOf(map[tx][ty][tz]['entity']), 1); // removes the target square from the pickable list
259 map[tx][ty][tz]['entity'].geometry.dispose();
260 map[tx][ty][tz]['entity'].material.dispose();
261 scene.remove(map[tx][ty][tz]['entity']);
262 map[tx][ty][tz]['entity']=0;
263
264 //console.log('Clicked ['+ tx +','+ ty +','+ tz +']');
265 // Now add any missing cubes to the nearby spaces
266 var numbombs = 0;
267 for(x=-1;x<=1;x++) {
268 if(tx+x>=0 && tx+x<matrixsize) {
269 for(y=-1;y<=1;y++) {
270 if(ty+y>=0 && ty+y<matrixsize) {
271 for(z=-1;z<=1;z++) {
272 if(tz+z>=0 && tz+z<matrixsize) {
273 if(!(x==0 && y==0 && z==0)) { // skip the cube we just deleted
274 if(map[tx+x] && map[tx+x][ty+y] && map[tx+x][ty+y][tz+z]) { // make sure this location exists
275 if(map[tx+x][ty+y][tz+z]['mine']==1) {
276 numbombs++;
277 }
278 if(map[tx+x][ty+y][tz+z]['flag']==1) {
279 numbombs--; // if the user placed a flag on a bomb, this will result in no change to the flag shown
280 }
281 if(map[tx+x][ty+y][tz+z]['entity']==null) { // block not created here yet
282 createblock(tx+x,ty+y,tz+z);
283 // while doing this process, also count number of nearby bombs
284 }
285 } } } } } } } }
286
287 //if(numbombs>0) {
288 map[tx][ty][tz]['tagvalue'] = numbombs;
289 if(numbombs>0) {
290 map[tx][ty][tz]['tag'] = new THREE.Sprite(tagset[numbombs]);
291 console.log('Setting '+ map[tx][ty][tz]['tagvalue']);
292 }else if(numbombs<0) {
293 map[tx][ty][tz]['tag'] = new THREE.Sprite(blankmaterial);
294 }else {
295 map[tx][ty][tz]['tag'] = new THREE.Sprite(warntag);
296 map[tx][ty][tz]['tag'].material.visible = false;
297 }
298 map[tx][ty][tz]['tag'].position.x = -(matrixsize-1)/2.0 +tx;
299 map[tx][ty][tz]['tag'].position.y = -(matrixsize-1)/2.0 +ty;
300 map[tx][ty][tz]['tag'].position.z = -(matrixsize-1)/2.0 +tz;
301 scene.add(map[tx][ty][tz]['tag']);
302 }
303 }
304 }
305 }
306
307 function myOnKeydown(myevent) {
308 console.log(myevent.key);
309 switch(myevent.key) {
310 case 'ArrowUp': controlx = -1; break;
311 case 'ArrowDown': controlx = 1; break;
312 case 'ArrowLeft': controly = -1; break;
313 case 'ArrowRight': controly = 1; break;
314 }
315 }
316
317 function myOnKeyup(myevent) {
318 switch(myevent.key) {
319 case 'ArrowUp': case 'ArrowDown': controlx = 0; break;
320 case 'ArrowLeft': case 'ArrowRight': controly = 0; break;
321 }
322 }
323
324 function onWindowResize() {
325 camera.aspect = $("#gamebox").offsetWidth / $("gamebox").offsetHeight;
326 camera.updateProjectionMatrix();
327 renderer.setSize( $("#gamebox").offsetWidth, $("gamebox").offsetHeight );
328 }
329
330 //animate();
331 </script>
332 </body>
333</html>