Как заменить сущность игрока коробки на модель GLB в NOA.JS + Babylon.js GameHtml

Программисты Html
Ответить Пред. темаСлед. тема
Anonymous
 Как заменить сущность игрока коробки на модель GLB в NOA.JS + Babylon.js Game

Сообщение Anonymous »

В настоящее время я работаю над игрой, построенной с использованием NOA.JS и Babylon.js. В существующем файле Entity.js из шаблона проекта игрок создается с помощью простой сетки коробки. Я успешно загрузил модель GLB в сцену, но она появляется отдельно и не наследует поведение или свойства существующего игрока (например, движение, управление или обработку столкновений). < /P>
Каков правильный способ заменить текущую коробку, используемую для объекта игрока с помощью модели GLB, в то время как он функционирует в качестве основного игрока, и контролирует). Двигатель?

Код: Выделить всё

import * as BABYLON from '@babylonjs/core';
import '@babylonjs/loaders';

import { noa } from './engine';
import { setMeshShadows } from './shadows';
import { blockIDs } from './registration';
import blastImg from './assets/blast.png';

let sheepMesh = null;
let gameActive = true;
let explosionSound = new Audio('./assets/explosion.mp3');

const npcSheepEntities = [];

/**
* Convert 3D mesh position to 2D screen coordinates.
*/
function toScreenPosition(mesh, scene) {
if (!mesh || !scene || !scene.activeCamera) {
return { x: window.innerWidth / 2, y: window.innerHeight / 2 };
}

const worldMatrix = mesh.getWorldMatrix();
const transformMatrix = scene.getTransformMatrix();
const camera = scene.activeCamera;

const engine = scene.getEngine();
const viewport = camera.viewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());

const projected = BABYLON.Vector3.Project(
mesh.position,
worldMatrix,
transformMatrix,
viewport
);

return { x: projected.x, y: projected.y };
}

/**
* Display a blast effect at given screen position.
*/
function showBlastEffect(screenX = window.innerWidth / 2, screenY = window.innerHeight / 2) {
return new Promise((resolve) => {
const blastElement = document.createElement('img');
blastElement.src = blastImg;
blastElement.style.position = 'fixed';
blastElement.style.top = `${screenY}px`;
blastElement.style.left = `${screenX}px`;
blastElement.style.transform = 'translate(-50%, -50%)';
blastElement.style.pointerEvents = 'none';
blastElement.style.zIndex = '9999';
blastElement.style.width = '300px';
blastElement.style.height = '300px';
blastElement.style.opacity = '1';
blastElement.style.transition = 'opacity 1s ease-out';

document.body.appendChild(blastElement);

setTimeout(() => { blastElement.style.opacity = '0'; }, 300);
setTimeout(() => {
document.body.removeChild(blastElement);
resolve();
}, 1100);
});
}

/**
* Load a GLB model and attach it to a given entity.
* Mesh follows entity position in game loop.
*/
async function loadAndAttachGLBToEntity(entityId, modelPath, modelFilename, options = {}) {
const scene = noa.rendering.getScene();
const dat = noa.entities.getPositionData(entityId);
const { width: w, height: h, position: pos } = dat;

const {
scaleMultiplier = 1,
yOffset = 0
} = options;

return new Promise((resolve, reject) => {
BABYLON.SceneLoader.ImportMesh(
null,
modelPath,
modelFilename,
scene,
(meshes) => {
const visualMesh = meshes.find(m => m.getTotalVertices && m.getTotalVertices() > 0) || meshes[0];
if (!visualMesh) return reject(new Error('No visible mesh found in GLB model.'));

visualMesh.position.set(pos[0], pos[1] + h / 2 + yOffset, pos[2]);
visualMesh.scaling = new BABYLON.Vector3(w, h, w).scale(scaleMultiplier);
visualMesh.material = noa.rendering.makeStandardMaterial();
visualMesh.visibility = 1;

noa.entities.addComponent(entityId, noa.entities.names.mesh, {
mesh: visualMesh,
offset: [0, h / 2 + yOffset, 0],
});

setMeshShadows(visualMesh, true);

if (entityId === noa.playerEntity) {
sheepMesh = visualMesh;
}

noa.on('beforeRender', () => {
if (!gameActive) return;
const data = noa.entities.getPositionData(entityId);
if (!data) return;
visualMesh.position.set(
data.position[0],
data.position[1] + yOffset,
data.position[2]
);
if (entityId === noa.playerEntity) {
checkFenceCollision(data.position[0], data.position[1], data.position[2]);
}
});

resolve(visualMesh);
},
null,
(scene, message, exception) =>  {
console.error('Error loading GLB model:', message, exception);
reject(exception);
}
);
});
}

/**
* Collision detection between player and fence blocks.
*/
function checkFenceCollision(x, y, z) {
if (!gameActive) return;
const blockBelow = noa.getBlock(x, y, z);
const blockAtFeet = noa.getBlock(x, y + 0.5, z);
if (blockBelow === blockIDs.fence || blockAtFeet === blockIDs.fence) {
endGame();
}
}

/**
* Update sheep counter in UI.
*/
function updateSheepCount() {
const sheepCountElement = document.querySelector('#sheep-counter .counter-value');
if (sheepCountElement) {
sheepCountElement.textContent = npcSheepEntities.length.toString();
}
}

/**
* End the game — hide sheep mesh, play sound and show blast.
*/
async function endGame() {
if (!gameActive) return;
gameActive = false;

const scene = noa.rendering.getScene();
let screenPos = { x: window.innerWidth / 2, y: window.innerHeight / 2 };
if (sheepMesh) {
screenPos = toScreenPosition(sheepMesh, scene);
sheepMesh.setEnabled(false);
}

explosionSound.play();
await showBlastEffect(screenPos.x, screenPos.y);

document.getElementById('end-game-screen').style.display = 'flex';
document.getElementById('game-ui').style.display = 'none';
}

/**
* Spawn a single NPC sheep entity.
*/
async function spawnNPCSheep(startX, startY, startZ) {
const eid = noa.entities.add([startX, startY, startZ], 0.5, 1.2);
npcSheepEntities.push(eid);

await loadAndAttachGLBToEntity(eid, '/castle/', 'sheep.glb', {
scaleMultiplier: 0.4,
yOffset: 0,
});

updateSheepCount();

// Give sheep circular wandering movement
const centerX = startX + (Math.random() - 0.5) * 100;
const centerZ = startZ + (Math.random() - 0.5) * 100;
const radius = 5 + Math.random() * 15;
const angularSpeed = 0.0005 + Math.random() * 0.001;
const angleOffset = Math.random() * 2 * Math.PI;

noa.on('beforeRender', () => {
if (!gameActive) return;
const time = performance.now();
const angle = angleOffset + angularSpeed * time;
const x = centerX + Math.cos(angle) * radius;
const z = centerZ + Math.sin(angle) * radius;
const currentY = noa.entities.getPosition(eid)[1];
noa.entities.setPosition(eid, [x, currentY, z]);
});
}

/**
* Spawn a herd of NPC sheeps around player.
*/
async function spawnNPCSheepHerd(centerX, centerY, centerZ) {
for (let i = 0; i < 5; i++) {
const randX = centerX + (Math.random() - 0.5) * 160;
const randZ = centerZ + (Math.random() - 0.5) * 160;
await spawnNPCSheep(randX, centerY, randZ);
}
}

/**
* Initialize player entity and NPC herd after game tick.
*/
noa.once('tick', async () => {
try {
const eid = noa.playerEntity;
if (!eid) throw new Error('Player entity not found');

// Replace box mesh with GLB model for player
await loadAndAttachGLBToEntity(eid, '/castle/', 'sheep.glb', {
scaleMultiplier: 0.4,
yOffset: 0
});

// Adjust camera follow position for player sheep
const sheepHeight = noa.ents.getPositionData(eid).height;
const eyeOffset = 0.8 * sheepHeight;

noa.ents.removeComponent(noa.camera.cameraTarget, 'followsEntity');
noa.ents.addComponent(noa.camera.cameraTarget, 'followsEntity', {
entity: eid,
offset: [0, eyeOffset, 0],
});

// Spawn NPC herd
const pos = noa.entities.getPosition(eid);
await spawnNPCSheepHerd(pos[0], pos[1], pos[2]);

console.log('Player sheep loaded and NPC herd spawned.');
} catch (error) {
console.error('Failed to initialize game:', error);
}
});
https://github.com/fenomas/noa-examples
i клонировать код отсюда

Подробнее здесь: https://stackoverflow.com/questions/796 ... on-js-game
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Как заменить сущность игрока коробки на модель GLB в NOA.JS + Babylon.js Game
    Anonymous » » в форуме CSS
    0 Ответы
    2 Просмотры
    Последнее сообщение Anonymous
  • Как реализовать функцию рекурсивного расстояния для оценки AI Game Game Game?
    Anonymous » » в форуме Python
    0 Ответы
    16 Просмотры
    Последнее сообщение Anonymous
  • Как реализовать функцию рекурсивного расстояния для оценки AI Game Game Game?
    Anonymous » » в форуме Python
    0 Ответы
    22 Просмотры
    Последнее сообщение Anonymous
  • Как реализовать функцию рекурсивного расстояния для оценки AI Game Game Game? [закрыто]
    Anonymous » » в форуме Python
    0 Ответы
    18 Просмотры
    Последнее сообщение Anonymous
  • Как реализовать функцию рекурсивного расстояния для оценки AI Game Game Game?
    Anonymous » » в форуме Python
    0 Ответы
    15 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Html»