“灵剑出鞘”小游戏开发日志(7)---- “剑出鞘”的打击玩法

背景

前面游戏场景和视角转换都已经差不多了,接下来进入真正的游戏玩法阶段。原先设计时把方块叠加这块设计的过于复杂了,这次借助gpt对它进行一次大的优化改造。

目标

生成一个“剑诀”,滑动“剑诀”,可在场上进行叠加,剑诀叠满自动出鞘,对所有套在剑诀内的单位造成1点伤害。当前阶段先不产生额外特效。

开发过程

定义:

grid: 技能网格

block: 剑诀(有大概几种  O T F L Z S ,就是俄罗斯方块里面基础形状,目前无长条)

block的坐标gx,gy为网格内的网格(grid)格子数坐标。

1、网格的初始化

BattleGridSystem.initGrid(entity);

在游戏开始前,需要在 10 * 5 的网格中创建一个数组,用于存储方块的状态。可以将数组中的每个元素初始化为 0 或空。

    static initGrid(entity: Entity) {
        const comp = entity.getComponent(BattleGridComp);
        if (comp) {
            for (let i = 0; i < ROWS; i++) {
                comp.gridData[i] = [];
                for (let j = 0; j < COLS; j++) {
                    comp.gridData[i][j] = 0;
                }
            }
        }
    }

2、初始方块的生成

BattleGridSystem.initActiveBlock(entity);

    static initActiveBlock(entity: Entity) {
        const comp = ooxh.game.entity.getComponent(BattleGridComp);
        if (comp) {
            comp.activeBlock = new Block()
            console.log("原始形状:");
            console.log(comp.activeBlock.shape);
            this.blockToGrid(comp, comp.activeBlock)
        }
    }

block是让GPT帮忙写的

class Block {
    shape: number[][];
    gx: number;
    gy: number;

    constructor() {
        // 随机生成方块形状和颜色
        const shapes = [
            [[1, 1], [2, 2]],
            [[1, 0], [2, 2], [0, 1]],
            [[0, 1, 2], [2, 1, 0]],
            [[1, 2, 2], [0, 1, 0]],
            [[1, 0, 0], [2, 2, 1]],
        ];
        this.shape = shapes[Math.floor(Math.random() * shapes.length)];
        // 放到网格的顶部居中位置
        this.gx = Math.floor(COLS / 2) - Math.floor(this.shape[0].length / 2);
        this.gy = 0;
    }

    // 方块旋转
    rotate() {
        const newShape = [];
        for (let i = 0; i < this.shape[0].length; i++) {
            newShape[i] = [];
            for (let j = 0; j < this.shape.length; j++) {
                newShape[i][j] = this.shape[this.shape.length - 1 - j][i];
            }
        }
        this.shape = newShape;
    }

    // 方块移动
    move(dx: number, dy: number) {
        this.gx += dx;
        this.gy += dy;
    }

}

3、方块的移动(这里只写了左移)


    static blockToLeft() {
        const comp = ooxh.game.entity.getComponent(BattleGridComp);
        if (comp && comp.activeBlock) {
            console.log('blockToLeft')
            this.clearOwnGrid(comp)
            let _is_can_move = BattleGridSystem.canMove(comp, comp.activeBlock, 1, 0)
            if (_is_can_move) {
                comp.activeBlock.move(1, 0)
                this.blockToGrid(comp, comp.activeBlock)
            } else {
                console.error('can`t blockToLeft')
                comp.gridData = [].concat(comp.tmpGridData) // 恢复成原先的
                console.log('恢复成原先的', [].concat(comp.gridData))
            }

        }
    }

4、方块的出击

    static checkAndMove(comp) {
        let _is_can_move = BattleGridSystem.canMove(comp, comp.activeBlock, 0, 1)
        console.log('_is_can_move:' + _is_can_move)
        if (_is_can_move) {
            comp.activeBlock.move(0, 1);
            console.log('block.move(0, 1)')
            this.checkAndMove(comp)
        } else {
            console.log('stop at x:' + comp.activeBlock.x + ' y:' + comp.activeBlock.y)
            this.blockToGrid(comp, comp.activeBlock)
            console.log("zz场景=============");
            if (BattleGridSystem.needChuQiao(comp)) {
                console.error("达到临界,出鞘!")
                return
            }
            console.log(comp.gridData);
            comp.activeBlock = null
            setTimeout(() => {
                comp.activeBlock = new Block()
                console.log("原始形状:");
                console.log(comp.activeBlock.shape);
            }, 1000)
        }
    }

5、查看console,看看数据效果

 嘿嘿,有点俄罗斯方块的意思了

接下来就是要把数据层的东西,在视图层给体现出来,因为战斗区域就5*7=35个,为了重复利用就一次性生成好。

    static initGrid(entity: Entity) {
        let _block_prefab = resources.get("prefabs/battle/blockItem", Prefab)
        const comp = entity.getComponent(BattleGridComp);
        if (comp) {
            for (let i = 0; i < ROWS; i++) {
                comp.gridData[i] = [];
                for (let j = 0; j < COLS; j++) {
                    comp.gridData[i][j] = 0;
                    // 记录到原始坐标里面
                    let v3pos = v3(200 - (j * 100), -600 + (i * 100), 0)
                    comp.posMap.set(i + '_' + j, v3pos)
                    // 记录到节点坐标里面
                    let _node = instantiate(_block_prefab);
                    _node.setPosition(v3pos)
                    _node.active = false
                    ooxh.game.gridsNode.addChild(_node);
                    comp.nodeMap.set(i + '_' + j, _node)
                }
            }
        }
    }

每次移动时,先用原先的缓动tween移动过去,完成后隐藏,回到原始位置

    static tweenMoveBlock(comp, move_y, callback) {
        let _s_num = 4;
        for (let i = 0; i < 3; i++) {
            for (let j = 0; j < COLS; j++) {
                let _node = comp.nodeMap.get(i + '_' + j)
                if (_node) {
                    tween(_node).to(0.3, {
                        position: v3(_node.position.x, _node.position.y + move_y * 100, _node.position.z)
                    }, { easing: easing.sineOut })
                        .call(() => {
                            // 隐藏,恢复到原位置
                            _node.active = false
                            _node.setPosition(comp.posMap.get(i + '_' + j))
                            _s_num--
                            if (_s_num == 0) {
                                callback && callback() // 全部完成回调
                            }
                        }).start();
                }
            }
        }
    }

接着加个伤害(暂时先隐藏)

    static attackUnits(comp) {
        // 转
        let tmp_map = new Map();
        for (let [key, _node] of comp.nodeMap.entries()) {
            if (_node.active) {
                let spacePos = NodeUtil.calculateASpaceToBSpacePos(_node.parent, ooxh.game.mapsNode, _node.position)
                tmp_map.set(spacePos.x + '_' + spacePos.y, _node)
            }
        }
        let unitMap = ooxh.game.entity.getComponent(BattleStateComp).unitMap
        for (let [key, _node] of unitMap.entries()) {
            let _at_grid_node: Node = tmp_map.get(_node.position.x + '_' + _node.position.y)
            if (_at_grid_node) {
                _node.active = false
            }
        }
        this.clearBlock(comp)
        tmp_map = null
    }

测试效果

后续还需完善触控和单位显示生命点数

下一个开发计划

 添加特效及额外打击特效

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值