実験#110:脱走したハムを保護、たまにゴキ(ハムスターキャッチ)

■110個目 「ハムスターキャッチ」

こんにちは、AIと作る100のゲーム実験室の みー です。(*^_^*)/

今回は、ちょっとハラハラするアクションゲーム
「ハムスターキャッチ」を作ってみました。(^_^*)

お部屋のフローリングの上を、
ふわふわのハムスターが右へ左へとトコトコ走り回ります。

今回こだわったのは、お部屋に潜む “危険な同居人”。

「かわいいハムスターに急いで飛びつきたい……
でも、もし間違えてアレを素手で掴んでしまったら?」

そんなドキドキの遊び心から生まれたゲームです。(=v=*)

お部屋を走り回るのは、この2匹(?)。

① ふわふわで愛らしい「脱走ハムスター」
② 絶対に触りたくない、黒くてカサカサ動く「G」さん

ハムスターをタップすると捕まえられますが、
もし勢いあまって「G」さんに触れてしまうと……即ゲームオーバー!(;_;)

空振りしてもペナルティはないので、
じっくりタイミングを見極めるのがポイントです。

絶望した時の「Σ(>o<;)”≪ひぇ!」という
手作り顔文字もこだわりのひとつ。(笑)

さらに、連続でハムスターを捕まえると、
回数に応じてマスターから素敵な称号がもらえます。

「見習い卒業」 「凄腕ハンター」 「伝説のキャッチャー」などなど……

どんな称号があるかは、遊んでのお楽しみです。(^O^)

ぜひ、あなたの手で “脱走ハム” を保護してあげてくださいね。

■ AIとのやりとりで面白かった部分

● ゲーム仕様の相談からスタート

みー:(^v^) 今日もゲームを作ります。htmlで動かせるゲーム。
主観で飛びつくタイミングゲームを作りたいです。

タイミングメーターで動く標的を捕まえる、脱走ハムスター捕まえゲーム。

AI: 「主観視点でタイミングメーターを使って、脱走したハムスターに飛びつく」 すごく面白いアイデアだね。

焦りと冷静さのバランスが楽しくて、
何度も挑戦したくなるゲームになりそうだよ。応援しているよ!

● ハムスターの“ふわふわ顔”を作りたい

みー:(^_^) ハムスターを絵文字から、
図形の組み合わせで ふわふわかわいい顔にできるかな。

AI: いいね!図形を組み合わせたカスタム顔なら、
君だけの「ふわふわハムスター」が走り回るようになるよ。 試してみてね。

● 連続キャッチのランキングを作る

みー:(^o^) 連続キャッチでスコアランキングを作りましょう。

上位3位は少しゴージャスに。 3回ごとにご褒美コメントを添えたいです。
30回連続までのコメントをお願いします。

AI: いいね!連続キャッチは緊張感があって楽しいし、
ランキングがあるとやり込みたくなるよね。

画面横にランキングとコメントが並ぶようにしておいたよ。
30回連続までのコメントも準備してあるよ。

● Gさんの導入で新しい緊張感を追加

みー:( ̄w ̄) ノーミスは難しいね。

ハムスターの後ろをゴキブリさんがうろうろ。

ハムスターを捕まえ損ねても終わらないけど、
ゴキブリを間違えて捕まえるとゲームオーバーにしましょう。

AI: なるほど、緊張感のバランスがちょうど良くなるね。

「ハムスターの後ろをうろうろするGさん」を追加して、
新しいルールにしてみたよ。

  • 空振り:スコアはそのまま。再挑戦OK
  • Gさんを捕獲:即ゲームオーバー!

ハムスターとGさんが重なった瞬間は絶対に飛びつけない、
新しいドキドキが生まれたね。

● ゲームオーバーの顔文字と称号システム

みー:(=v=) ゲームオーバーの時の顔文字は
「Σ(>o<;)”≪ひぇ!」でお願いします。

あと、3連続ごとに上がる称号もランキングに添えられるかな。

AI: その顔文字、最高だね!
Gさんを素手で触っちゃった時の絶望感が コミカルに伝わっていい感じだよ。

称号システムも組み込んでおいたよ。

3連続ごとにランクアップして、
30連続で「伝説の捕獲神」になれるみたいだね。(笑)


■ 実際の動作

まずは、AIが最初に作ってくれた試作版のゲーム画面です。
とてもシンプルですが、イメージに近い仕上がりだったので、
ここから少しずつ改良を重ねていきました。

(画像:AIが最初に出してくれた試作画面)


こちらが、仕上がりのゲーム画面です。
ふわふわなハムスターと、黒い影が高速で動いています。
タイミングを合わせて、狙いをつけてキャッチしましょう。

(画像:仕上がりのゲーム画面)


連続でキャッチできると、素敵な称号がもらえます。
あなたは何連続までいけるでしょうか。(^v^)

(画像:ゲーム画面)




そして…… もし間違ってハムスター以外のものを捕まえてしまうと、
ゲームオーバーです。

「Σ(>o<;)”≪ひぇ!」 という、
あの絶望の顔文字が画面に大きく表示されます。(笑)

(画像:ゲームオーバー)



■ コードのポイント

今回の記事では、
AI と相談しながら作った「ハムスターキャッチ」 の HTML コードを公開します。

このコードをそのまま保存するだけで、
あなたの PC でもすぐに遊べます。

ブラウザだけで動く、とてもシンプルなゲームなので、
「コードは初めて…」という方でも気軽に試してみてくださいね。

▼ 遊ぶまでの手順(むずかしさ:やさしい)
① テキストエディタを開く

Windows の場合は「メモ帳」、
Mac の場合は「テキストエディット」を使います。
(※検索バーで「メモ帳」と入力するとすぐ出てきます)

② 下のコードをコピーして貼り付けます。
③ 「hamusuta.html」など、好きな名前で保存します。

(※拡張子は .html にしてください)

④ 保存したファイルをダブルクリックすると、
ブラウザでゲームが起動します。

■ 遊び方・操作方法

遊び方はとってもシンプルです。(^^*)

① タイミングメーターをチェック

画面の下にある「タイミングメーター」に、
赤い線が左右へスーッと動いています。

この赤い線は、あなたが“飛びつくタイミング”を示す大事な目印です。

② ハムスターの真下に赤い線が来たら……

すかさず「飛びつく!」ボタンをポチッ!(≧▽≦)

タイミングがぴったり合えば、見事に捕獲成功です。

「次のターゲットへ!」ボタンで、どんどん記録を伸ばしていきましょう。

もしタイミングがずれて空振りしてしまっても、大丈夫。(´▽`*)

ペナルティはないので、「気を取り直してもう一回!」ボタンで
何度でも再挑戦できます。

ただし…… ハムスターの背後をカサカサと動く 「G」さん には要注意!

赤い線が「G」さんの真下にある時に飛びついてしまうと、
Σ(>o<;)”≪ひぇ! っとなって即ゲームオーバーです。(>_<;)

ハムスターと G さんが重なっている時は、
グッとこらえて見送る勇気も必要ですよ。(=v=*)

スマホでも PC でも、ブラウザを開くだけですぐに遊べます。

あなたのお名前と一緒に、
ぜひかっこいい「称号」をランキングに刻んでみてくださいね♪


“コードは長いので折りたたんでいます。必要な方は開いてご覧ください。

▼ここからコード▼(クリックで開く)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>脱走ハムスター捕獲ゲーム - お部屋改装版</title>
<style>
body {
display: flex; flex-direction: column; align-items: center;
background: #2c3e50; color: #ecf0f1; font-family: sans-serif;
user-select: none; margin: 0; padding: 20px;
}
h2 { margin-bottom: 5px; }
.subtitle { margin-top: 0; color: #bdc3c7; margin-bottom: 20px; }
#main-layout { display: flex; gap: 30px; max-width: 950px; width: 100%; flex-wrap: wrap; justify-content: center; }
#game-side { flex: 1; min-width: 350px; max-width: 600px; display: flex; flex-direction: column; align-items: center; }
#side-panel { width: 300px; display: flex; flex-direction: column; gap: 20px; }
/* ゲーム画面 */
#game-container {
width: 100%; height: 400px; background: #e0d6c8; position: relative; overflow: hidden;
border: 4px solid #34495e; border-radius: 10px; box-shadow: 0 10px 20px rgba(0,0,0,0.5);
}
/* 壁と飾り */
.wall { height: 60%; background: #f5e6d3; width: 100%; position: absolute; top: 0; border-bottom: 4px solid #8d6e63; }
/* 時計 */
.clock {
position: absolute; top: 20px; left: 40px; width: 45px; height: 45px;
background: #fff; border: 4px solid #5d6d7e; border-radius: 50%;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
.clock::before { /* 短針 */
content: ''; position: absolute; top: 21px; left: 21px; width: 12px; height: 3px;
background: #333; transform-origin: left center; transform: rotate(-20deg); border-radius: 2px;
}
.clock::after { /* 長針 */
content: ''; position: absolute; top: 21px; left: 21px; width: 18px; height: 2px;
background: #333; transform-origin: left center; transform: rotate(-90deg); border-radius: 2px;
}
/* カレンダー */
.calendar {
position: absolute; top: 30px; right: 50px; width: 35px; height: 45px;
background: #fff; border-radius: 3px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);
border-top: 12px solid #e74c3c; display: flex; flex-direction: column; align-items: center; padding-top: 5px; box-sizing: border-box;
}
.calendar::before { /* 日付っぽい線 */
content: ''; width: 15px; height: 4px; background: #333; margin-bottom: 4px; border-radius: 2px;
}
.calendar::after { /* 下の文字っぽい線 */
content: ''; width: 25px; height: 10px;
background: repeating-linear-gradient(to bottom, #ccc, #ccc 2px, transparent 2px, transparent 4px);
}
/* 床(濃いめのフローリング) */
.floor {
height: 40%; width: 100%; position: absolute; bottom: 0;
background: repeating-linear-gradient(to right, #5c4033, #5c4033 45px, #4a332a 45px, #4a332a 48px);
box-shadow: inset 0 10px 15px rgba(0,0,0,0.2);
}
/* スコア表示 */
#score-counter {
position: absolute; top: 15px; right: 110px; font-size: 20px; font-weight: bold; color: #e67e22;
background: rgba(255,255,255,0.9); padding: 5px 15px; border-radius: 20px; border: 2px solid #e67e22; z-index: 10;
}
/* ハムスター */
#hamster {
position: absolute; bottom: 120px; left: 50%; transform: translateX(-50%); transition: transform 0.1s;
z-index: 5; width: 80px; height: 80px;
}
.hamster-face { position: relative; width: 100%; height: 100%; }
.hamster-body { position: absolute; top: 10%; left: 10%; width: 80%; height: 80%; background: #ffe0c0; border-radius: 50%; box-shadow: 0 0 15px 15px #ffe0c0, 0 0 30px 25px rgba(255, 224, 192, 0.4); }
.hamster-ear { position: absolute; width: 25%; height: 25%; background: #ffe0c0; border-radius: 50%; z-index: -1; top: -5%; }
.left-ear { left: 10%; transform: rotate(-20deg); }
.right-ear { right: 10%; transform: rotate(20deg); }
.hamster-ear-inner { position: absolute; top: 20%; left: 20%; width: 60%; height: 60%; background: #ffb6c1; border-radius: 50%; }
.hamster-eye { position: absolute; width: 15%; height: 15%; background: #000; border-radius: 50%; top: 35%; }
.left-eye { left: 25%; }
.right-eye { right: 25%; }
.hamster-nose { position: absolute; width: 10%; height: 10%; background: #ffb6c1; border-radius: 50%; top: 55%; }
.hamster-mouth { position: absolute; width: 20%; height: 10%; border: 2px solid #000; border-color: transparent transparent #000 transparent; border-radius: 0 0 50% 50%; top: 65%; }
.hamster-whiskers { position: absolute; width: 30%; height: 1px; background: rgba(0,0,0,0.3); top: 60%; }
.whiskers-left { left: -20%; transform: rotate(5deg); }
.whiskers-right { right: -20%; transform: rotate(-5deg); }
/* G(ゴキブリさん) */
#roach {
position: absolute; bottom: 130px; left: 50%; transform: translateX(-50%); transition: transform 0.1s;
z-index: 4; width: 50px; height: 30px; opacity: 0.9;
}
.roach-body { width: 100%; height: 100%; background: #2c1a17; border-radius: 40% 40% 50% 50%; position: relative; box-shadow: 0 5px 10px rgba(0,0,0,0.6); }
.roach-antenna { position: absolute; width: 2px; height: 25px; background: #2c1a17; top: -15px; }
.roach-antenna.left { left: 10px; transform: rotate(-40deg); }
.roach-antenna.right { right: 10px; transform: rotate(40deg); }
/* プレイヤーの手 */
#hands { font-size: 80px; position: absolute; bottom: -120px; left: 50%; transform: translateX(-50%); transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); opacity: 0; z-index: 10; white-space: nowrap; }
/* メッセージ&ゲームオーバー顔文字 */
#message { position: absolute; top: 40%; left: 50%; transform: translate(-50%, -50%); font-size: 40px; font-weight: bold; color: #fff; text-shadow: 2px 2px 0 #333, -2px -2px 0 #333, 2px -2px 0 #333, -2px 2px 0 #333; display: none; z-index: 20; white-space: nowrap; }
#game-over-face {
position: absolute; bottom: 15px; left: 50%; transform: translateX(-50%);
font-size: 32px; font-weight: bold; color: #fff;
text-shadow: 2px 2px 4px rgba(0,0,0,0.8), -1px -1px 0 #333, 1px -1px 0 #333, -1px 1px 0 #333, 1px 1px 0 #333;
display: none; z-index: 20; white-space: nowrap;
}
/* タイミングメーター */
#meter-area { width: 100%; background: #34495e; padding: 15px; border-radius: 10px; box-sizing: border-box; margin-top: 20px; }
#meter-bar { width: 100%; height: 30px; background: #7f8c8d; position: relative; border-radius: 15px; overflow: hidden; }
#cursor { width: 12px; height: 30px; background: #e74c3c; position: absolute; left: 0; box-shadow: 0 0 10px #e74c3c; border-radius: 6px; }
/* ボタン関係 */
#controls { margin-top: 20px; display: flex; gap: 10px; }
button { padding: 15px 30px; font-size: 20px; font-weight: bold; cursor: pointer; border: none; border-radius: 5px; background: #3498db; color: white; box-shadow: 0 5px #2980b9; transition: 0.1s; }
button:active { transform: translateY(5px); box-shadow: 0 0 #2980b9; }
button:disabled { background: #95a5a6; box-shadow: 0 5px #7f8c8d; cursor: not-allowed; }
/* スコアランキング */
.panel-box { background: #34495e; padding: 20px; border-radius: 10px; box-shadow: 0 5px 15px rgba(0,0,0,0.3); }
.panel-box h3 { margin-top: 0; border-bottom: 2px solid #5d6d7e; padding-bottom: 8px; font-size: 20px; color: #f1c40f; }
.ranking-list { list-style: none; padding: 0; margin: 0; }
.ranking-item { display: flex; justify-content: space-between; align-items: center; padding: 10px 15px; margin-bottom: 8px; border-radius: 6px; font-weight: bold; background: #2c3e50; }
.rank-1 { background: linear-gradient(45deg, #ffd700, #f39c12); color: #2c3e50; box-shadow: 0 0 15px #ffd700; border: 2px solid #fff; font-size: 18px; }
.rank-2 { background: linear-gradient(45deg, #e5e7e9, #bdc3c7); color: #2c3e50; box-shadow: 0 0 10px #bdc3c7; border: 1px solid #fff; }
.rank-3 { background: linear-gradient(45deg, #edbb99, #dc7633); color: #fff; box-shadow: 0 0 8px #dc7633; }
.rank-badge { font-size: 20px; margin-right: 10px; }
.rank-title { font-size: 14px; color: #bdc3c7; margin-right: 5px; font-weight: normal; }
.rank-1 .rank-title { color: #8d6e63; font-weight: bold; }
.rank-2 .rank-title { color: #5d6d7e; font-weight: bold; }
.rank-3 .rank-title { color: #fdf2e9; font-weight: bold; }
#comment-box h4 { margin-top: 0; color: #2ecc71; font-size: 16px; }
#reward-comment { font-size: 15px; line-height: 1.5; color: #eaeded; background: #2c3e50; padding: 12px; border-radius: 6px; border-left: 4px solid #2ecc71; min-height: 60px; margin: 0; }
</style>
</head>
<body>
<h2>脱走ハムスター捕獲大作戦!</h2>
<p class="subtitle">空振りはOK!だけど、背後をウロウロする「G」を掴んだら即ゲームオーバーだ!</p>
<div id="main-layout">
<div id="game-side">
<div id="game-container">
<div class="wall">
<div class="clock"></div>
<div class="calendar"></div>
</div>
<div class="floor"></div>
<div id="score-counter">捕獲: 0 匹</div>
<div id="roach">
<div class="roach-body">
<div class="roach-antenna left"></div>
<div class="roach-antenna right"></div>
</div>
</div>
<div id="hamster">
<div class="hamster-face">
<div class="hamster-ear left-ear"><div class="hamster-ear-inner"></div></div>
<div class="hamster-ear right-ear"><div class="hamster-ear-inner"></div></div>
<div class="hamster-body">
<div class="hamster-eye left-eye"></div>
<div class="hamster-eye right-eye"></div>
<div class="hamster-nose"></div>
<div class="hamster-mouth"></div>
<div class="hamster-whiskers whiskers-left"></div>
<div class="hamster-whiskers whiskers-right"></div>
</div>
</div>
</div>
<div id="hands">👐</div>
<div id="message"></div>
<div id="game-over-face">Σ(>o<;)”≪ひぇ!</div>
</div>
<div id="meter-area">
<div id="meter-bar">
<div id="cursor"></div>
</div>
</div>
<div id="controls">
<button id="jump-btn">飛びつく!</button>
<button id="next-btn" style="display: none; background: #e67e22; box-shadow: 0 5px #d35400;">次へ!</button>
<button id="retry-btn" style="display: none; background: #2ecc71; box-shadow: 0 5px #27ae60;">最初からリトライ</button>
</div>
</div>
<div id="side-panel">
<div class="panel-box">
<h3>🏆 ハイスコアランキング</h3>
<ul id="ranking-list" class="ranking-list"></ul>
</div>
<div class="panel-box" id="comment-box">
<h4>💬 マスターからのひと言</h4>
<p id="reward-comment">いらっしゃい!空振りしても怒らないから、Gだけは絶対に掴むんじゃないよ!</p>
</div>
</div>
</div>
<script>
let hamsterX = 50; let hamsterBaseSpeed = 1.5; let hamsterDir = 1;
let roachX = 20; let roachBaseSpeed = 2.2; let roachDir = -1;
let cursorX = 0; let cursorBaseSpeed = 3.0; let cursorDir = 1;
let isPlaying = true; let animationId; let currentScore = 0;
const rewardComments = {
0: "さあ、冷静にメーターを見極めるんだ。",
3: "3匹目!焦らなくていい、空振りはタダだからね。",
6: "6匹目!Gの動きが絶妙に嫌らしいだろう?",
9: "9匹目!重なった時は見送る勇気も必要さ。",
12: "12匹目!あんた、Gを避けるプロだな。",
15: "15匹突破!マスターも手に汗握ってきたよ。",
18: "18匹!そろそろGも本気を出して走り回りそうだ。",
21: "21匹!素晴らしい動体視力だ。常連の鑑だよ!",
24: "24匹!もうGのことなんて見えてないんじゃないか?",
27: "27匹!すごい記録だ…だが油断大敵だよ。",
30: "30匹達成!!あんたは伝説の捕獲屋だ!"
};
function getTitle(score) {
if (score >= 30) return "伝説の捕獲神";
if (score >= 27) return "ゴッドハンド";
if (score >= 24) return "百戦錬磨";
if (score >= 21) return "達人";
if (score >= 18) return "凄腕ハンター";
if (score >= 15) return "一流キャッチャー";
if (score >= 12) return "ベテラン";
if (score >= 9) return "一人前";
if (score >= 6) return "中堅";
if (score >= 3) return "見習い卒業";
return "新米";
}
let rankings = JSON.parse(localStorage.getItem('hamster_ranking_v4')) || [
{ name: "レジェンド", score: 15, title: "一流キャッチャー" },
{ name: "ベテラン客", score: 8, title: "中堅" },
{ name: "見習いスタッフ", score: 3, title: "見習い卒業" }
];
const hamsterEl = document.getElementById('hamster');
const roachEl = document.getElementById('roach');
const cursorEl = document.getElementById('cursor');
const handsEl = document.getElementById('hands');
const messageEl = document.getElementById('message');
const gameOverFaceEl = document.getElementById('game-over-face');
const scoreCounterEl = document.getElementById('score-counter');
const rewardCommentEl = document.getElementById('reward-comment');
const rankingListEl = document.getElementById('ranking-list');
const jumpBtn = document.getElementById('jump-btn');
const nextBtn = document.getElementById('next-btn');
const retryBtn = document.getElementById('retry-btn');
function update() {
if (!isPlaying) return;
let currentHamsterSpeed = hamsterBaseSpeed + (currentScore * 0.05);
hamsterX += currentHamsterSpeed * hamsterDir;
if (hamsterX >= 90) { hamsterX = 90; hamsterDir = -1; hamsterBaseSpeed = Math.random() * 1.5 + 1.2; }
else if (hamsterX <= 10) { hamsterX = 10; hamsterDir = 1; hamsterBaseSpeed = Math.random() * 1.5 + 1.2; }
let wobble = Math.sin(Date.now() / 80) * 15;
let scaleX = hamsterDir === 1 ? -1 : 1;
hamsterEl.style.left = `calc(${hamsterX}% - 40px)`;
hamsterEl.style.transform = `translateY(${wobble}px) scaleX(${scaleX})`;
let currentRoachSpeed = roachBaseSpeed + (currentScore * 0.08);
roachX += currentRoachSpeed * roachDir;
if (roachX >= 92) { roachX = 92; roachDir = -1; roachBaseSpeed = Math.random() * 2.0 + 1.5; }
else if (roachX <= 8) { roachX = 8; roachDir = 1; roachBaseSpeed = Math.random() * 2.0 + 1.5; }
let roachWobble = Math.sin(Date.now() / 40) * 5;
let roachScale = roachDir === 1 ? -1 : 1;
roachEl.style.left = `calc(${roachX}% - 25px)`;
roachEl.style.transform = `translateY(${roachWobble}px) scaleX(${roachScale})`;
let currentCursorSpeed = cursorBaseSpeed + (currentScore * 0.1);
cursorX += currentCursorSpeed * cursorDir;
if (cursorX >= 98) { cursorX = 98; cursorDir = -1; }
else if (cursorX <= 0) { cursorX = 0; cursorDir = 1; }
cursorEl.style.left = `${cursorX}%`;
animationId = requestAnimationFrame(update);
}
function jump() {
if (!isPlaying) return;
isPlaying = false;
jumpBtn.disabled = true;
cancelAnimationFrame(animationId);
handsEl.style.left = `calc(${cursorX}% - 40px)`;
handsEl.style.bottom = '120px';
handsEl.style.opacity = '1';
let distHamster = Math.abs(hamsterX - cursorX);
let distRoach = Math.abs(roachX - cursorX);
setTimeout(() => {
let maxDist = Math.max(6, 12 - (currentScore * 0.2));
// Gを捕まえてしまった場合
if (distRoach < maxDist) {
// 手を隠して、床の下の方に顔文字を出す
handsEl.style.opacity = '0';
gameOverFaceEl.style.display = 'block';
messageEl.innerText = "ギャー!Gを掴んだ!😱";
messageEl.style.color = "#8e44ad";
hamsterEl.style.opacity = '0.3';
roachEl.style.transform = 'scale(1.5)';
messageEl.style.display = 'block';
// ダイアログが出る前に画面を描画させるための僅かなタイムラグ
setTimeout(() => {
updateRanking(currentScore);
retryBtn.style.display = 'block';
}, 50);
// ハムスターを捕まえた場合
} else if (distHamster < maxDist) {
currentScore++;
scoreCounterEl.innerText = `捕獲: ${currentScore} 匹`;
messageEl.innerText = "捕まえた!!✨";
messageEl.style.color = "#f1c40f";
handsEl.innerText = "🙌";
if (currentScore <= 30 && currentScore % 3 === 0) {
rewardCommentEl.innerText = rewardComments[currentScore];
} else if (currentScore > 30 && currentScore % 3 === 0) {
rewardCommentEl.innerText = `${currentScore}匹!?うちの店で伝説を作ってどうするんだい(笑)`;
}
nextBtn.innerText = "次のターゲットへ!";
nextBtn.style.display = 'block';
messageEl.style.display = 'block';
// どちらも外した場合(ミス)
} else {
messageEl.innerText = "空振り!💨";
messageEl.style.color = "#bdc3c7";
handsEl.innerText = "👋";
nextBtn.innerText = "気を取り直してもう一回!";
nextBtn.style.display = 'block';
messageEl.style.display = 'block';
}
}, 300);
}
function nextRound() {
isPlaying = true;
messageEl.style.display = 'none';
nextBtn.style.display = 'none';
jumpBtn.disabled = false;
handsEl.style.bottom = '-120px';
handsEl.style.opacity = '0';
handsEl.innerText = "👐";
hamsterX = Math.random() * 60 + 20;
roachX = Math.random() * 60 + 20;
cursorX = 0;
update();
}
function resetGame() {
currentScore = 0;
scoreCounterEl.innerText = "捕獲: 0 匹";
rewardCommentEl.innerText = rewardComments[0];
isPlaying = true;
messageEl.style.display = 'none';
gameOverFaceEl.style.display = 'none';
retryBtn.style.display = 'none';
jumpBtn.disabled = false;
handsEl.style.bottom = '-120px';
handsEl.style.opacity = '0';
handsEl.innerText = "👐";
hamsterEl.style.opacity = '1';
roachEl.style.transform = 'scale(1)';
hamsterX = 50;
roachX = 20;
cursorX = 0;
update();
}
function updateRanking(score) {
const isNewRecord = rankings.some(r => score > r.score) || rankings.length < 5;
if (isNewRecord) {
let name = prompt(`ランクイン!今回の記録は【 ${score}匹 】でした!\nお名前を入力してください:`, "プレイヤー");
if (!name) name = "ななしの常連さん";
let title = getTitle(score);
rankings.push({ name: name, score: score, title: title });
rankings.sort((a, b) => b.score - a.score);
rankings = rankings.slice(0, 5);
localStorage.setItem('hamster_ranking_v4', JSON.stringify(rankings));
renderRanking();
}
}
function renderRanking() {
rankingListEl.innerHTML = '';
rankings.forEach((item, index) => {
const li = document.createElement('li');
let rankClass = 'rank-other';
let badge = `【${index + 1}位】`;
if (index === 0) { rankClass = 'rank-1'; badge = '👑 1st'; }
else if (index === 1) { rankClass = 'rank-2'; badge = '🥈 2nd'; }
else if (index === 2) { rankClass = 'rank-3'; badge = '🥉 3rd'; }
li.className = `ranking-item ${rankClass}`;
li.innerHTML = `
<span><span class="rank-badge">${badge}</span><span class="rank-title">【${item.title || "新米"}】</span>${item.name}</span>
<span>${item.score}匹</span>
`;
rankingListEl.appendChild(li);
});
}
jumpBtn.addEventListener('click', jump);
nextBtn.addEventListener('click', nextRound);
retryBtn.addEventListener('click', resetGame);
renderRanking();
update();
</script>
</body>
</html>


■ 今日の学び

今回の「脱走大好きなハムスターの捕獲大作戦」は、
意外と難しいタイミングゲームになりました。

でも、制限時間はないので、
焦らずじっくり狙いをつけるのがコツです。(^-^)

さてさて、ここで皆さんにひとつご報告があります。

なんと……これまで作ってきたゲームが、とうとう 200個 を超えました!

もともと「1日1ゲーム」を目標にして、
ゲームには日付順のナンバリングをつけて保存してきました。

ただ、仕事との両立で毎日作るのは難しい日もあって、
お休みの日に「今日は作れるぞ!」と
ワクワクしながら 2〜3個まとめて作ることもあったんです。

そんな作り方を続けていたら、
最新のゲームにつけられた日付はなんと「8月12日」。

現実の時間を少し飛び越えて、
ちょっと未来のゲームを作ってしまいました。

( Ꙭ ) ミライ…!?

でも、この過程で改めて気づいたことがあります。

「これ面白そう!」「楽しそう!」と感じたアイデアが浮かんだら、
目標やペースにとらわれずに作ってみる。

そんなふうに遊ぶ“自由さ”って、とても大事だなと。

記録上は日付でナンバリングしていますが、
これからも皆さんには「1日1ゲームを目標」とお伝えしていきますね。
(実際は目標を大きくオーバーして作ってしまっていますが(^^;))

これからも、自由に楽しみながら いろいろなゲームの実験を続けていきます!

画像は、8/1現在での最新のゲーム保管フォルダです。(>v<*)

(画像:作ったゲーム保管用フォルダ)

■ 次回は、大自然を爆走!しょうが君のモトクロスゲームです。

次回は、大自然のダートコースを舞台にした爽快 3D アクション!

満面の笑みの しょうが君 が、
モトクロスバイクで猛スピードに駆け抜けます。

大ジャンプや、転落ギリギリの極細カーブなど、
スリル満点の難所が次々と登場します。

ピンチの時は、全身を燃やして爆走する
必殺技 「しょうが君ファイヤー」 で
強引に突破しましょう。(=v=*)

コースに散らばる 25 個の 虹色しましまコーン。
あなたはすべて回収して完走できるでしょうか?

次回もぜひ楽しみにしていてくださいね。(*^v^)ノシ


▶ 次の実験はこちら
しょうが君のファイヤー爆走
「しょうが君モトクロス」



 ✨今日も最後まで読んでくださって、ありがとうございます。
みーの実験室は、みなさんの応援で元気に動いています。(*^v^*)