案例代码图片资源 链接:https://pan.baidu.com/s/1Iv1JDXNzSVyC16zW3oZj6g 提取码:hmlo
拼图小游戏
app.json
{
"pages": [
"pages/index/index",
"pages/game/game"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#e64340",
"navigationBarTitleText": "拼图游戏",
"navigationBarTextStyle": "black"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
app.wxss
/**app.wxss**/
.container{
height: 100vh;
color: #e64340;
font-weight: bold;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
}
.title{
font-size: 18pt;
}
index页面 index.wxml
<!--index.wxml-->
<view class="container">
<!-- 标题 -->
<view class="title">游戏选关</view>
<!-- 关卡列表 -->
<view class="levelBox">
<view class="box" wx:for="{{levels}}" wx:key="levels{{index}}" bindtap="chooseLevel" data-level="{{item}}">
<image src="/images/{{item}}"></image>
<text>第{{index+1}}关</text>
</view>
</view>
</view>
index.wxss
/**index.wxss**/
/* 关卡区域列表 */
.levelBox{
width: 100%;
}
/* 单个关卡区域 */
.box{
width: 50%;
float: left;
margin: 25rpx 0;
display: flex;
flex-direction: column;
align-items: center;
}
/* 选关图片 */
image{
width: 260rpx;
height: 260rpx;
}
index.js
// index.js
Page({
/**
* 页面的初始数据
*/
data: {
levels:[
'pic01.jpg',
'pic02.jpg',
'pic03.jpg',
'pic04.jpg',
'pic05.jpg',
'pic06.jpg'
]
},
// 自定义选关函数
chooseLevel:function(e){
//console.log(e);
//获取选关图片
let level = e.currentTarget.dataset.level
//跳转游戏页面
wx.navigateTo({
url: '../game/game?level='+level,
})
}
})
game页面 game.wxml
<!--pages/game/game.wxml-->
<view class="container">
<!-- 顶端提示图 -->
<view class="title">提示图</view>
<image src="{{url}}"></image>
<!-- 游戏区域 -->
<canvas canvas-id="myCanvas" bindtouchstart="touchBox"></canvas>
<!-- 重新开始按钮 -->
<button type="warn" bindtap="restartGame">重新开始</button>
</view>
game.wxss
/* pages/game/game.wxss */
/* 提示图 */
image{
width: 250rpx;
height: 250rpx;
}
/* 游戏画布区域 */
canvas{
border: 1rpx solid;
width: 300px;
height: 300px;
}
game.js
// pages/game.js
// 方块的初始位置
var num=[
['00','01','02'],
['10','11','12'],
['20','21','22']
]
// 方块的宽度
var w=100
// 图片的初始位置
var url ='/images/pic01.jpg'
Page({
/**
* 页面的初始数据
*/
data: {
isWin:false
},
// 绘制画布内容
drawCanvas:function(){
let ctx = this.ctx
//清空画布
ctx.clearRect(0, 0, 300, 300)
//使用双重for循环语句绘制3X3拼图
for(var i=0; i<3; i++){
for(var j=0; j<3; j++){
if(num[i][j] != '22'){
//获取行和列
var row = parseInt(num[i][j] / 10)
var col = num[i][j] % 10
//绘制方块
ctx.drawImage(url, col * w, row * w, w, w, j * w, i * w, w, w)
}
}
}
ctx.draw()
},
//随机打乱方块顺序
shuffle:function(){
//先令所有方块回归初始位置
num = [
['00','01','02'],
['10','11','12'],
['20','21','22'],
]
//记录当前空白方块的行和列
var row = 2
var col = 2
//随机打乱方块顺序100次
for (let i = 0; i < 100; i++) {
//随机生成一个方向:上0,下1,左2,右3
var direction = Math.round(Math.random()*3)
//上:0
if(direction == 0){
//空白方块不能在最上面一行
if(row != 0){
//交换位置
num[row][col] = num[row-1][col]
num[row-1][col] = '22'
//更新空白块的行
row -= 1
}
}
// 下:1
if (direction == 1) {
// 空白方块不能在最下面一行
if (row != 2) {
// 交换位置
num[row][col] = num[row + 1][col]
num[row + 1][col] = '22'
// 更新空白方块的行
row += 1
}
}
// 左:2
if (direction == 2) {
// 空白方块不能在最左边一列
if (col != 0) {
// 交换位置
num[row][col] = num[row][col - 1]
num[row][col - 1] = '22'
// 更新空白方块的列
col -= 1
}
}
// 右:3
if (direction == 3) {
// 空白方块不能在最右边一列
if (col != 2) {
// 交换位置
num[row][col] = num[row][col + 1]
num[row][col + 1] = '22'
// 更新空白方块的列
col += 1
}
}
}
},
// 移动点击的方块
moveBox:function(i,j){
//情况1:如果被点击的方块不在最上方,检查可否上移
if(i > 0){
//如果方块的最上方是空白
if(num[i-1][j] == '22'){
//交换当前被点击的方块和空白的位置
num[i-1][j] = num[i][j]
num[i][j] = '22'
return
}
}
// 情况2:如果被点击的方块不在最下方,检查可否下移
if (i < 2) {
// 如果方块的下方是空白
if (num[i + 1][j] == '22') {
// 交换当前被点击的方块和空白的位置
num[i + 1][j] = num[i][j]
num[i][j] = '22'
return
}
}
// 情况3:如果被点击的方块不在最左侧,检查可否左移
if (j > 0) {
// 如果方块的左侧是空白
if (num[i][j - 1] == '22') {
// 交换当前被点击的方块和空白的位置
num[i][j - 1] = num[i][j]
num[i][j] = '22'
return
}
}
// 情况4:如果被点击的方块不在最右侧,检查可否右移
if (j < 2) {
// 如果方块的右侧是空白
if (num[i][j + 1] == '22') {
// 交换当前被点击的方块和空白的位置
num[i][j + 1] = num[i][j]
num[i][j] = '22'
return
}
}
},
//判断游戏是否成功
isWin:function(){
for(var i=0; i<3; i++){
for(var j=0; j<3; j++){
//如果有方块位置不对
if(num[i][j] != i*10+j){
//返回假,游戏尚未成功
return false
}
}
}
//游戏成功,更新状态
this.setData({
isWin:true
})
//返回真,游戏成功
return true
},
// 监听点击方块事件
touchBox:function(e){
//如果游戏已经成功,不做任何操作
if(this.data.isWin){
//终止本函数
return
}
//获取点击方块的坐标
var x = e.changedTouches[0].x
var y = e.changedTouches[0].y
//换算成行和列
var row = parseInt(y/w)
var col = parseInt(x/w)
//如果点击的不是空白位置
if(num[row][col] != '22'){
//尝试移动方块
this.moveBox(row,col)
//重新绘制画布内容
this.drawCanvas()
//判断游戏是否成功
if(this.isWin()){
//在画布上绘制提示语句
let ctx = this.ctx
//绘制完整画布内容
this.drawCanvas()
//判断游戏是否成功
if(this.isWin()){
//在画面上绘制提示语句
let ctx = this.ctx
//绘制完整图片
ctx.drawImage(url,0,0)
//绘制文字
ctx.setFillStyle('#e94340')
ctx.setTextAlign('center')
ctx.setFontSize(60)
ctx.fillText('游戏成功',150,150)
ctx.draw()
}
}
}
},
//重新开始游戏
restartGame:function(){
//更新游戏状态
this.setData({
isWin:false
})
//打乱方块顺序
this.shuffle()
//绘制画布内容
this.drawCanvas()
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
//更新图片路径地址
url = '/images/' + options.level
//更新提示图路径地址
this.setData({
url:url
})
//创建画布上下文
this.ctx = wx.createCanvasContext("myCanvas")
// 打乱方块顺序
this.shuffle()
//绘制画布内容
this.drawCanvas()
}
})
贪吃蛇
app.json
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
}
index页面 index.wxml
<!--index.wxml-->
<view class="container">
<image src="/images/snake01.png" bindtap="goToGame" data-level="easy"></image>
<image src="/images/snake02.png" bindtap="goToGame" data-level="hard"></image>
</view>
index.wxss
/**index.wxss**/
image{
width: 400rpx;
height: 400rpx;
}
index.js
// index.js
Page({
/**
* 页面的初始数据
*/
data: {
},
//跳转游戏页面
goToGame:function(e){
let level = e.currentTarget.dataset.level
let time=0
if(level=='easy'){
time=500
}else if(level=='hard'){
time =200
}
wx.navigateTo({
url: '../game/game?time='+time,
})
}
})
game页面 game.wxml
<!--pages/game/game.wxml-->
<view class="container">
<view>当前分数:{{score}}</view>
<canvas canvas-id="myCanvas"></canvas>
<view class="btnBox">
<button bindtap="up">↑</button>
<view>
<button bindtap="left">←</button>
<button bindtap="down">↓</button>
<button bindtap="right">→</button>
</view>
</view>
<button bindtap="restartGame">重新开始</button>
</view>
game.wxss
/* pages/game/game.wxss */
/* 游戏画布样式 */
canvas{
border: 1rpx solid #e64340;
width: 320px;
height: 320px;
}
/* 方向键按钮整体区域 */
.btnBox{
display: flex;
flex-direction: column;
align-items: center;
}
/* 方向键第二行 */
.btnBox view{
display: flex;
flex-direction: row;
}
/* 所有方向键按钮样式 */
.btnBox>button{
width: 90rpx;
height: 90rpx;
}
/* 所有按钮样式 */
button{
margin: 10rpx;
background-color: #e64340;
color: white;
}
game.js
// pages/game/game.js
// ================
// 游戏参数设置
// ================
// 蛇的身长
var t = 3
// 记录蛇的运动轨迹,用数组记录每个方块的坐标点
var snakeMap = []
// 蛇身单元格的宽度
var w = 20
// 方向代码:上1,下2,左3,右4
var direction = 1
// 蛇的初始坐标
var x = 0
var y = 0
// 食物的初始坐标
var foodX = 0
var foodY = 0
// 画布的宽和高
var width = 320
var height = 320
// 游戏界面刷新的间隔时间,单位毫秒
var time = 0
Page({
/**
* 页面的初始数据
*/
data: {
score: 0
},
/**
* 自定义函数--启动游戏
*/
gameStart: function() {
// 初始化蛇身长度
t = 3
// 初始化蛇身坐标
snakeMap = []
// 随机生成贪吃蛇的初始蛇头坐标
x = Math.floor(Math.random() * width / w) * w
y = Math.floor(Math.random() * height / w) * w
// 随机生成蛇的初始前进方向
direction = Math.ceil(Math.random() * 4)
// 随机生成食物的初始坐标
foodX = Math.floor(Math.random() * width / w) * w
foodY = Math.floor(Math.random() * height / w) * w
// 每隔time毫秒后刷新一次游戏画面
var that = this
this.interval = setInterval(function() {
that.gameRefresh()
}, time)
},
/**
* 自定义函数--绘制贪吃蛇
*/
drawSnake: function() {
let ctx = this.ctx
// 设置蛇身的填充颜色
ctx.setFillStyle('lightblue')
// 绘制全部蛇身
for (var i = 0; i < snakeMap.length; i++) {
ctx.fillRect(snakeMap[i].x, snakeMap[i].y, w, w)
}
},
/**
* 自定义函数--绘制食物
*/
drawFood: function() {
let ctx = this.ctx
// 设置食物的填充颜色
ctx.setFillStyle('red')
// 绘制食物
ctx.fillRect(foodX, foodY, w, w)
},
/**
* 自定义函数--游戏画面刷新
*/
gameRefresh: function() {
// 在随机位置绘制一个食物
this.drawFood()
// 将当前坐标添加到贪吃蛇运动轨迹数组中
snakeMap.push({
'x': x,
'y': y
})
// 数组只保留蛇身长度的数据,如果蛇前进了则删除最旧坐标
if (snakeMap.length > t) {
snakeMap.shift()
}
// 绘制贪吃蛇
this.drawSnake()
// 吃到食物判断
if (foodX == x && foodY == y) {
// 吃到一次食物加10分
let score = this.data.score + 10
this.setData({
score: score
})
// 随机生成下一个食物坐标
foodX = Math.floor(Math.random() * width / w) * w
foodY = Math.floor(Math.random() * height / w) * w
// 在新的位置绘制食物
this.drawFood()
// 蛇身长度+1
t++
}
// 在画布绘制全部内容
this.ctx.draw()
// 根据蛇头方向移动下一个位置
switch (direction) {
case 1:
y -= w
break
case 2:
y += w
break
case 3:
x -= w
break
case 4:
x += w
break
}
// 碰撞检测,返回值为0表示没有撞到
let code = this.detectCollision()
if (code != 0) {
// 游戏停止
clearInterval(this.interval)
var msg = ''
if (code == 1) {
msg = '失败原因:撞到了墙壁'
} else if (code == 2) {
msg = '失败原因:撞到了蛇身'
}
wx.showModal({
title: '游戏失败,是否重来?',
content: msg,
success:res=>{
if(res.confirm){
// 重新开始游戏
this.gameStart()
}
}
})
}
},
/**
* 自定义函数--监听方向键:上
*/
up: function() {
direction = 1
},
/**
* 自定义函数--监听方向键:下
*/
down: function() {
direction = 2
},
/**
* 自定义函数--监听方向键:左
*/
left: function() {
direction = 3
},
/**
* 自定义函数--监听方向键:右
*/
right: function() {
direction = 4
},
/**
* 自定义函数--碰撞检测
*/
detectCollision: function() {
// 如果蛇头碰撞到了四周的墙壁,游戏失败
if (x > width-20 || y > height-20 || x < 0 || y < 0) {
return 1
}
// 如果蛇头撞到了蛇身,游戏失败
for (var i = 0; i < snakeMap.length; i++) {
if (snakeMap[i].x == x && snakeMap[i].y == y) {
return 2
}
}
// 没有碰撞
return 0
},
/**
* 自定义函数--重启游戏
*/
restartGame: function () {
// 关闭刷新效果
clearInterval(this.interval)
// 重新开始游戏
this.gameStart()
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
// console.log(options.time)
// 更新游戏刷新时间
time = options.time
// 创建画布上下文
this.ctx = wx.createCanvasContext("myCanvas")
// 开始游戏
this.gameStart()
}
})
推箱子游戏
utils公用数据 data.js
//================================================
//地图数据map1-map4
//地图数据:1墙,2路,3终点,4箱子,5人物,0墙的外围
//================================================
//关卡1
var map1 = [
[0, 1, 1, 1, 1, 1, 0, 0],
[0, 1, 2, 2, 1, 1, 1, 0],
[0, 1, 5, 4, 2, 2, 1, 0],
[1, 1, 1, 2, 1, 2, 1, 1],
[1, 3, 1, 2, 1, 2, 2, 1],
[1, 3, 4, 2, 2, 1, 2, 1],
[1, 3, 2, 2, 2, 4, 2, 1],
[1, 1, 1, 1, 1, 1, 1, 1]
]
//关卡2
var map2 = [
[0, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 1, 3, 1, 0, 0, 0],
[0, 0, 1, 2, 1, 1, 1, 1],
[1, 1, 1, 4, 2, 4, 3, 1],
[1, 3, 2, 4, 5, 1, 1, 1],
[1, 1, 1, 1, 4, 1, 0, 0],
[0, 0, 0, 1, 3, 1, 0, 0],
[0, 0, 0, 1, 1, 1, 0, 0]
]
//关卡3
var map3 = [
[0, 0, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 3, 3, 1, 0, 0],
[0, 1, 1, 2, 3, 1, 1, 0],
[0, 1, 2, 2, 4, 3, 1, 0],
[1, 1, 2, 2, 5, 4, 1, 1],
[1, 2, 2, 1, 4, 4, 2, 1],
[1, 2, 2, 2, 2, 2, 2, 1],
[1, 1, 1, 1, 1, 1, 1, 1]
]
//关卡4
var map4 = [
[0, 1, 1, 1, 1, 1, 1, 0],
[0, 1, 3, 2, 3, 3, 1, 0],
[0, 1, 3, 2, 4, 3, 1, 0],
[1, 1, 1, 2, 2, 4, 1, 1],
[1, 2, 4, 2, 2, 4, 2, 1],
[1, 2, 1, 4, 1, 1, 2, 1],
[1, 2, 2, 2, 5, 2, 2, 1],
[1, 1, 1, 1, 1, 1, 1, 1]
]
//数据接口
module.exports = {
maps: [map1, map2, map3, map4]
}
app.wxss
/**app.wxss**/
/* 页面容器样式 */
.container {
height: 100vh;
color: #e64340;
font-weight: bold;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
}
/* 顶端标题样式 */
.title {
font-size: 18pt;
}
index页面 index.wxml
<!--index.wxml-->
<view class="container">
<!-- 标题 -->
<view class="title">游戏选关</view>
<!-- 关卡列表 -->
<view class="levelBox">
<view class="box" wx:for="{{levels}}" wx:key="levels{{index}}" bindtap="chooseLevel" data-level="{{index}}">
<image src="/images/{{item}}"></image>
<text>第{{index+1}}</text>
</view>
</view>
</view>
index.wxss
/**index.wxss**/
.levelBox{
width: 100%;
}
.box{
width: 50%;
float: left;
margin: 20rpx 0;
display: flex;
flex-direction: column;
align-items: center;
}
image{
width: 300rpx;
height: 300rpx;
}
index.js
// index.js
Page({
/**
* 页面的初始数据
*/
data: {
levels:[
'level01.png',
'level02.png',
'level03.png',
'level04.png'
]
},
//游戏选关
chooseLevel:function(e){
let level = e.currentTarget.dataset.level
wx.navigateTo({
url:'../game/game?level='+level
})
}
})
game页面 game.wxml
<!--game.wxml-->
<view class='container'>
<!-- 关卡提示 -->
<view class='title'>第{{level}}关</view>
<!-- 游戏画布 -->
<canvas canvas-id='myCanvas'></canvas>
<!-- 方向键 -->
<view class='btnBox' >
<button type='warn' bindtap='up' style="width: 90rpx;height: 90rpx;margin: 10rpx;">↑</button>
<view>
<button type='warn' bindtap='left' style="width: 90rpx;height: 90rpx;margin: 10rpx;">←</button>
<button type='warn' bindtap='down' style="width: 90rpx;height: 90rpx;margin: 10rpx;">↓</button>
<button type='warn' bindtap='right' style="width: 90rpx;height: 90rpx;margin: 10rpx;">→</button>
</view>
</view>
<!-- 重新开始按钮 -->
<button type='warn' bindtap='restartGame' style="margin: 10rpx;">重新开始</button>
</view>
game.wxss
/**game.wxss**/
/* 游戏画布样式 */
canvas {
border: 1rpx solid;
width: 320px;
height: 320px;
}
/* 方向键按钮整体区域 */
.btnBox {
display: flex;
flex-direction: column;
align-items: center;
}
/* 所有方向键按钮 */
.btnBox button {
width: 90rpx;
height: 90rpx;
}
/* 方向键按钮第二行 */
.btnBox view {
display: flex;
flex-direction: row;
}
/* 所有按钮样式 */
button {
margin: 10rpx;
}
game.js
// pages/game/game.js
//引用公用js文件
var data = require('../../utils/data')
//地图图层数据
var map = [
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]
]
//箱子图层数据
var box = [
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]
]
//方块的宽度
var w = 40
//初始化小鸟的行与列
var row = 0
var col = 0
Page({
/**
* 页面的初始数据
*/
data: {
level:1
},
//初始化地图数据
initMap:function(level){
let mapData = data.maps[level]
for(var i=0;i<8;i++){
for(var j=0;j<8;j++){
box[i][j] = 0
map[i][j] = mapData[i][j]
if(mapData[i][j] == 4){
box[i][j] = 4
map[i][j] = 2
}else if(mapData[i][j] == 5){
map[i][j] = 2
row = i
col = j
}
}
}
},
//绘制地图
drawCanvas:function(){
let ctx = this.ctx
ctx.clearRect(0,0,320,320)
for(var i=0; i<8; i++){
for(var j=0; j<8; j++){
let img='ice'
if(map[i][j] == 1){
img = 'stone'
}else if(map[i][j] == 3){
img = 'pig'
}
//绘制地图
ctx.drawImage('/images/icons/'+img+'.png',j*w,i*w,w,w)
if(box[i][j] == 4){
ctx.drawImage('/images/icons/box.png',j*w,i*w,w,w)
}
}
}
ctx.drawImage('/images/icons/bird.png',col * w, row * w, w, w)
ctx.draw()
},
//方向键上
up:function(){
if(row>0){
if(map[row-1][col]!=1 && box[row-1][col]!=4){
row = row -1
}else if(box[row-1][col]==4){
if(row-1>0){
if(map[row-2][col]!=1&&box[row-2][col]!=4){
box[row-2][col]=4
box[row-1][col]=0
row = row-1
}
}
}
this.drawCanvas()
this.checkWin()
}
},
//方向键下
down:function(){
if(row<7){
if(map[row+1][col]!=1 && box[row+1][col]!=4){
row = row +1
}else if(box[row+1][col]==4){
if(row+1<7){
if(map[row+2][col]!=1&&box[row+2][col]!=4){
box[row+2][col]=4
box[row+1][col]=0
row = row+1
}
}
}
this.drawCanvas()
this.checkWin()
}
},
//方向键左
left:function(){
if(col>0){
if(map[row][col-1]!=1 && box[row][col-1]!=4){
col = col -1
}else if(box[row][col-1]==4){
if(col-1>0){
if(map[row][col-2]!=1&&box[row][col-2]!=4){
box[row][col-2]=4
box[row][col-1]=0
col = col -1
}
}
}
this.drawCanvas()
this.checkWin()
}
},
//方向键右
right:function(){
if(col<7){
if(map[row][col+1]!=1 && box[row][col+1]!=4){
col = col +1
}else if(box[row][col+1]==4){
if(col+1<7){
if(map[row][col+2]!=1&&box[row][col+2]!=4){
box[row][col+2]=4
box[row][col+1]=0
col = col +1
}
}
}
this.drawCanvas()
this.checkWin()
}
},
//判断游戏成功
isWin:function(){
for(var i=0; i<8; i++){
for(var j=0; j<8; j++){
if(box[i][j] == 4 && map[i][j] != 3){
return false
}
}
}
return true
},
//游戏成功处理
checkWin:function(){
if(this.isWin()){
wx.showModal({
title:'恭喜',
content:'游戏成功!',
showCancel:false
})
}
},
//重新开始游戏
restartGame:function(){
this.initMap(this.data.level-1)
this.drawCanvas()
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
//获取关卡
let level = options.level
//更新页面关卡标题
this.setData({
level:parseInt(level)+1
})
this.ctx = wx.createCanvasContext('myCanvas')
this.initMap(level)
this.drawCanvas()
}
})
|