
【ゲーム】JavaScript:63 絵文字よけゲーム
「🏃♂️ 絵文字よけゲーム 🏃♂️」は、プレイヤー(🚗)を左右キーで操作し、上から降ってくる絵文字を一定時間よけ続けるアクションゲームです。制限時間(デフォルト25秒)を越えるとクリア、障害物にぶつかるとゲームオーバーになります。
遊び方・操作方法
- スタートボタンを押すとゲーム開始。
- ←キー/→キーで車(🚗)を左右に移動。
- 障害物として降ってくる絵文字(🍎,🍋,…)に当たらないように操作。
- 制限時間を過ぎるか、障害物に衝突すると終了画面に移行します。
ルール
- 制限時間:25秒
- 障害物:ランダム絵文字、時間経過で出現頻度と落下速度が上昇
- クリア条件:25秒間一度も衝突せずにプレイ
- ゲームオーバー:車と障害物が重なった瞬間
- 得点要素:タイム到達でクリア演出のみ(タイムトライアルとして楽しむ)
🎮ゲームプレイ
以下のリンク先から実際にプレイできます。
63 絵文字よけゲーム
素材のダウンロード
以下のリンクから使用する素材をダウンロードできます。
emoji_dodge_title.png | emoji_dodge_bg.png |
---|---|
![]() | ![]() |
ゲーム画面イメージ

プログラム全文(emoji_dodge.html)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>🏃♂️ 絵文字よけゲーム 🏃♂️</title>
<style>
html, body {
margin: 0; padding: 0;
width: 100vw; height: 100vh;
font-family: 'Yu Gothic', 'Meiryo', sans-serif;
background: url('emoji_dodge_bg.png') no-repeat center center fixed;
background-size: cover;
}
body {
width: 100vw;
height: 100vh;
overflow: auto;
}
.container {
width: 800px;
margin: 40px auto;
background: rgba(255,255,255,0.96);
border-radius: 22px;
box-shadow: 0 4px 24px rgba(0,0,0,0.13);
padding-bottom: 32px;
min-height: 540px;
position: relative;
}
.title-img {
display: block;
margin: 20px auto 18px auto;
width: 340px;
max-width: 80%;
height: auto;
}
h1 {
text-align: center;
font-size: 2.1em;
margin: 0.6em 0 0.15em 0;
color: #1976d2;
text-shadow: 1px 1px 7px #fff;
letter-spacing: 0.04em;
}
.rule-section {
background: rgba(235,245,255,0.98);
border-radius: 14px;
margin: 28px 32px 14px 32px;
padding: 16px 24px;
box-shadow: 0 2px 8px #4d90fe22;
}
.rule-title {
text-align: center;
font-weight: bold;
font-size: 1.3em;
margin-bottom: 10px;
color: #1976d2;
}
.rule-text {
text-align: left;
font-size: 1.09em;
line-height: 1.65;
color: #174078;
letter-spacing: 0.01em;
}
.btn {
display: block;
margin: 28px auto 0 auto;
padding: 14px 50px;
font-size: 1.2em;
border: none;
border-radius: 28px;
background: linear-gradient(90deg, #87c9fa, #1565c0);
color: #fff;
font-weight: bold;
box-shadow: 0 2px 8px #1976d266;
cursor: pointer;
transition: background 0.2s;
}
.btn:hover { background: linear-gradient(90deg, #b7e4fe, #1976d2); }
.game-area {
width: 740px;
margin: 36px auto 0 auto;
background: rgba(240,248,255,0.96);
border-radius: 16px;
box-shadow: 0 1px 10px #1565c055;
display: flex;
flex-direction: column;
align-items: center;
min-height: 330px;
padding: 16px 0 20px 0;
user-select: none;
}
.info {
text-align: center;
color: #1976d2;
font-size: 1.18em;
margin: 5px 0 0 0;
}
.game-canvas {
margin: 20px auto 0 auto;
background: #fff;
border-radius: 18px;
box-shadow: 0 0 12px #1976d245;
border: 2px solid #1565c0;
display: block;
}
.message-box {
text-align: center;
background: rgba(235,245,255,0.98);
font-size: 1.7em;
color: #1976d2;
font-weight: bold;
border-radius: 16px;
box-shadow: 0 4px 24px #1976d233;
width: 80%;
max-width: 480px;
margin: 34px auto 0 auto;
padding: 32px 18px;
position: relative;
z-index: 2;
}
.center-btn { margin: 22px auto 0 auto; }
.timer-bar {
text-align: center;
font-size: 1.14em;
margin-top: 6px;
color: #e53935;
font-weight: bold;
letter-spacing: 0.08em;
}
</style>
</head>
<body>
<div class="container" id="main-container"></div>
<script>
// ============================
// 🏃♂️ 絵文字よけゲーム
// ============================
// ゲームパラメータ
const CANVAS_W = 700;
const CANVAS_H = 330;
const PLAYER_W = 44;
const PLAYER_H = 44;
const PLAYER_Y = CANVAS_H - PLAYER_H - 4;
const OBSTACLE_W = 38;
const OBSTACLE_H = 38;
const OBSTACLE_EMOJIS = ["🍎","🍋","🍌","🍇","🍊","🍓","🥑","🍒","🥕","🌽","🥐","🍔","🍕"];
const PLAYER_EMOJI = "🚗";
const GAME_TIME = 25; // 秒避けきればクリア
let obstacles = [];
let playerX = 0;
let playerV = 0;
let startTime = 0;
let timerId = null;
let animId = null;
let gameActive = false;
let clearFlag = false;
// タイトル画面
function showTitleScreen() {
clearInterval(timerId);
cancelAnimationFrame(animId);
document.getElementById('main-container').innerHTML = `
<h1>🏃♂️ 絵文字よけゲーム 🏃♂️</h1>
<img src="emoji_dodge_title.png" class="title-img" alt="絵文字よけゲーム タイトル">
<div class="rule-section">
<div class="rule-title">🏃♂️ 遊び方・ルール 🏃♂️</div>
<div class="rule-text">
・左右キー(←→)で車(🚗)を操作します。<br>
・上から落ちてくる絵文字をよけ続けましょう。<br>
・${GAME_TIME}秒よけきるとクリア!<br>
・ぶつかるとゲームオーバーです。
</div>
</div>
<button class="btn" id="start-btn">スタート</button>
`;
document.getElementById('start-btn').onclick = showGameScreen;
}
// ゲーム初期化&開始
function showGameScreen() {
obstacles = [];
playerX = (CANVAS_W - PLAYER_W) / 2;
playerV = 0;
clearFlag = false;
startTime = Date.now();
gameActive = true;
// 描画
document.getElementById('main-container').innerHTML = `
<h1>🏃♂️ 絵文字よけゲーム 🏃♂️</h1>
<div class="game-area">
<div class="info">←→キーで操作・絵文字をよけよう!</div>
<div class="timer-bar" id="timer-bar">残り: ${GAME_TIME} 秒</div>
<canvas class="game-canvas" id="game-canvas" width="${CANVAS_W}" height="${CANVAS_H}"></canvas>
</div>
`;
// キーリスナー
window.onkeydown = (e) => {
if (!gameActive) return;
if (e.key === "ArrowLeft") playerV = -7;
else if (e.key === "ArrowRight") playerV = 7;
};
window.onkeyup = (e) => {
if (!gameActive) return;
if (e.key === "ArrowLeft" || e.key === "ArrowRight") playerV = 0;
};
// ループ開始
animId = requestAnimationFrame(gameLoop);
timerId = setInterval(()=>{
let t = Math.max(0, GAME_TIME - ((Date.now() - startTime) / 1000));
document.getElementById("timer-bar").textContent = `残り: ${t.toFixed(1)} 秒`;
}, 100);
}
// メインゲームループ
function gameLoop() {
const ctx = document.getElementById("game-canvas").getContext("2d");
ctx.clearRect(0, 0, CANVAS_W, CANVAS_H);
// 障害物生成
if (Math.random() < 0.028 + Math.min(0.07, (Date.now() - startTime)/30000)) {
// 落ちてくるx座標ランダム
const x = Math.floor(Math.random() * (CANVAS_W - OBSTACLE_W));
const emoji = OBSTACLE_EMOJIS[Math.floor(Math.random() * OBSTACLE_EMOJIS.length)];
obstacles.push({x, y: -OBSTACLE_H, emoji});
}
// 障害物移動
for (let obs of obstacles) {
obs.y += 4 + Math.min(6, (Date.now()-startTime)/8000); // 時間で加速
}
// 障害物と当たり判定
for (let obs of obstacles) {
if (
obs.x < playerX + PLAYER_W &&
obs.x + OBSTACLE_W > playerX &&
obs.y < PLAYER_Y + PLAYER_H &&
obs.y + OBSTACLE_H > PLAYER_Y
) {
// 当たり!ゲームオーバー
gameOver(false);
return;
}
}
// 画面外を削除
obstacles = obstacles.filter(obs => obs.y < CANVAS_H);
// プレイヤー移動
playerX += playerV;
if (playerX < 0) playerX = 0;
if (playerX > CANVAS_W - PLAYER_W) playerX = CANVAS_W - PLAYER_W;
// プレイヤー描画
ctx.font = "38px serif";
ctx.fillText("🚗", playerX, PLAYER_Y + PLAYER_H - 2);
// 障害物描画
for (let obs of obstacles) {
ctx.font = "33px serif";
ctx.fillText(obs.emoji, obs.x, obs.y + OBSTACLE_H - 4);
}
// 時間切れ判定
if (((Date.now() - startTime) / 1000) >= GAME_TIME) {
clearFlag = true;
gameOver(true);
return;
}
// ループ
if (gameActive) animId = requestAnimationFrame(gameLoop);
}
// ゲーム終了
function gameOver(isClear) {
gameActive = false;
clearInterval(timerId);
cancelAnimationFrame(animId);
setTimeout(() => showEndScreen(isClear), 300);
}
// 終了画面
function showEndScreen(isClear) {
document.getElementById('main-container').innerHTML = `
<h1>🏃♂️ 絵文字よけゲーム 🏃♂️</h1>
<img src="emoji_dodge_title.png" class="title-img" alt="絵文字よけゲーム タイトル">
<div class="message-box">
${
isClear
? "🎉 おめでとう!<br>すべての障害物を避けきりました!"
: "😢 ゲームオーバー!<br>またチャレンジしてね。"
}
</div>
<button class="btn center-btn" id="back-title-btn">タイトル画面に戻る</button>
`;
document.getElementById('back-title-btn').onclick = showTitleScreen;
window.onkeydown = null;
window.onkeyup = null;
}
// 初期表示
showTitleScreen();
</script>
</body>
</html>
アルゴリズムの流れ
手順 | 処理内容 |
---|---|
1 | タイトル画面描画 → スタートボタン押下でゲーム画面へ |
2 | showGameScreen() で初期化:プレイヤー位置、障害物配列、タイマー開始 |
3 | キー押下 (onkeydown )/離上 (onkeyup ) で左右移動フラグを制御 |
4 | gameLoop() :・障害物生成(時間経過で頻度UP)・障害物移動・衝突判定 |
5 | 衝突なければプレイヤーと障害物をCanvas描画 |
6 | 制限時間到達でクリア判定、衝突でゲームオーバー判定 |
7 | gameOver() → showEndScreen() で結果表示 |
関数の詳細
関数名 | 機能概要 | 詳細説明 |
---|---|---|
showTitleScreen() | タイトル画面描画 | HTMLを出し「スタート」ボタン設置。リスナー解除、タイマー&アニメ停止。 |
showGameScreen() | ゲーム初期化&画面描画 | 変数初期化、Canvas要素&タイマー要素を出力。キーイベント登録。メインループ開始。 |
handleKeyDown/Up() | プレイヤー移動フラグ制御 | ←→キーの押下離上をフラグ(playerV)に反映。 |
gameLoop() | ゲームループ本体 | 障害物生成・移動・消去/衝突判定/プレイヤー移動&描画/障害物描画/クリア判定/次フレーム呼び出しの一連処理。 |
updateTimer() | タイマー表示更新 | 経過時間から残り時間を計算し、画面上のテキストを更新。 |
gameOver(isClear) | 終了処理 | ループ停止、タイマー解除、結果表示遅延呼び出し。 |
showEndScreen() | 終了画面描画 | クリア or ゲームオーバーのメッセージを出力し、タイトルへの戻るボタンを設置。キーイベント解除。 |
改造のポイント
- 難易度調整
・GAME_TIME
を短くすれば緊張感UP、長くすれば初心者向けに。
・障害物落下速度や生成頻度(Math.random()
の閾値)をステージ経過で動的に増加させると、後半の難度が上がります。 - グラフィック&演出
・Canvasの背景や🎵サウンドエフェクトを追加して、視覚・聴覚で盛り上げる。
・衝突時・クリア時にアニメーション(画面フラッシュ、パーティクル)を実装。 - 操作の拡張
・スマホ向けに左右キーだけでなく、画面左半分タップで左、右半分で右移動などタッチ操作を追加。 - 新モード
・一定時間内に何体避けられるか「サバイバルモード」や、制限時間内にスコアを競う「ポイント制モード」を実装すると、リプレイ性が高まります。
アドバイス
まずはコアの避け動作と衝突判定をブラッシュアップし、動作が安定してから難易度調整や演出強化を進めましょう。段階的にモード追加・ランキング機能を取り入れると、より長く遊ばれるゲームになります!