経緯
とくにアイデアがあったわけではなかったのですが、Babylon.jsのアドベントカレンダーでしたので、何か書かねば…という使命感から登録はしたものの、何を書こうか悩んだあげく、全部ChatGPTにコードを作ってもらって手抜きしよう!と至ったわけです(笑
何を作ってもらおうか
もう、構想から全部ChatGPTに任せたのですが、そっちはうまく行かず…でも、その失敗作からヒントを得て、ブロック遊びの環境を作ってもらいました。
と思ったのですが、操作してみると、なんかデキの悪いマイクラのような感じですね、これ。
遊び方
矢印キー:カレントブロックの前後左右移動
PageUp/PageDown:カレントブロックの上下移動
Space:ブロックを設置
C:ブロックの色を変える
D:設置したブロックを削除
苦労した点
もう、コードのココをこう直せば解決するのにー!!!とウズウズしながら、それをGPTに修正させるため、懇切丁寧に教えてあげるのに、疲れました(笑
でも、教えてあげれば、ちゃんとコードを吐きだしてくれるのは便利ですね(早いし)
あ、でも、最後にコードはちょっとだけ削りました。
触らなくても動くは動くのですが、実行すると最初にエラーメッセージが出てたのですが、Playground上不要なコードがあったので、そこを削除して完成版としてあります。
※削除したことで、エラーメッセージも出なくなりました。
前職時代、社内アプリの開発を中国/ベトナムでやらせるオフショア開発をしてましたが、それと比べたら断然こっちの方が「楽」&「イライラしない」ので、ベトナムやインドに多そうなオフショア業者( ;∀;)なのでは…?と心配してしまった。
コード全文
const createScene = () => {
const scene = new BABYLON.Scene(engine);
// Camera and light
const camera = new BABYLON.ArcRotateCamera("camera", Math.PI / 2, Math.PI / 3, 20, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
// Disable cursor keys for camera control
camera.inputs.removeByType("ArcRotateCameraKeyboardMoveInput");
// Ground
const ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 20, height: 20 }, scene);
ground.material = new BABYLON.StandardMaterial("groundMat", scene);
ground.material.diffuseColor = BABYLON.Color3.Gray();
// LEGO-like block template
const createBlock = (x, y, z, color) => {
const block = BABYLON.MeshBuilder.CreateBox("block", { width: 2, height: 1, depth: 2 }, scene);
block.position = new BABYLON.Vector3(x, y, z);
block.material = new BABYLON.StandardMaterial("blockMat", scene);
block.material.diffuseColor = color || BABYLON.Color3.Yellow();
return block;
};
// Interactive placement
let currentBlock = createBlock(0, 0.5, 0, BABYLON.Color3.Yellow());
let currentColor = BABYLON.Color3.Yellow(); // Current color for blocks
const step = 2;
const verticalStep = 1;
const blocks = [];
// Highlight frame for current block
const createFrame = () => {
const frame = BABYLON.MeshBuilder.CreateBox("frame", { width: 2.1, height: 1.1, depth: 2.1 }, scene);
const frameMaterial = new BABYLON.StandardMaterial("frameMat", scene);
frameMaterial.diffuseColor = BABYLON.Color3.Black();
frameMaterial.wireframe = true;
frame.material = frameMaterial;
frame.isPickable = false; // Prevent interaction
return frame;
};
const frame = createFrame();
frame.parent = currentBlock; // Attach the frame to currentBlock
// Place a new block at the current position
const placeBlock = () => {
const newBlock = createBlock(
currentBlock.position.x,
currentBlock.position.y,
currentBlock.position.z,
currentColor // Use the current color
);
blocks.push(newBlock);
};
// Function to find and remove block at position (excluding `currentBlock`)
const removeBlockAtPosition = (position) => {
const blockToRemove = blocks.find(
(block) => block.position.equalsWithEpsilon(position, 0.01)
);
if (blockToRemove) {
blockToRemove.dispose(); // Dispose the block
blocks.splice(blocks.indexOf(blockToRemove), 1); // Remove from the blocks array
}
};
// Move block up or down
const moveBlockVertically = (direction) => {
const yOffset = direction === "up" ? verticalStep : -verticalStep;
currentBlock.position.y += yOffset;
};
window.addEventListener("keydown", (event) => {
switch (event.key) {
case "ArrowUp":
currentBlock.position.z -= step;
break;
case "ArrowDown":
currentBlock.position.z += step;
break;
case "ArrowLeft":
currentBlock.position.x -= step;
break;
case "ArrowRight":
currentBlock.position.x += step;
break;
case " ":
placeBlock(); // Place a block at the current position
break;
case "c":
currentColor = new BABYLON.Color3(Math.random(), Math.random(), Math.random());
currentBlock.material.diffuseColor = currentColor; // Change current block color
break;
case "Delete":
case "d":
removeBlockAtPosition(currentBlock.position); // Remove block at current position
break;
case "PageUp":
case "RollUp":
moveBlockVertically("up"); // Move block up
break;
case "PageDown":
case "RollDown":
moveBlockVertically("down"); // Move block down
break;
}
});
return scene;
};