微信小程序学习之改版雷电

 

博客班级 https://edu.cnblogs.com/campus/zjcsxy/SE2020
作业要求 https://edu.cnblogs.com/campus/zjcsxy/SE2020/homework/11334
作业目标  1.编写一个小程序,可以全新编写,也可以学习别人的小程序进行修改 2.熟悉git代码管理流程,将源代码上传到到github3.在博客园班级中写一篇相应的博文
作业源代码  https://github.com/Sklud1456/wx-xcx-Raiden
学号  31803224
 院系

 浙大城市学院计算机专业

班级姓名

计算机1803 沈科迪

  • 前言

  第一次学习做小程序,难免有些畏惧和困难,但好在计算机是一个开放的世界,在互联网上有着前辈们无数的经验和总结,而这些经验和知识让我感觉自己不是一个人在奋斗,而他们的经验也大大加快我学习的步伐。

  因为自己没有js和web方面的知识,从零开始的学习难免有些缓慢,于是我选择一边打基础一边直接阅读成体系的小程序demo来加强和巩固自己的知识。于是我在git上搜索了一份自己较为喜欢的代码,一遍遍的去尝试,一行行的阅读,然后慢慢地分析代码在整体小程序中所起的作用,然后根据他的缺陷设计并增加一定的功能,在学习的同时实践,这也让我对微信小程序的开发有了更深的认识。而我也是初学者,这篇博文也是把我学到的一些小知识分享给大家,希望能一起进步。

  • 使用工具为微信开发者工具。
  • 本次小程序在学习并理解了https://github.com/qutz/we_plain的代码,并以此为基础进行改进。
  • 界面展示

           开始界面                   加载界面               

    

 

        游戏界面                        结算界面                       

    

          排行榜界面

  • 文件结构及具体代码分析
  • 总体结构和逻辑

上图是文件的总体结构:

  images作为素材库提供图片素材

  lib是游戏性方面的主要逻辑文件

  pages是一些其他页面的跳转

  util中有一些数据

  其他则是一些基础的配置文件,接下来我们挑选一部分文件对该小程序进行有主次的分析

  • wxplain.js

  因为作为一个小游戏的小程序,不需要有太多的页面用来跳转或满足需求,用户大部分的时间仅仅花费在那个游戏界面,而游戏界面就不可能是静态的,需要交互和大量的逻辑规则,于是我们这个小程序的核心就十分的明显了,作为我们逻辑的关键,wxplain.js是该小程序的重中之重,同时也是我学习的最多,收获的最多的一个文件。

  作为一个小游戏,最重要的两个方面就是交互行动反馈,而且这些都是即时的,所以需要着重设计。

  •   交互行动:

  雷电类型的游戏交互行动十分的简单,就仅仅的手指拖动飞机进行躲避,所以运用了微信小程序自带的API,touchmove来监听手指的移动,并通过重新画玩家的飞机来实现移动。代码如下:

flyGame.prototype.touchmove = function( x, y ) {
   this.game.player.move( x, y );
}
player.move = function( x, y ) {
        player.lastX = player.x;
        player.lastY = player.y;
        player.x = x - player.width / 2;
        player.y = y - player.height / 2;
        player.x = player.x > c_width - player.width ? c_width - player.width : player.x;
        player.x = player.x < 0 ? 0 : player.x;
        player.y = player.y > c_height - player.height ? c_height - player.height : player.y;
        player.y = player.y < 0 ? 0 : player.y;
    }
    player.moveing = function() {
        if( !player.status ) {
            return;
        }
        cxt.drawImage( game.time % 30 > 15 ? player.model.src : player.model2.src, player.x, player.y, player.width, player.height );
        player.attacking();
    }

  不过这个demo在其基础上多了一个新的交互,使用炸弹,实现比较简单,监听到使用炸弹后就让屏幕里现存的敌方飞机全部坠毁。代码如下:

 player.useBomb = function() {
        if( game.player.bomb <= 0 ) {
            return;
        }
        game.player.bomb--;
        //playAudio( "use_bomb.mp3" );
        var plains_length = game.plains.length;
        for( var i = plains_length;i--; ) {
            var plain = game.plains[ i ];
            plain.die();
        }
    }
flyGame.prototype.touchclick = function() {
    this.game.player.useBomb();
}

 

  •  反馈:

  在玩家进行交互行动前,得先获取一部分的信息用来告知玩家怎么做,这些信息的获取在我看来属于静态的、客观的部分的反馈,而雷电类游戏的基本信息获取就是敌方飞机的到来,这种功能的实现比较简单,也是根据时间的推进不断的重画飞行单位即可,而不断重画背景部分也可使玩家更直观的感受到敌方单位的到来和自己的前进,虽然代码比较简单,但这是该游戏的基础。代码如下:

game.bgScroll = function() {

        var bg_img_height = game.bgImg.height;
        var bg_img_width = game.bgImg.width;
        game.bgScrollTime += 0.5;
        game.rltime+=0.1;
        if( game.bgScrollTime > bg_img_height ) {
            game.bgScrollTime = 0;
        }
        cxt.drawImage( game.bgImg.src, 0, game.bgScrollTime - bg_img_height, bg_img_width, bg_img_height );
        cxt.drawImage( game.bgImg.src, 0, game.bgScrollTime, bg_img_width, bg_img_height );
        cxt.drawImage(game.rlImg.src,0,320,50,150);
        cxt.drawImage(game.jtImg.src,50,game.rltime,30,20);
  
    }//背景的滚动


game.plainsScroll = function() {
        game.addPlain();
        var removePlain = [];
        var plains_length = game.plains.length;
        for( var i = plains_length;i--; ) {
            var plain = game.plains[ i ];
            if( plain.y > c_height || plain.status == false ) {
                game.plains.splice( i, 1 );
                continue;
            }

            plain.show();

            if( isCollide( plain ) ) {
                plain.die();
                game.life--;
                if(game.life<=0){
                    game.player.die();
                }
                
            }

            plain.y = plain.y + plain.speed;
        }//敌方飞机的前进

  在客观类型的反馈之外,最主要的当然是由玩家行动交互所引起的主观类型的反馈,雷电类型的游戏,主观的反馈只有两个,一个是敌方飞机被自己击毁,一个则是自己被击毁。

  敌方坠机:每个敌方飞机都有一定的生命值,当生命值被玩家击至零点及以下则直接坠毁,代码如下:

 

this.byAttack = function() {
            this.hp--;
            if( this.hp <= 0 ) {
                this.die();//这里就不展示了,就是在坠毁点依次重画飞机坠毁的画面
                return;
            }

            if( this.hp <= hp / 3 ) {
                this.model = flyimages[ "plain" + this.type + "_hurt" ];//有一部分的战损飞机的素材,使得反馈更加丰富,美工方面更加细致
            }
        }

  我方坠机:当触碰到敌方飞机时则直接坠毁,碰撞函数的实现比较易懂,因为玩家是一个方块形的图片,直接截取四角坐标,和现存的敌方飞机的边界依次比较即可,这一部分代码被集成在了敌方飞机的滚动函数中,就在上方,就不展示了,展示一下碰撞函数。代码如下:

 function isCollide( plain ) {
            var plainTopLeft = [ plain.x, plain.y ];
            var plainBottomRight = [ plain.x + plain.width, plain.y + plain.height ];
            var meTopLeft = [ game.player.x + game.player.width / 3, game.player.y ];
            var meBottomRight = [ game.player.x + ( game.player.width * 2 / 3 ), game.player.y + ( game.player.height * 2 / 3 ) ];

            var collideTopLeft = [ Math.max( plainTopLeft[ 0 ], meTopLeft[ 0 ] ), Math.max( plainTopLeft[ 1 ], meTopLeft[ 1 ] ) ];
            var collideBottomRight = [ Math.min( plainBottomRight[ 0 ], meBottomRight[ 0 ] ), Math.min( plainBottomRight[ 1 ], meBottomRight[ 1 ] ) ];

            if( collideTopLeft[ 0 ] < collideBottomRight[ 0 ] && collideTopLeft[ 1 ] < collideBottomRight[ 1 ] ) {
                return true;
            }

            return false;
        }
    }

  当然这个demo也加了一个新的反馈,就是拾取一些特殊道具的反馈,比如子弹变多或者可以使用炸弹。生成道具时通过random随机生成,并通过不断重画实现下坠效果,在通过类似碰撞检测实现获得道具的判断,这些代码逻辑比较简单,就不一 一展示了。

  • plain.js

  如果说wxplain.js是该小程序的内核,那么plain.js就是外面的外壳,将数据传入,同时也把最后的分数显示并且承担页面跳转的中枢。具体代码如下:

const WxFly = require('../../lib/wxplain.js');

Page({
    data: {
        modalHidden: "modal_hide",
        score: '0'
    },
    onLoad: function (options) {
        // 页面初始化 options为页面跳转所带来的参数
    },
    onReady: function () {
        // 页面渲染完成
    },
    startGame: function () {
        const fly = this.fly;
        this.setData({ score: 0, modalHidden: "modal_hide" }); //初始化
        fly.startGame();
    },

    move: function (event) {
        const fly = this.fly;
        var x = event.touches[0].x;
        var y = event.touches[0].y;
        fly.touchmove(x, y);  //传入手指的坐标
    },
    click: function () {
        const fly = this.fly;
        fly.touchclick();  //点击事件
    },
    onShow: function () {
        const fly = this.fly = new WxFly(
            {
                ctx: wx.createContext(),
                id: 'plainId',
                height: 625,
                width: 375,
            });
        fly.on('over', packet => {
            this.setData({ score: packet.score, modalHidden: "" });
        });
    },
    onHide: function () {
        // 页面隐藏
    },
    onUnload: function () {
        // 页面关闭
    }
})
  • plain.wxml,plain.wxss

  虽然小游戏注重的是游戏性的交互,但良好的UI界面也是提升用户体验的不二之选,而wxml和wxss的搭配可以使得界面更加的个性,多样化。这里只放一下wxml的代码

<view>
    <canvas canvas-id="plainId" class="canvas" bindtap="click" bindtouchmove="move"></canvas>
    <view id="modal" class="modal {{modalHidden}}">
        <view class="header">飞机大战分数</view>
        <view class="content" id="content">{{score}}</view>
            <button bindtap="checkphb">排 行 榜</button>
        <view class="footer">
            <button bindtap="startGame">继 续</button>
        </view>
    </view>
</view>
  • 新的改动

  在改动的方面,我主要将其分为两方面,游戏性的提升和游戏之外交互的提升。

  • 游戏性改动

  1.生命值

  

  在我体验demo的时候,抛去一些手感之类的主观性因素还是发现了两个比较值得修改的点,第一就是玩家在每次游戏中只有一条命,而一些疏忽玩家很容易结束游戏,并且因为随机刷飞机的因素会导致某个时刻特别难逃离,所以我增加了生命值的概念,玩家拥有三点生命值,在提高容错率的同时也会让玩家变得更加敢去操作,而不是畏手畏脚。

  代码实现比较简单,在玩家这里多设一个生命值属性,碰撞后先减去生命值,生命值降为0才结束游戏,同时右上角的生命值图片随着玩家生命值的减少而减少,用来提醒玩家的同时也与玩家发生交互。代码比较简单,这里就不用展示了。

   2.燃料条

  同样的,这也是我在体验demo同时发现的缺点,同样也是因为一部分随机性的原因可以使得玩家有一段时间可以苟在角落不用操作也可以活下去,这样游戏的难度就会降低,游戏性会有所下降,所以我增加了燃料条这一机制,初始有一定燃料,飞行需要消耗燃料,燃料用完直接游戏结束,只有通过击杀敌方的飞机才能补充自己的燃料。这一机制的增加可以提高玩家的目标性和紧迫感,和地铁跑酷中那个跟在你后面的胖警察一个道理,这样因为生命值增加而减少的难度又因为燃料条的存在重新提升回去了,同时也可通过调整这一数值来调节难度,实现梯度难度的关卡。

  代码实现也比较简单,同样多设置一个燃料属性,这一属性随着时间推移逐步减少,并在你击毁敌机后获得一部分燃料,我为了方便计算,将箭头的位置与燃料值绑定,以燃料条的长度作为范围,超出即直接游戏结束。这样即实现了燃料的即时性反馈也实现了逻辑自洽。代码比较分散,这里也不做展示。

  • 游戏之外交互的提升

  1.开始界面的设置

  原本的加载界面加载完后游戏是直接开始的,没有反应的时间,玩家一开始就缺失了交互感,并且有一种赶鸭子上架的急迫感,这一种比较负面的反馈是不太好的,所以我增设了一个开始界面,用做缓冲,同时也给到玩家一个准备时间,同时也做出提醒。

  开始界面不需要什么逻辑语句,只有一个页面跳转函数,这里只展示一下wxml的代码

<view class='page-header'>
  <text class='page-header-title'>{{title}}</text>

  <image class='background' src="../../images/bg.jpg" mode="aspectFill"></image>
  <view class='imagesize'>
      <image src="../../images/logo.png" class='in-image'   >
      </image>
    </view>
    <view class="footer">
            <button bindtap="start">开 始</button>
        </view>

</view>

 

  2.排行榜的设置

  排行榜的设置是我比较满意的,因为在游戏性交互之外最重要的交互就是社交性的交互了,在某些网游中,社交交互的比重甚至超过了游戏本身(比如传奇),因为有了游戏就很自然的想到玩家之间的交流和竞争,不过作为一个小程序,排行榜这种简单又有效的竞争模式就十分适合。

  在小程序刚兴起的一段时间,跳一跳的分数就在微信朋友圈中刷屏可见一斑,排行榜所实现的竞争交互对玩家有着较高的吸引力。于是我就在游戏的结算界面之后新增了排行榜界面,但碍于测试版没有办法进行联网的数据读取和存储,只能先实现这个模板。

  同样的,排行榜仅仅作为一个页面,没有多少逻辑性的交互,js代码几乎没有,这里还是放一下wxml代码:

<view class='page-header'>
  <text class='page-header-title'>{{title}}</text>
  <view class="content">
    <image class='background' src="../../images/bg.jpg" mode="aspectFill"></image>
    <!--页面其它部分-->
</view>
    <view id="modal" class="modal {{modalHidden}}">
        <view class="header">排 行 榜</view>
        <view class="footer">
          <view>{{showData[0].id}}  {{showData[0].name}}  {{showData[0].score}}</view>
          <view>{{showData[1].id}} {{showData[1].name}}  {{showData[1].score}}</view>
          <view>{{showData[2].id}} {{showData[2].name}}  {{showData[2].score}}</view>
          <view>{{showData[3].id}} {{showData[3].name}}  {{showData[3].score}}</view>
          <view>{{showData[4].id}} {{showData[4].name}}  {{showData[4].score}}</view>
          
          
        </view>
    </view>
</view>

  而配套的wxss代码使得该界面更加的美观

.modal {
    width: 360px;
    height: 300px;
    top: 100px;
    left: 55%;
    margin-left: -200px;
    border: #666 solid 2px;
    border-radius: 8px;
    position: absolute;
    font-size: 20px;
    background-color: #dddddd;
    z-index: 1002;
}

.modal_hide {
    display: none;
}

.header {
    height: 45px;
    line-height: 45px;
    font-weight: bold;
    text-align: center;
    border-bottom: #666 solid 2px; 
}

.content {
    height: 210px;
    line-height: 210px;
    font-weight: bold;
    text-align: center;
}

.footer {
    height: 45px;
    line-height: 45px;
    text-align: center;
    border-top: #666 solid 2px; 
}

.footer button {
    width: 120px;
    height: 42px;
    border: #666 solid 2px;
    border-radius: 15px;
    font-size: 15px;
    font-weight: bold;
    position: absolute;
    left: 50%;
    margin-left: -60px;
    color: #333;
    cursor: pointer;
}
  • 不足之处

  1.美术素材没有配套,美术展现有割裂感

  2.界面没有适配的很好

  3.排行榜仅有本地数据,也没有后台

  • 总结和收获

    一下子接触一个从未接触过的领域,在一开始总有一些畏难心理,就仿佛走出了自己的舒适圈,一开始不知道从何开始,感觉无所适从,但我知道,在学习新知识的时候总会伴随着阵痛,但在痛过后你所得到的将会更加的多。所以我就开始静下心来慢慢地观看教学视频和一遍遍阅读代码的时候,仿佛抽丝剥茧一般,慢慢地剥开了小程序的面纱,一步步从wxml,wxss,js和各种API去理解,去运用,并尝试在前人的基础上新增属于自己的东西。这种自我学习带来的收获感给了我极大地信心,再大的困难也是由一个个小困难堆叠而成的,而我要做的就是逐步去攻克这些小困难,并最终攻克最后的BOSS。学习软件工程开发的路还是很长,我会努力地去学习,努力地去提升自己,不断完善。

posted @ 2020-10-19 09:35  Skuld1456  阅读(463)  评论(1编辑  收藏  举报