人工智能实战:ClaudeAI辅助程序开发测试

以倒水小游戏为例

参考游戏

开发过程

小明:

(备注:一般从创建游戏原型开始,最好能给出游戏类型、参考游戏和目标引擎,比如问题里的color sort game、water sort puzzle和babylon。如果目标引擎如果支持多种语言,应指定想要使用的语言,比如问题里的Javascript。而且开发者应具备目标引擎的基础知识,知道如何将AI给出的代码应用到引擎的工程中)

Claude:

Here's a basic prototype for a color sort game in Babylon.js:

js

// Create scene

var scene = new BABYLON.Scene(engine);

// Create camera

var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, BABYLON.Vector3.Zero(), scene);

// Create light

var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);

// Create boxes

var boxes = [];

var boxSize = 1;

var boxGap = 0.5;

for (var i = 0; i < 10; i++) {

for (var j = 0; j < 10; j++) {

var box = BABYLON.MeshBuilder.CreateBox("box", {size: boxSize}, scene);

box.position.x = i * (boxSize + boxGap);

box.position.z = j * (boxSize + boxGap);

box.material = new BABYLON.StandardMaterial("boxMaterial", scene);

box.material.diffuseColor = new BABYLON.Color3(Math.random(), Math.random(), Math.random());

boxes.push(box);

}

}

// On pointer down

scene.onPointerDown = function(evt) {

var pickResult = scene.pick(evt.position.x, evt.position.y);

if (pickResult.hit && pickResult.pickedMesh.name === "box") {

var selectedBox = pickResult.pickedMesh;

// Find closest matching color

var closestBox;

var minDistance = Number.MAX_VALUE;

for (var i = 0; i < boxes.length; i++) {

if (boxes[i] != selectedBox) {

var distance = BABYLON.Vector3.Distance(selectedBox.material.diffuseColor, boxes[i].material.diffuseColor);

if (distance < minDistance) {

closestBox = boxes[i];

minDistance = distance;

}

}

}

// Swap positions

var pos1 = selectedBox.position.clone();

var pos2 = closestBox.position.clone();

selectedBox.position = pos2;

closestBox.position = pos1;

}

};

// Game loop

scene.registerBeforeRender(function() {

// Check if all boxes are sorted

var sorted = true;

for (var i = 0; i < boxes.length - 1; i++) {

if (BABYLON.Vector3.Distance(boxes[i].position, boxes[i+1].position) != boxSize + boxGap) {

sorted = false;

break;

}

}

if (sorted) {

console.log("Sorted! Game over.");

scene.onPointerDown = null; // Disable interaction

}

});

This creates a grid of colored boxes, and on pointer down, it finds the closest matching color and swaps the two boxes. It checks in the game loop if all boxes are sorted, and if so, ends the game.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

小明:

good, i want a orthographic camera, how can i do?

(备注:我们是想做一个2D游戏,所以需要的是正交相机,正交相机是一个开发者需要知道的基础知识)

Claude:

To use an orthographic camera instead of a perspective camera, you can do:

js

// Create orthographic camera

var camera = new BABYLON.FreeCamera("Camera", new BABYLON.Vector3(0, 10, 0), scene);

camera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;

camera.orthoLeft = -10;

camera.orthoRight = 10;

camera.orthoBottom = -10;

camera.orthoTop = 10;

This will create an orthographic camera with viewport bounds from -10 to 10 on the x and z axes.You'll also want to remove the ArcRotateCamera controls, since those are for perspective cameras. So your full camera setup would be:

js

// Create orthographic camera

var camera = new BABYLON.FreeCamera("Camera", new BABYLON.Vector3(0, 10, 0), scene);

camera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;

camera.orthoLeft = -10;

camera.orthoRight = 10;

camera.orthoBottom = -10;

camera.orthoTop = 10;

// Disable default controls

scene.detachControl();

// Attach custom controls

scene.onPointerDown = function(evt) {

// ...

}

This will give you an orthographic view and use your custom pointer down controls instead of the default ArcRotateCamera controls.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

按照AI给出的正交相机代码渲染了一个立方体,发现立方体被“压扁了”

小明:

the ratio of the object rendered by orthographic camera is wrong, how do i get the right ratio?

(备注:按照AI给出的代码渲染出来的物体变形,需要给相机设置正确的纵横比,纵横比是开发者需要知道的基础知识。但AI给出的解决变形的方案依然是错的,正确的解决方案请参考下面的对话代码)

Claude:

Good catch! Orthographic cameras render objects uniformly scaled, so without adjusting the scale, objects will appear distorted.

To fix this, you need to:

1. Set the camera's aspect ratio to match your canvas

2. Scale the objects by 1/aspect ratioSo your full camera setup would be:

js

// Get canvas size

var canvas = scene.getEngine().getRenderingCanvas();

var width = canvas.width;

var height = canvas.height;

// Create orthographic camera

var camera = new BABYLON.FreeCamera("Camera", new BABYLON.Vector3(0, 10, 0), scene);

camera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;

camera.orthoLeft = -10;

camera.orthoRight = 10;

camera.orthoBottom = -10;

camera.orthoTop = 10;

camera.aspectRatio = width / height;

// Scale objects

for (var i = 0; i < boxes.length; i++) {

boxes[i].scaling.x = 1 / camera.aspectRatio;

}

// Disable default controls

scene.detachControl();

// Attach custom controls

scene.onPointerDown = function(evt) {

// ...

}

Setting the camera's aspectRatio will ensure it has a proper field of view.

Scaling the objects by 1/aspectRatio will counteract the uniform scaling and make the objects appear normal.With these two changes, your orthographic view should render objects with the proper aspect ratio.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

小明:

i can't fix with your solution, this is my solution:

var ratio = window.innerHeight/window.innerWidth;

camera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;

camera.orthoLeft = -10;

camera.orthoRight = 10;

camera.orthoTop = 10 * ratio;

camera.orthoBottom = -10 * ratio;

(备注:如果AI给出的代码错误,给它正确的方法能提高AI准确度)

Claude:

You're absolutely right, setting the orthographic viewport based on the window aspect ratio is a better solution!

Your code:

js

var ratio = window.innerHeight/window.innerWidth;

camera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;

camera.orthoLeft = -10;

camera.orthoRight = 10;

camera.orthoTop = 10 * ratio;

camera.orthoBottom = -10 * ratio;

Is a perfect way to get the right aspect ratio with an orthographic camera. My previous solution with setting the camera aspect ratio and scaling objects would not actually fix the aspect ratio distortion.Your method is the correct way to setup an orthographic camera with the proper viewport. Nicely done!

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

小明:

the ratio is wrong again when i resize the browser window, how can i fix this?

Claude:

Good catch, you'll need to handle window resizes to update the orthographic camera viewport. You can do so with:

js

// On window resize

window.addEventListener("resize", function() {

// Get new ratio and update camera

var ratio = window.innerHeight / window.innerWidth;

camera.orthoTop = 10 * ratio;

camera.orthoBottom = -10 * ratio;

});

So your full code would be:

js

// Create orthographic camera

var camera = new BABYLON.FreeCamera("Camera", new BABYLON.Vector3(0, 10, 0), scene);

camera.mode = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;

camera.orthoLeft = -10;

camera.orthoRight = 10;

// Get initial ratio and set viewport

var ratio = window.innerHeight / window.innerWidth;

camera.orthoTop = 10 * ratio;

camera.orthoBottom = -10 * ratio;

// On window resize update viewport

window.addEventListener("resize", function() {

var ratio = window.innerHeight / window.innerWidth;

camera.orthoTop = 10 * ratio;

camera.orthoBottom = -10 * ratio;

});

// Disable default controls

scene.detachControl();

// Attach custom controls

scene.onPointerDown = function(evt) {

// ...

}

This will ensure your orthographic viewport is updated on resize to always match the window aspect ratio.

小明:

good job!

(备注:AI上一个问题给出的解决方案非常好,给它一个正向反馈,也许对它提高准确度有帮助)

Claude:

Thank you, I'm glad I could help explain orthographic cameras in Babylon.js!

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

小明:

i want to use cylinders to represent bottles and water rather than boxes, how do i implement?

(备注:AI能知道我用cylinder是为了更像瓶子,这一点儿还是体现了它的智能性)

Claude:

Great idea! Using cylinders instead of boxes will look much more realistic for bottles.

To implement this, you can:

1.Create cylinder meshes instead of box meshes

2.Set the cylinder height based on the amount of "water" it will hold

3.Raise and lower the water level (cylinder height) when bottles are filled/emptied

For example:

js

// Bottle height

var bottleHeight = 5;

// Create bottles

var bottles = [];

for (var i = 0; i < 10; i++) {

// Create cylinder mesh

var bottle = BABYLON.MeshBuilder.CreateCylinder("bottle", {

height: bottleHeight,

diameterTop: 1,

diameterBottom: 1

}, scene);

// Position bottle

bottle.position.x = i * 2;

// Create cylinder to hold water

var water = BABYLON.MeshBuilder.CreateCylinder("water", {

height: 3, // Start at 60% full

diameterTop: 1,

diameterBottom: 1

}, scene);

// Position water cylinder inside bottle cylinder

water.position.y = 2;

// Set materials

bottle.material = new BABYLON.StandardMaterial("bottleMaterial", scene);

water.material = new BABYLON.StandardMaterial("waterMaterial", scene);

// Add to bottles array

bottles.push({

bottle: bottle,

water: water

});

}

// On pointer down

scene.onPointerDown = function(evt) {

// Get bottle

var pickResult = scene.pick(evt.position.x, evt.position.y);

if (pickResult.hit && pickResult.pickedMesh.name === "water") {

var selectedBottle = pickResult.pickedMesh.parent;

// Get bottle info from bottles array

var bottleInfo = bottles.find(b => b.water == selectedBottle);

// Raise or lower the water level

if (bottleInfo.water.position.y > 1.5) { // If over half full

bottleInfo.water.position.y -= 0.5;

} else {

bottleInfo.water.position.y += 0.5;

}

}

}

This will create bottles full of "water", and on click will either raise or lower the water level in the selected bottle. Let me know if you have any other questions!

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

小明:

I want 2 to 4 different colors of water in each bottle

(备注:上一个问题给出的答案每个瓶子里只有一种颜色的水,明显是把要做颜色排序这个上下文给忘了,所以需要再明确问一下)

Claude:

To have multiple colors of water in each bottle, you can:

1.Create multiple cylinder meshes for the water, one for each color

2.Position the water cylinders at the same y position inside the bottle

3.Set a different material color for each water cylinderFor example:

js

// Bottle height

var bottleHeight = 5;

// Create bottles

var bottles = [];

for (var i = 0; i < 10; i++) {

// Create bottle cylinder

var bottle = BABYLON.MeshBuilder.CreateCylinder("bottle", { /* ... */ }, scene);

// Position bottle

bottle.position.x = i * 2;

// Create 2-4 water cylinders of different colors

var numColors = 2 + Math.floor(Math.random() * 3);

for (var j = 0; j < numColors; j++) {

// Create water cylinder

var water = BABYLON.MeshBuilder.CreateCylinder("water", { /* ... */ }, scene);

// Position at same y in bottle

water.position.y = 2;

// Set material color

water.material = new BABYLON.StandardMaterial("waterMaterial", scene);

water.material.diffuseColor = new BABYLON.Color3(Math.random(),

Math.random(),

Math.random());

// Add to bottle

bottle.addChild(water);

}

// Add bottle to bottles array

bottles.push(bottle);

}

// On pointer down

scene.onPointerDown = function(evt) {

// Get bottle

var pickResult = scene.pick(evt.position.x, evt.position.y);

if (pickResult.hit && pickResult.pickedMesh.name.startsWith("water")) {

var selectedWater = pickResult.pickedMesh;

var selectedBottle = selectedWater.parent;

// Get bottle info

var bottleInfo = bottles.find(b => b == selectedBottle);

// Raise or lower just the selected water cylinder

selectedWater.position.y += 0.5; // Raise

// Or

selectedWater.position.y -= 0.5; // Lower

}

}

This will create bottles with 2 to 4 cylinders of different colored "water" at the same level. On click, it will raise or lower just the selected water cylinder.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

对AI代码稍作修改之后的渲染结果

小明:

I want the water to be layered like a cocktail, so i think water should be at the same x position

(备注:上一个问题给出的代码没有做水平分层,再详细问一下,到这一步基本能把想要的瓶子给渲染出来了,但还是对代码做一些小的修改,比如要创建空瓶子、要在固定的4个颜色之间随机而不是完全随机、每个瓶子里所有的水不能是一种颜色)

Claude:

You're right, to have the water appear layered like a cocktail, the water cylinders should be at the same x position inside the bottle.

To implement this, you can:

1.Create the water cylinders at the same x position

2.Increment the y position for each new water cylinderFor example:

js

// Bottle height

var bottleHeight = 5;

// Create bottles

var bottles = [];

for (var i = 0; i < 10; i++) {

// Create bottle cylinder

var bottle = BABYLON.MeshBuilder.CreateCylinder("bottle", { /* ... */ }, scene);

// Position bottle

bottle.position.x = i * 2;

// Create 2-4 water cylinders of different colors

var numColors = 2 + Math.floor(Math.random() * 3);

var yPosition = 2; // Start at y=2

for (var j = 0; j < numColors; j++) {

// Create water cylinder at same x position

var water = BABYLON.MeshBuilder.CreateCylinder("water", {

height: 1,

diameterTop: 1,

diameterBottom: 1

}, scene);

water.position = bottle.position.clone(); // Same x as bottle

water.position.y = yPosition; // Increment y

// Set material color

water.material = new BABYLON.StandardMaterial("waterMaterial", scene);

water.material.diffuseColor = new BABYLON.Color3(Math.random(),

Math.random(),

Math.random());

// Add to bottle

bottle.addChild(water);

// Increment yPosition for next cylinder

yPosition += 1;

}

// Add bottle to bottles array

bottles.push(bottle);

}

// ...

// On pointer down

scene.onPointerDown = function(evt) {

// ...

// Raise or lower just the selected water cylinder

selectedWater.position.y += 0.5; // Raise

// Or

selectedWater.position.y -= 0.5; // Lower

}

This will create the water cylinders at the same x position inside the bottle, incrementing the y position, to appear layered.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

小明:

how can i get the children of bottle?

(备注:在如何获得瓶子里所有水的问题上,AI回答的有点儿傻,直接getChildren()就可以了,非要给我用遍历的方法。一开始以为是没告诉它是要获取拾取的瓶子的所有水,结果告诉它了也不行)

Claude:

You can get the children of a mesh (the bottle) using:

js

var bottleChildren = bottle.getChildren();

This will return an array of all the direct children of the bottle mesh.

So in your code, you could do:

js

// Create bottles

var bottles = [];

for (var i = 0; i < 10; i++) {

// Create bottle cylinder

var bottle = BABYLON.MeshBuilder.CreateCylinder("bottle", { /* ... */ }, scene);

// Position bottle

bottle.position.x = i * 2;

// Create water cylinders

// ...

// Add bottle to bottles array

bottles.push({

bottle: bottle,

waterCylinders: bottle.getChildren() // Store water cylinders

});

}

// On pointer down

scene.onPointerDown = function(evt) {

// Get selected bottle

var pickResult = scene.pick(evt.position.x, evt.position.y);

var selectedBottle = pickResult.pickedMesh;

// Get bottle info

var bottleInfo = bottles.find(b => b.bottle == selectedBottle);

// Get the water cylinders for this bottle

var waterCylinders = bottleInfo.waterCylinders;

// Raise or lower selected water cylinder

// ...

}

Now in your pointer down logic, you have access to waterCylinders which contains all the water cylinders for the selected bottle.

So you can raise/lower the selected water cylinder, remove cylinders, add new ones, etc.

小明:

how can i get the children of picked bottle?

Claude:

When a bottle is picked (selected), you can get its children (water cylinders) by:

  1. Storing the bottle mesh and its children in the bottles array
  2. When the bottle is picked, finding it in the bottles array to get the childrenFor example:

js

// Create bottles

var bottles = [];

for (var i = 0; i < 10; i++) {

// Create bottle

var bottle = BABYLON.MeshBuilder.CreateCylinder("bottle", { /* ... */ }, scene);

// Create water cylinders

var waterCylinders = [];

for (var j = 0; j < 3; j++) {

var water = BABYLON.MeshBuilder.CreateCylinder("water", { /* ... */ }, scene);

bottle.addChild(water);

waterCylinders.push(water);

}

// Store bottle and children in array

bottles.push({

bottle: bottle,

waterCylinders: waterCylinders

});

}

// On pointer down

scene.onPointerDown = function(evt) {

// Get picked bottle

var pickResult = scene.pick(evt.position.x, evt.position.y);

var selectedBottle = pickResult.pickedMesh;

// Find in bottles array to get children

var bottleInfo = bottles.find(b => b.bottle == selectedBottle);

var waterCylinders = bottleInfo.waterCylinders;

// Use waterCylinders ...

}

This will:- Store each bottle and its water cylinder children in the bottles array

- On pointer down, get the picked bottle mesh

- Find that bottle in the bottles array to get its .waterCylinders property

- Now you have access to the water cylinders for the selected bottle

小明:

i think your solution is complex, this is my simple solution:

scene.onPointerDown = (evt, pickInfo) => {

if (pickInfo.hit) {

(备注:不过给AI一些简单的示例代码,AI就能给出合理的方法了,我不知道它是真懂还是假懂,感觉是很厉害)

Claude:

You're right, accessing the picked mesh's .getChildren() directly is a simpler solution than storing all the parent-child relationships in an array.

Your solution would be:

js

// On pointer down

scene.onPointerDown = (evt, pickInfo) => {

if (pickInfo.hit) {

var selectedBottle = pickInfo.pickedMesh;

var waterCylinders = selectedBottle.getChildren();

// Use waterCylinders ...

}

}

This simply gets the .getChildren() of the picked bottle mesh, which will return its water cylinders.

So a full example would be:

js

// Create bottles

var bottles = [];

for (var i = 0; i < 10; i++) {

// Create bottle

var bottle = BABYLON.MeshBuilder.CreateCylinder("bottle", { /* ... */ }, scene);

// Create water cylinders

for (var j = 0; j < 3; j++) {

var water = BABYLON.MeshBuilder.CreateCylinder("water", { /* ... */ }, scene);

bottle.addChild(water);

}

bottles.push(bottle);

}

// On pointer down

scene.onPointerDown = (evt, pickInfo) => {

if (pickInfo.hit) {

var selectedBottle = pickInfo.pickedMesh;

var waterCylinders = selectedBottle.getChildren();

// Change water cylinder materials

for (var i = 0; i < waterCylinders.length; i++) {

waterCylinders[i].material.diffuseColor = BABYLON.Color3.Red();

}

}

}

This is indeed a simpler solution - nicely optimized! Directly accessing .getChildren() removes the need to track parent-child relationships separately.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

小明:

How do I check if the color of the water is the same?

(备注:开始写判断逻辑,主要是颜色相同判断,给的代码不太靠谱,能用的就是颜色的equals方法)

Claude:

You can check if two materials (and thus, two meshes) have the same color by comparing their diffuseColor properties.

For example:

js

// Get materials of two water cylinders

var water1Mat = water1.material;

var water2Mat = water2.material;

// Check if diffuseColors are equal

if (water1Mat.diffuseColor.equals(water2Mat.diffuseColor)) {

// Colors are the same!

} else {

// Colors are different

}

So in your code, you could do:

js

// On pointer down

scene.onPointerDown = function(evt) {

// Get selected bottle

var pickResult = scene.pick(evt.position.x, evt.position.y);

var selectedBottle = pickResult.pickedMesh;

// Get bottle info

var bottleInfo = bottles.find(b => b.bottle == selectedBottle);

// Check if selected color matches any other water cylinders

var selectedColor;

for (var i = 0; i < bottleInfo.waterCylinders.length; i++) {

var water = bottleInfo.waterCylinders[i];

if (water == pickResult.pickedMesh) {

selectedColor = water.material.diffuseColor;

} else if (selectedColor.equals(water.material.diffuseColor)) {

// Found a match!

console.log("Found matching color!");

}

}

}

This will loop through all the water cylinders in the selected bottle, check if any match the selected color, and log a message if a match is found.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

小明:

how do i set one water of one bottle as child of another?

(备注:开始写移动逻辑,主要是重设父物体并更新位置,感觉AI在对空间问题的处理上还比较差)

Claude:

o set a single water cylinder from one bottle as a child of another bottle, you can:

  1. Get the source bottle and water cylinder to reparent
  2. Get the target bottle to reparent to
  3. Remove the water cylinder from the source bottle
  4. Add the water cylinder as a child of the target bottleFor example:

js

// Bottle and water cylinder vars

var sourceBottle;

var targetBottle;

var waterToReparent;

// On reparent button click

function reparentWater() {

// Get source info

sourceBottle = bottles.find(b => /* ... */);

waterToReparent = sourceBottle.getChildren().find(w => /* ... */);

// Get target bottle

targetBottle = bottles.find(b => /* ... */);

// Remove from source parent

sourceBottle.removeChild(waterToReparent);

// Add to target parent

targetBottle.addChild(waterToReparent);

}

// ...

// On click, reparent water

reparentButton.onclick = reparentWater;

This will:- Get the source bottle and specific water cylinder to reparent

- Get the target bottle

- Remove the water cylinder from the source bottle

- Add the water cylinder as a child of the target bottleSo that single water cylinder will now appear inside the target bottle, having been reparented.

The .removeChild() and .addChild() methods are key to reparenting a mesh to a new parent.

一个基本可玩的版本

小明:

after i set one water as a child of another bottle, its position is still in the previous bottle, how do i set its position correct?

(备注:经过自己较多修改,做完这步之后,有了一个基本可以玩的版本,但随机算法有瑕疵,会出现瓶子填不满的情况)

Claude:

Good catch! When you reparent a mesh to a new parent, its local position remains the same. So you'll need to update its position to be relative to the new parent.

To fix the position of the reparented water cylinder, you can:

1. Get the new parent bottle's world matrix

2. Convert the water cylinder's local position to world space using its previous parent's world matrix

3. Transform the world position into the new parent's local space

4. Set the water cylinder's local position to the new local positionFor example:

js

// Bottle and water cylinder vars

var sourceBottle;

var targetBottle;

var waterToReparent;

// On reparent button click

function reparentWater() {

// ...

// Get new parent world matrix

var targetWorld = targetBottle.getWorldMatrix();

// Get water local and world positions

var waterLocal = waterToReparent.position;

var sourceWorld = sourceBottle.getWorldMatrix();

var waterWorld = BABYLON.Vector3.TransformCoordinates(waterLocal, sourceWorld);

// Transform to new local position

var newLocal = BABYLON.Vector3.TransformCoordinates(waterWorld,

targetWorld.invert());

// Set new local position

waterToReparent.position = newLocal;

}

// ...

This will:- Get the target bottle's world matrix

- Transform the water cylinder's local position to world space using the source bottle

- Invert the target bottle's world matrix to get its local space

- Transform the water world position into the target bottle's local space

- Set the water cylinder's local position to the new local positionSo after reparenting, the water cylinder will appear in the correct position relative to its new parent.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

解决完算法瑕疵的可玩版本

小明:

how to shuffle an array in javascript?

(备注:为解决之前随机算法的瑕疵,让AI给出一个洗牌算法,当然自己得先知道需要洗牌算法,否则不太好给AI描述清楚算法的瑕疵。解决完算法瑕疵就有了一个可玩版本,剩下的就是倒水效果等完善工作)

Claude:

You can shuffle an array in JavaScript using the .shuffle() method from lodash, or by implementing the Fisher-Yates shuffle algorithm.Using lodash:

js

let array = [1, 2, 3, 4, 5];

_.shuffle(array);

// array is now [3, 5, 1, 4, 2]

Implementing the Fisher-Yates shuffle:

js

let array = [1, 2, 3, 4, 5];

function shuffle(array) {

let m = array.length, t, i;

// While there remain elements to shuffle

while (m) {

// Pick a remaining element

i = Math.floor(Math.random() * m--);

// And swap it with the current element

[array[m], array[i]] = [array[i], array[m]];

}

return array;

}

shuffle(array);

// array is now [3, 5, 1, 4, 2]

The Fisher-Yates shuffle works by randomly swapping elements in the array until all elements have been swapped. This gives a properly randomized shuffle.

So either by using lodash's .shuffle() convenience method, or implementing the Fisher-Yates algorithm yourself, you can shuffle an array in JavaScript.

欢迎加入我们!

感兴趣的同学可以投递简历至:CYouEngine@cyou-inc.com

全部评论

相关推荐

01-26 19:51
门头沟学院 Java
点赞 评论 收藏
分享
bg双非本科,方向是嵌入式。这次秋招一共拿到了&nbsp;8&nbsp;个&nbsp;offer,最高年包&nbsp;40w,中间也有一段在海康的实习经历,还有几次国家级竞赛。写这篇不是想证明什么,只是想把自己走过的这条路,尽量讲清楚一点,给同样背景的人一个参考。一、我一开始也很迷茫刚决定走嵌入式的时候,其实并没有一个特别清晰的规划。网上的信息很零散,有人说一定要懂底层,有人说项目更重要,也有人建议直接转方向。很多时候都是在怀疑:1.自己这种背景到底有没有机会2.现在学的东西到底有没有用3.是不是已经开始晚了这些问题,我当时一个都没答案。二、现在回头看,我主要做对了这几件事第一,方向尽早确定,但不把自己锁死。我比较早就确定了嵌入式这个大方向,但具体做哪一块,是在项目、竞赛和实习中慢慢调整的,而不是一开始就给自己下结论。第二,用项目和竞赛去“证明能力”,而不是堆技术名词。我不会刻意追求学得多全面,而是确保自己参与的每个项目,都能讲清楚:我负责了什么、遇到了什么问题、最后是怎么解决的。第三,尽早接触真实的工程环境。在海康实习的那段时间,对我触动挺大的。我开始意识到,企业更看重的是代码结构、逻辑清晰度,以及你能不能把事情说清楚,而不只是会不会某个知识点。第四,把秋招当成一个需要长期迭代的过程。简历不是一次写完的,面试表现也不是一次就到位的。我会在每次面试后复盘哪些问题没答好,再针对性补。三、我踩过的一些坑现在看也挺典型的:1.一开始在底层细节上纠结太久,投入产出比不高2.做过项目,但前期不会总结,导致面试表达吃亏3.早期有点害怕面试,准备不充分就去投这些弯路走过之后,才慢慢找到节奏。四、给和我背景相似的人一点建议如果你也是双非,准备走嵌入式,我觉得有几件事挺重要的:1.不用等“准备得差不多了”再投2.项目一定要能讲清楚,而不是做完就算3.不要只盯着技术,多关注表达和逻辑很多时候,差的不是能力,而是呈现方式。五、写在最后这篇总结不是标准答案,只是我个人的一次复盘。后面我会陆续把自己在嵌入式学习、竞赛、实习和秋招中的一些真实经验拆开来讲,希望能对后来的人有点帮助。如果你正好也在这条路上,希望你能少走一点弯路。
x_y_z1:蹲个后续
点赞 评论 收藏
分享
评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务