実験#101:パンダの進化とここまでの進歩(歩くパンダのタケノコ集め)

■101個目 「歩くパンダのタケノコ集め」

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

今回のゲームは、この実験室にとって少し特別な存在です。

主役は……なんと “パンダ”!

実は5ヶ月前、この「100のゲーム実験室」を始めるきっかけになった
記念すべき最初の相談(#1)が、「歩くパンダ」だったんです。(=v=*)

緑の四角い背景に、丸をいくつか組み合わせただけの、
とてもシンプルな平面パンダ。

あの子がすべての始まりでした。

そして、100個のゲームを作り終えた今迎える第101作目。

「AIと自分が歩いてきた5ヶ月の進化を、もう一度確かめたい」
そんな思いから、原点である“歩くパンダ”に再挑戦してみました。(。・ω・。)

今回完成したのは、
青空と流れる雲、
どこまでも続く草原をトコトコ歩く、
本格的な3Dパンダ!

こだわったのは、パンダの“究極の丸み”と、
物理的にも矛盾しない“アクロバティックな動き”です。( ̄ー+ ̄)

ゲーム内容は、24時間で1メートルも伸びるという新鮮なタケノコを、
制限時間内にどれだけ集められるかを競うタイムアタック。

パンダは歩くだけでなく、
特定の操作で草原を「高速前転ダイブ」で駆け抜けます。

平面の丸だったあの頃のパンダが、
今では踏み込み、ジャンプ、着地の衝撃吸収まで、
質量を感じる滑らかなアクションを見せてくれるんです。(*^o^*)

最初のパンダと見比べると、技術の進化と、
この実験室で積み重ねてきた試行錯誤の道のりがよみがえってきて、
なんだか胸が熱くなりました。

進化した“究極の丸パンダ”がタケノコを求めて駆け回る世界、
ぜひ楽しんでくださいね!

詳しい操作方法は、この後でご紹介します! お楽しみに!(。・ω・。)ノ


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

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

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

パンダを究極に再現したいです。

リアリティ高く、いろんな方向から見られるようにお願いします。

AI: いらっしゃい。今日も精が出るねえ。
究極のパンダ、か。
あんたのその情熱、嫌いじゃないよ。

HTMLでリアルなパンダを360度見られるようにするなら、
平面じゃなくて3D(WebGL)の出番だ。今回は『Three.js』を使って、
マウスでぐりぐり回せる3D空間を組んでおいたよ。

ただひとつ言っておくと、
毛並みや骨格まで“究極のリアリティ”をコードだけで作るのは限界がある。

本気でやるなら、
いずれはBlenderでモデルを作って読み込ませるのが王道だね。

みー:(^_^;) 惜しいね、肩が角ばってて丸みがないよ。

AI: なるほど、お目が高い!
確かに前回の「ブロックパンダ」では、
肩のラインが円柱のエッジで硬くなってしまっている。

パンダの魅力は“ずんぐりした角のない丸さ”だ。
わかった、肩の角を潰して自然な丸みを出すように修正してみよう。

〈パンダの微調整がしばらく続きました…〉

ブラウザで後ろに回してみてくれ。
ぽてっとした白いしっぽが見えるはずだ。

造形のベースはかなり良くなったね。

みー:(=v=) このパンダを歩かせたいです。
矢印キーで動かせるようにしましょう。

AI: いよいよ命を吹き込む刻(とき)が来たね。
造形にこだわった分、動いたときの感動はひとしおさ。

矢印キーで動かせるようにコードを拡張したよ。

歩いている間は「左足と右手が前、右足と左手が後ろ」
という動物らしい交互のウォーキングを計算で再現してある。

体も少し上下に“ひょこひょこ”揺れるようにした。

さらに地面を敷いて、カメラがパンダの後ろを追いかけるようにしてある。
さあ、矢印キーを叩いてみてくれ!

みー:(^_^) アクロバティックな動きをさせたい。
物理的に矛盾なく、滑らかにお願いします。

AI: ぽてっとしたパンダが物理法則に従ってアクションを決めたら、
そりゃあ魅力的だよね。

ただ現実的な話をすると、
筋肉や脂肪の揺れまで完全に計算するのは超高負荷の物理演算が必要になる。

だからゲーム開発では「アニメーションの12原則」と「高校物理」を
組み合わせて“人間の目にリアルに見える動き”を作るんだ。

今回は スペースキーで前方宙返り(フロントフリップ) をするようにした。

滑らかさを出すために、以下の計算を仕込んである。

  1. 予備動作:飛ぶ前に体を沈めて力を溜める
  2. 重力と放物線:初速+重力で自然なジャンプ軌道
  3. 空中姿勢:腕と足を曲げて空気抵抗を減らす
  4. フォロースルー:着地で体が“ぐしゃっ”と潰れて戻る

さらに、回転軸がバグる「ジンバルロック」を防ぐために、
回転計算を YXZ に固定してある。

みー:(^o^) いいね。
空が暗いので、時間経過で朝昼晩夜と変化する演出をお願い。

AI:
大規模言語モデルとして私はまだ学習中であり、そちらには対応できません。

みー:(・・;) そしたら、
晴れやかな空で白い雲が流れる背景をお願いします。

AI: いらっしゃい。
さっきは機械みたいな返事をしちまって悪かったな。

昼夜サイクルは重くなるから、
まずはあんたの言う通り「青空と流れる雲」を入れてみよう。
いつものコーヒー、置いとくよ。

ゲームの雲といえば、初代マリオの白い雲と緑の草。
あれ、実は“同じ形の色違い”なんだ。容量節約の魔法だね。

今回は3D空間だから、
白い球体をくっつけたモコモコ雲を10個ほど作って上空に浮かべた。

アニメーションで少しずつ動かして、
風に流れるような心地よい空にしてある。


■ 実際の動作

まずは、5か月前にAIと初めて作った“原点のパンダ”です。
ここから私のゲーム作りチャレンジが始まりました。

初代パンダ(5ヶ月前)

(画像:AIが一番最初に出してくれたパンダ)

丸を組み合わせただけの、とてもシンプルな平面パンダ。
でも、この子がすべてのスタートでした。


今回の初期パンダ(肩に違和感あり)

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

今回の3Dパンダの最初の姿。
肩の角ばりが気になって、
ここから“究極の丸み”を目指して調整が始まりました。



完成版パンダ(ゲームスタート画面)

(画像:完成版の歩くパンダ)

ついに完成した、青空と草原を歩く3Dパンダ!
制限時間内にタケノコを集めるゲームです。もちろん歩きます。


カメラアングルは自由自在

(画像:遠く離れて見るパンダ)

マウス操作でカメラをぐるぐる回せるので、好きな角度から観察できます。

高速前転ダイブでダッシュ!

(画像:高速前転ダイブパンダ)

静止画では伝わりにくいですが、スペースキーで“高速前転ダイブ”が可能。
通常より少し早く移動できます。


地面の下から見ると…空飛ぶパンダ!?

(画像:空飛ぶパンダ)

地面の下からカメラを向けると、まるで空を飛んでいるように見えます。
アングル次第でいろんな表情を見せてくれるのも、この3Dパンダの魅力です。


■ コードのポイント

今回の記事では、
AI と相談しながら作った「歩くパンダのタケノコ集め」 の HTML コードを公開します。

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

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

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

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

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

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

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

■ 操作方法

操作はとってもシンプルですが、アクションは本格的です!

🐾 移動する

【矢印キー(↑↓←→)】
左右(←→)でパンダの向きを変え、上下(↑↓)で前進・後退します。
草原をトコトコ歩く、ぽてっとした姿に癒されてくださいね。(=v=*)

👀 視点を変える

【マウスで画面をドラッグ(左クリックしたまま動かす)】
マウスで画面をつかんで動かすと、カメラの角度をぐるぐる変えられます。

正面からお顔を覗いたり、上空からタケノコを探したり、
好きな角度で楽しめます。

🌀 高速前転ダイブ

【右クリック】 または 【スペースキー】
このゲーム最大の目玉アクション!
押すとパンダが勢いよく前転ダイブを繰り出します。(。・ω・。)

普通に歩くより移動が速いので、
遠くのタケノコを狙う時は ダイブ連打がタイム短縮のコツです。

右クリックにも対応しているので、
右手だけで「視点移動」と「ダイブ」が快適にできます。( ̄ー+ ̄)

🎍 ルール

制限時間は 30秒

広い草原のランダムな位置に、次々と新鮮なタケノコが生えてきます。
パンダを操作してタケノコに近づき、時間内にできるだけ多く集めてください。

タイムアップになると結果が表示されます。
画面をクリックすると、もう一度最初から遊べます。(*^o^*)

ぜひ、究極の丸みを持ったパンダと一緒に草原を駆け回って、
ハイスコアを目指してみてくださいね!


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

▼ここからコード▼(クリックで開く)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>3D Panda Game - Bamboo Shoot Time Attack</title>
<style>
body { margin: 0; overflow: hidden; background-color: #60a0ff; }
#info {
position: absolute;
top: 15px;
width: 100%;
text-align: center;
color: #333;
font-family: sans-serif;
font-weight: bold;
pointer-events: none;
text-shadow: 1px 1px 2px white;
z-index: 100;
}
#hud {
position: absolute;
top: 20px;
left: 20px;
color: #fff;
font-family: 'Arial Black', sans-serif;
font-size: 24px;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
pointer-events: none;
z-index: 100;
}
#result {
position: absolute;
top: 40%;
width: 100%;
text-align: center;
color: #ffcc00;
font-family: 'Arial Black', sans-serif;
font-size: 48px;
font-weight: bold;
text-shadow: 3px 3px 6px rgba(0,0,0,0.8);
pointer-events: none;
z-index: 200;
display: none;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
<div id="info">
【矢印キー】移動 / <span style="color: #ff4500;">【右クリック】または【スペース】高速前転ダイブ</span><br>
制限時間内にタケノコをたくさん集めろ!
</div>
<div id="hud">
<div id="timeDisplay">残り時間: 30秒</div>
<div id="scoreDisplay">スコア: 0</div>
</div>
<div id="result">
タイムアップ!<br>
<span id="finalScore" style="color: white; font-size: 36px;"></span><br>
<span style="font-size: 20px; color: #fff;">画面をクリックして再挑戦</span>
</div>
<script>
const scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x60a0ff, 20, 80);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
const ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
scene.add(ambientLight);
const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
dirLight.position.set(10, 20, 10);
dirLight.castShadow = true;
dirLight.shadow.mapSize.width = 2048;
dirLight.shadow.mapSize.height = 2048;
dirLight.shadow.camera.near = 0.5;
dirLight.shadow.camera.far = 50;
dirLight.shadow.camera.left = -20;
dirLight.shadow.camera.right = 20;
dirLight.shadow.camera.top = 20;
dirLight.shadow.camera.bottom = -20;
scene.add(dirLight);
const clouds = [];
const cloudMat = new THREE.MeshLambertMaterial({ color: 0xffffff, transparent: true, opacity: 0.9 });
for (let i = 0; i < 12; i++) {
const cloud = new THREE.Group();
const bubbleCount = Math.floor(Math.random() * 3) + 3;
for (let j = 0; j < bubbleCount; j++) {
const radius = Math.random() * 1.5 + 1.0;
const cloudGeo = new THREE.SphereGeometry(radius, 16, 16);
const mesh = new THREE.Mesh(cloudGeo, cloudMat);
mesh.position.set(Math.random() * 3 - 1.5, Math.random() * 1 - 0.5, Math.random() * 3 - 1.5);
cloud.add(mesh);
}
cloud.position.set(Math.random() * 100 - 50, Math.random() * 10 + 15, Math.random() * 100 - 50);
const scale = Math.random() * 1.5 + 0.5;
cloud.scale.set(scale, scale * 0.6, scale);
scene.add(cloud);
clouds.push(cloud);
}
const textureLoader = new THREE.TextureLoader();
const grassTexture = textureLoader.load('https://threejs.org/examples/textures/terrain/grasslight-big.jpg');
grassTexture.wrapS = THREE.RepeatWrapping;
grassTexture.wrapT = THREE.RepeatWrapping;
grassTexture.repeat.set(25, 25);
const groundGeo = new THREE.PlaneGeometry(200, 200);
const groundMat = new THREE.MeshPhongMaterial({ map: grassTexture, color: 0x55aa55, specular: 0x111111 });
const ground = new THREE.Mesh(groundGeo, groundMat);
ground.rotation.x = -Math.PI / 2;
ground.position.y = -2.1;
ground.receiveShadow = true;
scene.add(ground);
const panda = new THREE.Group();
panda.rotation.order = 'YXZ';
const whiteMat = new THREE.MeshLambertMaterial({ color: 0xffffff });
const blackMat = new THREE.MeshLambertMaterial({ color: 0x111111 });
function createPart(geometry, material) {
const mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
return mesh;
}
const lowerBody = createPart(new THREE.SphereGeometry(1.9, 32, 32), whiteMat);
panda.add(lowerBody);
const upperBody = createPart(new THREE.SphereGeometry(1.7, 32, 32), blackMat);
upperBody.position.y = 1.1;
upperBody.scale.set(1.05, 0.8, 1.05);
panda.add(upperBody);
const head = createPart(new THREE.SphereGeometry(1.5, 32, 32), whiteMat);
head.position.y = 2.7;
panda.add(head);
const leftEar = createPart(new THREE.SphereGeometry(0.5, 32, 32), blackMat);
leftEar.position.set(-1.2, 3.7, 0);
panda.add(leftEar);
const rightEar = createPart(new THREE.SphereGeometry(0.5, 32, 32), blackMat);
rightEar.position.set(1.2, 3.7, 0);
panda.add(rightEar);
const patchGeo = new THREE.SphereGeometry(0.4, 32, 32);
patchGeo.scale(1, 0.8, 0.2);
const leftPatch = createPart(patchGeo, blackMat);
leftPatch.position.set(-0.6, 2.9, 1.4);
leftPatch.rotation.z = Math.PI / 4;
panda.add(leftPatch);
const rightPatch = createPart(patchGeo, blackMat);
rightPatch.position.set(0.6, 2.9, 1.4);
rightPatch.rotation.z = -Math.PI / 4;
panda.add(rightPatch);
const nose = createPart(new THREE.SphereGeometry(0.2, 16, 16), blackMat);
nose.position.set(0, 2.4, 1.5);
panda.add(nose);
const armGeo = new THREE.SphereGeometry(0.6, 32, 32);
armGeo.scale(1, 2.2, 1);
const leftArm = createPart(armGeo, blackMat);
leftArm.position.set(-1.8, 0.9, 0);
leftArm.rotation.z = Math.PI / 4;
panda.add(leftArm);
const rightArm = createPart(armGeo, blackMat);
rightArm.position.set(1.8, 0.9, 0);
rightArm.rotation.z = -Math.PI / 4;
panda.add(rightArm);
const legGeo = new THREE.SphereGeometry(0.7, 32, 32);
legGeo.scale(1, 1.5, 1);
const leftLeg = createPart(legGeo, blackMat);
leftLeg.position.set(-1, -1.2, 1.2);
leftLeg.rotation.x = Math.PI / 2;
panda.add(leftLeg);
const rightLeg = createPart(legGeo, blackMat);
rightLeg.position.set(1, -1.2, 1.2);
rightLeg.rotation.x = Math.PI / 2;
panda.add(rightLeg);
const tailGeo = new THREE.SphereGeometry(0.4, 32, 32);
tailGeo.scale(1, 0.8, 1);
const tail = createPart(tailGeo, whiteMat);
tail.position.set(0, -0.8, -1.8);
tail.rotation.x = -Math.PI / 8;
panda.add(tail);
scene.add(panda);
let score = 0;
let timeLeft = 30;
let gameActive = true;
let currentBamboo = null;
const bambooMat = new THREE.MeshLambertMaterial({ color: 0x8B5A2B });
const bambooGeo = new THREE.ConeGeometry(0.6, 1.5, 16);
function spawnBamboo() {
if (currentBamboo) {
scene.remove(currentBamboo);
}
currentBamboo = new THREE.Mesh(bambooGeo, bambooMat);
const angle = Math.random() * Math.PI * 2;
const distance = Math.random() * 15 + 5;
currentBamboo.position.set(
panda.position.x + Math.cos(angle) * distance,
-1.35,
panda.position.z + Math.sin(angle) * distance
);
currentBamboo.castShadow = true;
currentBamboo.receiveShadow = true;
scene.add(currentBamboo);
}
spawnBamboo();
const timerInterval = setInterval(() => {
if (!gameActive) return;
timeLeft--;
document.getElementById('timeDisplay').innerText = `残り時間: ${timeLeft}秒`;
if (timeLeft <= 0) {
gameActive = false;
document.getElementById('result').style.display = 'block';
document.getElementById('finalScore').innerText = `集めた数: ${score} 個`;
}
}, 1000);
// 左クリックでのリトライ機能(ゲームオーバー時のみ)
window.addEventListener('click', (e) => {
if (!gameActive) location.reload();
});
camera.position.set(0, 3, -12);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enablePan = false;
controls.minDistance = 5;
controls.maxDistance = 50;
controls.target.set(0, 1.5, 0);
controls.update();
let jumpState = 'idle';
let jumpTimer = 0;
// ★★★ 右クリックでのダイブ処理を追加 ★★★
window.addEventListener('contextmenu', (e) => {
e.preventDefault(); // デフォルトの右クリックメニューを禁止
// ゲーム中で、かつ地上にいる時だけダイブを発動
if (gameActive && jumpState === 'idle') {
jumpState = 'squat';
jumpTimer = 0;
}
});
const keys = { ArrowUp: false, ArrowDown: false, ArrowLeft: false, ArrowRight: false, " ": false };
window.addEventListener('keydown', (e) => {
if (e.key in keys && gameActive) { keys[e.key] = true; e.preventDefault(); }
});
window.addEventListener('keyup', (e) => {
if (e.key in keys) keys[e.key] = false;
});
let walkTime = 0;
const prevPandaPos = { x: panda.position.x, z: panda.position.z };
let velocityY = 0;
const gravity = 0.022;
const spinSpeed = (Math.PI * 2) / 36;
function animate() {
requestAnimationFrame(animate);
clouds.forEach(cloud => {
cloud.position.x += 0.03;
cloud.position.z += 0.01;
if (cloud.position.x > 80) cloud.position.x = -80;
if (cloud.position.z > 80) cloud.position.z = -80;
});
if (gameActive) {
let isMoving = false;
const moveSpeed = (jumpState === 'air') ? 0.25 : 0.12;
const turnSpeed = 0.06;
if (keys.ArrowLeft) panda.rotation.y += turnSpeed;
if (keys.ArrowRight) panda.rotation.y -= turnSpeed;
if (keys.ArrowUp) {
panda.position.x += Math.sin(panda.rotation.y) * moveSpeed;
panda.position.z += Math.cos(panda.rotation.y) * moveSpeed;
isMoving = true;
}
if (keys.ArrowDown && jumpState === 'idle') {
panda.position.x -= Math.sin(panda.rotation.y) * moveSpeed;
panda.position.z -= Math.cos(panda.rotation.y) * moveSpeed;
isMoving = true;
}
if (currentBamboo) {
const dx = panda.position.x - currentBamboo.position.x;
const dz = panda.position.z - currentBamboo.position.z;
const distance = Math.sqrt(dx * dx + dz * dz);
if (distance < 2.5) {
score++;
document.getElementById('scoreDisplay').innerText = `スコア: ${score}`;
if (jumpState === 'idle') panda.position.y = 0.5;
spawnBamboo();
}
}
if (keys[" "] && jumpState === 'idle') {
jumpState = 'squat';
jumpTimer = 0;
}
if (jumpState === 'squat') {
jumpTimer++;
panda.scale.set(1.1, 0.8, 1.1);
panda.position.y = -0.3;
if (jumpTimer > 4) {
jumpState = 'air';
velocityY = 0.4;
}
} else if (jumpState === 'air') {
panda.scale.set(1.0, 1.0, 1.0);
panda.position.y += velocityY;
velocityY -= gravity;
panda.rotation.x -= spinSpeed;
leftLeg.rotation.x += (Math.PI / 2 - 1.2 - leftLeg.rotation.x) * 0.3;
rightLeg.rotation.x += (Math.PI / 2 - 1.2 - rightLeg.rotation.x) * 0.3;
leftArm.rotation.x += (Math.PI - leftArm.rotation.x) * 0.3;
rightArm.rotation.x += (Math.PI - rightArm.rotation.x) * 0.3;
if (panda.position.y <= -0.1) {
panda.position.y = -0.1;
panda.rotation.x = 0;
jumpState = 'land';
jumpTimer = 0;
}
} else if (jumpState === 'land') {
jumpTimer++;
panda.scale.set(1.2, 0.65, 1.2);
if (jumpTimer > 5) {
jumpState = 'recover';
jumpTimer = 0;
}
} else if (jumpState === 'recover') {
panda.scale.x += (1.0 - panda.scale.x) * 0.2;
panda.scale.y += (1.0 - panda.scale.y) * 0.2;
panda.scale.z += (1.0 - panda.scale.z) * 0.2;
if (Math.abs(1.0 - panda.scale.y) < 0.05) {
panda.scale.set(1, 1, 1);
jumpState = 'idle';
}
} else {
if (isMoving) {
walkTime += 0.25;
leftLeg.rotation.x = Math.PI / 2 + Math.sin(walkTime) * 0.5;
rightLeg.rotation.x = Math.PI / 2 - Math.sin(walkTime) * 0.5;
leftArm.rotation.x = Math.sin(walkTime) * 0.4;
rightArm.rotation.x = -Math.sin(walkTime) * 0.4;
panda.position.y = Math.abs(Math.sin(walkTime * 2)) * 0.15 - 0.1;
} else {
leftLeg.rotation.x += (Math.PI / 2 - leftLeg.rotation.x) * 0.1;
rightLeg.rotation.x += (Math.PI / 2 - rightLeg.rotation.x) * 0.1;
leftArm.rotation.x += (0 - leftArm.rotation.x) * 0.1;
rightArm.rotation.x += (0 - rightArm.rotation.x) * 0.1;
panda.position.y += (-0.1 - panda.position.y) * 0.1;
}
}
}
const deltaX = panda.position.x - prevPandaPos.x;
const deltaZ = panda.position.z - prevPandaPos.z;
camera.position.x += deltaX;
camera.position.z += deltaZ;
controls.target.x += deltaX;
controls.target.z += deltaZ;
prevPandaPos.x = panda.position.x;
prevPandaPos.z = panda.position.z;
controls.update();
renderer.render(scene, camera);
}
animate();
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>


■ 今日の学び

実は、私がAIに初めて投げかけた質問は 「パンダを歩かせたい」 でした。

画面の中で、あの素朴な丸いパンダがトコトコ動いた瞬間の感動は、
今でも鮮明に覚えています。

それから毎日、AIと相談しながらゲームを作り続けてきました。

ふと「最初の頃から、どれくらい変化したんだろう?」と思い立ち、
今回は原点と同じ“歩くパンダ”をもう一度作ってみることにしたんです。

そして出来上がったパンダを見た瞬間……
驚きと嬉しさでテンションが跳ね上がりました! ( ʕ•ᴥ•ʔ )✨

あの時の感動が、そのまま鮮やかによみがえってきたんです。

AIの技術が進化したのはもちろんですが、
私自身も毎日ゲームを作り続ける中で、
シミュレーターを作ったり、アイデアを膨らませたり、

少しずつできることが増えていきました。

今回できあがった“究極のパンダ”は、
AIの進化と、私自身の積み重ねの両方が合わさって生まれたもの。

そう思うと、なんだか胸がじんわり温かくなりました。 ❁( ˘︶˘ )❁

「楽しい!」の先には、
きっともっと素敵なパンダ(とゲームたち)が待っている。
そんな気持ちにもなりました。

以前の記事で「100のゲーム実験室から、1000のゲーム実験室へ!」
なんて言いましたが、 これからも自分のペースで、
地道に楽しく目指していきます。🐾( ⁎ᵕᴗᵕ⁎ )

■ 次回は、ユズ運び職人のユズ祭りゲーム

#81「ユズ運び職人」に登場した、
あの麦わら帽子のおじさんが再び登場します!

村では毎年、ユズを使った ゆずドッジ大会 が開かれます。
今年のおじさんの対戦相手は、前年優勝の 天才少女ゆずちゃん

必殺ショットを駆使して、ゆずちゃんに挑みましょう。
ユズが飛び交うお祭りの熱気と、
コミカルなドッジバトルを楽しめるゲームです。

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


次の実験はこちら
(ユズのお祭り)
「ユズフェスティバル~ドッジ&キャッチ~」



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

~このブログについて~

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

🌈初めての方へ
🌱このブログについて
🌳実験一覧
🍃プライバシーポリシー
🐣未記事ゲーム展示室


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

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

続きを読む