生化危机3D代码

const GAME_END_TIME = 10 * 60; // 游戏结束时, 单位秒

const MIN_GAME_PLAYER_NUM = 2; // 最小游戏人数

const GAME_HALFTIME = 5; // 两局游戏间隔时间, 单位秒

const GROUND_Y = 9; // 地面的Y坐标

const PLAYER_HEIGHT = 4; // 玩家高度

const XZ_BEGIN = 1; // x和z坐标的开始值

const XZ_END = 127; // x和z坐标的结束值

const ZOMBIE_PROBABILITY = 0.1; // 僵尸出现几率

const HUMAN_DAMAGE = 10; // 人类武器伤害

const HUMAN_DISTANCE = 30; // 人类武器距离

const ZOMBIE_BEAT_BACK_FORCE = 3; // 僵尸被击退的力道

// 实体属性

const ENTITY_ATTRIBUTES = {

    human: { // 人类的实体属性

        hp: 100, // 血量

        maxHp: 100, // 最大血量

        enableDamage: false, // 关闭伤害

    },

    zombie: { // 僵尸的实体属性

        hp: 1000,

        maxHp: 1000,

        enableDamage: true, // 关闭伤害

    },

};

// 玩家属性

const PLAYER_ATTRIBUTES = {

    human: { // 人类的玩家属性

        color: new Box3RGBColor(1, 1, 1), // 色彩

        walkSpeed: 0.22, // 走路最大速度

        walkAcceleration: 0.19, // 走路加速度

        runSpeed: 0.4, // 跑步最大速度

        runAcceleration: 0.35, // 跑步加速度

        jumpPower: 0.96, // 一段跳力量

        doubleJumpPower: 0.9, // 二段跳力量

    },

    zombie: { // 僵尸的玩家属性

        color: new Box3RGBColor(0, 1, 0),

        walkSpeed: 0.4,

        walkAcceleration: 0.3,

        runSpeed: 0.8,

        runAcceleration: 0.6,

        jumpPower: 1.2,

        doubleJumpPower: 1.1,

    },

};

// 武器设置

const WEAPON = {

    human: {

        mesh: world.querySelector('.人类用的武器').mesh,

        parts: [Box3BodyPart.RIGHT_HAND],

        scale: new Box3Vector3(0.2, 0.3, 0.3), // 调整大小

        orientation: new Box3Quaternion(0, 1, 0, 0).rotateX(Math.PI / 2).rotateY(-Math.PI / 2),

        offset: new Box3Vector3(0, -0.45, 0), //调整位置

    },

    zombie: {

        mesh: world.querySelector('.僵尸武器').mesh,

        parts: [Box3BodyPart.LEFT_HAND, Box3BodyPart.RIGHT_HAND],

        orientation: new Box3Quaternion(0, 1, 0, 0).rotateZ(-Math.PI / 2),

        scale: new Box3Vector3(0.2, 0.2, 0.2),

        offset: new Box3Vector3(0, -0.3, 0),

    },

};

const spawnPoints = []; // 出生点坐标

const zombies = new Set();

const human = new Set();

let finalTeam; // 最终队伍

let playerScore; // 玩家分数

let gameEndResolve; // 用于结束游戏的函数

// 主函数

(async function main() {

    // 打印开始时间的日志

    console.log(`-------[${new Date().toISOString()}]--------`)

    setup(); // 初始化

    // 主循环, 不断检测并开始新的游戏

    for(;;await sleep(GAME_HALFTIME * 1000)) {

        // 检测人数

        if (world.querySelectorAll('player').length < MIN_GAME_PLAYER_NUM) {

            world.say(`当前人数不足${MIN_GAME_PLAYER_NUM}人, 无法开始游戏!`);

            continue;

        }

        // 倒计时

        world.say('游戏即将开始!');

        for (let i = 0; i > 0; i--) {

            await sleep(1000);

            world.say(`${i}...`);

        }

        await start();

    }

})();

// 开始游戏

async function start() {

    const players = world.querySelectorAll('player');

    // 初始化玩家分数

    playerScore = { '': -1 };

    finalTeam = {};

    for (const entity of players) {

        playerScore[entity.player.name] = 0;

    }

    // 计算僵尸数量

    const zombieNum = Math.ceil(ZOMBIE_PROBABILITY * players.length);

    for (let i = 0; i < zombieNum; i++) {

        const entity = randomDelete(players); // 从玩家列表中随机删除一名玩家作为僵尸

        setPlayer(entity, 'zombie');

        setWeapon(entity, 'zombie');

        zombies.add(entity);

        finalTeam[entity.player.name] = 'zombie';

        entity.player.directMessage('你乃丧尸!');

    }

    for (const entity of players) {

        human.add(entity);

        setWeapon(entity, 'human');

        finalTeam[entity.player.name] = 'human';

        entity.player.directMessage('你奶战士!');

    }

    await new Promise(async (resolve) => {

        gameEndResolve = resolve; // 设置游戏结束函数

        await sleep(GAME_END_TIME * 1000); // 等待GAME_END_TIME秒

        resolve(); // 如果游戏没有提前结束, 就会由于到时间而结束

    });

    // 计算分数

    const winner = zombies.size > human.size ? 'zombie' : 'human';

    let best = '';

    for (const name in playerScore) {

        if (finalTeam[name] === winner && playerScore[name] > playerScore[best]) {

            best = name;

        }

    }

    const winnerName = winner === 'zombie' ? '僵尸' : '人类';

    const winnerScoreName = winner === 'zombie' ? '感染数' : '击杀数';

    world.say(`本局游戏${winnerName}获胜, ${best}以${playerScore[best]}的${winnerScoreName}成为MVP!`);

    // 僵尸恢复人类

    for (const entity of zombies) {

        initPlayer(entity);

    }

    zombies.clear(); // 清空僵尸

}

// 游戏初始化

function setup() {

    // 遍历地图, 寻找合适出生点

    for (let x = XZ_BEGIN; x < XZ_END; x++) {

        for (let z = XZ_BEGIN; z < XZ_END; z++) {

            let i = 0;

            while (i < PLAYER_HEIGHT && voxels.getVoxel(x, i + GROUND_Y, z) === 0) i++;

            // 如果(x, GROUND_Y, z)有足够空间容纳玩家, 则将其纳入出生点

            if (i === PLAYER_HEIGHT) {

                spawnPoints.push([x, GROUND_Y + 2, z])

            }

        }

    }

    // 删除所有临时实体

    world.querySelectorAll('.临时').forEach((e) => e.destroy());

    // 初始化人类属性

    world.onPlayerJoin(({entity}) => {

        initPlayer(entity);

    });

    // 人类射击

    world.onPress(({ entity, button, raycast: { hitEntity, direction, distance } }) => {

        if (!(button === 'action0' && human.has(entity) && zombies.has(hitEntity))) return;

        // 设置击中效果

        hitEntity.velocity.x += direction.x * ZOMBIE_BEAT_BACK_FORCE;

        hitEntity.velocity.y += 0.5;

        hitEntity.velocity.z += direction.z * ZOMBIE_BEAT_BACK_FORCE;

        // 计算伤害并应用

        const basicDamage = Math.max(1, HUMAN_DAMAGE * Math.min(1, HUMAN_DISTANCE / distance));

        const damage = Math.ceil(basicDamage * (1 + Math.random() * 0.3));

        hitEntity.hurt(damage, { attacker: entity });

    });

    // 僵尸死亡

    world.onDie(({entity, attacker}) => {

        if (!(human.has(attacker) && zombies.has(entity))) return;

        world.say(`@${attacker.player.name}击杀了僵尸${entity.player.name}.`);

        playerScore[attacker.player.name]++; // 人类分数+1

        attacker.player.directMessage(`击杀数: ${playerScore[attacker.player.name]}`);

        zombies.delete(entity); // 移除僵尸

        initPlayer(entity); // 恢复为人类, 可观战

        if (zombies.size === 0) gameEndResolve(); // 判断是否还有僵尸, 否则结束游戏

    });

    // 玩家离开

    world.onPlayerLeave(({entity}) => {

        // 从僵尸或人类中移除离开的玩家, 并判断游戏是否结束

        if (human.has(entity)) {

            human.delete(entity);

            if (human.size === 0) gameEndResolve();

        } else if (zombies.has(entity)) {

            zombies.delete(entity);

            if (zombies.size === 0) gameEndResolve();

        }

    });

    // 人类感染

    world.onEntityContact(({entity, other}) => {

        if (!(human.has(entity) && zombies.has(other))) return; // 只处理人类和僵尸碰撞

        world.say(`@${entity.player.name}被${other.player.name}感染, 成为了新的僵尸.`);

        playerScore[other.player.name]++; // 僵尸分数+1

        playerScore[entity.player.name] = 0; // 人类分数清零

        other.player.directMessage(`感染数: ${playerScore[other.player.name]}`);

        removeWearable(entity); // 移除人类武器

        setPlayer(entity, 'zombie'); // 设置僵尸属性

        setWeapon(entity, 'zombie'); // 设置僵尸武器

        finalTeam[entity.player.name] = 'zombie'; // 跟新最终阵营

        zombies.add(entity); // 添加到僵尸列表

        human.delete(entity); // 从人类列表中移除

        if (human.size === 0) gameEndResolve(); // 判断是否还有人类, 否则结束游戏

    });

}

// 移除装扮

function removeWearable(entity) {

    WEAPON.zombie.parts.forEach((part) => {

        const wearables = entity.player.wearables(part); // 查找所有可穿戴物品

        for (const wearable of wearables) {

            entity.player.removeWearable(wearable); // 移除可穿戴物品

        }

    });

}

// 装备武器

function setWeapon(entity, camp) {

    WEAPON[camp].parts.forEach((part) => entity.player.addWearable({

        bodyPart: part, // 装备在右手上

        mesh: WEAPON[camp].mesh, // 设置武器mesh

        orientation: WEAPON[camp].orientation, // 设置方向

        scale: WEAPON[camp].scale, // 设置大小

        offset: WEAPON[camp].offset, // 设置位置

    }));

}

// 初始化玩家为人类

function initPlayer(entity) {

    entity.position.set(...randomPick(spawnPoints)); // 随机位置

    // entity.player.cameraMode = 'FPS'; // 设置FPS模式

    setPlayer(entity, 'human'); // 初始化为人类属性

    removeWearable(entity); // 移除已装备的武器

}

// 设置玩家为人类或僵尸

function setPlayer(entity, camp = 'human') {

    Object.assign(entity, ENTITY_ATTRIBUTES[camp]); // 复制实体属性

    Object.assign(entity.player, PLAYER_ATTRIBUTES[camp]); // 复制玩家属性

}

// 随机数组下标

function randomIndex(arr) {

    return Math.floor(Math.random() * arr.length);

}

// 随机选取数组中的元素

function randomPick(arr) {

    return arr[randomIndex(arr)];

}

// 随机删除数组中的元素

function randomDelete(arr) {

    return arr.splice(randomIndex(arr), 1)[0];

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值