猫史档案馆


【代码岛3.0】圈地之王 重制版

用户:CODE张博睿CODE张博睿查看:3 回复:3 评论:3 创建时间:2020-02-29T22:32:38


代码:

const SECONDS_PER_TICK = 1000 / 128; 
const ROUND_TIME = 200 * SECONDS_PER_TICK;//每局游戏时长
const MIN_PLAYERS = 1;//玩家数量下限
const GRID_X = 128;
const GRID_Z = 128;

const TEAMS = [
    { r: 255, g: 0,   b: 0,    v: voxels.id('red_light'),      n: '红队',       score: 0, },
    { r: 255, g: 127, b: 0,    v: voxels.id('orange_light'),   n: '橙队',       score: 0, },
    { r: 255, g: 255, b: 0,    v: voxels.id('yellow_light'),   n: '黄队',       score: 0, },
    { r: 0,   g: 255, b: 0,    v: voxels.id('green_light'),    n: '绿队',       score: 0, },
    { r: 0,   g: 255, b: 255,  v: voxels.id('indigo_light'),   n: '靛蓝队',     score: 0, },
    { r: 55,  g: 98,  b: 156,  v: voxels.id('blue_light'),     n: '蓝队',       score: 0, },
    { r: 139, g: 0,   b: 255,  v: voxels.id('purple'),         n: '紫队',       score: 0, },
    { r: 255, g: 178, b: 229,  v: voxels.id('pink'),           n: '粉队',       score: 0, },
];

// 辅助函数,用于随机打乱一个数组
function shuffle (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;
}

async function startGame () {
    // 将地面初始化,全部变成white_light
    for (let j = 0; j < GRID_Z; ++j) {
        for (let i = 0; i < GRID_X; ++i) {
            voxels.setVoxel(i, 8, j, 'white_light');
        }
    }
    
    world.say('请稍后,正在重置地图......');
    await sleep(7000);
    world.say('重置地图完成!');
    await sleep(1000);

    // 等待玩家进入
    while (world.querySelectorAll('player').length < MIN_PLAYERS) {
        world.say('等待其他玩家加入...');
        await sleep(1000);
        world.say('1个玩家立即开始');
        await world.nextPlayerJoin();
    }

    // 足够玩家加入后,就开始倒计时
    for (let i = 3; i > 0; --i) {
        world.say(i + '...');
        await sleep(1000);
    }
    world.say('去圈地吧!看谁是圈地之王?');
    
    // 每局都随机打乱队伍
    const players = shuffle(world.querySelectorAll('player'));
    shuffle(TEAMS);
    
    // 设置玩家的颜色和初始位置
    function setTeam (p, t) {
        p.player.color.r = t.r;
        p.player.color.g = t.g;
        p.player.color.b = t.b;
        p.position.x = Math.random() * GRID_X;
        p.position.y = 30;
        p.position.z = Math.random() * GRID_Z;
        p.yes = true;
        p.player.canFly = false;
        p.player.jumpPower = 0;
        p.player.doubleJumpPower = 0;
    }

    // 获得初始团队
    const teams = players.map((p, i) => {
        const t = TEAMS[i % TEAMS.length]
        setTeam(p, t);
        return t;
    })
    
    //当玩家接触到地面任意方块时,更新该方块的颜色
    const contactHandler = world.onVoxelContact(({ entity, x, y, z }) => {
        if(entity.yes == true) {
            const idx = players.indexOf(entity);
            if (idx < 0) {
                return;
            }
            const t = teams[idx];
            voxels.setVoxelId(x, y, z, t.v);
        }
    });
    
    // 新玩家加入,会被随机分配到一个队伍
    const joinHandler = world.onPlayerJoin(({entity}) => {
        const t = TEAMS[(Math.random() * teams.length) | 0];
        setTeam(entity, t);
        teams.push(t);
        players.push(entity)
    });
    
    // 每局游戏会在计时到达时结束。
    const endTick = world.currentTick + ROUND_TIME;
    
    // 检测游戏是否进行中
    function gameInProgress () {
        let numActivePlayers = 0;
        for (let i = 0; i < players.length; ++i) {
            if (!players[i].destroyed) {
                numActivePlayers += 1;
            }
        }
        return world.currentTick < endTick && numActivePlayers >= MIN_PLAYERS;
    }
    
    // 通过深度优先搜索,将圈起来的地自动填色
    const visited = new Uint8Array(GRID_X * GRID_Z)
    const toVisit = []
    function mark (i, j, team) {
        const idx = i + j * GRID_X;
        if (i < 0 || i >= GRID_X ||
            j < 0 || j >= GRID_Z ||
            visited[idx] ||
            voxels.getVoxel(i, 8, j) === team) {
            return;
        }
        visited[idx] = true;
        toVisit.push(i, j);
    }
    function fillHoles (team) {
        visited.fill(0);
        for (let i = 0; i < Math.max(GRID_X, GRID_Z); ++i) {
            mark(i, 0, team);//更正了,将8改成了0
            mark(0, i, team);
            mark(GRID_X - 1, i, team);
            mark(i, GRID_Z - 1, team);
        }
        
        while (toVisit.length > 0) {
            const z = toVisit.pop() | 0;
            const x = toVisit.pop() | 0;
            mark(x - 1, z, team);
            mark(x + 1, z, team);
            mark(x, z - 1, team);
            mark(x, z + 1, team);
        }
        
        let score = 0;
        for (let j = 0; j < GRID_Z; ++j) {
            for (let i = 0; i < GRID_X; ++i) {
                const idx = i + j * GRID_X;
                if (!visited[idx]) {
                    voxels.setVoxelId(i, 8, j, team);
                    score += 1;
                }
            }
        }
        return score;
    }
    
    // 当游戏运行时
    while (gameInProgress()) {
        // 等待 1 Tick
        await world.nextTick();
        
        // 计算各队伍的分数
        for (let i = 0; i < TEAMS.length; ++i) {
            const c = TEAMS[i].score = fillHoles(TEAMS[i].v);
            
            // 如果有团队圈完全场,那么直接胜出
            if (c >= GRID_X * GRID_Z) {
                break;
            }
        }

        //看看有人掉出世界了么?
        world.querySelectorAll('player').forEach((e) => {
            if (e.position.y <= 0) {
                world.say(`哦,不!${e.player.name} 掉出去了!`);
                //await sleep(1000);
                e.position.x = Math.random() * GRID_X;
                e.position.y = 30;
                e.position.z = Math.random() * GRID_Z;
                e.yes = false;
                e.player.canFly = true;
                e.player.jumpPower = 0.96;
                e.player.doubleJumpPower = 0.9;
            }
        });
    }
    
    // 清除事件处理器
    contactHandler.cancel();
    joinHandler.cancel();

    // 重置玩家颜色
    for (let i = 0; i < players.length; ++i) {
        const c = players[i].player.color;
        c.r = c.g = c.b = 1;
    }
    world.say('本局游戏结束!');
    await sleep(5000);
    
    // 宣布获胜队伍
    TEAMS.sort((a, b) => b.score - a.score);
    world.say(`恭喜 ${TEAMS[0].n} 成为圈地之王!!`);
    
    //游戏结束了,飞起来么?
    world.querySelectorAll('player').forEach((e) => {
        e.player.canFly = true;
        e.player.jumpPower = 0.96;
        e.player.doubleJumpPower = 0.9;
    });

    await sleep(5000);
    world.say('休息一分钟吧~');
    await sleep(60000);
}

// 无限循环游戏
async function gameLoop () {
    while (true) {
        await startGame();    
    }
}

gameLoop();

更改:

1、增加掉下虚空,掉下虚空将取消你的本局资格
2、改成2D游戏,正常游戏下不能跳跃
3、结束后休息1分钟,可以飞
4、队伍数量加多


回复

上一页1 页 / 共 1下一页
cool-creepercool-creeper

牛批

点赞0


评论


if_爱爸喵if_爱爸喵

const SECONDS_PER_TICK = 1000 / 128; 
const ROUND_TIME = 200 * SECONDS_PER_TICK;//每局游戏时长
const MIN_PLAYERS = 1;//玩家数量下限
const GRID_X = 128;
const GRID_Z = 128;

const TEAMS = [
    { r: 255, g: 0,   b: 0,    v: voxels.id('red_light'),      n: '红队',       score: 0, },
    { r: 255, g: 127, b: 0,    v: voxels.id('orange_light'),   n: '橙队',       score: 0, },
    { r: 255, g: 255, b: 0,    v: voxels.id('yellow_light'),   n: '黄队',       score: 0, },
    { r: 0,   g: 255, b: 0,    v: voxels.id('green_light'),    n: '绿队',       score: 0, },
    { r: 0,   g: 255, b: 255,  v: voxels.id('indigo_light'),   n: '靛蓝队',     score: 0, },
    { r: 55,  g: 98,  b: 156,  v: voxels.id('blue_light'),     n: '蓝队',       score: 0, },
    { r: 139, g: 0,   b: 255,  v: voxels.id('purple'),         n: '紫队',       score: 0, },
    { r: 255, g: 178, b: 229,  v: voxels.id('pink'),           n: '粉队',       score: 0, },
];

// 辅助函数,用于随机打乱一个数组
function shuffle (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;
}

async function startGame () {
    // 将地面初始化,全部变成white_light
    for (let j = 0; j < GRID_Z; ++j) {
        for (let i = 0; i < GRID_X; ++i) {
            voxels.setVoxel(i, 8, j, 'white_light');
        }
    }
    
    world.say('请稍后,正在重置地图......');
    await sleep(7000);
    world.say('重置地图完成!');
    await sleep(1000);

    // 等待玩家进入
    while (world.querySelectorAll('player').length < MIN_PLAYERS) {
        world.say('等待其他玩家加入...');
        await sleep(1000);
        world.say('1个玩家立即开始');
        await world.nextPlayerJoin();
    }

    // 足够玩家加入后,就开始倒计时
    for (let i = 3; i > 0; --i) {
        world.say(i + '...');
        await sleep(1000);
    }
    world.say('去圈地吧!看谁是圈地之王?');
    
    // 每局都随机打乱队伍
    const players = shuffle(world.querySelectorAll('player'));
    shuffle(TEAMS);
    
    // 设置玩家的颜色和初始位置
    function setTeam (p, t) {
        p.player.color.r = t.r;
        p.player.color.g = t.g;
        p.player.color.b = t.b;
        p.position.x = Math.random() * GRID_X;
        p.position.y = 30;
        p.position.z = Math.random() * GRID_Z;
        p.yes = true;
        p.player.canFly = false;
        p.player.jumpPower = 0;
        p.player.doubleJumpPower = 0;
    }

    // 获得初始团队
    const teams = players.map((p, i) => {
        const t = TEAMS[i % TEAMS.length]
        setTeam(p, t);
        return t;
    })
    
    //当玩家接触到地面任意方块时,更新该方块的颜色
    const contactHandler = world.onVoxelContact(({ entity, x, y, z }) => {
        if(entity.yes == true) {
            const idx = players.indexOf(entity);
            if (idx < 0) {
                return;
            }
            const t = teams[idx];
            voxels.setVoxelId(x, y, z, t.v);
        }
    });
    
    // 新玩家加入,会被随机分配到一个队伍
    const joinHandler = world.onPlayerJoin(({entity}) => {
        const t = TEAMS[(Math.random() * teams.length) | 0];
        setTeam(entity, t);
        teams.push(t);
        players.push(entity)
    });
    
    // 每局游戏会在计时到达时结束。
    const endTick = world.currentTick + ROUND_TIME;
    
    // 检测游戏是否进行中
    function gameInProgress () {
        let numActivePlayers = 0;
        for (let i = 0; i < players.length; ++i) {
            if (!players[i].destroyed) {
                numActivePlayers += 1;
            }
        }
        return world.currentTick < endTick && numActivePlayers >= MIN_PLAYERS;
    }
    
    // 通过深度优先搜索,将圈起来的地自动填色
    const visited = new Uint8Array(GRID_X * GRID_Z)
    const toVisit = []
    function mark (i, j, team) {
        const idx = i + j * GRID_X;
        if (i < 0 || i >= GRID_X ||
            j < 0 || j >= GRID_Z ||
            visited[idx] ||
            voxels.getVoxel(i, 8, j) === team) {
            return;
        }
        visited[idx] = true;
        toVisit.push(i, j);
    }
    function fillHoles (team) {
        visited.fill(0);
        for (let i = 0; i < Math.max(GRID_X, GRID_Z); ++i) {
            mark(i, 0, team);//更正了,将8改成了0
            mark(0, i, team);
            mark(GRID_X - 1, i, team);
            mark(i, GRID_Z - 1, team);
        }
        
        while (toVisit.length > 0) {
            const z = toVisit.pop() | 0;
            const x = toVisit.pop() | 0;
            mark(x - 1, z, team);
            mark(x + 1, z, team);
            mark(x, z - 1, team);
            mark(x, z + 1, team);
        }
        
        let score = 0;
        for (let j = 0; j < GRID_Z; ++j) {
            for (let i = 0; i < GRID_X; ++i) {
                const idx = i + j * GRID_X;
                if (!visited[idx]) {
                    voxels.setVoxelId(i, 8, j, team);
                    score += 1;
                }
            }
        }
        return score;
    }
    
    // 当游戏运行时
    while (gameInProgress()) {
        // 等待 1 Tick
        await world.nextTick();
        
        // 计算各队伍的分数
        for (let i = 0; i < TEAMS.length; ++i) {
            const c = TEAMS[i].score = fillHoles(TEAMS[i].v);
            
            // 如果有团队圈完全场,那么直接胜出
            if (c >= GRID_X * GRID_Z) {
                break;
            }
        }

        //看看有人掉出世界了么?
        world.querySelectorAll('player').forEach((e) => {
            if (e.position.y <= 0) {
                world.say(`哦,不!${e.player.name} 掉出去了!`);
                //await sleep(1000);
                e.position.x = Math.random() * GRID_X;
                e.position.y = 30;
                e.position.z = Math.random() * GRID_Z;
                e.yes = false;
                e.player.canFly = true;
                e.player.jumpPower = 0.96;
                e.player.doubleJumpPower = 0.9;
            }
        });
    }
    
    // 清除事件处理器
    contactHandler.cancel();
    joinHandler.cancel();

    // 重置玩家颜色
    for (let i = 0; i < players.length; ++i) {
        const c = players[i].player.color;
        c.r = c.g = c.b = 1;
    }
    world.say('本局游戏结束!');
    await sleep(5000);
    
    // 宣布获胜队伍
    TEAMS.sort((a, b) => b.score - a.score);
    world.say(`恭喜 ${TEAMS[0].n} 成为圈地之王!!`);
    
    //游戏结束了,飞起来么?
    world.querySelectorAll('player').forEach((e) => {
        e.player.canFly = true;
        e.player.jumpPower = 0.96;
        e.player.doubleJumpPower = 0.9;
    });

    await sleep(5000);
    world.say('休息一分钟吧~');
    await sleep(60000);
}

// 无限循环游戏
async function gameLoop () {
    while (true) {
        await startGame();    
    }
}

gameLoop();

点赞0


评论


可可萝可可萝

不用let吗?为啥要用const? [不懂]

 

点赞0


评论