Webã¯çŸåšã©ãã«ã§ããããã¢ããªã±ãŒã·ã§ã³ãäœæããã³é
åžããããã®éåžžã«åŒ·åãªç°å¢ãæäŸããŸãã ã«ãŒãã®ä»£ããã«ïŒã³ãŒãã®äœæâã³ã³ãã€ã«âéå§ãã¢ããªã±ãŒã·ã§ã³ãæŽæ°ãããããã©ãŠã¶ã§ã³ãŒãããã©ã€ããã§äœæããã ãã§ãã ããã«ãèšå€§ãªæ°ã®ãã©ãããã©ãŒã ã§ã¢ããªã±ãŒã·ã§ã³ãé
åžããã®ã¯æ¯èŒçç°¡åã§ãã è峿·±ãããšã«ãé廿°å¹Žéã§ãHTML5ã䜿çšããã²ãŒã éçºãçŸå®ã®ãã®ã«ãªããŸããã
canvasèŠçŽ ã¯HTML5ã§å°å
¥ããããããæäœããããã®APIãæäŸããŸãã APIã¯ã·ã³ãã«ã§ãããã°ã©ãã£ãã¯ã¹ãäžåºŠã䜿çšããããšããªãå Žåã¯ãæ
£ãããŸã§æéãããããŸãã Canvasã¯å€æ°ã®ãã©ãŠã¶ã§ãµããŒããããŠãããããWebã¯ã²ãŒã ãäœæããããã®åªãããã©ãããã©ãŒã ã«ãªããŸãã
ãã£ã³ãã¹ã®äœ¿çšã¯ç°¡åã§ããã¿ã°ãäœæããJavaScriptã§è¡šç€ºã³ã³ããã¹ããäœæãããã®ã³ã³ããã¹ãã§fillRectãdrawImageãªã©ã®ã¡ãœããã䜿çšããŠãã©ãŒã ãç»åã衚瀺ããŸãã APIã«ã¯ãããŸããŸãªãã¹ã®äœæãç»å倿ãªã©ã®ããã®å€ãã®ã¡ãœãããå«ãŸããŠããŸãã
ãã®èšäºã§ã¯ããã£ã³ãã¹ã䜿çšããŠã²ãŒã ãäœæããŸãã ã¹ãã©ã€ããè¡çªã®è¿œè·¡ããããŠãã¡ããççºã䌎ãå®éã®ã²ãŒã ã ççºã®ãªããªããŠã²ãŒã ïŒ
ãããŠããããç§ãã¡ãäœæããããšããŠããã²ãŒã ã§ãã
æºåãã
ã²ãŒã ã¯è€éã«èŠãããããããŸããããå®éã«ã¯ããã€ãã®ã³ã³ããŒãã³ãã䜿çšããããšã«ãªããŸãã ãã£ã³ãã¹ãè€æ°ã®ã¹ãã©ã€ããã³ãªãžã§ã³ãã©ããã³ã°ãã²ãŒã ã«ãŒããã©ãã ã䜿çšã§ãããããã€ãé©ããŸããã
ã²ãŒã ã®ã³ã³ããŒãã³ãã«å®å
šã«çŠç¹ãåœãŠãããã«ãã³ãŒããšAPIã®ãã¹ãŠã®è¡ãåã¿ãŸããã ãã®èšäºã¯äžçŽã¬ãã«ã§æžãããŠããŸããããã¹ãŠã®ã¬ãã«ã®äººã
ãçè§£ã§ããããšãé¡ã£ãŠããŸãã ãã®èšäºã¯ãèªè
ããã§ã«JavaScriptãšHTMLã®åºæ¬ã«ç²ŸéããŠããããšãåæãšããŠããŸãã ãŸãããã£ã³ãã¹APIãšãã²ãŒã ã«ãŒããªã©ã®åºæ¬çãªã²ãŒã ã®ååã«ã€ããŠãè§ŠããŸãã
ãã£ã³ãã¹ãäœæ
ã³ãŒãã®åŠç¿ãå§ããŸãããã ã²ãŒã ã®ã»ãšãã©ã¯
app.jsã«ãããŸããæåã«è¡ãããšã¯ãã¿ã°ãäœæãããã®å¹
ãšé«ããèšå®ããããšã§ãã ãã¹ãŠãJSã«ä¿æããããã«ãããåçã«è¡ããŸãããHTMLããã¥ã¡ã³ãã§ãã£ã³ãã¹ãäœæãã
getElementByIdã䜿çšããŠååŸã§ããŸãã 2ã€ã®éã«éãã¯ãããŸãããããã¯åã«å¥œã¿ã®åé¡ã§ãã
Canvasã«ã¯ã衚瀺ã³ã³ããã¹ããååŸããããã«äœ¿çšããã
getContextã¡ãœããããããŸãã ã³ã³ããã¹ãã¯ããã£ã³ãã¹APIãšå¯Ÿè©±ããã¡ãœãããåŒã³åºãããšã«ãããªããžã§ã¯ãã§ãã 3Dã·ãŒã³ã«WebGLã䜿çšããå Žåã¯ããã©ã¡ãŒã¿ãŒ 'webgl'ãæž¡ãããšãã§ããŸãã
次ã«ã
ctx倿°ã䜿çšããŠãã¹ãŠã®èŠçŽ ã衚瀺ããŸãã
ã²ãŒã ãµã€ã¯ã«
ã²ãŒã ãåžžã«æŽæ°ããŠè¡šç€ºããã²ãŒã ãµã€ã¯ã«ãå¿
èŠã§ãã
ããã¯æ¬¡ã®ãããªãã®ã§ãã
ã·ãŒã³ãæŽæ°ããŠè¡šç€ºãã
requestAnimationFrameã䜿çšããŠæ¬¡ã®ã«ãŒãããã¥ãŒã«å
¥ããŸãã setTimeoutïŒã¡ã€ã³ã1000/60ïŒã䜿çšããŠã60ãã¬ãŒã /ç§ã衚瀺ããããšãããšãæ¬åœã«ç°¡åã«ãªããŸãã app.jsã®æäžéšã§requestAnimationFrameã®ã©ãããŒãäœæããŸããããã¹ãŠã®ãã©ãŠã¶ãŒããã®ã¡ãœããããµããŒãããŠããããã§ã¯ãªãããã§ãã
SetTimeoutïŒã¡ã€ã³ã1000/60ïŒã¯äœ¿çšãããŸãããããã¯ã粟床ãäœããäžèŠãªå Žåã«è¡šç€ºã«å€ãã®ãµã€ã¯ã«ãè²»ããããã§ãã
æŽæ°é¢æ°ã®dtã®ãã©ã¡ãŒã¿ãŒã¯ãçŸåšã®æå»ãšæåŸã®æŽæ°ã®æå»ã®å·®ã§ãã ãã¬ãŒã ã«äžå®ã®å€ã䜿çšããŠã·ãŒã³ããªãã¬ãã·ã¥ããªãã§ãã ããïŒã¹ããªããã§ã¯ãx + = 5ïŒã ã²ãŒã ã¯ç°ãªãã³ã³ãã¥ãŒã¿ãŒ/ãã©ãããã©ãŒã ã§ç°ãªãåäœãããããããã¬ãŒã ã¬ãŒãã«é¢ä¿ãªãã·ãŒã³ãæŽæ°ããå¿
èŠããããŸãã
ããã¯ãæåŸã®æŽæ°ããã®æéãèšç®ãããã¹ãŠã®åãã1ç§ãããã®ãã¯ã»ã«ã§è¡šçŸããããšã«ããå®çŸãããŸãã ãããŠãåãã¯æ¬¡ã®x + = 50 * dtãã€ãŸã50ãã¯ã»ã«/ç§ã«ãªããŸãã
ãªãœãŒã¹ã®èªã¿èŸŒã¿ãšã²ãŒã ã®èµ·å
ã³ãŒãã®æ¬¡ã®éšåã§ã¯ãã²ãŒã ãåæåããå¿
èŠãªãã¹ãŠã®ãªãœãŒã¹ãããŒãããŸãã ãããè¡ãã«ã¯ãåå¥ã«èšè¿°ããããã«ããŒã¯ã©ã¹ã®1ã€ã§ãã
resources.jsã䜿çšããŸãã ããã¯ããã¹ãŠã®ç»åãããŠã³ããŒããããã¹ãŠã®ç»åãèªã¿èŸŒãŸãããšã€ãã³ããçºçãããéåžžã«ã·ã³ãã«ãªã©ã€ãã©ãªã§ãã
ã²ãŒã ã«ã¯ãç»åãã·ãŒã³ããŒã¿ãªã©ã®ãªãœãŒã¹ãå«ãŸããŠããŸãã 2Dã²ãŒã ã®å Žåãäž»ãªãªãœãŒã¹ã¯ç»åã§ãã ããã«äœ¿çšã§ããããã«ããã«ã¯ãã¢ããªã±ãŒã·ã§ã³ãèµ·åããåã«ãã¹ãŠã®ãªãœãŒã¹ãããŠã³ããŒãããå¿
èŠããããŸãã
JavaScriptã䜿çšãããšãç»åãç°¡åã«ããŒãããŠãå¿
èŠãªãšãã«äœ¿çšã§ããŸãã
var img = new Image(); img.onload = function() { startGame(); }; img.src = url;
ãã¡ãããããããã®ç»åããªãéããããã¯éåžžã«é¢åã§ãã ããããã®ã°ããŒãã«å€æ°ãäœæããããŒããããã©ããããã§ãã¯ããå¿
èŠããããŸãã ããããã¹ãŠèªåçã«è¡ãããã®åºæ¬çãªãªãœãŒã¹ããŒããŒãäœæããŸããã
(function() { var resourceCache = {}; var loading = []; var readyCallbacks = [];
ä»çµã¿ïŒãã¹ãŠã®ã€ã¡ãŒãžãèªã¿èŸŒãã§resources.loadãåŒã³åºããæ¬¡ã«resources.onReadyãåŒã³åºããŠããã¹ãŠã®ããŒã¿ã®loadã€ãã³ãã§ã³ãŒã«ããã¯ãäœæããŸãã resources.loadã¯ã²ãŒã ã®åŸåã§äœ¿çšããããèµ·åæã«ã®ã¿äœ¿çšãããŸã
ã¢ããããŒããããç»åã¯resourcesCacheã«ãã£ãã·ã¥ããããã¹ãŠã®ç»åãã¢ããããŒãããããšããã¹ãŠã®ã³ãŒã«ããã¯ãåŒã³åºãããŸãã ãããè¡ãããšãã§ããŸãïŒ
resources.load([ 'img/sprites.png', 'img/terrain.png' ]); resources.onReady(init);
Resources.getïŒ 'img / sprites.pngïŒã䜿çšããŠç»åãååŸããŸãã ç°¡åïŒ
ãã¹ãŠã®ç»åãæåã§ããŠã³ããŒãããŠã²ãŒã ãå®è¡ããããããã»ã¹ãç°¡çŽ åããããã«resources.jsã®ç²Ÿç¥ã§äœãã䜿çšã§ããŸãã
äžèšã®ã³ãŒãã§ã¯ããã¹ãŠã®ç»åãèªã¿èŸŒãŸãããšinitãåŒã³åºãããŸãã Initã¯èæ¯ç»åãäœæãããPlay againããã¿ã³ã«ã€ãã³ããæããã²ãŒã ããªã»ããããŠéå§ããã²ãŒã ãéå§ããŸãã
function init() { terrainPattern = ctx.createPattern(resources.get('img/terrain.png'), 'repeat'); document.getElementById('play-again').addEventListener('click', function() { reset(); }); reset(); lastTime = Date.now(); main(); }
ã²ãŒã ã®ç¶æ
ããå§ããŸãããïŒ ã²ãŒã ããžãã¯ãå§ããŸãããã ãã¹ãŠã®ã²ãŒã ã®äžæ žã¯ãã²ãŒã ã®ç¶æ
ãã§ãã ãããã¯ãã²ãŒã ã®çŸåšã®ç¶æ
ã衚ãããŒã¿ã§ãããããäžã®ãªããžã§ã¯ãã®ãªã¹ãã座æšããã®ä»ã®ããŒã¿ã çŸåšã®ãã€ã³ããªã©ã
以äžãã²ãŒã ã®ç¶æ
ã§ãã
å€ãã®ããšã®ããã«æããŸãããå®éã«ã¯ããã¹ãŠãããã»ã©è€éã§ã¯ãããŸããã ã»ãšãã©ã®å€æ°ã¯è¿œè·¡ãããå€ã§ãïŒãã¬ãŒã€ãŒã®æåŸã®ã·ã§ããïŒlastFiredïŒãã²ãŒã ã®å®è¡æéïŒgameTimeïŒãã²ãŒã ã®çµäºïŒisGameOverïŒãå°åœ¢ç»åïŒterrainPatternïŒããã³ãã€ã³ãã ãããäžã®ãªããžã§ã¯ãã説æãããŠããŸãïŒåŒŸäžžãæµãççºã
ãã¬ãŒã€ãŒã®æ¬è³ªãããããã¬ãŒã€ãŒã®äœçœ®ãšã¹ãã©ã€ãã®ç¶æ
ã远跡ãããŸãã ã³ãŒãã«å
¥ãåã«ããšã³ãã£ãã£ãšã¹ãã©ã€ãã«ã€ããŠè©±ããŸãããã
ãšã³ãã£ãã£ãšã¹ãã©ã€ã
ãšã³ãã£ãã£
ãšã³ãã£ãã£ã¯ããããäžã®ãªããžã§ã¯ãã§ãã è¹ã匟䞞ãççºããã¹ãŠå®äœã§ãããã©ããã¯é¢ä¿ãããŸããã
ã·ã¹ãã å
ã®ãšã³ãã£ãã£ã¯ããªããžã§ã¯ãã®äœçœ®ãªã©ã«é¢ããæ
å ±ãæ ŒçŽããJavaScriptãªããžã§ã¯ãã§ãã ããã¯ãåã¿ã€ãã®ãšã³ãã£ãã£ãæåã§ç£èŠããéåžžã«ã·ã³ãã«ãªã·ã¹ãã ã§ãã åãšã³ãã£ãã£ã«ã¯ãposããã³spriteãããã³å Žåã«ãã£ãŠã¯ãã®ä»ã®ããããã£ããããŸãã ããšãã°ãæµããããã«è¿œå ããå Žåãæ¬¡ã®ããã«ããŸãã
enemies.push({ pos: [100, 50], sprite: new Sprite() });
ãã®ã³ãŒãã¯ãç¹å®ã®ã¹ãã©ã€ãã䜿çšããŠãäœçœ®x = 100ãy = 50ã§æµããããã«è¿œå ããŸãã
ã¹ãã©ã€ããšã¢ãã¡ãŒã·ã§ã³
ã¹ãã©ã€ãã¯ããšã³ãã£ãã£ã®è¡šçŸã衚瀺ããç»åã§ãã ã¢ãã¡ãŒã·ã§ã³ããªãå Žåãã¹ãã©ã€ãã¯ctx.drawImageã䜿çšããŠè¡šãããéåžžã®ç»åã§ãã
ããã€ãã®ç»åãèªã¿èŸŒãã§ãæéã®çµéãšãšãã«ãããã倿Žããããšã§ãã¢ãã¡ãŒã·ã§ã³ãå®è£
ã§ããŸãã ããã¯ãã¬ãŒã ã¢ãã¡ãŒã·ã§ã³ãšåŒã°ããŸãã

ãããã®ç»åãæåããæåŸãŸã§äº€äºã«äžŠã¹ããšã次ã®ããã«ãªããŸãã

ç»åã®ç·šéãšèªã¿èŸŒã¿ãç°¡åã«ããããã«ãéåžžã¯ãã¹ãŠã1ã€ã«ãŸãšããããŸããããã¯ã¹ãã©ã€ãã«ãŒããšåŒã°ããŸãã ãã®CSSãã¯ããã¯ã¯æ¢ã«ãåããããããŸããã
ããã¯ãã²ãŒã ã®ã¹ãã©ã€ããããã§ãïŒèæ¯ã¯éæã§ãïŒã
ããŒãããã¥ãŒã ã€ã¡ãŒãžã»ããã䜿çšããŸãã ãã®ã»ããã¯bmpãã¡ã€ã«ã®ã»ãããªã®ã§ãå¿
èŠãªç»åãã³ããŒããŠ1ã€ã®ã¹ãã©ã€ãã·ãŒããã貌ãä»ããŸããã ãã®ããã«ã¯ãã·ã³ãã«ãªã°ã©ãã£ãã¯ãšãã£ã¿ãŒãå¿
èŠã§ãã
ãã¹ãŠã®ã¢ãã¡ãŒã·ã§ã³ãæåã§ç®¡çããããšã¯å°é£ã§ãã ãããè¡ãã«ã¯ã2çªç®ã®ãã«ããŒã¯ã©ã¹
sprite.jsã䜿çšããŸãã ããã¯ãã¢ãã¡ãŒã·ã§ã³ããžãã¯ãå«ãå°ããªãã¡ã€ã«ã§ãã èŠãŠã¿ãŸãããïŒ
function Sprite(url, pos, size, speed, frames, dir, once) { this.pos = pos; this.size = size; this.speed = typeof speed === 'number' ? speed : 0; this.frames = frames; this._index = 0; this.url = url; this.dir = dir || 'horizontal'; this.once = once; };
ããã¯ãSpriteã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã§ãã å€ãã®è°è«ãå¿
èŠã§ããããã¹ãŠãå¿
é ãšããããã§ã¯ãããŸããã ãããã®ãããããèæ
®ããŠãã ããïŒ
- url ïŒç»åãã¹
- pos ïŒã¹ãã©ã€ããããäžã®ç»åã®xããã³y座æš
- ãµã€ãº ïŒãµã€ãºïŒ1ãã¬ãŒã ã®ã¿ïŒ
- é床 ïŒãã¬ãŒã /ç§ã®ã¢ãã¡ãŒã·ã§ã³é床
- ãã¬ãŒã ïŒã¢ãã¡ãŒã·ã§ã³é ã®ãã¬ãŒã ã€ã³ããã¯ã¹ã®é
å
- dir ïŒã¹ãã©ã€ããããäžã§ç§»åããæ¹åïŒ 'horizoâântalïŒããã©ã«ãïŒãŸãã¯' vertical '
- once ïŒã¢ãã¡ãŒã·ã§ã³ã«ãŒãã1ã€ã ã衚瀺ããå Žåã¯trueãããã©ã«ã-false
ãã¬ãŒã åŒæ°ã«ã€ããŠã¯ãããããããã«èª¬æãå¿
èŠã§ãã ã¢ãã¡ãŒã·ã§ã³ã®ãã¹ãŠã®ãã¬ãŒã ã¯åããµã€ãºã§ãããšçè§£ãããŠããŸãïŒããã¯äžèšã§æž¡ããããµã€ãºã§ãïŒã ã¢ãã¡ãŒã·ã§ã³äžãã·ã¹ãã ã¯ãäœçœ®pos cããéå§ããŠãxãŸãã¯yè»žã«æ²¿ã£ãŠãµã€ãºããšã«å¢åããŠãã¹ãã©ã€ããããã«æ²¿ã£ãŠïŒdirå€ã«å¿ããŠïŒåã«ãç§»åãããŸãã ã¢ãã¡ãŒã·ã§ã³ã®ãã¬ãŒã ãã©ã®ããã«ééããå¿
èŠãããããèšè¿°ããããã«ããã¬ãŒã ãå®çŸ©ããå¿
èŠããããŸãã [0ã1ã2ã3ã2ã1]ãã¬ãŒã ã®å€ã¯ãæåããæåŸãŸã§ããããŠæåããæåŸãŸã§æ»ããŸãã
ã¢ãã¡ãŒã·ã§ã³ã¯äžèŠãªãããurlãposãsizeã®ã¿ãå¿
èŠã§ãã
åSpriteãªããžã§ã¯ãã«ã¯ãã¢ãã¡ãŒã·ã§ã³ãæŽæ°ããããã®updateã¡ãœãããããããã®åŒæ°ã¯ã°ããŒãã«æŽæ°ãšåæ§ã«ãã«ã¿æéã§ãã åã¹ãã©ã€ãã¯ããã¬ãŒã ããšã«æŽæ°ããå¿
èŠããããŸãã
Sprite.prototype.update = function(dt) { this._index += this.speed*dt; }
åSpriteãªããžã§ã¯ãã«ã¯ãããèªäœãã¬ã³ããªã³ã°ããããã®renderã¡ãœããããããŸãã ã¢ãã¡ãŒã·ã§ã³ã®åºæ¬çãªããžãã¯ãå«ãŸããŠããŸãã ã©ã®ãã¬ãŒã ãæç»ããããç£èŠããã¹ãã©ã€ããããäžã®åº§æšãèšç®ããctx.drawImageãåŒã³åºããŠãã¬ãŒã ãæç»ããŸãã
Sprite.prototype.render = function(ctx) { var frame; if(this.speed > 0) { var max = this.frames.length; var idx = Math.floor(this._index); frame = this.frames[idx % max]; if(this.once && idx >= max) { this.done = true; return; } } else { frame = 0; } var x = this.pos[0]; var y = this.pos[1]; if(this.dir == 'vertical') { y += frame * this.size[1]; } else { x += frame * this.size[0]; } ctx.drawImage(resources.get(this.url), x, y, this.size[0], this.size[1], 0, 0, this.size[0], this.size[1]); }
drawImageã®3ã€ã®åœ¢åŒã䜿çšããŸããããã«ãããã¹ãã©ã€ãã®ãµã€ãºããªãã»ãããããã³æ¹åãåå¥ã«æå®ã§ããŸãã
ã·ãŒã³æŽæ°
ã²ãŒã ã«ãŒãã§ããã¬ãŒã ããšã«æŽæ°ïŒdtïŒãåŒã³åºããæ¹æ³ãèŠããŠããŸããïŒ ããã§ãã®é¢æ°ãå®çŸ©ããå¿
èŠããããŸãããã®é¢æ°ã¯ããã¹ãŠã®ã¹ãã©ã€ãã®æŽæ°ããšã³ãã£ãã£ã®äœçœ®ãšè¡çªã®æŽæ°ãåŠçããå¿
èŠããããŸãã
unction update(dt) { gameTime += dt; handleInput(dt); updateEntities(dt);
æµããããã«è¿œå ããæ¹æ³ã«æ³šæããŠãã ããã ã©ã³ãã ãªå€ãèšå®ããããããå€ãããå°ããå Žåã¯æµã远å ããèŠããªããšããã®å³åŽã«è¿œå ããŸãã 瞊座æšã¯ãä¹±æ°ã«ãããã®é«ããšæµã®é«ãã®å·®ãæããããšã«ãã£ãŠç¢ºç«ãããŸãã æµã®ç»åã®é«ãã¯ãããŒãã³ãŒãåããããŠããããããã®é«ãã¯ããã£ãŠããŸãããã®ã³ãŒãã¯äŸãšããŠäœ¿çšãããŸãã
ãããå€ã¯ã颿°
1 - Math.pow(.993, gameTime)
ã«ãã£ãŠæ¯åäžæããŸãã
ããŒã¹ãããŒã¯
ããŒã¹ãããŒã¯ãåŠçããããã«ãå¥ã®å°ããªã©ã€ãã©ãªãŒ
input.jsãäœæã
ãŸãã ã ããã¯ãkeyupããã³keydownã€ãã³ããã³ãã©ãŒã远å ããããšã«ãããæŒãããããŒã®ç¶æ
ãåçŽã«ä¿åããéåžžã«å°ããªã©ã€ãã©ãªã§ãã
ãã®ã©ã€ãã©ãªã¯ãinput.isDownãšãã1ã€ã®é¢æ°ãæäŸããŸãã 'a'ãªã©ã®åŒæ°ãšããŠåŒæ°ãåãããã®ããŒãæŒãããå Žåã«trueãè¿ããŸãã æ¬¡ã®å€ãæž¡ãããšãã§ããŸãã
- ã¹ããŒã¹
- å·Š
- å³
- ã¢ãã
- ããŠã³
ããã§ãããŒã¹ãããŒã¯ãåŠçã§ããŸãã
function handleInput(dt) { if(input.isDown('DOWN') || input.isDown('s')) { player.pos[1] += playerSpeed * dt; } if(input.isDown('UP') || input.isDown('w')) { player.pos[1] -= playerSpeed * dt; } if(input.isDown('LEFT') || input.isDown('a')) { player.pos[0] -= playerSpeed * dt; } if(input.isDown('RIGHT') || input.isDown('d')) { player.pos[0] += playerSpeed * dt; } if(input.isDown('SPACE') && !isGameOver && Date.now() - lastFire > 100) { var x = player.pos[0] + player.sprite.size[0] / 2; var y = player.pos[1] + player.sprite.size[1] / 2; bullets.push({ pos: [x, y], dir: 'forward', sprite: new Sprite('img/sprites.png', [0, 39], [18, 8]) }); bullets.push({ pos: [x, y], dir: 'up', sprite: new Sprite('img/sprites.png', [0, 50], [9, 5]) }); bullets.push({ pos: [x, y], dir: 'down', sprite: new Sprite('img/sprites.png', [0, 60], [9, 5]) }); lastFire = Date.now(); } }
ãã¬ãŒã€ãŒãsãŸãã¯äžç¢å°ãæŒããšããã¬ãŒã€ãŒã瞊座æšã«æ²¿ã£ãŠäžã«ç§»åããŸãã ãã£ã³ãã¹åº§æšç³»ã®å·Šäžé
ã«ã¯åº§æšïŒ0,0ïŒãããããããã¬ãŒã€ãŒã®äœçœ®ã倧ãããããšãç»é¢äžã®ãã¬ãŒã€ãŒã®äœçœ®ãå°ãããªããŸãã ä»ã®ãã¹ãŠã®ããŒã«ã€ããŠãåãããšãè¡ããŸããã
app.jsã®å
é ã§playerSpeedãå®çŸ©ããããšã«æ³šæããŠãã ããã èšå®ããéåºŠã¯æ¬¡ã®ãšããã§ãã
playerSpeedã«dtãã©ã¡ãŒã¿ãä¹ç®ããŠããã¬ãŒã å
ãç§»åãããã¯ã»ã«ã®åèšãèšç®ããŸãã æåŸã®æŽæ°ãã1ç§ãçµéããå Žåããã¬ãŒã€ãŒã¯200ãã¯ã»ã«ã0.5ã®å Žåã¯100ãã¯ã»ã«é²ã¿ãŸããããã¯ããã¬ãŒã ã¬ãŒãã«å¿ããäžå®ã®ç§»åé床ãšããŠè¡šç€ºãããŸãã
æåŸã«è¡ãã®ã¯ãããæ¡ä»¶äžã§ã®åŒŸäžžã·ã§ããã§ããã¹ããŒã¹ãæŒãããããã¯æåŸã®ã·ã§ãããã100ããªç§ä»¥äžçºçããŸããã lastFireã¯ã°ããŒãã«å€æ°ã§ãããã²ãŒã ã®ç¶æ
ã®äžéšã§ãã ã·ã§ããã®é »åºŠãå¶åŸ¡ããã®ã«åœ¹ç«ã¡ãŸããããããªããšããã¬ãŒã€ãŒã¯ãã¹ãŠã®ãã¬ãŒã ãæ®åœ±ã§ããŸãã ãšãŠãç°¡åã§ãããïŒ
var x = player.pos[0] + player.sprite.size[0] / 2; var y = player.pos[1] + player.sprite.size[1] / 2; bullets.push({ pos: [x, y], dir: 'forward', sprite: new Sprite('img/sprites.png', [0, 39], [18, 8]) }); bullets.push({ pos: [x, y], dir: 'up', sprite: new Sprite('img/sprites.png', [0, 50], [9, 5]) }); bullets.push({ pos: [x, y], dir: 'down', sprite: new Sprite('img/sprites.png', [0, 60], [9, 5]) }); lastFire = Date.now();
æ°ãã匟䞞ã®äœçœ®ãxããã³y座æšã§èšç®ããŸãã ãã¬ã€ã€ãŒã®äœçœ®ã«å ããŠããã¬ã€ã€ãŒã®é«ããšå¹
ã®ååãå ããŠããã¬ã€ã€ãŒãè¹ã®äžå¿ããæã€ããã«ããŸãã

åŒŸäžžã®æ¹åãç°ãªãããã3ã€ã®åŒŸäžžã远å ããŸãã ããã«ããããã¬ãŒã€ãŒããã©ããã§ããªããããã²ãŒã ãç°¡åã«ãªããŸãã ç®æ¡æžããšã³ãã£ãã£ãåºå¥ããããã«ããdirãããããã£ã«å€ãforwardãããupãããdownãã远å ããŸããã
ãšã³ãã£ãã£
ãã¹ãŠã®ãšã³ãã£ãã£ãæŽæ°ããå¿
èŠããããŸãã ãã¬ã€ã€ãŒã®æ¬è³ªãšãåŒŸäžžãæµãççºã®æ¬è³ªãæã€3ã€ã®ã¢ã¬ã€ããããŸãã
function updateEntities(dt) {
ããäžåºŠå§ããŸãããããã¬ãŒã€ãŒã®ã¹ãã©ã€ãã¯ãã¹ãã©ã€ãæŽæ°æ©èœãåŒã³åºãã ãã§æŽæ°ãããŸãã ããã«ãããã¢ãã¡ãŒã·ã§ã³ãåæ¹ã«ç§»åããŸãã
åŒŸäžžãæµãççºã®æ¬¡ã®3ã€ã®ãµã€ã¯ã«ã ããã»ã¹ã¯èª°ã§ãåãã§ããã¹ãã©ã€ããæŽæ°ããåããæŽæ°ãããšã³ãã£ãã£ãã·ãŒã³ã®å¢çãè¶ããå Žåã¯åé€ããŸãã ãã¹ãŠã®ãšã³ãã£ãã£ãç§»åã®æ¹åã倿Žããããšã¯ã§ããªããããå¯èŠé åãé¢ããåŸã«ãšã³ãã£ãã£ãä¿åããå¿
èŠã¯ãããŸããã
匟䞞ã®åããæãé£ããã§ãïŒ
switch(bullet.dir) { case 'up': bullet.pos[1] -= bulletSpeed * dt; break; case 'down': bullet.pos[1] += bulletSpeed * dt; break; default: bullet.pos[0] += bulletSpeed * dt; }
bullet.dir = 'up'ã®å Žåã匟䞞ãy軞ã®äžã«ç§»åããŸãã éã«ãdir = 'down'ã®å Žåãããã©ã«ãå€ã§ã¯æšªè»žã«æ²¿ã£ãŠç§»åããŸãã
次ã«ãç®æ¡æžããšã³ãã£ãã£ãåé€ã§ãããã©ããã確èªããŸãã 匟䞞ã¯ãããã®æ¹åã«ã®ã¿ç§»åãããããäœçœ®ã¯äžç«¯ãäžç«¯ãããã³å³ç«¯ã«å¯ŸããŠãã§ãã¯ãããŸãã
è¡é æåãåé€ããã«ã¯ããã®ãªããžã§ã¯ããé
åããåé€ããŠiãæžãããŸãã
è¡çªè¿œè·¡
誰ããæããŠãããã®ã®ããã«ïŒè¡çªè¿œè·¡ïŒ å®éãå°ãªããšãç§ãã¡ã®ã²ãŒã ã§ã¯ãèŠãç®ã»ã©é£ãããããŸããã
远跡ããå¿
èŠãããè¡çªã«ã¯3ã€ã®ã¿ã€ãããããŸãã
- æµãšåŒŸäžž
- æµãšãã¬ã€ã€ãŒ
- ãã¬ãŒã€ãŒãšç»é¢ã®ç«¯
2Dè¡çªã®æ€åºã¯ç°¡åã§ãïŒ
function collides(x, y, r, b, x2, y2, r2, b2) { return !(r <= x2 || x > r2 || b <= y2 || y > b2); } function boxCollides(pos, size, pos2, size2) { return collides(pos[0], pos[1], pos[0] + size[0], pos[1] + size[1], pos2[0], pos2[1], pos2[0] + size2[0], pos2[1] + size2[1]); }
ãããã®2ã€ã®æ©èœã1ã€ã«ãŸãšããããšãã§ããŸãããç§ã«ã¯ãšãŠãèªã¿ãããããã§ãã collidesã¯ãäž¡æ¹ã®ãªããžã§ã¯ãã®äž/å·Šããã³äž/å³é
ã®åº§æšãååŸãã亀差ããããã©ããã確èªããŸãã
boxCollides颿°ã¯ãåèŠçŽ ã®äœçœ®ãšãµã€ãºãæã€é
åãåãå
¥ããè¡çªã®ã©ãããŒã§ãã 颿°ã§ã¯ã次å
ã䜿çšããŠçµ¶å¯Ÿäœçœ®åº§æšãèšç®ããŸãã
ãããŠãå®éã«è¡çªãæ€åºããã³ãŒãã¯æ¬¡ã®ãšããã§ãã
function checkCollisions() { checkPlayerBounds();
è¡çªæ€åºã¯ææ°é¢æ°çã§ããã·ãŒã³äžã®åãšã³ãã£ãã£éã®è¡çªããã§ãã¯ããå¿
èŠãããããã§ãã ã²ãŒã ã§ã¯ããã¹ãŠã®æµããã¹ãŠã®åŒŸäžžã«å¯ŸããŠãã¹ãããå¿
èŠããããŸãã æµã®é
åãç¹°ãè¿ããå匟䞞ã®ãµã€ã¯ã«ã§è¡çªããã§ãã¯ããŸãã
BoxCollidesãåŒã³åºãããæµãšåŒŸäžžã®äœçœ®ãšãµã€ãºã颿°ã«æž¡ããŸãã颿°ãtrueãè¿ããšã次ã®ããšãèµ·ãããŸãã
- æµã®é€å»
- ãã€ã³ãã远å ãã
- ãšã¯ã¹ãããŒãžã§ã³ãšãã»ã³ã¹ã远å
- 匟䞞ã®é€å»
- æµãååšããªããããå
éšã®åŒŸäžžãµã€ã¯ã«ã忢ãã
ççºã®çºçæ¹æ³ã«æ³šæããŠãã ããã ããããã£posããã³ã¹ãã©ã€ãã䜿çšããŠãªããžã§ã¯ããäœæããã¹ãã©ã€ããããã§ã¢ãã¡ãŒã·ã§ã³çšã«13ãã¬ãŒã ãæå®ããŸãã ãŸããã¢ãã¡ãŒã·ã§ã³ã1åã ãåçãããããã«ãonceãã©ã¡ãŒã¿ãŒãtrueã§ããããšã瀺ããŸãã
次ã®3è¡ãèŠãŠãã ããã
if(boxCollides(pos, size, player.pos, player.sprite.size)) { gameOver(); }
ããã§ã¯ããã¬ã€ã€ãŒãšæµã®è¡çªããã§ãã¯ããè¡çªãããã°ã²ãŒã ãªãŒããŒã§ãã
æåŸã«ãcheckPlayerBoundsã«ã€ããŠèª¬æããŸãããã
function checkPlayerBounds() {
ãã¬ãŒã€ãŒãããããè¶
ããªãããã«ãã座æšã0ããã³canvas.width / canvas.heightå
ã«ç¶æããŸãã
ã¬ã³ããªã³ã°
ã»ãŒå®äºã§ãïŒ ããã§ã¯ãåãã¬ãŒã ã®ã·ãŒã³ã衚瀺ããããã«ã²ãŒã ã«ãŒãã«ãã£ãŠåŒã³åºãããã¬ã³ããŒé¢æ°ãå®çŸ©ããå¿
èŠããããŸãã ããã¯æ¬¡ã®ãããªãã®ã§ãã
æåã«è¡ãããšã¯ãèæ¯ã®æç»ã§ãã ctx.createPatternã䜿çšããŠinit颿°ã§å°åœ¢ã®èæ¯ãäœæããfillStyleãèšå®ããŠfillRect颿°ãåŒã³åºããŠèæ¯ãã¬ã³ããªã³ã°ããŸãã
次ã«ããã¬ã€ã€ãŒããã¹ãŠã®åŒŸäžžããã¹ãŠã®æµãšççºãæããŸãã renderEntitesã¯ããšã³ãã£ãã£ã®é
åãã«ãŒãããŠæç»ããŸãã renderEntityã¯ããã£ã³ãã¹å€æã䜿çšããŠãªããžã§ã¯ããç»é¢ã«é
眮ããŸãã ctx.saveã¯çŸåšã®å€æãä¿åããctx.restoreã¯ããã埩å
ããŸãã
ã¹ãã©ã€ãã¬ã³ããŒé¢æ°ãèŠããšãã¹ãã©ã€ããäœçœ®ïŒ0,0ïŒã«ããããšãããããŸãããctx.translateãåŒã³åºããšããªããžã§ã¯ããæ£ããå Žæã«ç§»åããŸãã
ã²ãŒã ãªãŒããŒ
æåŸã«è¡ãå¿
èŠãããã®ã¯ãã²ãŒã ã®çµäºãåŠçããããšã§ããã²ãŒã ãçµäºããããã®ç»é¢ã衚瀺ãã颿°gameOverãšãã²ãŒã ãåã³éå§ããå¥ã®ãªã»ãããå®çŸ©ããå¿
èŠããããŸãã
gameOverã¯ãindex.htmlã§å®çŸ©ãããç»é¢ã«ãGane Overããšè¡šç€ºããããrestartããã¿ã³ã衚瀺ãããŸãããªã»ããã¯ããã¹ãŠã®ã²ãŒã ç¶æ
å€ãåæã«èšå®ããã²ãŒã çµäºç»é¢ãé衚瀺ã«ããŠãã²ãŒã ãåèµ·åããŸããæçµçãªèã
ãã®èšäºã§ã¯å€ãã®ããšãåŠã¶å¿
èŠããããŸãããã²ãŒã ã®äœæãããã»ã©é£ãããªãããšã瀺ãããã«ãããªãåçŽãªéšåã«åå²ããããšãé¡ã£ãŠããŸããäœã¬ãã«ã®Canvas APIã䜿çšããŠãæè¿ã®2Dã²ãŒã ã®äœæãããã«ç°¡åããæããã«ããããšã«çŠç¹ãåœãŠãŸããããã¡ãããæ¬åœã«è€éãªãã®ãäœæããããã«äœ¿çšã§ããããã€ãã®ã²ãŒã ãšã³ãžã³ããããŸããå€ãã®ã²ãŒã ãšã³ãžã³ã¯ããšã³ãã£ãã£ã®ã€ã³ã¿ãŒãã§ã€ã¹ãæšæºåããŠãããåã¿ã€ãã®ã¬ã³ããªã³ã°ããã³æŽæ°é¢æ°ãå®çŸ©ããã ãã§ãã·ãŒã³ãããŒãžã£ãŒã¯ãã¹ãŠã®ãã¬ãŒã ã®ãã¹ãŠã®ãšã³ãã£ãã£ã«å¯ŸããŠããããèªåçã«åŒã³åºããŸãã