matrix-engine-wgpu
Version:
Networking implemented - based on kurento openvidu server. fix arcball camera,instanced draws added also effect pipeline blend with instancing option.Normalmap added, Fixed shadows casting vs camera/video texture, webGPU powered pwa application. Crazy fas
303 lines (275 loc) • 11.3 kB
JavaScript
import {uploadGLBModel} from "../../../src/engine/loaders/webgpu-gltf";
import {LOG_FUNNY, LOG_MATRIX} from "../../../src/engine/utils";
import {Hero} from "./hero";
import {startUpPositions} from "./static";
export class Creep extends Hero {
heroAnimationArrange = {
dead: null,
walk: null,
salute: null,
attack: null,
idle: null
}
creepFocusAttackOn = null;
constructor(o, archetypes = ["creep"], group = "enemy", team) {
super(o.name, archetypes);
this.name = o.name;
this.core = o.core;
this.group = group;
this.team = team;
this.loadCreep(o);
return this;
}
loadCreep = async (o) => {
this.o = o;
try {
var glbFile01 = await fetch(o.path).then(res => res.arrayBuffer().then(buf => uploadGLBModel(buf, this.core.device)));
this.core.addGlbObjInctance({
material: {type: 'standard', useTextureFromGlb: true},
scale: [20, 20, 20],
position: o.position,
name: o.name,
texturesPaths: ['./res/meshes/glb/textures/mutant_origin.png'],
raycast: {enabled: true, radius: 1.1},
pointerEffect: {
enabled: true,
energyBar: true
}
}, null, glbFile01);
// make small async - cooking glbs files
this.asyncHelper(this.o).then(() => {
console.log('good')
}).catch(() => {
console.log('catch')
setTimeout(() => {this.asyncHelper(this.o);}, 3000);
});
} catch(err) {throw err;}
}
asyncHelper = async (o) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
this.heroe_bodies = app.mainRenderBundle.filter(obj => obj.name && obj.name.includes(o.name));
if(this.heroe_bodies.length == 0 ||
this.core.net.session == null
) {
reject();
return;
}
this.heroe_bodies.forEach((subMesh, idx) => {
subMesh.position.thrust = this.moveSpeed;
subMesh.glb.animationIndex = 0;
// adapt manual if blender is not setup
subMesh.glb.glbJsonData.animations.forEach((a, index) => {
// console.info(`%c Animation loading for creeps: ${a.name} index ${index}`, LOG_MATRIX)
if(a.name == 'dead') this.heroAnimationArrange.dead = index;
if(a.name == 'walk') this.heroAnimationArrange.walk = index;
if(a.name == 'salute') this.heroAnimationArrange.salute = index;
if(a.name == 'attack') this.heroAnimationArrange.attack = index;
if(a.name == 'idle') this.heroAnimationArrange.idle = index;
});
// adapt
subMesh.globalAmbient = [1, 1, 1, 1];
if(this.name.indexOf('friendly_creeps') != -1) {
subMesh.globalAmbient = [12, 12, 12, 1];
} else if(this.name.indexOf('enemy_creep') != -1) {
subMesh.globalAmbient = [12, 1, 1, 1];
}
if(this.group == 'friendly' && this.name.indexOf('friendly_creeps') != -1) {
if(idx == 0) {
if(this.core.net.virtualEmiter == this.core.net.session.connection.connectionId) {
subMesh.position.teams[0] = app.player.remoteByTeam[app.player.data.team];
subMesh.position.teams[1] = app.player.remoteByTeam[app.player.data.enemyTeam];
subMesh.position.netObject = subMesh.name;
let t = subMesh.name.replace('friendly_creeps', 'enemy_creep');
subMesh.position.remoteName = t;
subMesh.rotation.teams[0] = app.player.remoteByTeam[app.player.data.team];
subMesh.rotation.teams[1] = app.player.remoteByTeam[app.player.data.enemyTeam];
subMesh.rotation.emitY = subMesh.name;
subMesh.rotation.remoteName = t;
subMesh.sharedState.emitAnimationEvent = true;
}
}
}
if(idx == 0) this.core.collisionSystem.register((o.name), subMesh.position, 15.0, this.group);
});
this.setStartUpPosition();
this.attachEvents();
resolve();
setTimeout(() => {
if(this.core.net.virtualEmiter != null) {
console.info(`%c virtualEmiter navigateCreeps : `, LOG_MATRIX)
app.localHero.navigateCreeps();
}
}, 3000);
}, 9000);
})
}
setWalk() {
this.heroe_bodies.forEach(subMesh => {
subMesh.glb.animationIndex = this.heroAnimationArrange.walk;
console.info(`%chero walk`, LOG_MATRIX)
});
}
setSalute() {
this.heroe_bodies.forEach(subMesh => {
subMesh.glb.animationIndex = this.heroAnimationArrange.salute;
console.info(`%chero salute`, LOG_MATRIX)
});
}
setDead() {
this.heroe_bodies.forEach(subMesh => {
subMesh.glb.animationIndex = this.heroAnimationArrange.dead;
console.info(`%chero dead`, LOG_MATRIX)
});
}
setIdle() {
this.heroe_bodies.forEach(subMesh => {
subMesh.glb.animationIndex = this.heroAnimationArrange.idle;
console.info(`%chero idle`, LOG_MATRIX)
});
}
setAttack() {
this.heroe_bodies.forEach(subMesh => {
subMesh.glb.animationIndex = this.heroAnimationArrange.attack;
console.info(`%chero attack`, LOG_MATRIX)
});
}
setStartUpPosition() {
if(this.group == 'enemy') {
this.heroe_bodies.forEach((subMesh, idx) => {
subMesh.position.setPosition(
startUpPositions[this.core.player.data.enemyTeam][0],
startUpPositions[this.core.player.data.enemyTeam][1],
startUpPositions[this.core.player.data.enemyTeam][2]);
});
} else {
this.heroe_bodies.forEach((subMesh, idx) => {
subMesh.position.setPosition(
startUpPositions[this.core.player.data.team][0],
startUpPositions[this.core.player.data.team][1],
startUpPositions[this.core.player.data.team][2]);
});
}
}
setStartUpPosCreep() {
if(this.group == 'enemy') {
this.heroe_bodies.forEach((subMesh, idx) => {
subMesh.position.setPosition(
startUpPositions[this.core.player.data.enemyTeam][0],
startUpPositions[this.core.player.data.enemyTeam][1],
startUpPositions[this.core.player.data.enemyTeam][2]);
});
} else {
this.heroe_bodies.forEach((subMesh, idx) => {
subMesh.position.setPosition(
startUpPositions[this.core.player.data.team][0],
startUpPositions[this.core.player.data.team][1],
startUpPositions[this.core.player.data.team][2]);
});
}
}
attachEvents() {
addEventListener(`onDamage-${this.name}`, (e) => {
if(this.group == 'enemy') {
console.info(`%c onDamage-${this.name} group: ${this.group} creep damage!`, LOG_FUNNY);
} else {
console.log('friendly creep damage must come from net. [never]');
return;
}
this.heroe_bodies[0].effects.energyBar.setProgress(e.detail.progress);
this.core.net.sendOnlyData({
type: "damage-creep",
defenderName: e.detail.defender,
defenderTeam: this.team,
hp: e.detail.hp,
progress: e.detail.progress
});
if(e.detail.progress == 0) {
this.setDead();
console.info(`%c Creep dead [${this.name}], attacker[${e.detail.attacker}]`, LOG_MATRIX);
setTimeout(() => {
this.setStartUpPosCreep(this.name[this.name.length - 1]);
this.setWalk();
this.creepFocusAttackOn = null;
this.gotoFinal = false;
this.setStartUpPosCreep(this.name[this.name.length - 1]);
this.hp = 300;
this.heroe_bodies[0].effects.energyBar.setProgress(1);
app.localHero.setWalkCreep(this.name[this.name.length - 1]);
dispatchEvent(new CustomEvent('navigate-friendly_creeps', {detail: 'test'}));
}, 700);
}
});
if(this.group != 'enemy') {
addEventListener(`animationEnd-${this.heroe_bodies[0].name}`, (e) => {
// CHECK DISTANCE
if(e.detail.animationName != 'attack') { // && this.creepFocusAttackOn == null) {
return;
}
if(this.group == "friendly") {
if(this.creepFocusAttackOn == null) {
// console.info('setIdle:', e.detail.animationName)
let isEnemiesClose = false;
this.core.enemies.enemies.forEach((enemy) => {
if(typeof enemy.heroe_bodies === 'undefined') return;
let tt = this.core.RPG.distance3D(
this.heroe_bodies[0].position,
enemy.heroe_bodies[0].position);
if(tt < this.core.RPG.distanceForAction) {
// console.log(`%c ATTACK DAMAGE ${enemy.heroe_bodies[0].name}`, LOG_MATRIX)
isEnemiesClose = true;
this.calcDamage(this, enemy);
// no need ?? this.creepFocusAttackOn = null;
return;
}
});
this.core.enemies.creeps.forEach((creep) => {
if(typeof creep.heroe_bodies === 'undefined') return;
let tt = this.core.RPG.distance3D(
this.heroe_bodies[0].position,
creep.heroe_bodies[0].position);
if(tt < this.core.RPG.distanceForAction) {
// console.log(`%c ATTACK DAMAGE ${creep.heroe_bodies[0].name}`, LOG_MATRIX)
isEnemiesClose = true;
this.calcDamage(this, creep);
// no need ?? this.creepFocusAttackOn = null;
return;
}
});
let enemytron = this.core.RPG.distance3D(
this.heroe_bodies[0].position,
app.enemytron.position);
if(enemytron < this.core.RPG.distanceForAction) {
console.log(`%c ATTACK ENEMY TRON ${creep.heroe_bodies[0].name}`, LOG_MATRIX);
isEnemiesClose = true;
this.calcDamage(this, app.enemytron);
return;
}
// if(isEnemiesClose == false) this.setIdle();
return;
} else {
// Focus on enemy vs creeps !
let tt;
if(typeof this.creepFocusAttackOn.position !== 'undefined') {
tt = this.core.RPG.distance3D(
this.heroe_bodies[0].position,
this.creepFocusAttackOn.position);
} else {
tt = this.core.RPG.distance3D(
this.heroe_bodies[0].position,
this.creepFocusAttackOn.heroe_bodies[0].position);
}
if(tt < this.core.RPG.distanceForAction) {
console.log(`%c [creep] ATTACK DAMAGE ON`, LOG_MATRIX)
this.calcDamage(this, this.creepFocusAttackOn);
return;
} else {
this.creepFocusAttackOn = null;
dispatchEvent(new CustomEvent('navigate-friendly_creeps', {detail: 'test'}))
}
}
}
})
}
}
}