精选 1000 + 微信小游戏源码:休闲 / 益智 / 竞技类全覆盖
在移动互联网流量见顶的今天,微信小游戏凭借其无需下载、即点即玩的特性,依然保持着强大的生命力和用户粘性。对于开发者、创业者或是编程爱好者而言,小游戏是一个绝佳的实践和创富领域。本文旨在为你打开一扇通往微信小游戏开发宝库的大门,精选覆盖休闲、益智、竞技三大主流类型的源码资源,并提供核心代码解析与开发教程,助你从“玩家”蜕变为“创造者”。
源码及演示:y.wxlbyx.icu
准备工作:搭建你的小游戏开发环境
在深入源码之前,我们必须先配好“剑”——开发环境。
注册微信小程序账号: 访问微信公众平台,注册一个小程序账号(小游戏属于小程序的一个类目),获取你的专属 AppID。
安装开发者工具: 下载并安装最新的微信开发者工具。这是官方提供的集成开发环境,集成了编码、调试、预览和上传等功能。
创建小游戏项目: 打开开发者工具,选择“小游戏”,使用你的 AppID 创建一个新项目。项目模板选择“小游戏项目”,你会看到一个最基础的“Hello World”示例。
项目结构初窥:
一个标准的微信小游戏项目通常包含以下核心文件:
game.js: 小游戏的入口文件,负责初始化游戏。game.json: 配置文件,用于设置窗口大小、页面路径、网络超时时间等。project.config.json: 项目配置文件,保存了你的 AppID 等个性化设置。js/目录:存放主要的游戏逻辑 JavaScript 文件。images/和audio/目录:存放游戏所需的图片、音效等资源。
准备工作就绪,现在让我们进入激动人心的源码世界。
休闲类源码实战:经典“跳一跳”核心逻辑解析
休闲类游戏规则简单,易于上手,是小游戏中的绝对主力。我们以曾经风靡一时的“跳一跳”为例,剖析其核心逻辑。
核心玩法: 玩家长按屏幕蓄力,松开后角色(小人)跳跃到下一个方块上。按压力度决定跳跃距离。
我们将其简化为几个关键部分:角色、方块、物理跳跃和输入控制。
1. 角色与方块的定义(main.js)
// 角色类
class Player {
constructor() {
this.x = 100; // 角色初始x坐标
this.y = 200; // 角色初始y坐标
this.width = 40; // 角色宽度
this.height = 40; // 角色高度
this.jumping = false; // 是否正在跳跃
this.jumpForce = 0; // 跳跃力度
this.targetX = 0; // 目标方块x坐标
this.targetY = 0; // 目标方块y坐标
}
// 绘制角色
draw(ctx) {
ctx.fillStyle = '#333333';
ctx.fillRect(this.x - this.width / 2, this.y - this.height, this.width, this.height);
}
// 更新角色状态
update() {
if (this.jumping) {
// 简单的抛物线运动模拟
let dx = this.targetX - this.x;
let dy = this.targetY - this.y;
let distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 1) {
this.x += dx * 0.1; // 横向移动速度
this.y += dy * 0.1; // 纵向移动速度
} else {
this.jumping = false;
// 跳跃完成,可以生成新的方块
}
}
}
// 开始跳跃
jumpTo(targetX, targetY, force) {
this.jumping = true;
this.targetX = targetX;
this.targetY = targetY;
this.jumpForce = force; // 力度的具体应用可以在update中更精细地模拟
}
}
// 方块类
class Block {
constructor(x, y, width) {
this.x = x;
this.y = y;
this.width = width;
this.height = 20;
}
draw(ctx) {
ctx.fillStyle = '#7EC0EE';
ctx.fillRect(this.x - this.width / 2, this.y - this.height / 2, this.width, this.height);
}
}
2. 输入控制与主循环(main.js续)
// 初始化
const canvas = wx.createCanvas();
const ctx = canvas.getContext('2d');
let player = new Player();
let currentBlock = new Block(100, 300, 60); // 第一个方块
let nextBlock = generateNewBlock(); // 生成下一个方块
let pressTime = 0; // 按压时间,用于计算力度
// 生成新方块(简单随机)
function generateNewBlock() {
let x = currentBlock.x + Math.random() * 100 + 50; // 随机距离
let y = currentBlock.y;
let width = 40 + Math.random() * 40;
return new Block(x, y, width);
}
// 触摸开始事件
wx.onTouchStart(() => {
pressTime = Date.now(); // 记录按压开始时间
});
// 触摸结束事件
wx.onTouchEnd(() => {
let force = (Date.now() - pressTime) / 500; // 计算力度(按压时间/500ms)
force = Math.min(force, 2.0); // 限制最大力度
// 玩家跳跃到下一个方块的中心
player.jumpTo(nextBlock.x, nextBlock.y, force);
// 更新方块:当前方块变为下一个,再生成一个新的下一个方块
currentBlock = nextBlock;
nextBlock = generateNewBlock();
});
// 游戏主循环
function gameLoop() {
// 清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 更新和绘制角色
player.update();
player.draw(ctx);
// 绘制方块
currentBlock.draw(ctx);
nextBlock.draw(ctx);
// 请求下一帧动画
requestAnimationFrame(gameLoop);
}
// 启动游戏循环
gameLoop();
教程要点:
核心是状态管理: 游戏通过
player.jumping状态来区分角色是在静止还是跳跃中。输入映射: 将用户的触摸时间映射为跳跃力度,这是休闲游戏常见的交互设计。
运动模拟: 示例中使用的是简单的线性插值,更真实的模拟可以加入重力加速度和抛物线运动。
通过这个简化版源码,你已经掌握了“跳一跳”类游戏的核心骨架。在此基础上,你可以添加分数计算、方块类型(普通、加分、破碎等)、粒子特效等,让游戏变得丰富起来。
益智类源码实战:三消游戏“连连看”匹配算法
益智类游戏考验玩家的逻辑思维,如三消、拼图、数独等。我们以“连连看”的路径匹配算法为例。
核心玩法: 在网格中,选择两个相同的图案,如果它们可以用不超过三根直线连接起来,则消除。
关键算法: 判断两个点 (pointA, pointB)是否可以在“三线”内连通。
路径匹配算法(link-game.js)
// 游戏地图,0表示空白,非0表示不同的图案
const map = [
[1, 2, 3, 4],
[2, 0, 0, 3],
[1, 0, 0, 4],
[5, 5, 6, 6]
];
// 检查两点是否可以连通
function canConnect(x1, y1, x2, y2) {
// 1. 检查是否是同一个点或图案不同
if ((x1 === x2 && y1 === y2) || map[y1][x1] !== map[y2][x2]) {
return false;
}
// 2. 检查直接相连(0折线)
if (checkDirectLink(x1, y1, x2, y2)) {
return true;
}
// 3. 检查一个拐角相连(1折线)
if (checkOneCornerLink(x1, y1, x2, y2)) {
return true;
}
// 4. 检查两个拐角相连(2折线)
if (checkTwoCornerLink(x1, y1, x2, y2)) {
return true;
}
return false;
}
// 直接相连:水平或垂直线上没有障碍物
function checkDirectLink(x1, y1, x2, y2) {
// 水平线检查
if (x1 === x2) {
let minY = Math.min(y1, y2);
let maxY = Math.max(y1, y2);
for (let y = minY + 1; y < maxY; y++) {
if (map[y][x1] !== 0) return false; // 路径上有障碍
}
return true;
}
// 垂直线检查
if (y1 === y2) {
let minX = Math.min(x1, x2);
let maxX = Math.max(x1, x2);
for (let x = minX + 1; x < maxX; x++) {
if (map[y1][x] !== 0) return false;
}
return true;
}
return false;
}
// 一个拐角相连:假设拐点为C(x1, y2)和D(x2, y1)
function checkOneCornerLink(x1, y1, x2, y2) {
// 拐点C
if (map[y2][x1] === 0) { // 拐点C必须是空白
if (checkDirectLink(x1, y1, x1, y2) && checkDirectLink(x1, y2, x2, y2)) {
return true;
}
}
// 拐点D
if (map[y1][x2] === 0) { // 拐点D必须是空白
if (checkDirectLink(x1, y1, x2, y1) && checkDirectLink(x2, y1, x2, y2)) {
return true;
}
}
return false;
}
// 两个拐角相连:遍历所有可能的空白点作为中间点
function checkTwoCornerLink(x1, y1, x2, y2) {
// 遍历水平方向可能的连接点
for (let x = 0; x < map[0].length; x++) {
if (x !== x1 && x !== x2 && map[y1][x] === 0) {
// 假设从(x1,y1) -> (x, y1) -> (x, y2) -> (x2, y2)是通路
if (checkDirectLink(x1, y1, x, y1) &&
checkDirectLink(x, y1, x, y2) &&
checkDirectLink(x, y2, x2, y2)) {
return true;
}
}
}
// 遍历垂直方向可能的连接点
for (let y = 0; y < map.length; y++) {
if (y !== y1 && y !== y2 && map[y][x1] === 0) {
// 假设从(x1,y1) -> (x1, y) -> (x2, y) -> (x2, y2)是通路
if (checkDirectLink(x1, y1, x1, y) &&
checkDirectLink(x1, y, x2, y) &&
checkDirectLink(x2, y, x2, y2)) {
return true;
}
}
}
return false;
}
// 使用示例
let result = canConnect(0, 0, 3, 0); // 检查(0,0)和(3,0)的“1”是否可以连通
console.log(result); // 输出 true 或 false
教程要点:
算法思维: 将复杂问题(三线连通)分解为简单情况的组合(直线、单拐角、双拐角)。
性能考虑: 双拐角检查需要遍历,在大型地图上可能成为性能瓶颈。优化方法包括使用更高效的搜索算法(如BFS)或预先计算连通性。
游戏逻辑: 匹配成功后,需要将两个点的图案置为0(空白),并检查游戏是否完成。
这个算法是“连连看”游戏的灵魂。理解了它,你就能创造出各种复杂的消除规则。

竞技类源码实战:IO游戏“球球大作战”基础同步原理
竞技类游戏强调玩家间的实时对抗,如 IO 游戏(球球大作战、蛇蛇大作战)、轻度射击游戏等。其核心技术挑战是网络同步。
核心玩法: 玩家控制一个球,吃掉地图上的小豆子变大,可以吃掉比自己小的玩家,同时要躲避比自己大的玩家。
我们重点讲解如何用 WebSocket 实现多个玩家状态的同步。
1. 客户端逻辑(client.js)
class GameClient {
constructor() {
this.socket = null;
this.playerId = null;
this.players = new Map(); // 存储所有玩家信息 {id: {x, y, size}}
this.foods = []; // 存储所有食物信息
}
// 连接游戏服务器
connect() {
this.socket = wx.connectSocket({
url: 'wss://your-game-server.com'
});
this.socket.onOpen(() => {
console.log('连接服务器成功');
});
this.socket.onMessage((res) => {
let message = JSON.parse(res.data);
this.handleMessage(message);
});
// 定时向服务器发送本机玩家的输入状态(如目标方向)
setInterval(() => {
if (this.playerId) {
this.sendInput();
}
}, 50); // 每50ms发送一次,频率可根据游戏调整
}
// 处理服务器消息
handleMessage(msg) {
switch (msg.type) {
case 'login':
this.playerId = msg.id;
break;
case 'update':
// 服务器广播的全局状态更新
this.players = new Map(Object.entries(msg.players));
this.foods = msg.foods;
this.render(); // 根据新状态渲染游戏画面
break;
}
}
// 发送玩家输入(例如鼠标/触摸点的方向)
sendInput() {
// 假设通过触摸事件获取了目标点(targetX, targetY)
let inputMsg = {
type: 'input',
targetX: this.targetX,
targetY: this.targetY
};
this.socket.send({
data: JSON.stringify(inputMsg)
});
}
// 渲染游戏画面
render() {
const ctx = wx.createCanvas().getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制所有食物
this.foods.forEach(food => {
drawCircle(ctx, food.x, food.y, food.size, food.color);
});
// 绘制所有玩家(包括自己)
this.players.forEach((player, id) => {
let isMe = id === this.playerId;
drawCircle(ctx, player.x, player.y, player.size, isMe ? 'blue' : 'red');
if (isMe) {
// 如果是自己,可以额外绘制名字等
ctx.fillText(`我(${player.size})`, player.x, player.y - player.size - 5);
}
});
}
// 触摸事件,设置目标方向
onTouchMove(e) {
let touch = e.touches[0];
this.targetX = touch.clientX;
this.targetY = touch.clientY;
}
}
function drawCircle(ctx, x, y, radius, color) {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
ctx.closePath();
}
// 初始化客户端
const client = new GameClient();
client.connect();
wx.onTouchMove((e) => client.onTouchMove(e));
2. 服务器端逻辑简析(Node.js示例)
服务器端(如使用 Node.js + WebSocket 库)的核心职责是:
权威验证: 所有玩家的移动、吃食物、碰撞检测等逻辑都应在服务器端进行,防止客户端作弊。
状态广播: 以固定的频率(例如每秒20次)将整个游戏世界的状态(所有球的位置、大小,食物的位置)广播给所有连接的客户端。
// 伪代码,展示服务器主循环思路
setInterval(() => {
// 1. 遍历所有客户端发送的input,更新他们控制的球的方向/速度
clients.forEach(client => {
if (client.input) {
updatePlayerPosition(client.player, client.input);
}
});
// 2. 进行游戏逻辑判断(吃食物、玩家碰撞)
checkCollisions();
// 3. 构建状态快照
let gameState = {
type: 'update',
players: getAllPlayersData(),
foods: getAllFoodsData()
};
// 4. 广播给所有客户端
broadcast(JSON.stringify(gameState));
}, 50); // 每50ms(20FPS)更新并广播一次
教程要点:
状态同步 vs 帧同步: 此例采用的是“状态同步”,服务器是权威,只同步结果状态。另一种是“帧同步”(常用于RTS、MOBA),同步的是输入指令,各客户端运行相同的确定性逻辑。小游戏多采用状态同步,更简单。
网络优化: 为减少带宽,可以只发送变化的部分(差值同步),而不是全量状态。
延迟处理: 真实的游戏需要加入插值、预测等算法来掩盖网络延迟,提升操作手感。

结语
微信小游戏开发是一片充满机遇的沃土。通过深入研究这上千份覆盖休闲、益智、竞技等类型的源码,你相当于站在了巨人的肩膀上。从分析“跳一跳”的物理交互,到破解“连连看”的匹配算法,再到理解“球球大作战”的网络同步,每一步都是你技术栈的一次坚实拓展。记住,源码是地图,实践是脚步。现在,就打开微信开发者工具,选择一份你感兴趣的源码,开始你的第一个小游戏项目吧!从模仿到创新,下一个爆款小游戏的创造者,可能就是你。
