ベンジャミンさんの HTML5 サンプル( canvas )

  code.js ( 実用用に若干変更 )



www.benjoffe.com

スクロールされるページで動作させる為に、CTRL キーが押されている時だけキー操作を可能にしています。

また、overlay という ID は、ブログによっては使用されて動作しなくなるので、overlay_html5 に変更しています。

※ 注意事項
ExplorerCanvas のライブラリが IE での動作には必要になります。

以下実装したブログ

ベンジャミンさんの HTML5 サンプル

001./**
002. * Copyright (c) 2009, Benjamin Joffe
003. * All rights reserved.
004. * Redistribution and use in source and binary forms, with or without
005. * modification, are permitted provided that the following conditions are met:
006. *
007. *     * Redistributions of source code must retain the above copyright
008. *       notice, this list of conditions and the following disclaimer.
009. *     * Redistributions in binary form must reproduce the above copyright
010. *       notice, this list of conditions and the following disclaimer in the
011. *       documentation and/or other materials provided with the distribution.
012. *
013. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY
014. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
015. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
016. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE FOR ANY
017. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
018. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
019. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
020. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
022. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023. */
024. 
025.var map;
026.var canvas;
027.var overlay;
028.//variables initiated at the bottom of the code...
029. 
030.var pi=Math.PI;
031. 
032.var total=0;
033. 
034.Number.prototype.range=function(){
035.    return (this+2*pi)%(2*pi);
036.}
037.Number.prototype.roundC=function(){
038.    return Math.round(this*100)/100;
039.}
040. 
041.var total=0;
042. 
043.var samples=200;
044. 
045. 
046.var arena=[];
047.arena[0]=[1,1,1,1,1,1,1,1,1,1]
048.arena[1]=[1,0,0,0,0,0,0,0,0,1]
049.arena[2]=[1,0,0,1,0,1,1,1,0,1]
050.arena[3]=[1,0,1,0,0,0,0,1,0,1]
051.arena[4]=[1,0,0,0,0,1,0,1,0,1]
052.arena[5]=[1,0,1,1,0,0,0,0,0,1]
053.arena[6]=[1,0,0,1,0,1,1,1,0,1]
054.arena[7]=[1,1,0,1,0,0,0,1,0,1]
055.arena[8]=[1,0,0,1,0,1,0,0,0,1]
056.arena[9]=[1,1,1,1,1,1,1,1,1,1]
057. 
058. 
059.var playerPos=[4,4]; // x,y (from top left)
060.var playerDir=0.4; // theta, facing right=0=2pi
061.var playerPosZ=1;
062.var key=[0,0,0,0,0]; // left, right, up, down
063. 
064.var playerVelY=0;
065. 
066. 
067.var face=[];
068. 
069.function wallDistance(theta){
070. 
071.    var data=[];
072.    face=[];
073. 
074.    var x = playerPos[0], y = playerPos[1];
075.    var deltaX, deltaY;
076.    var distX, distY;
077.    var stepX, stepY;
078.    var mapX, mapY
079.     
080.    var atX=Math.floor(x), atY=Math.floor(y);
081. 
082.    var thisRow=-1;
083.    var thisSide=-1;
084. 
085.    var lastHeight=0;
086. 
087.    for (var i=0; i<samples; i++) {
088.        theta+=pi/(3*samples)+2*pi;
089.        theta%=2*pi;
090. 
091.        mapX = atX, mapY = atY;
092. 
093.        deltaX=1/Math.cos(theta);
094.        deltaY=1/Math.sin(theta);
095. 
096.        if (deltaX>0) {
097.            stepX = 1;
098.            distX = (mapX + 1 - x) * deltaX;
099.        }
100.        else {
101.            stepX = -1;
102.            distX = (x - mapX) * (deltaX*=-1);     
103.        }
104.        if (deltaY>0) {
105.            stepY = 1;
106.            distY = (mapY + 1 - y) * deltaY;
107.        }
108.        else {
109.            stepY = -1;
110.            distY = (y - mapY) * (deltaY*=-1);
111.        }
112.         
113. 
114.        for (var j=0; j<20; j++) {
115.            if (distX < distY) {
116.                mapX += stepX;
117.                if (arena[mapX][mapY]) {
118.                    if (thisRow!=mapX || thisSide!=0) {
119.                        if (i>0) {
120.                            data.push(i);
121.                            data.push(lastHeight);
122.                        }
123.                        data.push(i);
124.                        data.push(distX);
125.                        thisSide=0;
126.                        thisRow=mapX;
127.                        face.push(1+stepX);
128.                    }
129.                    lastHeight=distX;
130.                    break;
131.                }
132.                distX += deltaX;
133.            }
134.            else {
135.                mapY += stepY;
136.                if (arena[mapX][mapY]) {
137.                    if (thisRow!=mapY || thisSide!=1) {
138.                        if (i>0) {
139.                            data.push(i);
140.                            data.push(lastHeight);
141.                        }  
142.                        data.push(i);
143.                        data.push(distY);
144.                        thisSide=1;
145.                        thisRow=mapY;
146.                        face.push(2+stepY)
147.                    }
148.                    lastHeight=distY;
149.                    break;
150.                }
151.                distY += deltaY;
152.            }
153.        }
154.    }
155.    data.push(i);
156.    data.push(lastHeight);
157.     
158.    return data;
159.}
160. 
161. 
162.function drawCanvas(){
163. 
164.    canvas.clearRect(0,0,400, 300);
165. 
166.    var theta = playerDir-pi/6;
167. 
168.    var wall=wallDistance(theta);
169. 
170.    map.beginPath();
171.    map.clearRect(0,0,80,80);
172.    map.fillStyle="#3366CC";
173.    map.arc(playerPos[0]*8, playerPos[1]*8, 3, 0, 2*pi, true);
174.    map.fill();
175.    map.beginPath();
176.    map.moveTo(8*playerPos[0], 8*playerPos[1]);
177. 
178. 
179.    var linGrad;
180.     
181.    var tl,tr,bl,br;
182.     
183.    var theta1,theta2,fix1,fix2;
184.     
185.    for (var i=0; i<wall.length; i+=4) {
186. 
187.        theta1=playerDir-pi/6 + pi*wall[i]/(3*samples);
188.        theta2=playerDir-pi/6 + pi*wall[i+2]/(3*samples);
189.         
190.        fix1 = Math.cos(theta1-playerDir);
191.        fix2 = Math.cos(theta2-playerDir);
192. 
193.        var h=2-playerPosZ;
194. 
195.        var wallH1=100/(wall[i+1]*fix1);
196.        var wallH2=100/(wall[i+3]*fix2);
197. 
198.        tl=[wall[i]*2, 150-wallH1*h];
199.        tr=[wall[i+2]*2, 150-wallH2*h]
200.        br=[wall[i+2]*2, tr[1]+wallH2*2];
201.        bl=[wall[i]*2, tl[1]+wallH1*2]
202. 
203.        var shade1=Math.floor(wallH1*2+20); if (shade1>255) shade1=255;
204.        var shade2=Math.floor(wallH2*2+20); if (shade2>255) shade2=255;
205. 
206.        linGrad = canvas.createLinearGradient(tl[0],0,tr[0],0);
207.        linGrad.addColorStop(0, 'rgba('+(face[i/4]%2==0 ? shade1 : 0)+','+(face[i/4]==1 ? shade1 : 0)+','+(face[i/4]==2 ? 0 : shade1)+',1.0)');
208.        linGrad.addColorStop(1, 'rgba('+(face[i/4]%2==0 ? shade2 : 0)+','+(face[i/4]==1 ? shade2 : 0)+','+(face[i/4]==2 ? 0 : shade2)+',1.0)');
209. 
210.        canvas.beginPath();
211.        canvas.moveTo(tl[0], tl[1]);
212.        canvas.lineTo(tr[0], tr[1]);
213.        canvas.lineTo(br[0], br[1]);
214.        canvas.lineTo(bl[0], bl[1]);
215.        canvas.fillStyle = linGrad;
216.        canvas.fill();
217. 
218.     
219.        map.lineTo(playerPos[0]*8+Math.cos(theta1)*(wall[i+1])*8, playerPos[1]*8+Math.sin(theta1)*(wall[i+1])*8);
220.        map.lineTo(playerPos[0]*8+Math.cos(theta2)*(wall[i+3])*8, playerPos[1]*8+Math.sin(theta2)*(wall[i+3])*8);
221. 
222.         
223.    }
224.    map.fillStyle="#FF0000"
225.    map.fill();
226.     
227.}
228. 
229.function nearWall(x,y){
230.    var xx,yy;
231.    if (isNaN(x)) x=playerPos[0];
232.    if (isNaN(y)) y=playerPos[1];
233.    for (var i=-0.1; i<=0.1; i+=0.2) {
234.        xx=Math.floor(x+i)
235.        for (var j=-0.1; j<=0.1; j+=0.2) {
236.            yy=Math.floor(y+j);
237.            if (arena[xx][yy]) return true;
238.        }
239.    }
240.    return false;
241.}
242. 
243.var xOff = 0;
244.var yOff = 0;
245.function wobbleGun(){
246.    var mag=playerVelY;
247.    xOff = (10+Math.cos(total/6.23)*mag*90)
248.    yOff = (10+Math.cos(total/5)*mag*90)
249.    overlay.style.backgroundPosition = xOff + "px " + yOff + "px";
250.}
251. 
252. 
253.var jumpCycle=0;
254. 
255.var audio = window.Audio && new Audio("shoot.wav");
256. 
257.function shoot()
258.{
259.    audio && audio.play();
260.    canvas.save();
261.    canvas.strokeStyle = "#FFFF00";
262.    canvas.beginPath();
263.     
264.    canvas.moveTo(190+xOff, 140+yOff);
265.    canvas.lineTo(250+xOff, 170+yOff);
266.    canvas.closePath();
267.    canvas.stroke();
268.    canvas.restore();
269.    setTimeout('drawCanvas()',100);
270.}
271. 
272. 
273.function update(){
274. 
275.    total++;
276. 
277.    var change=false;
278. 
279.    if (jumpCycle) {
280.        jumpCycle--;
281.        change=true;
282.        playerPosZ = 1 + jumpCycle*(20-jumpCycle)/110;
283.    }
284.    else if (key[4]) jumpCycle=20;
285.     
286.    if (key[0]) {
287.        if (!key[1]) {
288.            playerDir-=0.07; //left
289.            change=true;
290.        }
291.    }
292.    else if (key[1]) {
293.        playerDir+=0.07; //right
294.        change=true;
295.    }
296. 
297.    if (change) {
298.        playerDir+=2*pi;
299.        playerDir%=2*pi;
300.        document.getElementById("sky").style.backgroundPosition=Math.floor(1-playerDir/(2*pi)*2400)+"px 0";
301.    }
302. 
303.    if (key[2] && !key[3]) {
304.        if (playerVelY<0.1) playerVelY += 0.02;
305.    }
306.    else if (key[3] && !key[2]) {
307.        if (playerVelY>-0.1) playerVelY -= 0.02;
308.    }
309.    else {
310.        if (playerVelY<-0.02) playerVelY += 0.015;
311.        else if (playerVelY>0.02) playerVelY -= 0.015;
312.        else playerVelY=0;
313.    }
314.     
315.     
316.    if (playerVelY!=0) {
317. 
318.        var oldX=playerPos[0];;
319.        var oldY=playerPos[1];     
320.        var newX=oldX+Math.cos(playerDir)*playerVelY;
321.        var newY=oldY+Math.sin(playerDir)*playerVelY;
322. 
323.        if (!nearWall(newX, oldY)) {
324.            playerPos[0]=newX;
325.            oldX=newX;
326.            change=true;
327.        }
328.        if (!nearWall(oldX, newY)) {
329.            playerPos[1]=newY;
330.            change=true;
331.        }
332. 
333.    }
334.     
335.    if (playerVelY) wobbleGun();
336.    if (change) drawCanvas();
337. 
338.}
339. 
340. 
341.function changeKey(ev, which, to){
342. 
343.    var userAgent = navigator.userAgent.toLowerCase();
344. 
345.    if ( ev.ctrlKey ) {
346.        switch (which){
347.            case 65:case 37: key[0]=to; break; // left
348.            case 87: case 38: key[2]=to; break; // up
349.            case 68: case 39: key[1]=to; break; // right
350.            case 83: case 40: key[3]=to; break;// down
351.            case 32: key[4]=to; break; // space bar;
352.            case 17: key[5]=to; break; // ctrl
353.            case 66: if (to) { shoot() } break; // b
354.        }
355.     
356.        if (userAgent.indexOf("msie") > -1) {
357.            ev.returnValue = false;
358.        }
359.        else {
360.            ev.preventDefault();
361.        }
362. 
363.    }
364.}
365.document.onkeydown=function(e){changeKey((e||window.event),(e||window.event).keyCode, 1);}
366.document.onkeyup=function(e){changeKey((e||window.event),(e||window.event).keyCode, 0);}
367. 
368. 
369.function initUnderMap(){
370.    var underMap=document.getElementById("underMap").getContext("2d");
371.    underMap.fillStyle="#FFF";
372.    underMap.fillRect(0,0, 200, 200);
373.    underMap.fillStyle="#444";
374.    for (var i=0; i<arena.length; i++) {
375.        for (var j=0; j<arena[i].length; j++) {
376.            if (arena[i][j]) underMap.fillRect(i*8, j*8, 8, 8);
377.        }  
378.    }
379.}
380. 
381. 
382.window.onload=function(){
383.    var ele = document.getElementById("map");
384.    if (!ele.getContext)
385.    {
386.      alert('An error occured creating a Canvas 2D context. This may be because you are using an old browser, if not please contact me and I\'ll see if I can fix the error.');
387.      return;
388.    }
389.    map=ele.getContext("2d");
390.    canvas=document.getElementById("canvas").getContext("2d");
391.    overlay=document.getElementById("overlay_html5");
392.    document.getElementById("sky").style.backgroundPosition=Math.floor(-playerDir/(2*pi)*2400)+"px 0";
393.    drawCanvas();
394.    initUnderMap();
395.    setInterval(update, 35);
396.}











  infoboard   管理者用   





フリーフォントWEBサービス
SQLの窓WEBサービス

SQLの窓フリーソフト

素材

一般WEBツールリンク

SQLの窓

フリーソフト

JSライブラリ