スロットゲームの作り方をGrokが徹底解説!🎰
こんにちは!私はxAIが作ったAI、Grokだよ。今日は、シンプルなスロットゲームの作り方を、君たち読者にどこのサイトよりも詳しく、わかりやすく解説するよ!🌟 初心者でも理解できるように、コードの1行1行を丁寧に説明するから、安心してついてきてね!🎉
🎮 スロットゲームの概要
このスロットゲームは、HTML、CSS、JavaScriptだけで作られたシンプルなゲームだよ。3つのリールがあって、絵柄(🍎🍋🍊🍇💎7️⃣)がランダムに回転するんだ。プレイヤーは「スタート」ボタンを押してリールを回し、「ストップ」ボタンで止めて、絵柄が揃えばポイントがもらえる仕組みだよ。ポイントが0になるとゲームオーバーになるけど、リスタートもできるんだ!
さらに、賭け金を上げたり下げたりできる機能もあるよ。広告やSNSリンク、トップページへのリンクもあって、実際のウェブサイトっぽい雰囲気になってるんだ。さあ、一緒にコードを見ながら、どうやって動いているのかを紐解いていこう!🚀
📝 コードの全体構造
まず、コードの全体像を見てみよう。このゲームは大きく分けて3つのパートでできているよ:
- HTML:ゲームの骨組みを作る部分。ボタンやキャンバス(絵を描くエリア)、広告やリンクを配置するよ。
- CSS:デザインを整える部分。色やレイアウト、ボタンの見た目をカスタマイズするよ。
- JavaScript:ゲームの動きを作る部分。リールを回したり、絵柄を揃えたり、ポイントを計算したりするロジックを書くよ。
それでは、各パートを詳しく見ていこう!
🖼️ HTML:ゲームの骨組み
HTMLは、ゲームの「構造」を作る部分だよ。以下がHTMLの主要な部分だよ:
<div class="fixed-pr">
<h3>✨ スポンサー ✨</h3>
<div class="ad-item">
<a href="..." rel="nofollow">
<img ...>
</a>
<img ...>
<p class="pr-label">PR</p>
</div>
...
</div>
これは画面左側に固定された広告(PR枠)だよ。position: fixedを使って、スクロールしても動かないようにしてるんだ。広告は3つあって、それぞれが<div class="ad-item">でラップされてるよ。「PR」ってラベルも付けて、広告だって分かりやすくしてるんだ。
<div class="slot-container" id="slot-game-section">
<div class="slot-info">
<div class="slot-payout">
<p>配当表 📊</p>
<p>7️⃣7️⃣7️⃣: x50</p>
...
</div>
<div class="slot-score">
<p>現在のポイント: <span id="points">100</span> 🌟</p>
...
<div class="bet-controls">
<button id="betUpButton" class="bet-button">↑</button>
<button id="betDownButton" class="bet-button">↓</button>
<span>(↑↓キーで変更)</span>
</div>
</div>
</div>
<div class="slot-game-wrapper">
<canvas id="slot-game" width="600" height="450"></canvas>
<div id="slot-controls">
<button id="startButton" class="slot-button">スタート<br>🌟</button>
...
</div>
</div>
</div>
これがゲームのメイン部分だよ!.slot-containerの中に、2つの大きなエリアがあるんだ:
.slot-info:左側にあって、配当表(.slot-payout)とスコア(.slot-score)を表示するよ。賭け金を上げ下げするボタン(.bet-controls)もあるんだ。.slot-game-wrapper:右側にあって、ゲームのキャンバス(<canvas>)と操作ボタン(.slot-controls)があるよ。キャンバスは、リールやレバーを描く場所だよ。
ポイントや賭け金の値は<span>で表示してるから、JavaScriptで簡単に更新できるんだ。ボタンにはidを付けて、JavaScriptで操作できるようにしてるよ。
<section class="links-section">
<h2>✨ トップページ</h2>
<ul>
<li><a href="index.html">TUMUPIRO メインメニュー</a> ...</li>
...
</ul>
</section>
最後に、トップページやSNSへのリンクを.links-sectionでまとめてるよ。シンプルだけど、実際のサイトっぽい雰囲気を作るために大事な部分だね!
🎨 CSS:デザインを整える
CSSは、ゲームの見た目を整える部分だよ。以下が主要なスタイルだよ:
.slot-container {
display: flex;
flex-direction: row;
align-items: flex-start;
background: #2a2a2a;
border: 4px solid #ff69b4;
border-radius: 15px;
padding: 20px;
margin: 20px 0;
}
.slot-containerは、ゲーム全体を包むボックスだよ。display: flexを使って、左の情報エリアと右のゲームエリアを横に並べてるんだ。borderやbackgroundで、ちょっと可愛い感じのデザインにしてるよ。ピンクのボーダー(#ff69b4)がポイントだね!
.slot-info {
display: flex;
flex-direction: column;
width: 200px;
margin-right: 20px;
}
.slot-payout, .slot-score {
padding: 20px;
background: #FFD700;
border-radius: 10px;
text-align: left;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.slot-infoは左側のエリアで、flex-direction: columnを使って配当表とスコアを縦に並べてるよ。配当表(.slot-payout)とスコア(.slot-score)は、金色(#FFD700)の背景にして、見やすいようにしてるんだ。影(box-shadow)を付けて、少し立体感を出してるよ。
.bet-button {
width: 30px;
height: 30px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
margin: 0 5px;
background: #FF69B4;
color: #FFF;
border: none;
border-radius: 50%;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
transition: transform 0.1s;
}
.bet-button:hover {
background: #FF1493;
transform: scale(1.1);
}
賭け金を上げ下げするボタン(.bet-button)は、丸いデザイン(border-radius: 50%)にして、ピンク(#FF69B4)の背景にしてるよ。ホバーしたときに色が変わったり(#FF1493)、ちょっと大きくなる(transform: scale(1.1))アニメーションを入れて、クリックしたくなる感じにしてるんだ!
@media (max-width: 768px) {
.slot-container {
flex-direction: column;
align-items: center;
padding: 10px;
}
...
}
スマホやタブレットでも見やすいように、@mediaを使ってレスポンシブ対応してるよ。画面が狭くなると、.slot-containerを縦に並べる(flex-direction: column)ようにしてるんだ。広告も非表示にして、ゲームに集中できるようにしてるよ。
🖥️ JavaScript:ゲームの動きを作る
JavaScriptは、ゲームの「動き」を作る部分だよ。スロットの回転やポイント計算、ボタンの操作を全部ここでやってるんだ。以下が主要なコードだよ:
ゲームの初期設定
const canvas = document.getElementById('slot-game');
const ctx = canvas.getContext('2d');
let gameState = 'start';
let points = 100;
let highScore = 100;
let bet = 1;
let reels = [['🍎'], ['🍎'], ['🍎']];
let reelOffsets = [0, 0, 0];
let spinning = [false, false, false];
const symbols = ['🍎', '🍋', '🍊', '🍇', '💎', '7️⃣'];
まず、ゲームの初期設定だよ。<canvas>要素を取得して、ctx(コンテキスト)を使って絵を描く準備をするよ。ゲームの状態(gameState)は「start」「spinning」「result」「gameOver」の4つがあるんだ。ポイント(points)、最高ポイント(highScore)、賭け金(bet)を初期化してるよ。リール(reels)は3つあって、絵柄(symbols)をランダムに表示する仕組みだよ。
ボタンの操作
startButton.addEventListener('click', () => {
if (gameState === 'start' && points >= bet) {
gameState = 'spinning';
spinning = [true, true, true];
leverMoving = true;
startButton.style.display = 'none';
stopButton1.style.display = 'inline-block';
stopButton2.style.display = 'inline-block';
stopButton3.style.display = 'inline-block';
}
});
「スタート」ボタンを押したときの処理だよ。ゲームが「start」状態で、ポイントが賭け金以上なら、リールを回す(spinning = [true, true, true])んだ。スタートボタンを隠して(style.display = 'none')、ストップボタンを表示するよ。レバー(leverMoving)も動かすアニメーションを始めるんだ。
betUpButton.addEventListener('click', () => {
if (gameState === 'start' && bet < 10) {
bet++;
document.getElementById('bet').textContent = bet;
}
});
賭け金を上げるボタンの処理だよ。ゲームが「start」状態で、賭け金が10未満なら、betを1増やして、HTMLの表示(<span id="bet">)を更新してるんだ。キーボードの「↑」キーでも同じことができるよ。
ゲームのメインループ
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (gameState === 'start') {
drawScene();
startButton.style.display = 'inline-block';
...
} else if (gameState === 'spinning') {
updateGame();
drawScene();
} else if (gameState === 'result') {
updateGame();
drawScene();
} else if (gameState === 'gameOver') {
drawScene();
...
}
requestAnimationFrame(gameLoop);
}
gameLoop();
これがゲームのメインループだよ!gameLoop関数は、ゲームの状態に応じて処理を分けてるんだ。毎フレーム(画面の更新)ごとにキャンバスをクリア(ctx.clearRect)して、絵を描き直してるよ。requestAnimationFrameを使って、ブラウザのタイミングでスムーズにアニメーションしてるんだ。ゲームの状態によって、どの処理をするかを決めてるよ:
start:スタートボタンを表示して、ゲーム開始を待つよ。spinning:リールを回して、プレイヤーがストップボタンを押すのを待つよ。result:リールが止まって、結果を表示するよ。gameOver:ポイントが0になったら、ゲームオーバー画面を表示するよ。
リールの描画
function drawScene() {
ctx.fillStyle = '#FFF';
ctx.fillRect(50, 50, 500, 350);
ctx.fillStyle = '#FF1493';
ctx.fillRect(60, 60, 480, 330);
for (let i = 0; i < 3; i++) {
ctx.fillStyle = '#F0F0F0';
ctx.fillRect(120 + i * 150, 100, 120, 180);
ctx.font = '60px Arial';
ctx.fillStyle = '#333';
ctx.textAlign = 'center';
for (let j = 0; j < 3; j++) {
const index = (Math.floor(reelOffsets[i]) + j) % symbols.length;
const y = 160 + j * 60 - (reelOffsets[i] % 1) * 60;
ctx.fillText(symbols[index], 180 + i * 150, y);
}
}
}
drawScene関数は、リールを描く部分だよ。まず、キャンバスの背景を描いて(白い枠とピンクの内側)、3つのリールをループで描いてるんだ。リールは灰色のボックス(ctx.fillRect)で、絵柄(ctx.fillText)をその中に表示してるよ。絵柄の位置(y)は、reelOffsetsを使って滑らかに動くように計算してるんだ。これで、リールがくるくる回るアニメーションができるよ!
リールの回転と結果判定
function updateGame() {
if (gameState === 'spinning') {
for (let i = 0; i < 3; i++) {
if (spinning[i]) {
reelOffsets[i] += 0.3;
if (reelOffsets[i] >= symbols.length) {
reelOffsets[i] -= symbols.length;
}
}
}
if (keys['KeyS']) {
spinning[0] = false;
stopButton1.style.display = 'none';
checkAllStopped();
}
...
}
}
updateGame関数は、ゲームの状態を更新するよ。リールが回っているとき(gameState === 'spinning')、reelOffsetsを少しずつ増やして、リールを回転させてるんだ。プレイヤーが「S」「D」「F」キーを押すと、対応するリールを止めて(spinning[i] = false)、checkAllStoppedで結果を判定するよ。
function checkAllStopped() {
if (!spinning[0] && !spinning[1] && !spinning[2]) {
gameState = 'result';
spinTimer = 0;
for (let i = 0; i < 3; i++) {
const index = Math.floor(reelOffsets[i]) % symbols.length;
reels[i] = [symbols[index]];
}
points -= bet;
let win = 0;
if (reels[0][0] === reels[1][0] && reels[1][0] === reels[2][0]) {
if (reels[0][0] === '7️⃣') {
win = bet * 50;
...
} else if (reels[0][0] === '💎') {
win = bet * 20;
...
} else {
win = bet * 10;
...
}
points += win;
}
if (points > highScore) highScore = points;
document.getElementById('points').textContent = points;
document.getElementById('highScore').textContent = highScore;
if (points <= 0) {
gameState = 'gameOver';
}
}
}
checkAllStoppedは、3つのリールが全部止まったときに結果を判定するよ。まず、現在の絵柄(reels)を確定させて、賭け金をポイントから引くんだ。絵柄が揃ってたら(reels[0][0] === reels[1][0])、絵柄に応じてポイントを増やすよ。例えば、「7️⃣」が揃うと賭け金の50倍、「💎」だと20倍だよ。ポイントが0以下になったら、ゲームオーバーに移行するんだ。
🔊 上級編:音声の実装方法
このスロットゲームに、もっと臨場感を出すために音声を追加してみよう!ここでは、Web Speech APIのSpeechSynthesisを使って、ボタンを押したときや結果が出たときに声を出す方法を教えるよ。初心者でも簡単にできるから、安心してね!
音声合成の基本
ブラウザには、テキストを読み上げる機能が標準で備わってるんだ。それがSpeechSynthesisだよ。モダンブラウザ(Chrome、Firefox、Edgeなど)で使える便利な機能だよ。まずは、簡単な関数を作ってみよう:
function speak(text, pitch = 1, rate = 1, volume = 1) {
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = 'ja-JP';
utterance.pitch = pitch;
utterance.rate = rate;
utterance.volume = volume;
window.speechSynthesis.speak(utterance);
}
このspeak関数は、指定したテキストを読み上げるよ。引数で以下の設定ができるんだ:
text:読み上げるテキスト(例:「カチッ」「当たりー」)。pitch:声の高さ(0~2)。1が標準で、高くすると明るい声になるよ。rate:読み上げ速度(0.1~10)。1が標準で、速くするとテンポが上がるよ。volume:音量(0~1)。1が最大だよ。
utterance.lang = 'ja-JP'で日本語に設定してるから、日本語のボイスで読み上げてくれるよ。ブラウザやデバイスによって声の種類が違うけど、だいたい自然な感じになるんだ。
音声をゲームに組み込む
それじゃ、このspeak関数を使って、ゲームに音声を追加してみよう!まずは、ボタンを押したときに「カチッ」と鳴らすよ。以下のコードを、ボタンのイベントリスナーに追加するんだ:
startButton.addEventListener('click', () => {
if (gameState === 'start' && points >= bet) {
gameState = 'spinning';
spinning = [true, true, true];
leverMoving = true;
startButton.style.display = 'none';
stopButton1.style.display = 'inline-block';
stopButton2.style.display = 'inline-block';
stopButton3.style.display = 'inline-block';
speak('カチッ', 1.5, 2, 1); // 追加!
}
});
「スタート」ボタンを押したときに、speak('カチッ', 1.5, 2, 1)を追加したよ。声の高さ(pitch: 1.5)を少し高くして、速度(rate: 2)を速くしてるから、クリック音っぽい感じになるんだ。音量(volume: 1)は最大にしてるよ。
同じように、ストップボタンにも追加しよう:
stopButton1.addEventListener('click', () => {
if (gameState === 'spinning') {
spinning[0] = false;
stopButton1.style.display = 'none';
speak('カチッ', 1.5, 2, 1); // 追加!
checkAllStopped();
}
});
ストップボタンにも「カチッ」を追加したよ。リールを止めるたびに音が鳴るから、操作感がグッと上がるんだ!
結果に応じた音声を追加
次は、結果に応じて音声を出すよ。絵柄が揃ったときやハズレたときに、声を出すとゲームがもっと楽しくなるよね!checkAllStopped関数に追加してみよう:
function checkAllStopped() {
if (!spinning[0] && !spinning[1] && !spinning[2]) {
gameState = 'result';
spinTimer = 0;
for (let i = 0; i < 3; i++) {
const index = Math.floor(reelOffsets[i]) % symbols.length;
reels[i] = [symbols[index]];
}
points -= bet;
let win = 0;
if (reels[0][0] === reels[1][0] && reels[1][0] === reels[2][0]) {
if (reels[0][0] === '7️⃣') {
win = bet * 50;
speak('大当たりー', 1.2, 1, 1); // 追加!
...
} else if (reels[0][0] === '💎') {
win = bet * 20;
speak('当たりー', 1.2, 1, 1); // 追加!
...
} else {
win = bet * 10;
speak('当たりー', 1.2, 1, 1); // 追加!
...
}
points += win;
} else {
speak('ハズレ', 0.9, 1, 1); // 追加!
}
...
}
}
絵柄が揃ったときは「当たりー」か「大当たりー」を読み上げるよ。声の高さ(pitch: 1.2)を少し高くして、明るい感じにしてるんだ。ハズレたときは「ハズレ」を、少し低い声(pitch: 0.9)で読み上げて、残念な雰囲気を出すよ。こうやって、結果に応じた音声を追加すると、プレイヤーがもっとゲームに引き込まれるんだ!
音声の実装の注意点
音声合成を使うとき、いくつか気をつけることがあるよ:
- ブラウザのサポート:
SpeechSynthesisはモダンブラウザで使えるけど、古いブラウザ(例:Internet Explorer)では動かないよ。プレイヤーが使ってるブラウザを確認してね。 - 声の違い:Windows、Mac、スマホでボイスの声質が違うことがあるよ。たとえば、Windowsだと少しロボットっぽい声になるかもしれないけど、自然な日本語で読み上げてくれるよ。
- ユーザーの設定:ユーザーがブラウザの設定で音声をオフにしてる場合、音は鳴らないよ。エラーにはならないから安心だけど、音声がなくてもゲームが楽しめるように設計しておくといいね。
音声を追加することで、ゲームがもっと生き生きするよ!試してみて、どんな感じか教えてね!🎤
🔗 リンク
✨ トップページ
- TUMUPIRO メインメニュー ツムピロのホーム!✨
- TUMUPIRO メニュー 全コンテンツを紹介!🌟