こんにちは、AM0500です。
ちいかわラーメンの豚でラーメン食べてきました。こういうコラボ系の食事処にしては頑張っている印象で、みんな撮影しながら食べていました。楽しいー!
さて、今回はちいかわの「郎」で注文をするゲームを作ってみました。ちいかわの代わりに文字をタップしてコールを完成させましょう。
🔗 実際にプレイしてみる
▼ ブラウザでそのまま遊べます:
👉 ちいかわの「郎」でオーダーをするゲーム
👉 作成に使用したAI Claude(claude 4 sonnet)はこちら
🎮 ゲーム画面(スクリーンショット)


📝 一言コメント
リアル店舗のちいかわ豚行ってきました🍜
ちいかわの郎のコールをゲームにできないかなと考えて作ったのがこちらのゲームになります。ちいかわの代わりにコールしてあげましょう!
誤入力は「戻る」ボタンで消すことができます。
もしよかったら遊んでみてください。
ちいかわパークのアトラクションでこんなのあったらどうでしょう?
🧠 使用したClaudeへのプロンプト
今回、使用したプロンプトです。
以下の要件をもとに、スマホやPCのブラウザ上で動作するHTML + CSS + JavaScriptのシンプルなゲームを作成してください。
【ゲームの概要】
「ちいかわの郎(ラーメン屋)」で、出されたオーダーを正しく入力していくゲームです。ラーメン二郎のような「ニンニクマシヤサイマシアブラフツウカラメ」などのオーダー例が出され、それを画面上の動く文字の中から探して順番に選択していきます。
【ゲームの仕様】
1. オーダーの表示
- 画面上部にランダムなオーダー(例:「ニンニクマシ」など)を表示します。
- オーダーは徐々に長くなっていきます(ステージ制)。
2. 文字の選択
- 画面内にオーダーで使われる文字が1文字づつ分割されてランダムな位置に表示されます(例:「ニンニクマシ」ならニ,ン,ニ,ク,マ,シの6つ文字が画面内を飛び回ります。
- 文字はゆっくりとランダムな方向に移動し、画面内の枠の中を反射して移動します。
- ユーザーは順番通りに、目的の文字をクリックまたはタップして入力していきます。
- 間違った文字も複数表示されており、誤って選ぶとその文字が入力されてしまいます。間違った文字(ダミーの文字)はすべてカタカナとします。
- タップした文字は消えて、代わりに他の文字が表示されます。
3. 操作方法
- 入力はクリック/タップのみで行います。
- 間違えたときのために、「バックスペース」ボタンが用意されています。
4. クリア・失敗条件
- 正しく全ての文字を順に選べたらステージクリア。
- 制限時間内に入力できなければゲームオーバー。
5. オーダー語彙(基本構成)
- パーツ1(味の種類): 「ニンニク」「ヤサイ」「アブラ」「カラメ」
- パーツ2(量の指定): 「スクナメ」「フツウ」「マシ」「マシマシ」
- 例: 「ニンニクマシ」「ヤサイフツウ」「アブラマシマシ」など
なお、味の種類は各1回づつでアブラアブラのように同じ味の種類は複数回登場しない。
また、パーツ2もパーツ1の後ろに1回くっつけるだけで、スクナメフツウのように複数個くっつく事はありません。
【技術要件】
- HTML、CSS、JavaScriptで完結すること。
- 外部ライブラリ(できれば使用しない or 使用してもCDN経由のみ)。
- スマホとPCの両方でクリック/タップ操作ができるようにしてください。
【段階的ステージ設計】
- 序盤はパーツ1の種類を1から2個まで、(例:「ニンニクマシ」、「ヤサイフツウアブラマシ」)
- 難易度が上がるとパーツ1の種類が最大4つまで増える。(例:「ニンニクマシヤサイマシアブラフツウカラメ」)
- 難易度の上げる過程で、文字の移動速度が上がったり、ダミーの文字が増えたり、制限時間が少なくなったりします。
【補足】
- 文字が画面に表示されてから数秒ごとにゆっくり移動するアニメーションをつけてください。
- ユーザーの入力欄を画面中央または上部に表示し、現在の入力内容が確認できるようにしてください。
- オーダーに含まれる文字は、必ず画面内に出現させてください。
-文字数に応じて制限時間を伸ばしてください。例えば序盤は1文字6秒+数秒くらいの計算で、後半になると1文字あたり2秒~3秒くらいの制限時間+数秒くらいの時間調整を行なってください。
-またステージが進むにつれて、文字の移動速度を上げたり、フェイクの文字が増えるなどの難易度調整を行なってください。
基本的にはこれで作成されますが、必要に応じて修正依頼を行うようにしてください。ブログ公開の作品はブログの表示の問題により記号や背景色の調整しております。
🕹️ Claudeが返してくれた説明文
ゲームの特徴:
・オーダーシステム
ラーメン二郎風のオーダー(「ニンニクマシ」「ヤサイフツウ」など)
ステージが進むにつれて複雑になる(最大4つの味の組み合わせ)
・文字選択システム
画面内を飛び回る文字をタップ/クリックで選択
正解文字とダミー文字が混在
文字は壁で反射しながら移動
・難易度調整
ステージが進むにつれて文字の移動速度が上昇
ダミー文字の数が増加
制限時間が厳しくなる(序盤:1文字6秒、後半:1文字2-3秒)
・操作方法
スマホ・PC両対応(タップ/クリック)
バックスペース機能付き
直感的なUI
・視覚的な工夫
可愛いグラデーション背景
アニメーション付きの文字
進捗バーで入力状況を表示
レスポンシブデザイン
ゲームを開始すると、画面上部にオーダーが表示され、画面内を飛び回る文字から正しい順番で選択していきます。間違えても「←戻る」ボタンで修正できます。
ステージをクリアするとスコアが加算され、次のステージへ進みます。頑張って高スコアを目指してください!
💡 ソースコード(HTML)
下記がゲーム本体のhtmlの中身になります。ご自由にご利用ください。もちろん改変などもOKです。リンクや紹介していただけたら嬉しいです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ちいかわの郎 - オーダー入力ゲーム</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(135deg, #ff6b6b, #4ecdc4);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
color: #333;
}
.game-container {
width: 90vw;
max-width: 800px;
height: 90vh;
max-height: 650px;
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
}
.header {
background: linear-gradient(45deg, #ff9a9e, #fecfef);
padding: 15px;
text-align: center;
border-radius: 20px 20px 0 0;
}
.title {
font-size: 24px;
font-weight: bold;
color: #333;
margin-bottom: 10px;
}
.game-info {
display: flex;
justify-content: space-between;
font-size: 14px;
color: #666;
}
.order-display {
background: #fff;
margin: 15px;
padding: 15px;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
text-align: center;
}
.order-text {
font-size: 20px;
font-weight: bold;
color: #e74c3c;
margin-bottom: 10px;
}
.input-display {
font-size: 18px;
color: #2c3e50;
min-height: 25px;
border: 2px dashed #bdc3c7;
padding: 8px;
border-radius: 5px;
background: #f8f9fa;
}
.game-area {
position: relative;
flex: 1;
margin: 0 15px;
background: linear-gradient(45deg, #a8edea, #fed6e3);
border-radius: 10px;
overflow: hidden;
border: 3px solid #fff;
min-height: 250px;
}
.character {
position: absolute;
width: 40px;
height: 40px;
background: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
border: 2px solid #333;
user-select: none;
}
.character:hover {
transform: scale(1.2);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}
.controls {
display: flex;
justify-content: center;
gap: 15px;
margin: 15px;
padding: 10px;
flex-shrink: 0;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 25px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3);
}
.btn-backspace {
background: #f39c12;
color: white;
}
.btn-start {
background: #27ae60;
color: white;
}
.btn-restart {
background: #e74c3c;
color: white;
}
.modal {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.8);
display: flex;
align-items: center;
justify-content: center;
border-radius: 20px;
z-index: 1000;
}
.modal-content {
background: white;
padding: 30px;
border-radius: 15px;
text-align: center;
max-width: 300px;
}
.modal h2 {
margin-bottom: 15px;
color: #333;
}
.modal p {
margin-bottom: 20px;
color: #666;
}
.progress-bar {
width: 100%;
height: 8px;
background: #ecf0f1;
border-radius: 4px;
overflow: hidden;
margin: 10px 0;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #ff6b6b, #4ecdc4);
transition: width 0.3s ease;
}
@media (max-width: 600px) {
.game-container {
width: 95vw;
height: 95vh;
max-height: 700px;
}
.title {
font-size: 20px;
}
.character {
width: 35px;
height: 35px;
font-size: 16px;
}
.controls {
flex-wrap: wrap;
gap: 10px;
}
.btn {
padding: 8px 16px;
font-size: 14px;
}
}
</style>
</head>
<body>
<div class="game-container">
<div class="header">
<div class="title">🍜 ちいかわの郎 🍜</div>
<div class="game-info">
<span>ステージ: <span id="stage">1</span></span>
<span>時間: <span id="timer">30</span>秒</span>
<span>スコア: <span id="score">0</span></span>
</div>
</div>
<div class="order-display">
<div class="order-text" id="orderText">ゲームを開始してください</div>
<div class="input-display" id="inputDisplay">入力した文字がここに表示されます</div>
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
</div>
<div class="game-area" id="gameArea">
</div>
<div class="controls">
<button class="btn btn-backspace" id="backspaceBtn" onclick="backspace()">←戻る</button>
<button class="btn btn-start" id="startBtn" onclick="startGame()">ゲーム開始</button>
<button class="btn btn-restart" id="restartBtn" onclick="restartGame()" style="display:none">もう一度</button>
</div>
<div class="modal" id="modal" style="display:none">
<div class="modal-content">
<h2 id="modalTitle"></h2>
<p id="modalText"></p>
<button class="btn btn-start" onclick="hideModal()">OK</button>
</div>
</div>
</div>
<script>
// グローバル変数
let gameState = {
currentOrder: '',
currentInput: '',
currentStage: 1,
score: 0,
timeLeft: 30,
gameRunning: false,
timerInterval: null,
characters: [],
animationId: null
};
// オーダー語彙
const orderParts = {
taste: ['ニンニク', 'ヤサイ', 'アブラ', 'カラメ'],
amount: ['スクナメ', 'フツウ', 'マシ', 'マシマシ']
};
const dummyChars = ['ア', 'イ', 'ウ', 'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ', 'サ', 'シ', 'ス', 'セ', 'ソ', 'タ', 'チ', 'ツ', 'テ', 'ト', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ', 'ミ', 'ム', 'メ', 'モ', 'ユ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ', 'ワ', 'ヲ', 'ン'];
function generateOrder(stage) {
// ステージに応じた味の数(1-4個)
const numTastes = Math.min(Math.max(1, stage), 4);
const selectedTastes = [];
// 重複しないように味を選択
const availableTastes = [...orderParts.taste];
for (let i = 0; i < numTastes; i++) {
const randomIndex = Math.floor(Math.random() * availableTastes.length);
selectedTastes.push(availableTastes[randomIndex]);
availableTastes.splice(randomIndex, 1);
}
// 各味に量を追加
let order = '';
selectedTastes.forEach(taste => {
const amount = orderParts.amount[Math.floor(Math.random() * orderParts.amount.length)];
order += taste + amount;
});
return order;
}
function createCharacter(char, isCorrect = true) {
const gameArea = document.getElementById('gameArea');
const character = document.createElement('div');
character.className = 'character';
character.textContent = char;
// 初期位置をランダムに設定
const maxX = gameArea.offsetWidth - 40;
const maxY = gameArea.offsetHeight - 40;
character.style.left = Math.random() * maxX + 'px';
character.style.top = Math.random() * maxY + 'px';
// 移動速度を設定
const baseSpeed = 0.5 + (gameState.currentStage - 1) * 0.2;
character.vx = (Math.random() - 0.5) * baseSpeed;
character.vy = (Math.random() - 0.5) * baseSpeed;
// イベントリスナーを追加
character.addEventListener('click', function(e) {
e.preventDefault();
selectCharacter(char, character);
});
character.addEventListener('touchstart', function(e) {
e.preventDefault();
selectCharacter(char, character);
});
gameArea.appendChild(character);
return character;
}
function selectCharacter(char, element) {
if (!gameState.gameRunning) {
return;
}
// 文字を入力に追加
gameState.currentInput += char;
document.getElementById('inputDisplay').textContent = gameState.currentInput;
// 文字を削除
element.remove();
gameState.characters = gameState.characters.filter(c => c.element !== element);
// 新しいダミー文字を追加
const dummyChar = dummyChars[Math.floor(Math.random() * dummyChars.length)];
const newDummy = createCharacter(dummyChar, false);
gameState.characters.push({
element: newDummy,
char: dummyChar,
isCorrect: false
});
// 進捗更新
updateProgress();
// 正解チェック
if (gameState.currentInput === gameState.currentOrder) {
clearStage();
}
}
function updateProgress() {
const progress = gameState.currentOrder.length > 0 ?
(gameState.currentInput.length / gameState.currentOrder.length) * 100 : 0;
document.getElementById('progressFill').style.width = progress + '%';
}
function backspace() {
if (gameState.currentInput.length > 0) {
gameState.currentInput = gameState.currentInput.slice(0, -1);
document.getElementById('inputDisplay').textContent = gameState.currentInput || '入力した文字がここに表示されます';
updateProgress();
}
}
function startGame() {
gameState.gameRunning = true;
gameState.currentStage = 1;
gameState.score = 0;
document.getElementById('startBtn').style.display = 'none';
document.getElementById('restartBtn').style.display = 'inline-block';
startStage();
}
function startStage() {
// 新しいオーダーを生成
gameState.currentOrder = generateOrder(gameState.currentStage);
gameState.currentInput = '';
// 制限時間を計算
const timePerChar = Math.max(2, 6 - gameState.currentStage * 0.5);
gameState.timeLeft = Math.floor(gameState.currentOrder.length * timePerChar + 5);
// UI更新
document.getElementById('orderText').textContent = gameState.currentOrder;
document.getElementById('inputDisplay').textContent = '入力した文字がここに表示されます';
document.getElementById('stage').textContent = gameState.currentStage;
document.getElementById('score').textContent = gameState.score;
document.getElementById('timer').textContent = gameState.timeLeft;
// 既存の文字をクリア
gameState.characters.forEach(char => {
if (char.element && char.element.parentNode) {
char.element.remove();
}
});
gameState.characters = [];
// オーダーの文字を作成
const orderChars = gameState.currentOrder.split('');
orderChars.forEach(char => {
const element = createCharacter(char, true);
gameState.characters.push({
element: element,
char: char,
isCorrect: true
});
});
// ダミー文字を追加
const dummyCount = Math.min(10, 3 + gameState.currentStage);
for (let i = 0; i < dummyCount; i++) {
const dummyChar = dummyChars[Math.floor(Math.random() * dummyChars.length)];
const element = createCharacter(dummyChar, false);
gameState.characters.push({
element: element,
char: dummyChar,
isCorrect: false
});
}
updateProgress();
startTimer();
animateCharacters();
}
function startTimer() {
clearInterval(gameState.timerInterval);
gameState.timerInterval = setInterval(() => {
gameState.timeLeft--;
document.getElementById('timer').textContent = gameState.timeLeft;
if (gameState.timeLeft <= 0) {
gameOver();
}
}, 1000);
}
function animateCharacters() {
const gameArea = document.getElementById('gameArea');
const areaWidth = gameArea.offsetWidth;
const areaHeight = gameArea.offsetHeight;
function animate() {
if (!gameState.gameRunning) return;
gameState.characters.forEach(char => {
const element = char.element;
if (!element || !element.parentNode) return;
let x = parseFloat(element.style.left) || 0;
let y = parseFloat(element.style.top) || 0;
x += element.vx || 0;
y += element.vy || 0;
// 壁で反射
if (x <= 0 || x >= areaWidth - 40) {
element.vx = -(element.vx || 0);
x = Math.max(0, Math.min(areaWidth - 40, x));
}
if (y <= 0 || y >= areaHeight - 40) {
element.vy = -(element.vy || 0);
y = Math.max(0, Math.min(areaHeight - 40, y));
}
element.style.left = x + 'px';
element.style.top = y + 'px';
});
gameState.animationId = requestAnimationFrame(animate);
}
animate();
}
function clearStage() {
gameState.score += gameState.currentStage * 100;
gameState.currentStage++;
showModal(
'ステージクリア!',
`ステージ ${gameState.currentStage - 1} クリア!\n獲得スコア: ${(gameState.currentStage - 1) * 100}点`
);
setTimeout(() => {
hideModal();
startStage();
}, 2000);
}
function gameOver() {
gameState.gameRunning = false;
clearInterval(gameState.timerInterval);
cancelAnimationFrame(gameState.animationId);
showModal(
'ゲームオーバー',
`最終ステージ: ${gameState.currentStage}\n最終スコア: ${gameState.score}点`
);
}
function restartGame() {
gameState.gameRunning = false;
clearInterval(gameState.timerInterval);
cancelAnimationFrame(gameState.animationId);
gameState.currentStage = 1;
gameState.score = 0;
gameState.currentInput = '';
gameState.currentOrder = '';
// 全ての文字をクリア
gameState.characters.forEach(char => {
if (char.element && char.element.parentNode) {
char.element.remove();
}
});
gameState.characters = [];
// UI リセット
document.getElementById('orderText').textContent = 'ゲームを開始してください';
document.getElementById('inputDisplay').textContent = '入力した文字がここに表示されます';
document.getElementById('stage').textContent = '1';
document.getElementById('score').textContent = '0';
document.getElementById('timer').textContent = '30';
document.getElementById('progressFill').style.width = '0%';
document.getElementById('startBtn').style.display = 'inline-block';
document.getElementById('restartBtn').style.display = 'none';
}
function showModal(title, text) {
document.getElementById('modalTitle').textContent = title;
document.getElementById('modalText').textContent = text;
document.getElementById('modal').style.display = 'flex';
}
function hideModal() {
document.getElementById('modal').style.display = 'none';
}
// タッチイベントの重複を防ぐ
document.addEventListener('touchstart', function(e) {
if (e.target.classList.contains('character')) {
e.preventDefault();
}
}, { passive: false });
</script>
</body>
</html>🔔 補足・注意事項
このコードや説明は、Claudeのバージョンや環境によって出力内容が異なる可能性があります。
同じ命令をしても、まったく違うコードが返ってくることもあるので、再現性は参考程度にご覧ください。

0 件のコメント:
コメントを投稿