JavaScriptのローグライク/ RPG(30行のコード)

30行の単純なJavaScript玩具の実装に関する一連の投稿の後、私はこの「競争」に挑戦することにしました。 夕方に座った後、「本格的な」ローグライク/ RPGを作成することが判明しました(ジャンルについてはあまり知りませんが、この方向で何かが起こりました)。 同時に、私はJavaScriptを学びました(その前にJavaScriptを書いたことはありませんでしたが、どういうわけかすべてのC ++に手を出しました)。



画像



機能:





ゲームについて


あなたはドラゴンから王女を救わなければならない勇敢な騎士としてプレイします。 騎士と一緒にドラゴンの洞窟に向かう途中で、モンスターとの戦いや小さな集落の訪問など、さまざまな冒険が行われます。 モンスターとの戦いの後、ヒーローは金と人生の経験を受け取ります。 ゴールドは、途中にあるお店で治療薬や治療薬の購入に使うことができます。 人生経験は主人公のレベルを上げ、そこから攻撃と防御が成長します。 ゲームの目的は、ドラゴンとの戦いに総合的に準備し、ドラゴンを倒して王女を解放することです。



フィドルへのリンク。



コード


基礎として、 この投稿からコードを取得し、必要な状態に「完成」させました。



ソースコード( フィドルを見てください):

ソースコード
(function(elid, wi, he, exp, pot, gld, hp, lvl, cur_e, e_sz){ var hit = function(){ evs[cur_e][8]-=lvl*4+6; if(evs[cur_e][8]<=0) { alert("Monster defeated and you got "+evs[cur_e][10]+"EXP and $"+evs[cur_e][11]); exp+=evs[cur_e][10];gld+=evs[cur_e][11]; while(exp>=lvl*10){exp-=lvl*10;lvl++;alert("Level Up!")} cur_e++; if(cur_e==e_sz) alert("Victory!") } else { hp-=Math.max(0,evs[cur_e][9]-lvl*2-1); if(hp<=0) alert("Game Over!") } } var use = function(){ if (pot>0){pot--;hp+=10;if(hp>100)hp=100} } var nxt = function(){ cur_e++ }, battle = ["Attack","Use Potion +10HP","Skip Battle",hit,use,nxt], canvas=document.querySelector(elid), ctx=canvas.getContext("2d"), evs=[], e_tp=[ ["Shop", "Wizard provides his services", "Buy Potion $20", "Full Heal $100", "Leave", function(){ if(gld>=20){gld-=20;pot++} }, function(){ if(gld>=100){gld-=100;hp=100} }, nxt ], ["Skeleton", "A terrible skeleton on your way"].concat(battle,70,15,25,100), ["Goblin", "Green goblin wants to get your money"].concat(battle,50,10,15,70), ["Slime", "What the strange jelly monster?"].concat(battle,20,6,7,30), ["Dragon", "Omg! It is evil Dragon!","Attack","Use Potion +10HP","-",hit,use,,300,25,100,1000 ] ], q=e_tp.length-1; canvas.width=wi; canvas.height=he; for (var i=0;i<e_sz-1;i++) evs.push( e_tp[Math.floor(Math.random()*q)].slice(0) ); evs.push( e_tp[q].slice(0) ); var game = setInterval(function(){ ctx.clearRect(0,0,wi,he); ctx.fillText("NanoRPG in 30 lines of JavaScript by ripatti",10,15); ctx.fillText("LVL "+lvl+" HP "+hp+"/100 EXP "+exp+"/"+lvl*10+" ATK "+(lvl*4+6)+ " DEF "+(lvl*2+1)+" Gold $"+gld+" Potions "+pot,10,30); for (var i=0;i<e_sz;i++) ctx.fillText((i==e_sz-1||i<=cur_e)?evs[i][0]:"??",i*50+15,70); ctx.fillText("@",cur_e*50+25,60); ctx.fillText(evs[cur_e][1],20,100); if (evs[cur_e].length>8) ctx.fillText("Enemy HP "+evs[cur_e][8],250,100); for (var i=0;i<3;i++) { ctx.strokeRect(i*120+5,120,110,20); ctx.fillText(evs[cur_e][i+2],i*120+10,133); } }, 100); document.addEventListener('click', function(e){ for (var i=0;i<3;i++) if (i*120+5<=e.pageX && e.pageX<i*120+115 && 120<=e.pageY && e.pageY<140) if (hp>0) evs[cur_e][i+5]() }, false); })("#canvas",365,150,0,3,100,100,1,0,7);
      
      







50行のもう少し読みやすいバージョン( fiddleを見てください):

ソースコード
 (function(elid, wi, he, exp, pot, gld, hp, lvl, cur_e, e_sz){ var hit = function(){ evs[cur_e][8]-=lvl*4+6; if (evs[cur_e][8]<=0) { alert("Monster defeated and you got "+evs[cur_e][10]+"EXP and $"+evs[cur_e][11]); exp+=evs[cur_e][10]; gld+=evs[cur_e][11]; while (exp>=lvl*10) { exp-=lvl*10; lvl++; alert("Level Up!") } cur_e++; if (cur_e==e_sz) alert("Victory!") } else { hp-=Math.max(0,evs[cur_e][9]-lvl*2-1); if(hp<=0) alert("Game Over!") } } var use = function(){ if (pot>0){pot--;hp+=10;if(hp>100)hp=100} } var nxt = function(){ cur_e++ } var battle = ["Attack", "Use Potion +10HP", "Skip Battle", hit, use, nxt]; var canvas=document.querySelector(elid), ctx=canvas.getContext("2d"); canvas.width=wi; canvas.height=he; var evs=[], e_tp=[ ["Shop", "Wizard provides his services", "Buy Potion $20", "Full Heal $100", "Leave", function(){ if(gld>=20){gld-=20;pot++} }, function(){ if(gld>=100){gld-=100;hp=100} }, nxt ], ["Skeleton", "A terrible skeleton on your way"].concat(battle,70,15,25,100), ["Goblin", "Green goblin wants to get your money"].concat(battle,50,10,15,70), ["Slime", "What the strange jelly monster?"].concat(battle,20,6,7,30), ["Dragon", "Omg! It is evil Dragon!","Attack","Use Potion +10HP","-",hit,use,,300,25,100,1000 ] ]; var q=e_tp.length-1; for (var i=0;i<e_sz-1;i++) evs.push( e_tp[Math.floor(Math.random()*q)].slice(0) ); evs.push( e_tp[q].slice(0) ); var game = setInterval(function(){ ctx.clearRect(0,0,wi,he); ctx.fillText("NanoRPG in 30 lines of JavaScript by ripatti",10,15); ctx.fillText("LVL "+lvl+" HP "+hp+"/100 EXP "+exp+"/"+lvl*10+" ATK "+(lvl*4+6)+ " DEF "+(lvl*2+1)+" Gold $"+gld+" Potions "+pot,10,30); for (var i=0;i<e_sz;i++) ctx.fillText((i==e_sz-1||i<=cur_e)?evs[i][0]:"??",i*50+15,70); ctx.fillText("@",cur_e*50+25,60); ctx.fillText(evs[cur_e][1],20,100); if (evs[cur_e].length>8) ctx.fillText("Enemy HP "+evs[cur_e][8],250,100); for (var i=0;i<3;i++) { ctx.strokeRect(i*120+5,120,110,20); ctx.fillText(evs[cur_e][i+2],i*120+10,133); } }, 100); document.addEventListener('click', function(e){ if (hp>0) for (var i=0;i<3;i++) if (i*120+5<=e.pageX && e.pageX<i*120+115 && 120<=e.pageY && e.pageY<140) evs[cur_e][i+5]() }, false); })("#canvas",365,150,0,3,100,100,1,0,7);
      
      







私はhtmlとcssコードを考慮しませんでしたが、誰かが興味があるなら:html-コードの1行、css-4。



おわりに


レースの agegorinヘビの DjComandosアルカノイドのリノリウムの おかげです 。 ソースコードを読んで、これに基づいて独自のコードを書くのは興味深いことでした。



4K JavaScriptコードのUPDローグライク/ RPG


同志shvedovkaは、私が実際に行った、複雑さを伴う循環ゲームの作成を提案しました。 30行ではまったく上がらず、別の制限がありました。コードは4キロバイト以下にする必要があります(これはlolmausの発言と一致しており、個人的にはより気に入っています)。 サイクリックゲームを台無しにして、さらにいくつかのイベントを追加しました。非常に制限されたコンテンツでゲームを埋めました。



すなわち:



世界の世代の小さな変化:



そして、すべてとすべてのバランスの観点からの多くの小さな変更。 そしてはい...今、王女は本当に保存することができます。



フィドルのゲームのこのバージョンへのリンク。 それはかなり筋金入りでした。



もちろん、 コードです。 フォーマットはあまり明確ではありません-4000文字に収まるようにいくつかのスペースを削除しました。 原則として、たとえば、別のイベントを押し出すためにコードをさらに強く絞ることができます(カジノのようなものを作るというアイデアがありました)。 しかし、私はこれを行うのが面倒です。



これで、ゲームの作業が完了したと考えます。



All Articles