猫史档案馆


有大佬教植物大战僵尸吗?求程序!

用户:oSomiwwwoSomiwww查看:1 回复:3 评论:1 创建时间:2022-01-10T19:39:51


有大佬教植物大战僵尸吗?求程序!


回复

上一页1 页 / 共 1下一页
星辰_零柒星辰_零柒

你是说岛三的吗?

 

点赞0


评论


星辰_零柒星辰_零柒

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),
    },
};

am; // 最终队伍
let playerScore; // 玩家分数
let gameEndResolve; // 用于结束游戏的函数
// 主函数
(async function main() {
    // 打印开始时间的日志
    console.log(`-------[${new Date().toISOString()}]--------`)
    setup(); // 初始化const spawnPoints = []; // 出生点坐标
const zombies = new Set();
const human = new Set();
let finalTe
    // 主循环, 不断检测并开始新的游戏
    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 = rando喵elete(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 rando喵elete(arr) {
    return arr.splice(randomIndex(arr), 1)[0];
}

点赞0


评论


oSomiwwwoSomiwww

谢大佬

 

点赞0


评论