#打卡不停更# 简单的JS鸿蒙小游戏——飞行棋之游戏逻辑

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#打卡不停更# 简单的JS鸿蒙小游戏——飞行棋之游戏逻辑相关的知识,希望对你有一定的参考价值。

前言

我们之前完成了游戏的基本布局,今天我们接着来讲下如何实现飞行棋的游戏逻辑。

游戏逻辑

  • 掷骰子:随机地掷出点数1~6,根据骰子点数和当前阵营的棋子状态改变对应棋子的disabled属性,以控制该棋子是否可交互移动,若无符合交互条件的棋子可操作则进行回合轮替。
todice() 
    this.dice_dab = true;
    this.dice_num = Math.floor(Math.random()*6+1);
    switch(this.dice_num) 
        case 1:
            this.dice_pic = "point1";
            break;
        case 2:
            this.dice_pic = "point2";
            break;
        case 3:
            this.dice_pic = "point3";
            break;
        case 4:
            this.dice_pic = "point4";
            break;
        case 5:
            this.dice_pic = "point5";
            break;
        case 6:
            this.dice_pic = "point6";
            break;
        default:
            console.log("骰子意外出错");
            break;
    
    // 骰子点数小于6,若有飞行状态的棋子可点击,该回合可操作,否则回合轮替
    if(6 > this.dice_num) 
        var operable = false;
        for(var i=0; i<4; i++) 
            if("flying" == thetype[i].type) 
                thetype[i].chess_dab = false;
                operable = true;
            
        
        if(false == operable) 
            this.rotate();
        
        else 
    
    // 骰子点数为6,除已到达的棋子都可点击
    else 
        for(var i=0; i<4; i++) 
            if("arrive" != thetype[i].type) 
                thetype[i].chess_dab = false;
            
        
    
,
  • 选择棋子:玩家选择可移动的棋子行动,根据棋子状态移动棋子。若棋子还未“起飞”,则移动到起点;若棋子已经行走在航线上,则移动与骰子点数对应的步数,若超过终点则回退多余步数。
// 选中棋子行动
appoint(thecamp, num) 
    for(var i=0; i<4; i++) 
        thecamp[i].chess_dab = true;
    
    // 若该棋子已进入航线
    if(null != thecamp[num].step) 
        for(var t=0; t<MapData[Route[this.theround%4][thecamp[num].step]].chess.length; t++) 
            if(thecamp[num].index == MapData[Route[this.theround%4][thecamp[num].step]].chess[t].index) 
                MapData[Route[this.theround%4][thecamp[num].step]].chess.splice(t, 1);
                break;
            
        
    
    // 如果该棋子处于待机状态,进入起点,最后结束
    if("wait" == thecamp[num].type) 
        MapData[thecamp[num].index].chess.pop();
        thecamp[num].step = 0;
        thecamp[num].type = "flying";
        thecamp[num].x = MapData[Route[this.theround%4][thecamp[num].step]].x;
        thecamp[num].y = MapData[Route[this.theround%4][thecamp[num].step]].y;
        thecamp[num].angle = MapData[Route[this.theround%4][thecamp[num].step]].angle;
        MapData[Route[this.theround%4][thecamp[num].step]].chess.push(thecamp[num]);
        this.dice_num = 0;
        this.dice_dab = false;
        this.dice_pic = "dice";
        return;
    
    temp = this.dice_num;
    // 若走不到终点
    if(56 >= (thecamp[num].step + this.dice_num)) 
        forward = temp;
    
    // 超过终点,回退几步
    else 
        forward = 56 - thecamp[num].step;
        backward = temp - forward;
    
    // 0.5秒执行一次走棋方法
    onestep = setInterval(()=> 
        this.move(thecamp[num]);
    , 500);
,
  • 棋子移动:重复定时器执行棋子移动方法,一步一步走完后确认落点,先后进行是否触发踩棋子判定或位移判定,之后再进行回合轮替。当有棋子行至终点时更新左侧的飞行进度,若其中三名玩家完成游戏则游戏结束,弹出排行榜,未完成的一方为最后一名。

// 移动棋子
move(thechess) 
    // 若前进步数为0,且需要后退
    if((0 == forward) && (0 != backward)) 
        thechess.step -= 1;
        backward --;
    
    // 若需要前进
    if(forward != 0) 
        thechess.step += 1;
        forward --;
    
    thechess.x = MapData[Route[this.theround%4][thechess.step]].x;
    thechess.y = MapData[Route[this.theround%4][thechess.step]].y;
    thechess.angle = MapData[Route[this.theround%4][thechess.step]].angle;
    temp -= 1;

    // 若步数走完
    if(0 == temp) 
        clearInterval(onestep);
        forward = 0;
        backward = 0;
        this.complex(thechess);     // 踩棋子判断
        this.getjump(thechess);     // 位移判断

        // 向棋子当前落点写入棋子信息
        ruzhan = setTimeout(()=> 
            MapData[Route[this.theround%4][thechess.step]].chess.push(thechess);
        , 1200);

        // 延迟后进行回合轮替
        changeturn = setTimeout(()=> 
            // 若该棋子到达终点,更新进度
            if(56 == thechess.step) 
                thechess.type = "arrive";
                this.flylog[this.theround%4].progress += 1;

                // 若该棋子走完后刚好全部到达,计入排行榜
                if(4 == this.flylog[this.theround%4].progress) 
                    this.allrank.push(
                        
                            rank: this.allrank.length + 1,
                            chess: this.flylog[this.theround%4].camp,
                            round: "用时" + this.theround + "回合",
                        
                    )
                    if(3 == this.allrank.length) 
                        for(var i=0; i<4; i++) 
                            if(this.flylog[i].progress < 4) 
                                var chesstemp = this.flylog[i].camp;
                            
                        
                        this.allrank.push(
                            
                                rank: this.allrank.length + 1,
                                chess: chesstemp,
                                round: "未完成",
                            
                        )
                        this.dice_dab = true;
                        this.result = true;
                        return;
                    
                
            
            this.rotate();
        , 1500);
    
,
  • 踩棋事件判定:当棋子落点处已有其它棋子时判断是否异色,若为同方阵营的棋子则共处一格;若为其它阵营的棋子则会被击落回到起点。

// 落点是否有棋子
complex(thechess) 
    if(52 > MapData[Route[this.theround%4][thechess.step]].index) 
        if(0 != MapData[Route[this.theround%4][thechess.step]].chess.length) 
            // 我方棋子
            if(thechess.color == MapData[Route[this.theround%4][thechess.step]].chess[0].color) 
            
            // 敌方棋子,踩回起点
            else 
                for(var i=0; i<MapData[Route[this.theround%4][thechess.step]].chess.length; i++) 
                    MapData[Route[this.theround%4][thechess.step]].chess[i].type = "wait";
                    MapData[Route[this.theround%4][thechess.step]].chess[i].step = null;
                    MapData[Route[this.theround%4][thechess.step]].chess[i].x =
                    MapData[MapData[Route[this.theround%4][thechess.step]].chess[i].index].x;
                    MapData[Route[this.theround%4][thechess.step]].chess[i].y =
                    MapData[MapData[Route[this.theround%4][thechess.step]].chess[i].index].y;
                    MapData[Route[this.theround%4][thechess.step]].chess[i].angle =
                    MapData[MapData[Route[this.theround%4][thechess.step]].chess[i].index].angle;
                    this.flylog[this.theround%4].hit += 1;
                
                MapData[Route[this.theround%4][thechess.step]].chess.splice(0, MapData[Route[this.theround%4][thechess.step]].chess.length);
            
        
    
,
  • 位移事件判定:若棋子与落点处棋格颜色相同,则触发跳跃移动到下一个同色棋格位置,接着再进行一次踩棋事件判定。

// 判断触发位移
getjump(thechess) 
    // 在进入最后的直航线前的转角前都有可能触发位移
    if(46 >= thechess.step) 
        if(thechess.color == MapData[Route[this.theround%4][thechess.step]].color) 
            if(18 == thechess.step) 
                thechess.step += 12;
            
            else 
                thechess.step += 4;
            
            jump1 = setTimeout(()=> 
                thechess.x = MapData[Route[this.theround%4][thechess.step]].x;
                thechess.y = MapData[Route[this.theround%4][thechess.step]].y;
                thechess.angle = MapData[Route[this.theround%4][thechess.step]].angle;
                // 第二次踩棋子
                this.complex(thechess);
                if(18 == thechess.step) 
                    jump2 = setTimeout(()=> 
                        thechess.step += 12;
                        thechess.x = MapData[Route[this.theround%4][thechess.step]].x;
                        thechess.y = MapData[Route[this.theround%4][thechess.step]].y;
                        thechess.angle = MapData[Route[this.theround%4][thechess.step]].angle;
                        // 第三次踩棋子
                        this.complex(thechess);
                    , 500);
                
            , 500);
        
    
,
  • 回合轮替:以回合数%4的方式进行回合轮替,若玩家掷出点数6则追加一次掷骰子机会。
// 回合轮替
rotate() 
    // 刚刚是否投出6,是则再来一次,否则回合数加一,进行轮替
    if(6 == this.dice_num) 
        if(4 == this.flylog[this.theround%4].progress) 
            this.theround += 1;
        
    
    else 
        this.theround += 1;
    
    this.dice_num = 0;
    this.dice_pic = "dice";
    this.dice_dab = false;

    switch(this.theround % 4) 
        case 0:     // 红的回合
            thetype = this.RED;
            this.roundtitle = "红色方的回合";
            break;
        case 1:     // 绿的回合
            thetype = this.GREEN;
            this.roundtitle = "绿色方的回合";
            break;
        case 2:     // 黄的回合
            thetype = this.YELLOW;
            this.roundtitle = "黄色方的回合";
            break;
        case 3:     // 蓝的回合
            thetype = this.BLUE;
            this.roundtitle = "蓝色方的回合";
            break;
        default:
            console.log("意外出错");
            break;
    

    // 若该颜色的4枚棋子都已到达终点,直接进行回合轮替
    var win = 0;
    for(var i=0; i<4; i++) 
        if("arrive" == thetype[i].type) 
            win += 1;
        
    
    if(4 == win) 
        this.rotate();
    
,
  • 重新开始游戏:为了避免误触,将按钮事件设定为长按触发,长按后重置游戏各个变量为初始值。

// 重新开始游戏
restart() 
    // 重置游戏其它变量
    clearInterval(onestep);
    temp = 0;
    forward = 0;
    backward = 0;
    clearTimeout(jump1);
    clearTimeout(jump2);
    clearTimeout(ruzhan);
    clearTimeout(changeturn);
    this.roundtitle = "";
    this.theround = 0;
    this.dice_pic = "dice";
    this.dice_num = 0;
    this.dice_dab = false;
    this.result = false;

    // 重置地图
    for(var i=0; i<MapData.length; i++) 
        MapData[i].chess = [];
    

    // 重置飞行记录和排行榜
    for(var j=0; j<4; j++) 
        this.flylog[j].hit = 0;
        this.flylog[j].progress = 0;
    
    this.allrank = [];

    // 重置棋子
    for(var k=0; k<4; k++) 
        this.RED[k].type = "wait";
        this.RED[k].chess_dab = true;
        this.RED[k].step = null;
        this.RED[k].x = MapData[this.RED[k].index].x;
        this.RED[k].y = MapData[this.RED[k].index].y;
        this.RED[k].angle = MapData[this.RED[k].index].angle;

        this.GREEN[k].type = "wait";
        this.GREEN[k].chess_dab = true;
        this.GREEN[k].step = null;
        this.GREEN[k].x = MapData[this.GREEN[k].index].x;
        this.GREEN[k].y = MapData[this.GREEN[k].index].y;
        this.GREEN[k].angle = MapData[this.GREEN[k].index].angle;

        this.YELLOW[k].type = "wait";
        this.YELLOW[k].chess_dab = true;
        this.YELLOW[k].step = null;
        this.YELLOW[k].x = MapData[this.YELLOW[k].index].x;
        this.YELLOW[k].y = MapData[this.YELLOW[k].index].y;
        this.YELLOW[k].angle = MapData[this.YELLOW[k].index].angle;

        this.BLUE[k].type = "wait";
        this.BLUE[k].chess_dab = true;
        this.BLUE[k].step = null;
        this.BLUE[k].x = MapData[this.BLUE[k].index].x;
        this.BLUE[k].y = MapData[this.BLUE[k].index].y;
        this.BLUE[k].angle = MapData[this.BLUE[k].index].angle;
    

    // 棋子归位
    for(var l=0; l<4; l++) 
        MapData[77+l].chess.push(this.RED[l]);
        MapData[82+l].chess.push(this.GREEN[l]);
        MapData[87+l].chess.push(this.YELLOW[l]);
        MapData[92+l].chess.push(this.BLUE[l]);
    

    // 默认红色先手
    thetype = this.RED;
    this.roundtitle = "红色方的回合";
,

结语

至此,飞行棋小游戏项目开发完毕,希望大家能从游戏中理清逻辑,学到需要的知识。

<br>项目仓库链接 https://gitee.com/zhan-weisong/flight-chess

附件链接:https://ost.51cto.com/resource/2365

本文作者:Looker_song

想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com/#bkwz​

以上是关于#打卡不停更# 简单的JS鸿蒙小游戏——飞行棋之游戏逻辑的主要内容,如果未能解决你的问题,请参考以下文章

简单的JS鸿蒙小游戏——垃圾分类(上)

简单的JS鸿蒙小游戏——垃圾分类(下)

简单的JS鸿蒙小游戏——拼图(冬奥一起拼)

#打卡不停更# HarmonyOS - 基于ArkUI(JS)实现虚拟摇杆组件

#打卡不停更# HarmonyOS - 基于ArkUI(ETS) 实现心电图组件

#打卡不停更#三方库移植之NAPI开发[2]C/C++与JS的数据类型转换