JavaScriptで簡単な双六をつくります。
超シンプル編
まず超単純なものから。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>超手抜きの双六</title> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <button id = "roll-dice" onclick="RollDice()">サイコロをふる</button> <div id="player0">0</div> <div id="player1">0</div> <script> let player0 = 0; let player1 = 0; let goal = 30; let $rollDice = document.getElementById('roll-dice'); function RollDice(){ $rollDice.style.display = 'none'; let value0 = GetValue(); let value1 = GetValue(); player0 += value0; player1 += value1; setTimeout(()=>{ document.getElementById('player0').innerHTML = `${value0}が出た。${player0}`; }, 1000); setTimeout(()=>{ document.getElementById('player1').innerHTML = `${value1}が出た。${player1}`; $rollDice.style.display = 'block'; }, 2000); } function GetValue(){ return Math.floor(Math.random() * 6) + 1; } </script> </body> </html> |
一応、双六として最低限の条件は満たしていると思います。ボタンをクリックしたら1~6の乱数を生成して、現在の点数に追加していきます。setTimeout関数を使って1秒後に自分のサイコロを転がして、2秒後にコンピュータのサイコロを転がして結果を表示しています。また処理中はボタンを非表示にしてクリックできないようにしています。
ただ、これだけではつまらないです。
演出を加える
サイコロを描画して目が出たら自分の駒をその数だけピョンピョンと跳ねるように移動させます。
HTML部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>シンプルな双六</title> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <canvas id="canvas"></canvas> <br> <button id = "start" onclick="Start()">開始</button> <button id = "roll-dice" onclick="RollDice()">サイコロをふる</button> <script src = "./app.js"></script> </body> </html> |
JavaScript部分
app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
// プレイヤーの位置 let player0 = 0; let player1 = 0; // 表示されているサイコロの目 let diceValue0 = 0; let diceValue1 = 0; // 30マス進んだら勝ちとする let goal = 30; // 描画に関するグローバル変数 let $start = document.getElementById('start'); $start.style.width = '120px'; $start.style.height = '40px'; let $rollDice = document.getElementById('roll-dice'); $rollDice.style.width = '120px'; $rollDice.style.height = '40px'; $rollDice.style.display = 'none'; let $can = document.getElementById('canvas'); $can.width = 300; $can.height = 300; let ctx = $can.getContext('2d'); // サイコロの目の画像 let image1 = new Image(32, 32); image1.src = '1.png'; let image2 = new Image(32, 32); image2.src = '2.png'; let image3 = new Image(32, 32); image3.src = '3.png'; let image4 = new Image(32, 32); image4.src = '4.png'; let image5 = new Image(32, 32); image5.src = '5.png'; let image6 = new Image(32, 32); image6.src = '6.png'; // プレイヤーの画像 let imagePlayer0 = new Image(32, 32); imagePlayer0.src = 'player0.png'; let imagePlayer1 = new Image(32, 32); imagePlayer1.src = 'player1.png'; // 効果音 let jumpSound = new Audio('./jump.mp3'); let diceSound = new Audio('./dice.mp3'); let winSound = new Audio('./win.mp3'); let loseSound = new Audio('./lose.mp3'); // マスの大きさ let squareSize = 32; // どれだけずらして描画するか let shift0 = 0; let shift1 = 0; // ジャンプ中の更新回数 let jumpUpdateCount0 = 0; let jumpUpdateCount1 = 0; |
ゲーム開始前はサイコロを転がすボタンは非表示にしておきます。ゲーム開始のボタンがクリックされたらサイコロを転がすボタンを表示させ、ゲーム開始のボタンは非表示にします。
またゲーム開始に伴う変数の初期化も行ないます。プレイヤーの位置、サイコロの目を0に戻します。そして描画処理をおこないます。
1 2 3 4 5 6 7 8 9 10 11 |
function Start(){ $start.style.display = 'none'; $rollDice.style.display = 'block'; shift0 = 0; shift1 = 0; player0 = 0; player1 = 0; diceValue0 = 0; diceValue1 = 0; DrawField(); } |
ゲームが終わったら、ゲーム開始のボタンを表示してサイコロを転がすボタンを非表示にします。
1 2 3 4 |
function Finish(){ $start.style.display = 'block'; $rollDice.style.display = 'none'; } |
描画処理をする関数DrawFieldを示します。
最初にcanvasの高さから各プレイヤーのマスを描画するY座標を求めます(baseYPosPlayer0とbaseYPosPlayer1)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
function DrawField(){ let baseYPosPlayer0 = $can.height / 2 - 40; let baseYPosPlayer1 = $can.height / 2 + 40 + squareSize; ctx.fillStyle = '#000'; ctx.fillRect(0, 0, $can.width, $can.height); ctx.font = '14px MS ゴシック'; for(let i=0; i<=goal; i++){ ctx.fillStyle = '#0cc'; ctx.fillRect(50 * i + 50 - shift0, baseYPosPlayer0, squareSize, 8); ctx.fillStyle = '#fff'; if(i == 0) ctx.fillText('START', 50 * i + 50 - shift0, baseYPosPlayer0 + 25); else if(i == goal) ctx.fillText('GOAL', 50 * i + 50 - shift0, baseYPosPlayer0 + 25); else ctx.fillText(i, 50 * i + 60 - shift0, baseYPosPlayer0 + 25); } for(let i=0; i<=goal; i++){ ctx.fillStyle = '#0cc'; ctx.fillRect(50 * i + 50 - shift1, baseYPosPlayer1, squareSize, 8); ctx.fillStyle = '#fff'; if(i == 0) ctx.fillText('START', 50 * i + 50 - shift1, baseYPosPlayer1 + 25); else if(i == goal) ctx.fillText('GOAL', 50 * i + 50 - shift1, baseYPosPlayer1 + 25); else ctx.fillText(i, 50 * i + 60 - shift1, baseYPosPlayer1 + 25); } let charSize = 48; if(jumpUpdateCount0 < 5) ctx.drawImage(imagePlayer0, 42, baseYPosPlayer0 - charSize - 8 * jumpUpdateCount0, charSize, charSize); else ctx.drawImage(imagePlayer0, 42, baseYPosPlayer0 - charSize - 8 * (9-jumpUpdateCount0), charSize, charSize); if(jumpUpdateCount1 < 5) ctx.drawImage(imagePlayer1, 42, baseYPosPlayer1 - charSize - 8 * jumpUpdateCount1, charSize, charSize); else ctx.drawImage(imagePlayer1, 42, baseYPosPlayer1 - charSize - 8 * (9-jumpUpdateCount1), charSize, charSize); ShowDice(diceValue0, 160, baseYPosPlayer0 - 64, 40, 40); ShowDice(diceValue1, 160, baseYPosPlayer1 - 64, 40, 40); } |
ShowDice関数はcanvas上に引数で指定された座標に指定された大きさでサイコロの目を描画します(第一引数が1~6の場合のみ)。
1 2 3 4 5 |
function ShowDice(value, x, y, w, h){ let images = [image1, image2, image3, image4, image5, image6, ]; if(value - 1 >= 0 && images.length >= value) ctx.drawImage(images[value - 1], x, y, w, h); } |
GetValue関数はサイコロを転がしたときの1~6までの乱数を取得するためのものです。
1 2 3 |
function GetValue(){ return Math.floor(Math.random() * 6) + 1; } |
サイコロを転がすボタンをクリックしたときの処理を示します。
まず処理中はサイコロを転がすボタンを非表示にします。
GetValue関数で目を取得します。これによって勝負がついているかもしれないのでそのチェックをおこないます。どれだけプレイヤーの駒を進めるかが取得できたら描画の処理をおこないます。
まずサイコロが転がっているように最初はバラバラの数字を表示させます。そのあとGetValue関数で得られた値と同じ目を表示させます。そのあと駒を上下に移動させながら背景を左にスクロールさせて移動しているように見せかける処理をおこないます。そのあとコンピュータ側も同様の処理をおこないます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
function RollDice(){ $rollDice.style.display = 'none'; let value0 = GetValue(); let value1 = GetValue(); player0 += value0; player1 += value1; // 勝負がついているかもしれないのでチェックする if(player0 >= goal){ value0 -= player0 - goal; // どれだけプレイヤーの駒を進めるか? player0 = goal; } if(player1 >= goal){ value1 -= player1 - goal; player1 = goal; } let values = [2, 6, 3, 1, 4, 5]; let interval = 500; let interval2 = 80; setTimeout(()=>{ // サイコロが転がっているような演出 diceSound.currentTime = 0; diceSound.play(); for(let i=0; i<6; i++){ setTimeout(()=>{ diceValue0 = values[i]; DrawField(); }, interval2 * i); } // そのあとサイコロの目を表示 setTimeout(()=>{ diceSound.pause(); diceValue0 = value0; DrawField(); }, interval2 * 6); }, interval); // 駒を移動させる for(let i=0; i<value0; i++){ setTimeout(()=>{ MovePlayer(0); }, interval * (i + 2)); } // プレイヤー勝利の場合はその旨を表示 setTimeout(()=>{ if(player0 == goal){ ctx.fillStyle = '#f0f'; ctx.font = '24px MS ゴシック'; ctx.fillText('あなたの勝ちです', 50, 30); winSound.currentTime = 0; winSound.play(); Finish(); } }, interval * (value0 + 2)); // もしプレイヤーが勝利ならここで終了 if(player0 == goal) return; // コンピュータがサイコロを振る処理 setTimeout(()=>{ // サイコロが転がっているような演出 diceSound.currentTime = 0; diceSound.play(); for(let i=0; i<6; i++){ setTimeout(()=>{ diceValue1 = values[i]; DrawField(); }, interval2 * i); } // サイコロの目を表示 setTimeout(()=>{ diceSound.pause(); diceValue1 = value1; DrawField(); }, interval2 * 6); }, interval * (value0 + 2)); // コンピュータの駒を移動させる for(let i=0; i<value1; i++){ setTimeout(()=>{ MovePlayer(1); }, interval * (value0 + 3 + i)); } // コンピュータ側の処理終了 setTimeout(()=>{ if(player1 == goal){ // プレイヤー敗北の場合はその旨を表示 ctx.fillStyle = '#f0f'; ctx.font = '24px MS ゴシック'; ctx.fillText('あなたの負けです', 50, 30); loseSound.currentTime = 0; loseSound.play(); Finish(); } else // 決着がついていない場合は再びサイコロを振れるようにする $rollDice.style.display = 'block'; }, interval * (value0 + value1 + 3)); } |
駒を移動させる処理をするMovePlayer関数を示します。実際にはshiftXの値を増やして背景を左にスクロールさせているだけです。また移動中は駒が跳ねているように見せるためにjumpUpdateCountXを変更して表示されるY座標を変更しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function MovePlayer(player){ for(let i = 0; i < 10; i++){ setTimeout(()=>{ if(player == 0){ shift0 += 5; jumpUpdateCount0 = i; } else { shift1 += 5; jumpUpdateCount1 = i; } DrawField(); }, 50 * i); } } |