用户:
卑微OIer查看:22 回复:14 评论:22 创建时间:2022-04-26T17:53:09
const CELL_POSITION = {
x: [66, 197],
y: [30, 40],
z: [627, 661],
};
const OBJECT_START_POSITION = {
x: [102, 162],
y: [73, 83],
z: [148, 159],
};
const HUMAN_START_POSITION = {
x: [116, 150],
y: [31, 34],
z: [313, 335],
};
const NOTIFY_INTERVAL = 2 * 1000; // notify间隔时间, 单位毫秒
const CHECK_START_GAME_INTERVAL = 5; // 检测游戏开始的间隔时间, 单位秒
const COUNTDOWN_TIME = 5; // 倒计时多少秒开始游戏
const MIN_GAME_PLAYER_NUM = 2; // 最少多少人才能开始游戏
const GAME_TIME = 3 * 60; // 一局游戏时长, 单位秒
const CATCH_RATIO = 4 / 5; // 抓完多少物品就算人类赢
const TEAM_HUMAN_NAME = '人类队'; // 抓人队名称
const TEAM_OBJECT_NAME = '妖怪队'; // 变身队名称
/* 上面是配置 */
const players = [];
const humanPlayers = new Set();
const objectPlayers = new Set();
let catchCount = 0;
let winCatchNum = 0;
const objects = world.querySelectorAll('*').filter(isSmallEntity);
console.log(`共找到${objects.length}个于玩家变身的实体`);
let resolveHumanWin;
function isSmallEntity(e) {
return !e.hasTag('大件物品');
}
function randomSetVec3(v, p) {
v.set(
randomRange(p.x),
randomRange(p.y),
randomRange(p.z),
);
}
function initPlayer(entity) {
entity.player.showName = true;
entity.position.copy(entity.player.spawnPoint);
entity.mesh = '';
entity.player.invisible = false;
entity.player.runSpeed = 0.4;
entity.player.runAcceleration = 0.35;
entity.player.walkSpeed = 0.22;
entity.player.walkAcceleration = 0.19;
awaitDirectMessage(entity, '请等待新的一局游戏开始');
}
function fakeObject(player, object) {
player.mesh = object.mesh;
player.meshOrientation = object.meshOrientation;
player.meshScale = object.meshScale;
player.showName = false;
}
function catchObject(p, o) {
if (!humanPlayers.has(p) || !objectPlayers.has(o)) return;
objectPlayers.delete(o);
initPlayer(o);
if (++catchCount === winCatchNum) {
notify(`${p.player.name} 找到了最后一名${TEAM_OBJECT_NAME}成员${o.player.name}.`);
resolveHumanWin(true);
} else {
notify(`${p.player.name} 找到了 ${o.player.name}, 当前${TEAM_OBJECT_NAME}还剩下${objectPlayers.size}人.`);
}
}
const nitifyQueue = [];
let notifying = false;
let notifyFinish = Promise.resolve();
async function notify(s) {
nitifyQueue.push(s);
if (notifying) return;
notifying = true;
let resolve;
notifyFinish = new Promise((r) => resolve = r);
while (nitifyQueue.length > 0) {
world.say(nitifyQueue.shift());
await sleep(NOTIFY_INTERVAL);
}
notifying = false;
resolve();
}
function setup() {
world.onPlayerJoin(({entity}) => {
randomSetVec3(entity.player.spawnPoint, CELL_POSITION);
initPlayer(entity);
players.push(entity);
});
world.onPlayerLeave(({entity}) => {
if (!arrayRemoveElement(players, entity)) {
console.error(`玩家退出时出现错误, 找不到需要删除的玩家${entity.id}`);
}
const isHuman = humanPlayers.has(entity);
const isObject = objectPlayers.has(entity);
if (isHuman) {
humanPlayers.delete(entity);
} else if (isObject) {
objectPlayers.delete(entity);
if (objectPlayers.size === 0) {
resolveHumanWin(true);
}
} else {
return;
}
notify(`${entity.player.name} 退出游戏, ${isHuman ? TEAM_HUMAN_NAME : TEAM_OBJECT_NAME}失去了一份力量.`);
});
world.onPress(({ entity, button, raycast:{ hitEntity } }) => {
if (button === 'action0') {
catchObject(entity, hitEntity);
}
});
world.onEntityContact(({entity, other}) => {
if (objectPlayers.has(entity) && isSmallEntity(other) && !other.isPlayer) {
fakeObject(entity, other);
} else {
catchObject(entity, other);
}
});
}
async function main() {
// world.onPress(({ entity, button, raycast:{ hitVoxel, hitPosition } }) => {
// if (hitVoxel) {
// console.log(`${hitVoxel}: ${Math.floor(hitPosition.x)}, ${Math.floor(hitPosition.y)}, ${Math.floor(hitPosition.z)}`)
// }
// });
// return;
setup();
while (true) {
await sleep(CHECK_START_GAME_INTERVAL * 1000);
await startGame();
}
}
main();
async function startGame() {
if (!await isReady()) return;
arrayShuffle(players);
// 当玩家数为奇数是, 人队比物队多一人
const teamObjectNum = Math.floor(players.length / 2);
catchCount = 0;
winCatchNum = Math.ceil(teamObjectNum * CATCH_RATIO);
for (let i = 0; i < teamObjectNum; i++) {
const e = players[i];
objectPlayers.add(e);
randomSetVec3(e.position, OBJECT_START_POSITION);
fakeObject(e, arrayRandomPick(objects));
e.player.invisible = true;
delayDirectMessage(e, `你属于${TEAM_OBJECT_NAME}, 触碰物品即变身,不要被发现!`);
}
for (let i = teamObjectNum; i < players.length; i++) {
const e = players[i];
humanPlayers.add(e);
randomSetVec3(e.position, HUMAN_START_POSITION);
delayDirectMessage(e, `你属于${TEAM_HUMAN_NAME}, 快去抓假装物品的家伙!`);
e.player.runSpeed = 0.8;//菲比:给抓人队加速
e.player.runAcceleration = 0.7;//菲比:给抓人队加速
e.player.walkSpeed = 0.4;//菲比:给抓人队加速
e.player.walkAcceleration = 0.25;//菲比:给抓人队加速
}
await sleep(NOTIFY_INTERVAL);
//world.say('开始游戏!');
const isHumanWin = await new Promise(async (resolve) => {
resolveHumanWin = resolve;
await sleep(GAME_TIME * 1000);
resolve(false);
});
notify(`游戏结束, ${isHumanWin ? TEAM_HUMAN_NAME : TEAM_OBJECT_NAME} 胜利!`);
humanPlayers.forEach(initPlayer);
objectPlayers.forEach(initPlayer);
humanPlayers.clear();
objectPlayers.clear();
}
async function isReady() {
if (players.length < MIN_GAME_PLAYER_NUM) {
notify(`当前在线${players.length}人, 达到${MIN_GAME_PLAYER_NUM}人即开始游戏!`);
return false;
}
notify('游戏即将开始!');
await sleep(NOTIFY_INTERVAL);
for (let i = COUNTDOWN_TIME; i > 0; i--) {
world.say(`倒计时 ${i}...`);
await sleep(1000);
}
if (players.size < MIN_GAME_PLAYER_NUM) {
notify(`有人退出游戏, 导致游戏人数不足, 无法开始游戏!`);
return false;
}
return true;
}
async function awaitDirectMessage(p, m) {
await notifyFinish;
p.player.directMessage(m);
}
async function delayDirectMessage(p, m) {
await sleep(5000);
p.player.directMessage(m);
}
function randomRange(r) {
return r[0] + Math.random() * [r[1] - r[0]];
}
function arrayShuffle (array) {
for (let i = 1; i < array.length; ++i) {
const temp = array[i];
const x = (Math.random() * (i + 1)) | 0;
array[i] = array[x];
array[x] = temp;
}
return array;
}
function arrayRandomIndex(a) {
return Math.floor(Math.random() * a.length);
}
function arrayRandomPick(a) {
return a[arrayRandomIndex(a)];
}
function arrayRandomSplice(a) {
return a.splice(arrayRandomIndex(a), 1)[0];
}
function arrayRemoveElement(a, e) {
const idx = a.indexOf(e);
if (idx < 0) return false;
a.splice(idx, 1);
return true;
}
//吉吉不要啊))))If we know it easyer