実験#72:究極のあたりを求めて(福袋シミュレーター)

■72個目 「福袋シミュレーター」

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

今回は、みんな大好き「福袋」をテーマにしたゲームを作ってみました。 お正月じゃなくても、あの袋を開ける瞬間のドキドキを味わえちゃいます。

その名も、 「一攫千金!5万円福袋シミュレーター」 です。(^^*)ノ

🎁 今回のこだわりポイント
  • 福袋ならではのワクワク感
  • 1000種類の圧倒的アイテム数
  • 1円〜999,999円までの超格差アイテム

福袋の中身は全部で5つ。 5万円で買った福袋が「プラスになるか」「大赤字になるか」……まさに運試しのゲームです。d(^^o)

🏷 アイテムのカテゴリ

アイテムは大きく6つのランクに分かれています。

  • 神引き
  • 大当たり
  • 当たり
  • 普通
  • ハズレ
  • 絶望

それぞれの例を少し紹介すると……

神引き ・無人島 ・宇宙旅行ペアチケット ・伝説の聖剣

大当たり ・最新スマートフォン ・松阪牛1頭分 ・高級電動アシスト自転車

当たり ・ノイズキャンセリングイヤホン ・全自動コーヒーメーカー ・国産うなぎ蒲焼10尾

普通 ・特選コーヒー豆1kg ・人気のボードゲーム ・今治タオル高級セット

ハズレ ・マスターの特製ステッカー ・謎の木彫りの熊 ・派手な柄の靴下

絶望 ・道端の石ころ ・ちぎれた輪ゴム

などなど……。(^^;)

🎉 開封演出も盛りだくさん

福袋を開けると、5つのアイテムがバババン!と表示され、 最後に合計金額がドーン!と登場します。

  • 5万円以上なら大喜び演出(20万円超えで金色!)
  • 赤字ならしょんぼり演出(1円を引くと地獄…)

視覚的にも楽しい仕掛けになっています。

🌈 まずは世界観を楽しんでね

操作方法は記事の後半で紹介しますので、 まずはこのワクワクする福袋の世界を感じてもらえたら嬉しいです。(^v^人)

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

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

みー:(^v^) 今日もゲームを作ります。HTML形式で動くゲーム。

今回は「5万円福袋シミュレーター」の提案です。

  • 1000アイテム
  • 1円〜999,999円の超格差
  • 1袋5アイテム
  • 平均は1万円になるように調整
  • 開封すると5つのアイテムが文字で表示
  • 合計金額が5万円より多いか少ないかで演出が変わる

こんな感じのワクワクするゲームを作りたいです。

AI: いらっしゃい!今日も来てくれたんだね。

まずは「福袋」の雑学をひとつ──(雑学パート)

そして、あんたのアイデア通りに1000アイテムを用意しておいたよ。
平均が5万円になるように確率も調整済みさ。

● アイテムの幅をもっと広げたい

みー:(=v=) 商品名の種類をもっと増やせるかな?
999,999円と1円の“極端アイテム”も極小確率で入れたいです。

AI: じゃあ今日の雑学は「一円玉」の話を──(雑学パート)

要望通り、

  • 超特大ホームラン(999,999円)
  • 大ハズレの極み(1円) を極小確率で追加しておいたよ。
● 演出の強化

みー:(^v^) プラスになった時に紙吹雪を降らせたいです。
20万円超えは金色の紙吹雪で。

AI: 今日の雑学は「紙吹雪」の語源を──(雑学パート)

プラスなら紙吹雪、20万円超えなら金色の紙吹雪が舞うようにしたよ。

● 残念演出も入れたい

みー:_(め_ゅ)_ 残念演出も入れましょう。 1円が出たらどん底表現で。

AI: 今日の小話は「失敗から生まれた発明」──(雑学パート)

冷たい雨の残念演出と、 1円を引いた時の“画面暗転どん底演出”を追加したよ。


■ 実際の動作

ゲームのスタート画面

(画像:スタート画面)

福袋を開けるボタンを押すと、
福袋がガサガサ揺れるアニメーションが入り、
期待感が一気に高まります。

(画像:福袋開封画面)
袋が開くと、5つのアイテムがババン!と表示されます。


5万円を下回ると、 背景に冷たい雨が降る残念演出になります。
しょんぼり感がすごい……。

(画像:購入額以下の雨演出)


5万円を超えると、 画面いっぱいに紙吹雪が舞い上がります。
一気にお祝いムード!

(画像:購入額以上の紙吹雪演出)

総額が20万円を超えると、 豪華な金色の紙吹雪が降ってくる特別演出に。

(画像:20万円越えの金の紙吹雪)


■ コードのポイント

今回の記事では、AI と相談しながら作った
「福袋シミュレーター」 の HTML コードを公開します。

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

ブラウザだけで動く、とてもシンプルなゲームなので、
気軽に試してみてくださいね。

▼ 遊ぶまでの手順

①PC の「メモ帳」(※Windowsの場合)や  
 Mac の「テキストエディット」など、テキストエディタを開きます。

②下のコードをコピーして貼り付けます。

③「fukubukuro.html」など、好きな名前で保存します。
 (※拡張子は .html にしてください)

④保存したファイルをブラウザで開けば、すぐに遊べます。

 

■「福袋シミュレーター」操作方法♪

操作はとってもシンプル! ボタンをぽちぽち押すだけです。(^v^)

ステップ1:福袋を購入する

ゲームを開始すると、画面中央に可愛い「🎁」アイコンと
大きな 「5万円で運試し!」 ボタンが表示されます。

このボタンをクリックしてください。

これで、あなたは5万円の福袋を購入しました。(≧▽≦*)

ステップ2:福袋を開ける!

購入ボタンを押すと、画面が切り替わり、
「🛍️」アイコンと 「福袋を開ける!」 ボタンが登場します。

心の準備ができたら、このボタンをクリック(タップ)!

すると…… 福袋がガタガタと揺れ始めます。 w(゜o゜)w

「開封中…」の約1.5秒間。 ここが一番ドキドキする瞬間です。(・人・)
どんなお宝が出るか、お祈りして待ちましょう。

ステップ3:中身を確認して、もう一度!

開封演出が終わると、 5つのアイテムが バババン! と表示され、
最後に総額が ドーン! と発表されます。(^^)

アイテム名と金額を見て、一喜一憂してくださいね。

■ 結果に応じた特別演出

  • 大勝利:紙吹雪(カラフル / 金色)🎉
  • 残念:冷たい雨が降る演出 ☔
  • 1円を引いた時:画面が暗転する“どん底演出” 💀

結果画面の下には 「もう一度挑戦する」 ボタンが表示されます。

押すとステップ1に戻るので、 何度でも気の済むまで運試しできます。

■ 最後に

いかがでしたか?(^^*)
操作はとってもシンプルで、ボタンをぽちぽち押すだけ。

その裏では、1000個のアイテムから何が出るか、
壮大なドラマが生まれています。(=v=*)

ぜひ、あなたの 「神引き」 を体験してみてくださいね!(^_^)ノ

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

▼ここからコード▼(クリックで開く)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>一攫千金!5万円福袋シミュレーター 天国と地獄(サウンド付き)</title>
<style>
body {
text-align: center;
background-color: #f0f8ff;
font-family: 'Hiragino Maru Gothic ProN', 'Comic Sans MS', sans-serif;
margin: 0;
padding: 20px;
color: #333;
overflow: hidden;
transition: background-color 0.5s, color 0.5s;
}
#game-outer-container {
position: relative;
max-width: 500px;
margin: 0 auto;
}
#effect-canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 100;
}
#game-container {
background-color: #fff;
border: 4px solid #ff4500;
border-radius: 15px;
padding: 30px;
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
position: relative;
z-index: 10;
transition: all 0.5s;
}
h1 {
color: #ff4500;
font-size: 24px;
transition: color 0.5s;
}
.bag-icon {
font-size: 100px;
margin: 20px 0;
cursor: pointer;
transition: transform 0.2s;
}
.bag-icon:hover {
transform: scale(1.1);
}
.shake {
animation: shake 0.5s infinite;
}
@keyframes shake {
0% { transform: translate(1px, 1px) rotate(0deg); }
10% { transform: translate(-1px, -2px) rotate(-5deg); }
20% { transform: translate(-3px, 0px) rotate(5deg); }
30% { transform: translate(3px, 2px) rotate(0deg); }
40% { transform: translate(1px, -1px) rotate(5deg); }
50% { transform: translate(-1px, 2px) rotate(-5deg); }
60% { transform: translate(-3px, 1px) rotate(0deg); }
70% { transform: translate(3px, 1px) rotate(-5deg); }
80% { transform: translate(-1px, -1px) rotate(5deg); }
90% { transform: translate(1px, 2px) rotate(0deg); }
100% { transform: translate(1px, -2px) rotate(-5deg); }
}
button {
background-color: #ff8c00;
color: white;
border: none;
padding: 15px 30px;
font-size: 18px;
border-radius: 8px;
cursor: pointer;
font-weight: bold;
box-shadow: 0 4px 6px rgba(0,0,0,0.2);
}
button:hover {
background-color: #ff7f50;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
#result-area {
display: none;
margin-top: 20px;
}
.item-list {
list-style-type: none;
padding: 0;
text-align: left;
background: #fffafa;
border: 2px dashed #ffa07a;
padding: 15px;
border-radius: 10px;
transition: background 0.5s, border-color 0.5s;
}
.item {
font-size: 16px;
margin-bottom: 10px;
border-bottom: 1px solid #ccc;
padding-bottom: 5px;
display: flex;
justify-content: space-between;
}
.total-price {
font-size: 28px;
font-weight: bold;
margin: 20px 0;
}
.win {
color: #dc143c;
animation: pop 0.5s ease-out;
}
.lose {
color: #4169e1;
}
.legendary {
color: #ffd700;
font-weight: bold;
text-shadow: 1px 1px 2px #000;
}
.trash {
color: #a9a9a9;
}
.message {
font-size: 22px;
font-weight: bold;
margin-bottom: 20px;
}
@keyframes pop {
0% { transform: scale(0.5); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
.hidden {
display: none;
}
/* どん底モードのスタイル */
body.rock-bottom-mode {
background-color: #0a0a0a;
color: #555;
}
body.rock-bottom-mode #game-container {
background-color: #1a1a1a;
border-color: #333;
box-shadow: 0 0 20px rgba(0,0,0,0.8);
animation: dropDown 1s ease-in forwards;
}
body.rock-bottom-mode h1 {
color: #666;
}
body.rock-bottom-mode .item-list {
background: #111;
border-color: #333;
}
body.rock-bottom-mode .lose {
color: #8b0000;
text-shadow: 2px 2px 4px #000;
}
@keyframes dropDown {
0% { transform: translateY(0) scale(1); filter: grayscale(0); }
50% { transform: translateY(20px) scale(0.98); filter: grayscale(0.5); }
100% { transform: translateY(50px) scale(0.95); filter: grayscale(1); opacity: 0.9; }
}
</style>
</head>
<body>
<div id="game-outer-container">
<canvas id="effect-canvas"></canvas>
<div id="game-container">
<h1>🛍️ 5万円福袋シミュレーター 天国と地獄</h1>
<p>中身は5つのアイテム!神引きか、それとも底なしの絶望か…</p>
<p style="font-size: 0.8em; color: #888;">※ボタンを押すと音が鳴ります</p>
<div id="shop-area">
<div class="bag-icon">🎁</div>
<button id="buy-btn">5万円で運試し!</button>
</div>
<div id="open-area" class="hidden">
<div class="bag-icon" id="target-bag">🛍️</div>
<button id="open-btn">福袋を開ける!</button>
</div>
<div id="result-area">
<h3>✨ 福袋の中身 ✨</h3>
<ul class="item-list" id="item-list"></ul>
<div class="total-price" id="total-price"></div>
<div class="message" id="result-message"></div>
<button id="retry-btn">もう一度挑戦する</button>
</div>
</div>
</div>
<script>
// --- 8bitサウンド生成システム(Web Audio API) ---
const AudioContext = window.AudioContext || window.webkitAudioContext;
let audioCtx;
let bgmInterval;
let bgmStep = 0;
let isBgmPlaying = false;
// レトロな波形(矩形波)で音を鳴らす
function playTone(freq, type, duration, vol=0.1) {
if (!audioCtx) return;
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = type; // 'square' でファミコン風
osc.frequency.setValueAtTime(freq, audioCtx.currentTime);
gain.gain.setValueAtTime(vol, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + duration);
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start();
osc.stop(audioCtx.currentTime + duration);
}
// BGM再生
function startBGM() {
if (!audioCtx) {
audioCtx = new AudioContext();
}
if (audioCtx.state === 'suspended') audioCtx.resume();
if (isBgmPlaying) return;
isBgmPlaying = true;
// ちょっと気の抜けたお店のBGMループ
const melody = [261.63, 0, 329.63, 0, 392.00, 392.00, 523.25, 0, 392.00, 0, 329.63, 0, 261.63, 0, 0, 0];
bgmInterval = setInterval(() => {
let note = melody[bgmStep % melody.length];
if (note > 0) playTone(note, 'square', 0.15, 0.03); // BGMは少し音量小さめ
bgmStep++;
}, 200);
}
function stopBGM() {
clearInterval(bgmInterval);
isBgmPlaying = false;
}
// 各種効果音
function playBuySE() {
playTone(880, 'square', 0.1, 0.1); // ピッ
}
function playDrumRollSE() {
// ドコドコドコという期待感を煽る音
let count = 0;
let roll = setInterval(() => {
playTone(150 + Math.random()*50, 'square', 0.05, 0.1);
count++;
if (count > 25) clearInterval(roll);
}, 50);
}
function playWinSE() {
// ファンファーレ風
playTone(523.25, 'square', 0.1, 0.1); // C
setTimeout(() => playTone(659.25, 'square', 0.1, 0.1), 150); // E
setTimeout(() => playTone(783.99, 'square', 0.4, 0.1), 300); // G
}
function playGodSE() {
// 神引きの激しいアルペジオ
for(let i=0; i<10; i++) {
setTimeout(() => playTone(523.25 + i*100, 'square', 0.1, 0.1), i*80);
}
}
function playLoseSE() {
// 残念な下降音
playTone(392.00, 'square', 0.2, 0.1); // G
setTimeout(() => playTone(349.23, 'square', 0.2, 0.1), 250); // F
setTimeout(() => playTone(329.63, 'square', 0.5, 0.1), 500); // E
}
function playDespairSE() {
// 絶望の低音
playTone(100, 'sawtooth', 1.0, 0.2); // 重いブー音
setTimeout(() => playTone(80, 'sawtooth', 1.5, 0.2), 300);
}
// --- エフェクトシステム(紙吹雪 & 雨) ---
class EffectSystem {
constructor(canvas) {
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
this.particles = [];
this.effectType = 'none';
this.animationId = null;
this.resize();
window.addEventListener('resize', () => this.resize());
}
resize() {
this.canvas.width = this.canvas.parentElement.offsetWidth;
this.canvas.height = this.canvas.parentElement.offsetHeight;
}
start(type) {
this.stop();
this.effectType = type;
if (type === 'none') return;
this._createParticles();
this._loop();
}
stop() {
if (this.animationId) {
cancelAnimationFrame(this.animationId);
this.animationId = null;
}
this.particles = [];
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
_createParticles() {
let count = 100;
if (this.effectType === 'gold') count = 150;
if (this.effectType === 'rain') count = 150;
const colorful = ['#FFC0CB', '#FF69B4', '#FF1493', '#ADFF2F', '#7CFC00', '#00FFFF', '#1E90FF', '#FFD700'];
const gold = ['#FFD700', '#DAA520', '#B8860B', '#F4A460', '#FFE4B5'];
const rain = ['rgba(100, 149, 237, 0.6)', 'rgba(70, 130, 180, 0.6)', 'rgba(176, 196, 222, 0.6)'];
for (let i = 0; i < count; i++) {
let p = {
x: Math.random() * this.canvas.width,
y: Math.random() * this.canvas.height - this.canvas.height,
opacity: 1
};
if (this.effectType === 'rain') {
p.sizeX = 2;
p.sizeY = Math.random() * 15 + 10;
p.color = rain[Math.floor(Math.random() * rain.length)];
p.speedX = Math.random() * 0.5 - 0.25;
p.speedY = Math.random() * 10 + 15;
p.angle = 0;
p.spin = 0;
} else {
let colors = this.effectType === 'gold' ? gold : colorful;
p.sizeX = Math.random() * 8 + 4;
p.sizeY = p.sizeX;
p.color = colors[Math.floor(Math.random() * colors.length)];
p.speedX = Math.random() * 2 - 1;
p.speedY = Math.random() * 3 + 2;
p.angle = Math.random() * Math.PI * 2;
p.spin = Math.random() * 0.2 - 0.1;
}
this.particles.push(p);
}
}
_updateParticles() {
for (let i = 0; i < this.particles.length; i++) {
const p = this.particles[i];
p.x += p.speedX;
p.y += p.speedY;
p.angle += p.spin;
if (this.effectType !== 'rain') {
p.opacity -= 0.002;
}
if (p.y > this.canvas.height) {
if (this.effectType === 'rain') {
p.y = -p.sizeY;
p.x = Math.random() * this.canvas.width;
} else if (p.opacity < 0) {
this.particles.splice(i, 1);
i--;
}
}
}
}
_drawParticles() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.particles.forEach(p => {
this.ctx.save();
this.ctx.globalAlpha = p.opacity;
this.ctx.translate(p.x, p.y);
this.ctx.rotate(p.angle);
this.ctx.fillStyle = p.color;
this.ctx.fillRect(-p.sizeX / 2, -p.sizeY / 2, p.sizeX, p.sizeY);
this.ctx.restore();
});
}
_loop() {
this._updateParticles();
this._drawParticles();
if (this.particles.length > 0 || this.effectType === 'rain') {
this.animationId = requestAnimationFrame(() => this._loop());
} else {
this.animationId = null;
}
}
}
// アイテムプールの生成
const itemPool = [];
const categories = [
{ name: "神", min: 999999, max: 999999, prob: 0.001, class: "legendary", items: ["無人島", "宇宙旅行ペアチケット", "伝説の聖剣", "世界一周クルーズ券"] },
{ name: "超絶レア", min: 100000, max: 300000, prob: 0.009, class: "win", items: ["幻の純金製コーヒーミル", "ハワイ旅行ペアチケット", "最新ゲーミングPCフルセット", "高級ブランドの腕時計", "謎の天才画家の絵画", "高級ホームシアターセット", "プロ用一眼レフカメラ"] },
{ name: "大当たり", min: 30000, max: 99900, prob: 0.09, class: "", items: ["最新スマートフォン", "松阪牛1頭分(部位セット)", "ロボット掃除機最上位モデル", "オーダーメイドスーツお仕立券", "高級電動アシスト自転車", "有名温泉ペア宿泊券", "高級羽毛布団"] },
{ name: "当たり", min: 10000, max: 29900, prob: 0.20, class: "", items: ["ノイズキャンセリングイヤホン", "高級フレンチペア食事券", "全自動コーヒーメーカー", "有名デザイナーの椅子", "国産うなぎ蒲焼10尾", "高級和牛すき焼きセット", "コードレス掃除機", "美容家電セット"] },
{ name: "普通", min: 3000, max: 9900, prob: 0.30, class: "", items: ["特選コーヒー豆1kg", "おしゃれなペアマグカップ", "人気のボードゲーム", "アロマディフューザー", "今治タオル高級セット", "ご当地レトルトカレーセット", "高級オリーブオイル", "Bluetoothスピーカー", "モバイルバッテリー"] },
{ name: "ハズレ", min: 100, max: 2900, prob: 0.399, class: "", items: ["マスターの特製ステッカー", "うまい棒1年分", "謎の木彫りの熊", "消しゴム詰め合わせ", "ただのタワシ", "肩たたき券", "ポケットティッシュ100個", "よくわからない置物", "大量の輪ゴム", "派手な柄の靴下"] },
{ name: "絶望", min: 1, max: 1, prob: 0.001, class: "trash", items: ["道端の石ころ", "ちぎれた輪ゴム", "誰かのサインの切れ端", "使用済み切手", "期限切れのクーポン"] }
];
for(let i = 0; i < 1000; i++) {
let rand = Math.random();
let cumulativeProb = 0;
let selectedTier;
for (let tier of categories) {
cumulativeProb += tier.prob;
if (rand < cumulativeProb) {
selectedTier = tier;
break;
}
}
let price = selectedTier.min === selectedTier.max ? selectedTier.min : Math.floor((Math.random() * (selectedTier.max - selectedTier.min) + selectedTier.min) / 100) * 100;
let itemName = selectedTier.items[Math.floor(Math.random() * selectedTier.items.length)];
itemPool.push({ name: itemName, price: price, class: selectedTier.class });
}
// 要素の取得
const shopArea = document.getElementById('shop-area');
const openArea = document.getElementById('open-area');
const resultArea = document.getElementById('result-area');
const buyBtn = document.getElementById('buy-btn');
const openBtn = document.getElementById('open-btn');
const retryBtn = document.getElementById('retry-btn');
const targetBag = document.getElementById('target-bag');
const itemList = document.getElementById('item-list');
const totalPriceEl = document.getElementById('total-price');
const resultMessage = document.getElementById('result-message');
const effectCanvas = document.getElementById('effect-canvas');
const effects = new EffectSystem(effectCanvas);
buyBtn.addEventListener('click', () => {
playBuySE();
startBGM(); // オーディオコンテキストの起動とBGM開始
shopArea.classList.add('hidden');
openArea.classList.remove('hidden');
});
openBtn.addEventListener('click', () => {
targetBag.classList.add('shake');
openBtn.disabled = true;
openBtn.textContent = "開封中...";
stopBGM(); // 開封中はBGMを止めてドラムロール
playDrumRollSE();
setTimeout(() => {
targetBag.classList.remove('shake');
openArea.classList.add('hidden');
showResults();
}, 1500);
});
function showResults() {
resultArea.style.display = 'block';
itemList.innerHTML = '';
let total = 0;
let hasDespair = false;
const shuffled = [...itemPool].sort(() => 0.5 - Math.random());
const selectedItems = shuffled.slice(0, 5);
selectedItems.forEach(item => {
if (item.price === 1) hasDespair = true;
const li = document.createElement('li');
li.className = 'item';
const nameSpan = document.createElement('span');
nameSpan.textContent = item.name;
if (item.class) nameSpan.classList.add(item.class);
const priceSpan = document.createElement('span');
priceSpan.textContent = `${item.price.toLocaleString()}円`;
if (item.class) priceSpan.classList.add(item.class);
li.appendChild(nameSpan);
li.appendChild(priceSpan);
itemList.appendChild(li);
total += item.price;
});
totalPriceEl.textContent = `総額: ${total.toLocaleString()}円`;
const cost = 50000;
if (hasDespair) {
document.body.classList.add('rock-bottom-mode');
totalPriceEl.className = 'total-price lose';
resultMessage.textContent = `💀 絶望の淵へようこそ… 全てを失った気分だね…`;
resultMessage.className = 'message lose';
effects.start('none');
playDespairSE();
}
else if (total >= 999999) {
totalPriceEl.className = 'total-price win';
resultMessage.textContent = `🌟 神引き!!! 伝説を目撃したね! 🌟`;
resultMessage.className = 'message win';
effects.start('gold');
playGodSE();
}
else if (total > cost) {
totalPriceEl.className = 'total-price win';
resultMessage.textContent = `🎉 大勝利! ${ (total - cost).toLocaleString() }円の得だね! 🎉`;
resultMessage.className = 'message win';
effects.start(total > 200000 ? 'gold' : 'colorful');
playWinSE();
}
else if (total === cost) {
totalPriceEl.className = 'total-price';
resultMessage.textContent = "奇跡のトントン! 損はしてないよ!";
resultMessage.className = 'message';
effects.start('none');
playBuySE();
}
else {
totalPriceEl.className = 'total-price lose';
resultMessage.textContent = `💸 痛恨! ${ (cost - total).toLocaleString() }円の損… 冷たい雨が心に染みるね。`;
resultMessage.className = 'message lose';
effects.start('rain');
playLoseSE();
}
}
retryBtn.addEventListener('click', () => {
playBuySE();
startBGM(); // 再度BGMをスタート
resultArea.style.display = 'none';
shopArea.classList.remove('hidden');
openBtn.disabled = false;
openBtn.textContent = "福袋を開ける!";
document.body.classList.remove('rock-bottom-mode');
effects.stop();
});
</script>
</body>
</html>


■ 今日の学び

今回は、このゲームを作る中で感じた、
私なりの「学び」についてお話ししたいと思います。d(^^o)

■ 福袋の本当の楽しさって何だろう?(=v=*)

福袋のあの「何が入っているか分からないワクワク感」が大好きなんです。

でも最近は、中身が最初から分かっていたり、
購入金額より高いものが確実に入っている
“お得な福袋”が増えましたよね。(^^;)

それはそれで嬉しいんですけど、
昔ながらの「運試し」の要素がちょっと薄れている気がして……。

そこで今回は、あえてその「お得」という前提を捨ててみました。

中身がプラスになるかマイナスになるか、完全にランダム!
「当たり」と「外れ」のバランスを自分で調整して、
ヒリヒリするような体験を目指しました。

■ 確率と金額の、絶妙なバランス設定(^艸^)

ゲームとしての公平性やリアリティを保つために、こんな工夫をしました。

  • 1000個のアイテムを用意
  • その総額を1000で割るとちょうど5万円
  • つまり1アイテム平均1万円
  • 5個引くと平均5万円(トントン)

これでしっかりしたベースができました。

でも、これだけだとちょっと平凡ですよね。(^^;)

そこでさらに── 極小確率で、とんでもないアイテムを追加!

  • 神引き(999,999円)✨
  • 絶望(1円)💀

この「夢」と「絶望」の両極端が加わったことで、
ただのシミュレーションではなく、
ドラマチックなゲームに進化しました。(^_^)

■ 当たるまでやってみたい!という「中毒性」(≧▽≦*)

実際にプレイしてみて感じたのは……

  • 「とんでもない当たりが出るまで、何度でもやりたい!」
  • 「絶望を引いたけど、次こそ勝つ!」

という、ちょっと中毒性のある面白さでした。(^^;)

「何が出るか分からない」という福袋のワクワク感は、
ゲームにするとこんなにも強い魅力になるんだな、と実感しました。

■ 現実の福袋の思い出(^_^)~

ところで、みなさんは現実の福袋の思い出、何かありますか?

私は雑貨屋さんの福袋が大好きで……
生活雑貨からガーデニンググッズまで、
本当にいろいろ入っていました。

でも、中には「あちゃ〜(^^;)」という強烈な外れもあって……

例えば──

  • 開けた瞬間に甘い匂いが広がる「チョコレートの香りの入浴剤」(@@;)
  • どこで履けばいいのか本気で悩んだ「金色のスリッパ」(=°Д°=)

今思えば、そんな“使いどころに困るもの”も含めて、
後で笑い話になるのが福袋の醍醐味なのかもしれません。(=v=*)

このシミュレーターでも、ぜひあなただけの 「笑えるハズレ」
「奇跡の大当たり」 を見つけて、 笑顔の思い出にしてくださいね!

■ ついに……伝説の景品が出ました!

何度も挑戦して、ドキドキしながら開封を繰り返していたのですが…… ついにその瞬間が訪れました。

・・・30分ほどゲームを続けて、ようやく伝説の景品の一つが当たりました。

(画像:伝説のあたりの画像)

思わず「やったー!」と声が出ちゃいました。(≧▽≦*)
この“いつ出るか分からないワクワク感”こそ、福袋の醍醐味ですよね。


■ 次回は、
地味な趣味と思われがちな、盆栽をゲームにしてみました。

時間をかけて、自分だけの盆栽を育てていくゲームです。

実際の成長スピードの 何百倍 もの速さで成長する松の木を、

  • 枝の形を整えたり
  • 余分な葉を取ったり
  • 枝ぶりを調整したり

そんな“手入れ”をしながら育てていきます。

次回もぜひ遊びに来てくださいね。(*^v^)ノシ

▶ 次の実験はこちら  
  人の手による自然の制御)「盆栽職人~松の造形~」



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

~このブログについて~

AIと一緒に遊び、
100の実験でゲームを育てるブログ

🌈初めての方へ
🌱このブログについて
🌳実験一覧
🍃プライバシーポリシー


AIと作る100のゲーム実験室(*^v^*)をもっと見る

今すぐ購読し、続きを読んで、すべてのアーカイブにアクセスしましょう。

続きを読む