【图片消消乐】单机游戏-微信小程序项目开发入门

这篇具有很好参考价值的文章主要介绍了【图片消消乐】单机游戏-微信小程序项目开发入门。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这是一个微信小程序项目,是类似开心消消乐的休闲小游戏,老少皆宜,游戏互动里面的图片是用的任何图片素材,根据自己的需求更换图片即可。想要做游戏不知道怎么做,建议从这个小程序入手,花时间研究学习,很快就拥有属于自己的小程序。

准备

  • 会使用微信开发工具
  • 有游戏图片素材
  • 有游戏背景音效

打开微信开发工具,选择一个小程序项目,点+号新建,依次选择

创建小程序

  • 不使用云服务
  • JavaScript - 基础模板

修改项目名,点确定,就可以开始做了

页面布局

首先,开始做项目的时候,设计稿或者效果图是准备好的,这样让我们知道下一步该怎么做

效果图

来看一看效果图,要做的游戏页面是像下面这样的
【图片消消乐】单机游戏-微信小程序项目开发入门

布局

有目标,加油干!

这里做页面是用基础模板template来做的,有vue基础的就很容易完成,

在页面文件pages/game/game.wxml中的添加布局,大致如下

<view class="container">
  <view class="row">
    <view class="expand">
      <view class="row">
        <image src="{{firstImg}}" class="icon" mode="scaleToFill" />
        <view>
          <text>×{{scope}}</text>
        </view>
      </view>
    </view>
    <view class="" style="width: 28vw;">
      <view class="row">
        <image src="/static/five_oclock_3d.png" class="icon" mode="scaleToFill"/>
        <view>
          <text>{{timerNum}}s</text>
        </view>
      </view>
    </view>
  </view>
  <view class="expand">
    <view class="canvas-box">
      <canvas class="canvas" id="canv" type="2d" bindtouchstart="onTouchStart" bindtouchend="onTouchEnd"></canvas>
    </view>
  </view>
  <progress percent="{{progressPercent}}" activeColor="#38f" backgroundColor="#ccc" />
</view>

还有样式文件,这里不展开讲,自己知道怎么改样式,做成效果图一样的就好了
效果图中的弹出对话框,这是小程序系统自带的,做的时候忽略掉

以上页面的布局中,有两个部分

  • 一个画布canvas,显示游戏画面
  • 一个显示游戏状态信息,还有进度条

游戏逻辑

接下来,就写写游戏逻辑了,整理一下游戏思路,比如做一份流程图,把思路现出来

流程图

一个流程图出来了,如下所示,这下思路变清晰了吧

大纲

看一下大纲,就能知道大概的游戏逻辑吧,

游戏的相关配置如下,是可以调节的

const MatchCount = 3;//达到3个可消除
const AnimationTime = 10;//动画延迟10ms
const isShowClearLine = false;//圈出欲消除的图片
const maxTimeNum = 300;//倒计时最大值
const ColNum = 7;//列数,数字越大装得图片越多

逻辑代码,都写在一个页面文件pages/game/game.js中,方便阅读,代码如下

Page({
	/**
	 * 页面的初始数据
	 */
	data: {
	  firstImg:"",//第一个图片
	  progressPercent:100,//进度条进度
	  timerNum:maxTimeNum,//计数
	  scope:0,//消除数量
	  imgList:[],//存放游戏图片
	},
	/**
	 * 生命周期函数--监听页面加载
	 */ 
	onLoad(options){
		//...这里处理初始化
	},
	/**
	 * 生命周期函数--监听页面卸载
	 */
	onUnload() {
		//关闭定时器
		if(this.data.timer){
		  clearInterval(this.data.timer);
		}
		//销毁游戏背景音
		if(this.data.audioPlay && this.data.audioPlay.destroy){
		  this.data.audioPlay.destroy(); 
		}
	},
	onTouchStart(e){
		//...用户触摸时,会触发这个事件方法
		//就在这里处理用户选图片的逻辑
	},
	onTouchEnd(){
		//...用户不触摸时,会触发这个事件
	},
	showGameoverModal(){
		//...游戏结束,计算得分,用对话框提示
	},
	initCanvasData(canvasData){
		//...初始化画布数据,用于绘制游戏图
	},
	clearGrids(callback){
		//...处理消除逻辑,包括消除动画,处理完成后回调callback
	},
	//...剩下的方法省略
})

在方法onLoad(options)这里,写初始化逻辑,代码如下

//根据id获取到画布的节点node和大小size
wx.createSelectorQuery().select('#canv').fields({ node:true, size:true },res=>{
	const { width, height, node:canvas } = res;
	const canvasData = {
	  canvas,//画布元素(节点)
	  context: canvas.getContext('2d'),//获取画布的操作对象(上下文)
      columns: ColNum,//每行的个数,设置在6~12之间最佳
	};
	   //这是一些图片名字
	const ImageList = [
	  //...更多图片资源
	  "deer","chicken","chipmunk","cow_face","crab",
	];
	//加入微任务列表
	let taskList = ImageList.map(function(filename){
		//加载图片是异步操作的
	  return new Promise(function(resolve,reject){
	    let image = canvas.createImage();
	    //...省略更多
		//加载项目下static文件夹里面的图片资源
	    image.src=`/static/${filename}_3d.png`;
	  });
	});
	//执行微任务
	Promise.all(taskList).then(imgs=>{
		//执行到这里,微任务执行结束,就显示第一个图片
		if(!this.data.firstImg) {
          this.setData({
            firstImg:'../../'+imgs[0].src
          })
        }
        this.data.imgList = imgs;
        this.initCanvasData(canvasData);
        this.initAudioPlay();//初始化游戏音效
		//...省略更多,
		//开始执行消除处理动画的方法
		  this.clearGrids(()=>{
		    //...省略更多
		    //消除完了,开始倒计时
		    this.data.timer = setInterval(()=>{
		      let num = this.data.timerNum-1;
		      if (num<0){
		      	//倒计时结束了
		        clearInterval(this.data.timer);
		        this.data.timer = null;
		        //游戏结束,弹出对话框提示
		        this.showGameoverModal();
		        return;
		      }
		      // 更新倒计时和进度条
		      this.setData({
		        timerNum:num,
		        progressPercent:Math.trunc(num*100/maxTimeNum)
		      })
		    },1000);
		  });
	}).catch(function(err){
		//如果执行有问题,会将错误输出到控制台
	  console.error(err)
	});
	//...
}).exec();

代码中有调用的其它方法,它们不是重要的,这里不展开讲,
如果你对这个Promise感到陌生,它是处理异步(微)任务的,建议你熟悉 Promise,相信这对你很有帮助

初始化数据

在这个方法initCanvasData(canvasData)里去实现初始化,参数canvasData表示画布数据,很简单,代码如下

let padding = 1;//初始内边距
const bgColor = '#000';//背景色
const lineColor = '#ff3';//选中边框色
//获取初始化数据对象
const { canvas } = this.data.canvasData;
const { width, height } = canvas;
padding += Math.trunc((width-padding*2)%columns/2);
//根据画布宽高,算出单元格大小
const gridSize = Math.trunc((width-padding*2)/columns);
//算出有多少行
const rows = Math.trunc((height-padding*2)/gridSize);
//网格列表
const gridList = [];
for(let row=0; row<rows; row++){
  for(let col=0; col<columns; col++){
    let grid = {
      //...
    };
    //获取随机的图片(索引)
    grid.font = this.getRandomFont();
    //加入列表
    gridList.push(grid);
  }
}
//所有初始化数据放到canvasData中
Object.assign(canvasData, { bgColor, lineColor, gridList, gridSize, padding, columns, rows });
this.data.canvasData = canvasData;

其中方法getRandomFont() 是获取随机的图片,返回图片列表中的索引即可,代码如下,只写一行足矣

return Math.trunc(Math.random()*this.data.imgList.length);

重复写代码是低效率的,要这样做,将重复的代码块放进一个方法中,后面有很多地方会调用到

处理用户选图片

这应该不难吧,在这个方法onTouchStart(e)中去处理,参数e是用户触摸画布时由系统处理传入的,代码如下

//触摸时,获取第一个坐标点对象
const t = e.touches[0];
const { selectedGrid, isAnimating } = this.data;
//如果在进行动画,就直接返回,不继续执行
if(isAnimating) return;
const { context, canvas, gridList, gridSize, bgImg } = this.data.canvasData;
//获取触摸到的图片索引
let gIndex = this.getTouchGridIndex(t);
//若触摸的不是图片,就直接返回
if(gIndex<0) return;
//开始清理画布
this.clearCanvas(true);
context.drawImage(bgImg,0,0,canvas.width,canvas.height);
//选中图片,画出选中小效果
let grid = gridList[gIndex];
//获取图片的坐标
let coord = this.getGridCoordinate(grid);
context.rect(coord.left,coord.top,gridSize,gridSize);
context.stroke();
//将选中的图片存到起
let newSelectedGrid = {
  //...
};
if (selectedGrid) {
  this.data.selectedGrid = null;
  //选到了两个图片,这里开始处理切换动画
  this.startToggleAnimation(selectedGrid,newSelectedGrid);
}else{
  this.data.selectedGrid = newSelectedGrid;
}

其中,两个方法getTouchGridIndex(touch)getGridCoordinate(grid)是很容易实现的,这里不展开讲,

另一个方法 startToggleAnimation(selectedGrid,nextSelectedGrid) ,是处理切换动画效果的,实现起来有难度,这里大致讲一下,代码如下

//...
//判断选的两个图片是否可以切换
const isToggle = this.calcIsClearUp(selectedGrid,nextSelectedGrid);
let hasEq;
//...省略判断逻辑
//如果可以消除
if(hasEq){
  //...
  //设置动画进行中状态
  this.data.isAnimating=true;
  const { canvas, context, gridSize, gridList, bgImg } = this.data.canvasData;
  const { grids, direction } = hasEq;
  //...
  //动画结束方法
  const stopAnimation = () => {
    if(isToggle){
      //...
    }
    //...
    this.redrawBg(()=>{
	    //处理消除逻辑的方法
	    this.clearGrids(res=>{
	      const { count } = res;
	      if(count>0){
	      	//更新消除结果
	        this.setData({
	          scope:this.data.scope+count,
	          timerNum:maxTimeNum,
	          progressPercent:100
	        })
	      }
	    });
    });
  }
  function startAnimation(){
    this.clearCanvas(true);
    context.drawImage(bgImg,0,0,canvas.width,canvas.height);
    //...省略了开始动画逻辑
    setTimeout(startAnimation,AnimationTime*2);
  }
  //重新绘制背景的方法
  this.redrawBg((img)=>{
	 //开始动画
     startAnimation();
  });
}

代码中还用到了好几个方法,这里就不展开讲,
代码中用到了好几个箭头符号,据说这个是叫语法糖,

考虑到有的萌新小同学看不懂,这里讲一下语法糖,
箭头符号表示什么意思,看如下代码,应该能明白吧

//箭头函数
const fun1 = (args) => {
	console.log('hello')
};

//编译器把箭头函数还原
function fun1(args) {
	console.log('hello')
}

也许有同学疑问:没看出什么用途。
在一个对象实例 中,写方法(函数 )里有写了this的,就用箭头函数吧。

为方便阅读思路清晰,避免搞混,代码中用到的this,都是统一指向当前页面的实例对象

处理消除逻辑

在一个方法clearGrids(callback,count=0)里实现,这是最难的实现部分,代码如下

const { gridList, gridSize, columns, rows, padding } = this.data.canvasData;
//先扫描可以清除的网格,记录下来
let clearGridsAtCols = [];
for(let x=0; x<columns; x++){
  //...
  for(let y=rows-1; y>=0; y--){
    //...
  }
  //...
}
//如果有清除的网络
if(clearGridsAtCols.length>0) {
	//这里添加需要移动的数据
  clearGridsAtCols.forEach(item=>{
    //...
    for(let y=rows-1; y>=0; y--){
      //...
    }
  });
  const offset = 4;
  //开始动画
  const startAnimating=()=>{
    let isDownMove=false;
    //处理移动的数据,更新移动位置
    clearGridsAtCols.forEach(x=>{
      //...
    });
    //如果没有可以移动的,就结束动画
    if(!isDownMove){
    	//...  
	    this.redrawBg(()=>{
			//...  处理完,回调返回消除数量
	      if(typeof callback == 'function') callback({ count });
	    });
      return;
    }
    this.redrawBg();
    //还能向下移动的,再调用startAnimating方法
    setTimeout(startAnimating,AnimationTime);
  }
	//重新绘制一遍
  this.redrawBg();
  if(!this.data.isAnimating){
    this.data.isAnimating=true;
    this.data.audioPlay.play();//播放游戏音效
    // console.log('start autio')
  }
  startAnimating();
  return true;
}
//没有可消除的,直接返回状态
this.data.isAnimating=false;
return false;

关于项目

相关代码就讲到这了,有了上面的思路,应该能自己做出来吧,接下来是运行测试

运行效果

做好后,运行效果图如下,换个水果之类的图片,看着感觉还可以

【图片消消乐】单机游戏-微信小程序项目开发入门
为什么不用表情图片了?

有人体验后反馈,说玩久了眼睛看着会不舒服,

原因吧,是显示的图片又多又小,还有图片之间颜色相似的也多,找起来容易引起视觉疲劳,

使用表情图片大多数都是黄脸,所以颜色相似的很多,这是作为图形设计师的基本常识把,
知道了这点不足,就换了图片,看上面的感觉还好,

运行小程序项目,游戏交互效果,动图如下
【图片消消乐】单机游戏-微信小程序项目开发入门

既然能换图片,那就改名项目为图片消消乐好了文章来源地址https://www.toymoban.com/news/detail-499504.html

项目源码

  • 用到的图片素材,是参考 fluent-emoji 这里,有很多可以选几个当作游戏素材,
  • 用到的游戏背景音,也是从网上找来的,很容易找到,
  • 想看项目源代码,请前往 下载点这里 找消消乐项目源码

到了这里,关于【图片消消乐】单机游戏-微信小程序项目开发入门的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序保存图片到相册 微信小程序实现将图片保存到手机相册(方案一)

    目录 微信小程序实现将图片保存到手机相册(方案一) 微信小程序实现将图片保存到手机相册(方案二) 微信小程序之点击复制文本到剪贴板 微信小程序---判断是IOS还是安卓 微信小程序分享图片给微信好友 首先我们需要调用wx.downloadFile方法下载文件资源到本地,然后利用

    2023年04月20日
    浏览(44)
  • 微信小程序(二)微信小程序选择本地图片显示并预览(实现左右滑动)

    在微信小程序里面实现选择图片然后预览是一个非常普遍的功能,在我们上传图片文件的时候,都会选择本地的图片进行上传,在上传之前会查看一下自己上传的图片是否准确。所以要做到预览图片。 下面就实现一个简单的本地图片显示预览的功能~~ 1、创建页面 这里我直接

    2024年02月03日
    浏览(76)
  • 微信小程序(5)——下载图片

    一、普通下载图片 实现功能:点击下载按钮,将图片保存到本地相册。 代码如下: 按照官方文档,简单这样写即可,开发测试和发布测试时通常也都能正常下载。但是偶尔会遇到报错: errMsg: \\\"saveImageToPhotosAlbum:fail auth deny\\\" 二、用户授权下载图片 需要用户授权进行保存操作

    2024年02月11日
    浏览(46)
  • 微信小程序上传图片写法

    小程序上传图片需要用到小程序API中的wx.uploadFile()方法。以下是一个基本的示例代码: 在这个示例代码中,首先使用wx.chooseImage()方法让用户选择一张图片,然后通过wx.uploadFile()方法将选中的图片上传到指定的接口地址。在上传成功后,我们可以在success回调函数中获

    2024年02月11日
    浏览(83)
  • 微信小程序图片使用示例

    小程序官方API:https://developers.weixin.qq.com/miniprogram/dev/component/image.html 1:加载本地文件夹图片 image src=\\\"/image/pig.jpg\\\" mode=\\\"aspectFill\\\" /image mnn 2:加载服务器图片 wxml: image src=\\\"{ {imageUrl}}\\\" mode=\\\"aspectFill\\\" /image js: Page({ data: { imageUrl: \\\"

    2024年02月10日
    浏览(34)
  • 微信小程序-图片预览图

    有时候图片列表图片过小看不清图片内容,这时我们一般就希望点击图片可以放大显示进行预览,那么,接下来我们就调用微信原生API的的浏览图片程序进行对图片预览的实现。 通过微信原生API实现单张图片的浏览 wxml代码 添加对应js的点击事件,调用预览图片的API,实现图

    2024年02月08日
    浏览(70)
  • 微信小程序猜数字小游戏

     我的首页(效果图)使用的是index03 开始游戏使用的是index 游戏规则使用的是index01 关于其他使用的是index02 (创建文件在app.json里面,这是我的app.json创建的文件) (由于我的首页效果图使用的是index03,所以要放在前面) WXML代码 WXSS代码 WXML代码 WXSS代码 index.js代码 WXML代码 WX

    2023年04月10日
    浏览(52)
  • 石头剪刀步微信小程序游戏

    之前接了学弟的一个课程作业,但是因为某些原因,最终换成了一个新的爬虫项目。 这个作业就是一个石头剪刀步的微信小游戏。就是与系统随机的 单机 PK,暂时没有去做联接的,没有那个云服务器,但是可以用轮讯的方式去多人联机玩儿。内容虽小但是传统的基本框架都

    2024年02月07日
    浏览(38)
  • 基于微信小程序的游戏账号交易小程序

    文末联系获取源码 开发语言:Java 框架:ssm JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7/8.0 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9 浏览器:谷歌浏览器 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序运行软件:微信开发者 随着网络和计算机

    2024年02月09日
    浏览(46)
  • 【小程序图片水印】微信小程序图片加水印功能 canvas绘图

    感觉有用的话,可以打赏一把么?一毛不嫌少,十块不嫌多 更多详细代码请关注公众号索取(备注:公众号):

    2024年04月29日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包