• 微信小程序 | 游戏开发之接宝石箱子游戏


    1、什么是微信小游戏

    微信小游戏是小程序的一个类目,小游戏是微信开放给小程序的更多的能力,让小程序开发者有了开发游戏的能力。微信小游戏是在小程序的基础上添加了游戏库API。微信小游戏只能运行在小程序环境中,微信小游戏没有小程序中WXSS、WXML、多页面等内容,所以微信小游戏开发时小程序的组件就无法使用;但增加了一些渲染、文件系统以及后台多线程的功能。

    小游戏提供了CommonJS风格的模块API,可以将一些公共的代码抽离成为一个单独的JS文件,作为一个模块。可以通过module.exports或者exports导出模块,通过require引入模块。

    2、接宝石箱子游戏

    接宝石箱子小游戏运行后底部出现主角工人,屏幕上方不断掉落宝石箱子,主角工人每接住一个箱子积分增加1分,玩家通过触碰屏幕左侧或者右侧控制工人移动方向。本游戏运行界面如图1所示。

     

     ■ 图1  接宝石箱子小游戏运行效果

    1. // common.js
    2. function sayHello(name) {
    3. console.log('Hello' + name + '!')
    4. }
    5. function sayGoodbye(name) {
    6. console.log('Goodbye'+ name+'!')
    7. }
    8. module.exports.sayHello = sayHello //提供对外的接口
    9. module.exports.sayGoodbye = sayGoodbye //提供对外的接口

     在game.js中require common.js,就可以调用common模块导出的接口。所有输出接口都会成为输入对象的属性。

    1. var common = require('./js/libs/common.js')
    2. common.sayHello('xmj')
    3. common.sayGoodbye('xmj')

    在模块化时,也可以使用export default命令和import命令。

    使用import命令是用户需要知道所加载的变量或者函数名,否则无法加载,为了方便用户,使其不用预先知道就能加载模块,这是可以使用export default为模块指定默认输出。

    1. // common2.js
    2. export default function test() { //当然也可以是一个类
    3. console.log("大家好");
    4. };

     导入时可以如下:

    1. import t from './js/libs/common2.js'
    2. t('xmj')

     这时使用import导入时可以使用任意名称指定模块js文件的导出方法test()。本质上export default就是输出一个叫做Default的方法,只是系统容许为它任意取名。微信小游戏支持ES6,所以开发时可以使用export default class定义各种类模块,例如Bullet子弹类,Sprite精灵类,Enemy敌人类模块,使用import导入类模块。

    1. import Player from './player/index'
    2. import Enemy from './npc/enemy'

     小游戏并不能调用所有小程序的API,但是能调用到大部分的API。例如像wx.request,wx.chooseImage,wx.showToast等API,小游戏都可以调用到。更详细的API能力见微信官方API文档。

    03、程序设计的步骤

    使用微信开发者工具新建项目,左侧类别选择小游戏,右侧的项目名称输入“接宝石箱子游戏”,单击“新建”按钮,就新建一个新的小游戏。

    在图2界面中的中间部分,为文件结构区域。右键文件结构区域上方+号,下拉菜单中选择“目录”,建立文件夹test/images结构,放入相关游戏图片(箱子,工人)。

     ■ 图2  放入相关游戏图片

    准备工作完成后,修改game.js文件。本游戏不使用Adapter(适配器),使用微信wx API自行开发。

    1. /*import './js/libs/weapp-adapter'
    2. import './js/libs/symbol'
    3. import Main from './js/main'
    4. new Main()
    5. */
    6. const DROP_SPEED = 8 //箱子下移速度
    7. const MOVE_SPEED = 4 //人物左右移速度
    8. const canvas = wx.createCanvas()
    9. const context = canvas.getContext('2d')
    10. context.fillStyle = "#ffff00"
    11. context.font = "40px Arial"

     加载工人图片,并设置设置位置坐标(imgX,imgY)。

    1. const image = wx.createImage() //人物图片
    2. let imgX = canvas.width / 2 - 18 //人物位置
    3. let imgY = canvas.height - 80
    4. image.onload = function () {
    5. context.drawImage(image, imgX, imgY)
    6. }
    7. image.src = 'test/images/player.png'

     drawRect(x, y)函数清空屏幕,重绘宝石箱子、人物和积分文字。

    1. let score = 0
    2. const { windowWidth, windowHeight } = wx.getSystemInfoSync() //屏幕宽度和高度
    3. function drawRect(x, y) {
    4. context.clearRect(0, 0, windowWidth, windowHeight) //重绘清空屏幕
    5. context.drawImage(boxImage, x, y) //画宝石箱子
    6. context.drawImage(image, imgX, imgY) //画人物
    7. context.fillText("积分" + score, 30, 50) //绘制积分文字
    8. }

     设置宝石箱子坐标初始位置(imgX,imgY)为屏幕顶端中央。调用box(rectX, rectY)在指定位置(rectX, rectY)绘制箱子。

    1. let rectX = canvas.width / 230 //宝石箱子坐标
    2. let rectY = 0
    3. const boxImage = wx.createImage() //宝石箱子图片
    4. box(rectX, rectY) //调用box((rectX, rectY)在指定位置(rectX, rectY)绘制箱子
    5. function box(x, y) {
    6. // Math.ceil(); 只要有小数总是向上取整数; 例如Math.ceil(1.1) 输出为2
    7. let number = Math.ceil(Math.random() * 7) //随机产生1-7数字
    8. let box_src = 'test/images/box' + number + '.png'
    9. boxImage.onload = function () {
    10. context.drawImage(boxImage, x, y)
    11. }
    12. boxImage.src = box_src
    13. }

     以下触摸(碰)事件处理。判断触碰位置在人物的左侧则移动方向direction值为-1,这样x坐标可以不断减少。触碰位置在人物的右侧则移动方向direction值为1,这样x坐标可以不断增加。

    1. var direction = 0
    2. var touchX = imgX
    3. var touchY = imgY
    4. wx.onTouchStart(function (res) {//触碰事件
    5. touchX = res.changedTouches[0].clientX - 18
    6. if (touchX < imgX) { //触碰位置在人物的左侧
    7. direction = -1 //向左移动
    8. console.log("left")
    9. } else { //触碰位置在人物的右侧
    10. direction = 1 //向右移动
    11. console.log("right")
    12. }
    13. })

    loop()是用来实现游戏帧循环达到动画效果。首先判断工人达到屏幕两侧边界,如果判断工人的位置到达屏幕最左侧,则改向右;到达屏幕最右侧,则改向左。箱子Y坐标不断,显示出下落效果,工人位置坐标根据移动方向不断修改,同时重新绘制箱子,工人,积分。

    如果箱子到达底部区域,则判断与工人之间距离,如果小于50则认为碰撞(就是工人接到宝石箱子),进行加分处理。如果箱子出了屏幕底部,重新设置箱子图片并设置位于顶部。最后调用requestAnimationFrame(loop);起到循环渲染效果。

    1. function loop() {
    2. if (imgX <= 10) { //人物位置到达屏幕最左侧,改向右
    3. direction = 1
    4. } else if (imgX >= canvas.width - 50) {//人物位置到达屏幕最右侧,改向左
    5. direction = -1
    6. }
    7. rectY += DROP_SPEED //箱子下移DROP_SPEED
    8. imgX += direction * MOVE_SPEED //改变人物位置坐标
    9. drawRect(rectX, rectY) //重新绘制箱子,人物,积分
    10. if (rectY > canvas.height - 100 && rectY <= canvas.height) {//达到底部
    11. let range = Math.abs(rectX - imgX) //与人物之间距离
    12. if (range <= 50) { //检测碰撞
    13. rectY = canvas.height
    14. score++ //加分
    15. }
    16. }
    17. if (rectY > canvas.height) {
    18. rectY = 0
    19. let spwanX = Math.floor(Math.random() * (canvas.width - 80))
    20. box(spwanX, rectY) //重新设置箱子位于顶部
    21. rectX = spwanX
    22. }
    23. requestAnimationFrame(loop); //循环渲染
    24. }
    25. loop()

     

  • 相关阅读:
    2022下半年各省软考报名费用汇总,不知道的看这里
    Re61:读论文 PRP Get an A in Math: Progressive Rectification Prompting
    dubbo泛化调用之消费者传递JavaBean
    我又造了个轮子:GrpcGateway
    指向指针的指针pp指向指针p
    2022年Java学习笔记目录
    Android学习笔记 70. 学会帮助自己【自理】
    Spring Boot 事务详解
    logstash和elasticsearch的几种交互接口
    QT常用的控件总结
  • 原文地址:https://blog.csdn.net/qq_41640218/article/details/126826168