小游戏小程序是运行在微信生态系统(或其他支持小程序的平台)中的轻量级应用程序,专为休闲游戏体验而设计的小程序子类别,小游戏小程序通常体积较小,加载速度快,用户无需等待长时间即可开始游戏。用户无需下载或安装单独的游戏应用程序,即可通过小程序入口直接进入游戏,同时小游戏小程序通常包含排行榜、分享功能等社交元素,可以增强游戏体验并促进用户参与。
源码及演示:casgams.top/gm
一、羊了个羊
1、项目结构设计
/minigame/
├── pages/ 游戏主页
│ ├── index.js 逻辑层
│ ├── index.wxml 视图层
│ ├── index.wxss 样式层
│ └── index.json 页面配置
├── components/ 通用组件
│ ├── block.js 方块组件
│ ├── button.js 操作按钮
│ ├── score-board.js 得分板
│ └── modal.js 弹窗提示
├── utils/ 工具类
│ ├── collision.js 碰撞检测
│ ├── animation.js 动画控制
│ └── sound.js 音效管理
├── assets/ 资源文件
│ ├── images/ 游戏素材
│ │ ├── block.png 块状元素
│ │ └── bg.jpg 背景图
│ ├── audio/ 音效文件
│ │ ├── click.mp3 点击音效
│ │ └──消除音效.mp3
│ └── ...
├── cloud/ 云开发配置(可选)
│ └── functions/ 云端函数
└── app.js 全局配置
2、核心模块解析
1.视图层(index.wxml)
<view class="game-container">
<!-- 动态生成的方块区域 -->
<block-list blocks="{{blocks}}" bind:tap="handleTap" />
<!-- 操作按钮 -->
<button-component
text="重试"
bind:click="restartGame"
/>
<!-- 得分板 -->
<score-board score="{{score}}" />
<!-- 弹窗提示 -->
<modal visible="{{showModal}}"
content="{{modalContent}}"
bind:confirm="handleConfirm"
/>
</view>
2.逻辑层(index.js)
Page({
data: {
blocks: [], // 当前所有方块数组
score: 0, // 当前得分
gridSize: 6, // 游戏区域格子数(6x6)
lastTapPosition: null, // 上一次点击位置
isMatching: false // 是否处于匹配状态
},
onLoad() {
this.initGame();
},
initGame() {
// 初始化游戏布局
this.generateBlocks();
wx.setStorageSync('highScore', this.data.score);
},
generateBlocks() {
// 生成随机方块
const blocks = [];
for(let i=0; i<this.gridSize2; i++) {
blocks.push({
id: i,
type: Math.random() < 0.5 ? 'normal' : 'special',
x: Math.floor(Math.random() this.gridSize),
y: Math.floor(Math.random() this.gridSize),
status: 'idle' // 状态:闲置/选中/消除
});
}
this.setData({ blocks });
},
handleTap(e) {
const { block } = e.detail;
if(block.status !== 'idle') return;
// 处理连续点击逻辑
if(this.lastTapPosition) {
this.checkMatch([this.lastTapPosition.block, block]);
} else {
this.selectBlock(block);
}
this.lastTapPosition = { block };
},
checkMatch(selectedBlocks) {
// 匹配算法核心
const [a, b] = selectedBlocks;
if(a.type !== b.type) return false;
// 计算曼哈顿距离是否在允许范围内
const distance = Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
return distance <= 2; // 允许最多间隔1个空格
},
// 消除动画逻辑
animateElimination(effects) {
effects.forEach(effect => {
wx.createAnimation({
duration: 300,
timingFunction: 'ease-out',
transform: `translate(${effect.dx}px, ${effect.dy}px) scale(0)`
}).exec((anim) => {
anim.step();
});
});
},
// 游戏结束检测
checkGameOver() {
if(this.data.score >= 10) {
wx.showModal({
title: '游戏胜利',
content: '恭喜通关!得分:' + this.data.score,
showCancel: false,
confirmButtonText: '再来一局'
});
return true;
}
return false;
}
});
3.WXS响应式计算(collision.js)
module.exports = {
methods: {
// 精确碰撞检测(包含边界)
isColliding(obj1, obj2) {
return (
obj1.x < obj2.x + obj2.width &&
obj1.x + obj1.width > obj2.x &&
obj1.y < obj2.y + obj2.height &&
obj1.y + obj1.height > obj2.y
);
}
}
};
3、关键技术实现
1.触摸滑动优化
// 处理复杂手势(长按/滑动)
Page({
touchStart(e) {
this.setData({ touchStart: e.touches[0] });
},
touchMove(e) {
const deltaX = e.touches[0].pageX - this.data.touchStart.pageX;
const deltaY = e.touches[0].pageY - this.data.touchStart.pageY;
// 根据滑动方向调整方块位置
if(Math.abs(deltaX) > Math.abs(deltaY)) {
// 左右滑动
this.handleHorizontalSwipe(deltaX);
} else {
// 上下滑动
this.handleVerticalSwipe(deltaY);
}
}
});
2.动态粒子效果
// 创建消除特效
createEffect(ctx, x, y) {
const particles = [];
for(let i=0; i<20; i++) {
particles.push({
x: x + Math.random() 20 - 10,
y: y + Math.random() 20 - 10,
size: Math.random() 3 + 1,
speedX: (Math.random() - 0.5) 2,
speedY: (Math.random() - 0.5) 2
});
}
return particles;
}
3.微信支付集成
// 调用微信支付接口
wx.requestPayment({
timeStamp: '...',
nonceStr: '...',
package: 'prepay_id=...',
signType: 'MD5',
success(res) {
console.log('支付成功', res);
wx.navigateTo({
url: '/pages/result/index'
});
},
fail(e) {
wx.showToast({ title: '支付失败' });
}
});
4、性能优化建议
1.Canvas替代方案:
// 使用<canvas>标签提升渲染效率
<canvas
canvas-id="gameCanvas"
style="width: 100%; height: 100vh;"
bindtouchstart="handleTouchStart"
bindtouchmove="handleTouchMove"
/>
// 在JS中获取上下文
Page({
onReady() {
this.ctx = wx.createCanvasContext('gameCanvas', this);
}
})
2.虚拟列表技术:
// 仅渲染可见区域的方块
computedBlocks() {
const visibleBlocks = [];
this.data.blocks.forEach(block => {
if(
block.x >= this.visibleLeft &&
block.x <= this.visibleRight &&
block.y >= this.visibleTop &&
block.y <= this.visibleBottom
) {
visibleBlocks.push(block);
}
});
return visibleBlocks;
}
3.离线缓存机制:
// 本地存储高分记录
wx.getStorage({
key: 'highScore',
success(e) {
this.setData({ highScore: e.data || 0 });
}
});
5、扩展功能实现
1.道具系统:
// 添加炸弹道具
useBomb() {
this.setData({ bombCount: this.data.bombCount - 1 });
// 创建爆炸动画
this.animateBomb();
}
2.社交分享:
// 分享游戏成就
wx.showShareMenu({
withShareTicket: true
});
onShareAppMessage() {
return {
title: `我在《羊了个羊》获得了${this.data.score}分!`,
imageUrl: '/assets/share.jpg'
};
}
3.AI智能提示:
// 简单匹配算法实现
getHint() {
// 查找最短距离的可匹配对
let minDistance = Infinity;
let bestPair = null;
this.data.blocks.forEach(pair => {
if(this.checkMatch(pair)) {
const distance = Math.abs(pair[0].x - pair[1].x) + Math.abs(pair[0].y - pair[1].y);
if(distance < minDistance) {
minDistance = distance;
bestPair = pair;
}
}
});
return bestPair;
}
// app.js
App({
onLaunch() {
// 小程序启动时执行的初始化操作
console.log('App Launch')
},
onShow() {
// 小程序显示时执行的操作
console.log('App Show')
},
onHide() {
// 小程序隐藏时执行的操作
console.log('App Hide')
},
globalData: {
// 全局数据,可以在各个页面中共享
userInfo: null,
gameData: {
// 游戏数据,可以根据需要扩展
sheepCount: 0, // 羊的数量
level: 1, // 游戏关卡
},
},
})
// game.js
Page({
data: {
// 页面数据
tip: '点击屏幕开始玩', // 游戏提示信息
sheepList: [], // 羊的列表
isGameOver: false, // 游戏是否结束
},
onLoad() {
// 页面加载时执行的操作
this.initGame();
},
initGame() {
// 初始化游戏数据
this.setData({
sheepList: [],
isGameOver: false,
tip: '点击屏幕开始玩',
});
// 随机生成羊的位置和数量(简化处理,仅生成几只羊作为示例)
for (let i = 0; i < 3; i++) {
const sheep = {
id: i + 1,
x: Math.floor(Math.random() 300) + 50,
y: Math.floor(Math.random() 400) + 50,
};
this.data.sheepList.push(sheep);
}
// 更新页面数据
this.setData({
sheepList: this.data.sheepList,
});
},
onTap(event) {
// 处理点击事件
const { x, y } = event.touches[0];
const sheepList = this.data.sheepList;
for (let i = 0; i < sheepList.length; i++) {
const sheep = sheepList[i];
const distance = Math.sqrt((sheep.x - x) 2 + (sheep.y - y) 2);
// 判断点击位置是否在羊的范围内(简化处理,仅通过距离判断)
if (distance < 30) {
// 点击到羊,处理点击逻辑(例如:增加分数、移除羊等)
wx.showToast({
title: `抓到羊了!`,
icon: 'success',
duration: 2000,
});
// 移除抓到的羊
sheepList.splice(i, 1);
// 更新页面数据
this.setData({
sheepList: sheepList,
});
// 判断游戏是否结束(例如:羊全部被抓完)
if (sheepList.length === 0) {
this.setData({
isGameOver: true,
tip: '恭喜你,抓到所有羊了!',
});
}
break;
}
}
},
restartGame() {
// 重新开始游戏
this.initGame();
},
})
// game.wxml
<view class="container">
<text class="tip">{{tip}}</text>
<canvas canvas-id="myCanvas" style="width: 350px; height: 450px;"></canvas>
<button wx:if="{{!isGameOver}}" bindtap="restartGame">重新开始</button>
</view>
// game.wxss
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
.tip {
margin-top: 20px;
font-size: 20px;
color: #333;
}
button {
margin-top: 20px;
padding: 10px 20px;
background-color: #1aad19;
color: #fff;
border: none;
border-radius: 5px;
}
说明
app.js:小程序的全局配置文件,用于初始化全局数据和生命周期函数。
game.js:游戏页面的逻辑文件,包含页面数据、生命周期函数、事件处理函数等。
onLoad:页面加载时初始化游戏数据。
initGame:随机生成羊的位置和数量,并更新页面数据。
onTap:处理点击事件,判断点击位置是否在羊的范围内,并处理相应的逻辑。
restartGame:重新开始游戏的函数。
game.wxml:游戏页面的结构文件,定义了页面的布局和组件。
使用<canvas>组件绘制羊的图像(需要配合JavaScript代码在game.js中绘制)。
使用<text>组件显示游戏提示信息。
使用<button>组件提供重新开始游戏的按钮。
game.wxss:游戏页面的样式文件,定义了页面的样式和布局。
二、贪吃蛇(基础版)
1.项目结构
/pages/snake/
├── index.js 逻辑层
├── index.wxml 视图层
├── index.wxss 样式层
└── snake.png 蛇身素材
2.核心逻辑
Page({
data: {
snake: [], // 蛇身坐标数组
food: {}, // 食物坐标
direction: 'right' // 移动方向
},
onLoad() {
this.initGame();
},
initGame() {
// 初始化蛇身和食物
this.snake = [{x:10, y:10}];
this.createFood();
// 绑定键盘事件
wx.onAccelerometerChange(this.handleMove.bind(this));
},
handleMove(e) {
const { x, y } = e;
let newDir = this.direction;
// 根据加速度改变方向
if(abs(x) > abs(y)) {
newDir = x > 0 ? 'right' : 'left';
} else {
newDir = y > 0 ? 'down' : 'up';
}
// 方向限制逻辑
switch(this.direction) {
case 'right': newDir = (x < 0) ? 'down' : newDir; break;
// 其他方向同理...
}
this.setData({ direction: newDir });
},
move() {
// 计算新头部坐标
const head = {
x: this.snake[0].x + (this.direction === 'right' ? 1 : this.direction === 'left' ? -1 : 0),
y: this.snake[0].y + (this.direction === 'down' ? 1 : this.direction === 'up' ? -1 : 0)
};
// 碰撞检测
if(head.x < 0 || head.x >= 30 || head.y < 0 || head.y >= 30) {
return this.restart();
}
// 身体碰撞检测
if(this.snake.slice(1).some(pos => pos.x === head.x && pos.y === head.y)) {
return this.restart();
}
// 更新蛇身
this.snake.unshift(head);
if(this.snake.length > 15) this.snake.pop();
// 吃食物检测
if(JSON.stringify(head) === JSON.stringify(this.food)) {
this.createFood();
}
wx.requestAnimationFrame(() => this.move());
},
createFood() {
const food = {
x: Math.floor(Math.random() 30),
y: Math.floor(Math.random() 30)
};
this.setData({ food });
},
restart() {
this.setData({
snake: [{x:10, y:10}],
food: {x:15, y:15},
direction: 'right'
});
this.move();
}
});
3.关键样式
css
.game-container {
width: 100%;
height: 100vh;
background-color: #f0f0f0;
}
.snake {
position: absolute;
width: 2px;
height: 2px;
background-color: #ff6b6b;
border-radius: 50%;
}
.food {
position: absolute;
width: 4px;
height: 4px;
background-color: #4CAF50;
border-radius: 50%;
}
三、翻牌记忆游戏
1.技术要点
-使用Canvas实现动态卡片翻转
-记录点击状态和计时器
-包含计分系统和提示功能
2.核心代码片段
javascript
Page({
data: {
cards: [], // 所有卡片数据
flipped: [], // 已翻开的卡片索引
timer: null, // 计时器
score: 0 // 当前得分
},
onLoad() {
this.shuffleCards();
wx.createSelectorQuery()
.select('#memoryCanvas')
.node((res) => {
this.ctx = res.context;
this.drawImage();
})
},
shuffleCards() {
// 生成带图片和答案的卡片数组
const cards = [];
for(let i=0; i<16; i++) {
cards.push({
id: i,
image: `https://example.com/image${i}.png`,
answer: `答案${i}`
});
}
this.setData({ cards });
wx.shuffleArray(cards); // 自定义洗牌函数
},
drawImage() {
// 绘制所有卡片初始状态
this.ctx.setFillStyle('#ffffff');
this.ctx.fillRect(0, 0, 320, 480);
this.cards.forEach((card, index) => {
this.ctx.drawImage(
card.image,
index % 4 80,
Math.floor(index/4) 120,
80, 120
);
});
},
flipCard(e) {
const { dataset } = e.currentTarget;
const index = parseInt(dataset.index);
if(this.flipped.length >= 2) return;
// 显示卡片内容
this.flipped.push(index);
this.ctx.setFillStyle('#f5f5f5');
this.ctx.fillText(
this.cards[index].answer,
index % 4 80 + 30,
Math.floor(index/4) 120 + 60
);
// 判断是否匹配
setTimeout(() => {
if(this.flipped[0] === this.flipped[1]) {
this.score++;
} else {
// 恢复卡片
this.flipBack(this.flipped[0]);
this.flipBack(this.flipped[1]);
}
this.flipped = [];
}, 1000);
},
flipBack(index) {
// 恢复卡片图像
this.ctx.setFillStyle('#ffffff');
this.ctx.fillRect(
index % 4 80,
Math.floor(index/4) 120,
80, 120
);
this.ctx.drawImage(
this.cards[index].image,
index % 4 80,
Math.floor(index/4) 120,
80, 120
);
}
});
四、跑酷类小游戏(H5实现)
1.特性说明
-重力感应控制
-动态障碍物生成
-积分系统
-微信支付接口集成
2.关键逻辑
五、数独游戏(WXS响应式)
1.实现特点
-WXS响应式计算
-智能数独求解算法
-错误提示功能
-多难度选择
2.核心代码
Page({
data: {
player: { x: 100, y: 300 }, // 玩家坐标
obstacles: [], // 障碍物数组
score: 0, // 当前分数
isRunning: false // 游戏运行状态
},
startGame() {
this.setData({ isRunning: true });
this.obstacleInterval = setInterval(() => {
this.createObstacle();
}, 2000);
wx.startAccelerometer({
success: () => {
wx.onAccelerometerChange(this.handleMovement.bind(this));
}
});
},
handleMovement(e) {
const { x, y } = e;
let moveX = 0;
let moveY = 0;
// 根据加速度调整移动方向
if(y > 0.5) {
moveY = -1; // 向上
} else if(y < -0.5) {
moveY = 1; // 向下
}
this.setData({
player: {
x: this.player.x + moveX,
y: this.player.y + moveY
}
});
},
createObstacle() {
const obstacle = {
type: Math.random() < 0.5 ? 'vertical' : 'horizontal',
x: Math.random() (wx.getSystemInfoSync().windowWidth - 50),
y: Math.random() (wx.getSystemInfoSync().windowHeight - 100)
};
this.obstacles.push(obstacle);
},
checkCollision() {
// 玩家与障碍物碰撞检测
this.obstacles.forEach(obs => {
if(obs.type === 'vertical') {
if(this.player.x < obs.x + 50 &&
this.player.x + 50 > obs.x &&
this.player.y > obs.y - 50 &&
this.player.y < obs.y + 50) {
this.gameOver();
}
} else {
// 水平障碍物检测逻辑...
}
});
},
gameOver() {
clearInterval(this.obstacleInterval);
wx.showModal({
title: '游戏结束',
content: `得分:${this.data.score}`,
showCancel: false,
confirmButtonText: '再来一局'
});
}
});
3.页面逻辑
javascript
const sudokuLogic = require('../../utils/sudoku.js');
Page({
data: {
grid: [
[0, 0, 3, 0, 0, 0, 0, 0, 0],
[0, 9, 0, 0, 1, 0, 0, 5, 0],
[0, 0, 0, 7, 4, 0, 0, 0, 0],
[5, 0, 0, 0, 0, 0, 0, 0, 3],
[0, 0, 0, 0, 8, 0, 0, 0, 9],
[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]
]
},
selectCell(e) {
const { row, col } = e.currentTarget.dataset;
const possible = sudokuLogic.calculatePossibleNumbers(
this.data.grid,
row,
col
);
this.setData({
selectedRow: row,
selectedCol: col,
possibleNumbers: possible
});
},
inputNumber(e) {
const num = parseInt(e.detail.value);
if(num === 0 || num > 9) return;
// 更新数独并验证
this.setData({
grid: this.data.grid.map(r =>
r.map((v, c) => c === col && r === row ? num : v)
)
}, () => {
this.checkSudokuValidity();
});
}
});
六、太空大战(Canvas+粒子效果)
1.技术亮点
-Canvas粒子系统
-物理碰撞检测
-微信支付集成
-动态背景音乐
2.游戏循环核心
javascript
Page({
canvasCtx: null,
onReady() {
this.canvasCtx = wx.createCanvasContext('spaceCanvas', this);
this.initGameObjects();
this.startGameLoop();
},
initGameObjects() {
// 创建玩家飞船、敌人、子弹等对象
this.player = new GameObject({
type: 'player',
x: 100,
y: 300,
speed: 5
});
this.enemies = Array.from({length:5}, () =>
new GameObject({
type: 'enemy',
x: Math.random() 300,
y: Math.random() 500,
speed: Math.random() 2 + 1
})
);
this.bullets = [];
},
startGameLoop() {
setInterval(() => {
this.update();
this.render();
}, 16);
},
update() {
// 物体移动
this.player.move();
this.enemies.forEach(enemy => enemy.move());
this.bullets.forEach(bullet => bullet.move());
// 碰撞检测
this.checkCollisions();
},
checkCollisions() {
// 玩家与敌人碰撞检测
this.enemies.forEach(enemy => {
if(this.detectCollision(this.player, enemy)) {
this.gameOver();
}
});
// 子弹与敌人碰撞检测
this.bullets.forEach(bullet => {
this.enemies.forEach(enemy => {
if(this.detectCollision(bullet, enemy)) {
bullet.destroy();
enemy.destroy();
}
});
});
},
detectCollision(obj1, obj2) {
return (
obj1.x < obj2.x + obj2.width &&
obj1.x + obj1.width > obj2.x &&
obj1.y < obj2.y + obj2.height &&
obj1.y + obj1.height > obj2.y
);
}
});
部署注意事项
1.性能优化:
-使用`wx.requestAnimationFrame`替代`setInterval`
-对图片资源进行压缩处理
-合并重复使用的WXS模块
2.兼容性处理:
javascript
if (wx.canIUse('canvas')) {
// 初始化Canvas
} else {
wx.showToast({ title: '您的微信版本过低' });
}
3.支付集成:
javascript
wx.requestPayment({
timeStamp: '...',
nonceStr: '...',
package: 'prepay_id=...',
signType: 'MD5',
success(res) {
console.log('支付成功', res);
}
});