【HTML5游戏开发教程】零基础入门合成大西瓜游戏实战 | JS物理引擎+Canvas动画+完整源码详解
《从咖啡杯到财务自由:一个程序员的合成之旅——当代码遇上物理引擎的匠心之作》
🌟 这是小游戏开发系列的第四篇送福利文章,感谢一路以来支持和关注这个项目的每一位朋友!
💡 文章力求严谨,但难免有疏漏之处,欢迎各位朋友指出,让我们一起在交流中进步。
💌 如果您有任何想法、建议或疑问,都欢迎在评论区留言或通过私信与我交流。您的每一个反馈都是项目进步的动力!
这款游戏不仅融合了流行的合成玩法,更加入了大量程序员文化元素,让我们在休闲娱乐的同时,感受到浓浓的技术氛围。
合成大西瓜Pro版 - 纯程序猿元素风
文章目录
- 《从咖啡杯到财务自由:一个程序员的合成之旅——当代码遇上物理引擎的匠心之作》
- 游戏介绍:从咖啡杯到财务自由
- 演示视频:
- 部分截图:
- 技术栈:轻量而强大
- 模块详解:游戏架构拆解
- 1. 核心游戏模块 (Game.js)
- 2. 物品渲染模块 (ItemRenderer.js)
- 3. 音频管理模块 (AudioManager.js)
- 4. IDE风格控制台 (ConsoleManager.js)
- 5. 彩蛋系统:游戏点睛之笔
- 主要彩蛋类型:
- 开发难点与解决方案
- 1. 物理碰撞的稳定性
- 2. 游戏性能优化
- 项目代码:
- 写在最后
游戏介绍:从咖啡杯到财务自由
“程序员版合成大西瓜"是一款基于物理引擎的休闲合成游戏,专为程序员群体量身定制。游戏的主要目标是通过合成相同物品,一步步从最基础的程序员日常用品(咖啡杯)开始,最终合成象征成功的"财务自由”。
游戏流程十分直观:
- 玩家点击屏幕顶部,投放物品(初始为咖啡杯)
- 物品会根据物理规则自由下落并互相碰撞
- 当两个相同物品碰撞并满足特定条件时,会合成为更高级的物品
- 随着得分增加,玩家的"程序员等级"会提升,解锁更多游戏内容
- 当物品堆积过高达到警戒线时,游戏结束
我们设计了一条充满程序员文化的合成路径:
咖啡杯(☕) → 键盘(⌨️) → 笔记本(💻) → 显示器(🖥️) → 主机(🖥️) → 服务器(🖧) → 财务自由(💰)
每一级合成都会带来翻倍的分数回报:从咖啡杯的2分,到财务自由的128分。当玩家成功合成三个"财务自由"时,将触发游戏通关彩蛋,获得专属的程序员成就证书!
演示视频:
合成大西瓜Pro版-程序员风
部分截图:
本游戏有非常非常多的彩蛋,每种彩蛋触发时机不同,需要玩家自行探索~~~
首页:
财富自由彩蛋:
终极彩蛋:
技术栈:轻量而强大
为了确保游戏运行流畅且易于扩展,我们精心选择了以下技术栈:
- 前端基础:HTML5、CSS3、JavaScript (ES6+)
- 构建工具:Vite(提供极速的开发体验)
- 物理引擎:Matter.js(处理游戏物体的物理行为和碰撞)
- 包管理:npm
值得一提的是,我们没有使用任何重量级前端框架(如React、Vue),而是选择了纯原生JavaScript实现。这不仅减轻了项目体积,提升了加载速度,还降低了学习门槛,让更多对游戏开发感兴趣的朋友能够轻松理解代码结构。
模块详解:游戏架构拆解
1. 核心游戏模块 (Game.js)
这是整个游戏的中枢神经系统,负责协调各个模块的工作,管理游戏状态和物理世界。
核心功能:
- 物理世界的创建与管理
- 游戏主循环的实现
- 物品合成逻辑的控制
- 分数计算与等级提升
- 游戏状态(开始、暂停、结束)管理
引擎初始化代码:
constructor() {// Matter.js 模块初始化this.engine = Matter.Engine.create({enableSleeping: true,constraintIterations: 3,positionIterations: 8,velocityIterations: 6,timing: {timeScale: 1.1,timestamp: 0}})// 创建运行器,固定帧率this.runner = Matter.Runner.create({isFixed: true,delta: 1000 / 60 // 固定60帧})// 设置渲染器this.render = Matter.Render.create({element: document.getElementById('app'),engine: this.engine,options: {width: GAME_CONFIG.width,height: GAME_CONFIG.height,wireframes: false,background: 'transparent',pixelRatio: window.devicePixelRatio || 1,fps: 60}})// 设置重力this.engine.gravity.y = PHYSICS_CONFIG.gravity
}
这段代码展示了如何初始化物理引擎。我们精心调整了物理参数,以确保游戏体验的流畅性。特别是positionIterations
和velocityIterations
参数的提高,使物理模拟更加精确,减少了物体穿透的可能性。
开发难点:
物品合成判定是最大的挑战之一。为了实现自然流畅的合成体验,我们采用了复合判定条件:结合物品间的距离、接触时间以及相对速度三个关键因素。这种方法解决了合成触发不稳定的问题,提升了游戏的可玩性。
// 碰撞检测与合并逻辑
Matter.Events.on(this.engine, 'collisionStart', (event) => {if (this.isPaused || this.gameOver) returnevent.pairs.forEach((pair) => {const { bodyA, bodyB } = pair// 检查两个物体是否相同类型且不在活动合并列表中if (bodyA.itemType && bodyB.itemType && bodyA.itemType.name === bodyB.itemType.name) {const pairId = [bodyA.id, bodyB.id].sort().join('-')// 避免重复添加if (!activeMergingPairs.has(pairId) && !collisionPairs.has(pairId)) {// 记录碰撞信息collisionPairs.set(pairId, {bodyA, bodyB,time: Date.now(),contactPoint: {x: (bodyA.position.x + bodyB.position.x) / 2,y: (bodyA.position.y + bodyB.position.y) / 2},initialVelocityA: { ...bodyA.velocity },initialVelocityB: { ...bodyB.velocity },contactFrames: 0})}}})
})
合并条件判定代码:
// 合并条件判定
const distCondition = dist < GAME_CONFIG.mergeThreshold * 1.5 * totalRadius;
const timeCondition = now - time > GAME_CONFIG.mergeWindow * 0.7;
const velocityCondition = totalVelocity < 0.8 && contactFrames > 15;if (distCondition && (timeCondition || velocityCondition)) {this.handleMerge(bodyA, bodyB);collisionPairs.delete(pairId);activeMergingPairs.delete(pairId);
}
这是游戏核心机制的一部分,通过综合考虑多种条件,使合成过程更加智能和自然。当两个物体足够接近且满足时间或速度条件时,会触发合并处理。
2. 物品渲染模块 (ItemRenderer.js)
负责游戏中各种物品的视觉呈现,确保每个物品都有鲜明的辨识度和程序员文化气息。
核心功能:
- 使用Canvas API绘制各类程序员物品
- 实现物品合成的视觉特效
- 处理不同大小物品的适配渲染
程序化绘制代码示例:
// 渲染咖啡杯
static renderCoffee(ctx, x, y, size) {const scale = size / 100;// 绘制杯子主体ctx.beginPath();ctx.fillStyle = '#75432A';ctx.moveTo(x - 30 * scale, y - 15 * scale);ctx.bezierCurveTo(x - 32 * scale, y + 25 * scale,x - 28 * scale, y + 35 * scale,x - 20 * scale, y + 35 * scale);ctx.lineTo(x + 20 * scale, y + 35 * scale);ctx.bezierCurveTo(x + 28 * scale, y + 35 * scale,x + 32 * scale, y + 25 * scale,x + 30 * scale, y - 15 * scale);ctx.closePath();ctx.fill();// 绘制咖啡液体ctx.beginPath();ctx.fillStyle = '#4A2C1A';ctx.ellipse(x, y - 15 * scale, 30 * scale, 10 * scale, 0, 0, Math.PI * 2);ctx.fill();// 绘制杯把ctx.beginPath();ctx.strokeStyle = '#75432A';ctx.lineWidth = 5 * scale;ctx.arc(x + 35 * scale, y + 10 * scale, 10 * scale, Math.PI * 1.2, Math.PI * 1.8);ctx.stroke();
}
这段代码展示了如何使用Canvas API绘制咖啡杯物品。我们使用贝塞尔曲线和基本形状组合创建了具有立体感的图形,而不是使用图片资源。
合并动画效果代码:
static renderMergeAnimation(ctx, x, y, size, progress) {// 创建闪光效果const radius = size * (1 + progress * 0.5);const opacity = 1 - progress;// 绘制外部光环ctx.beginPath();ctx.arc(x, y, radius, 0, Math.PI * 2);ctx.fillStyle = `rgba(255, 255, 255, ${opacity * 0.7})`;ctx.fill();// 绘制内部光芒const gradient = ctx.createRadialGradient(x, y, 0, x, y, radius);gradient.addColorStop(0, `rgba(255, 215, 0, ${opacity})`);gradient.addColorStop(0.7, `rgba(255, 140, 0, ${opacity * 0.5})`);gradient.addColorStop(1, `rgba(255, 69, 0, 0)`);ctx.beginPath();ctx.arc(x, y, radius * 0.8, 0, Math.PI * 2);ctx.fillStyle = gradient;ctx.fill();// 添加粒子效果const particles = 8;for (let i = 0; i < particles; i++) {const angle = (i / particles) * Math.PI * 2;const dist = radius * 0.6 * progress;const px = x + Math.cos(angle) * dist;const py = y + Math.sin(angle) * dist;const particleSize = (1 - progress) * size * 0.2;ctx.beginPath();ctx.arc(px, py, particleSize, 0, Math.PI * 2);ctx.fillStyle = `rgba(255, 215, 0, ${opacity * 0.8})`;ctx.fill();}
}
这段代码实现了物品合成时的视觉特效。通过创建光环、渐变和粒子效果,使合成过程更加生动直观。效果随progress参数(0到1)动态变化,形成平滑的动画效果。
开发难点:
我们选择了程序化生成图形,而非使用图片资源。这种方式虽然增加了编码复杂度,但显著减少了资源加载时间,提升了游戏启动速度,同时也为未来可能的物品自定义提供了基础。
3. 音频管理模块 (AudioManager.js)
负责游戏中所有音效和背景音乐的控制,为游戏增添听觉体验。
核心功能:
- 音频资源的预加载
- 游戏事件触发的音效播放
- 背景音乐的循环播放与控制
音频加载与错误处理代码:
export class AudioManager {constructor() {this.sounds = {};this.bgm = null;this.isMuted = false;this.loadFailed = false;}loadAudio() {try {// 加载背景音乐this.bgm = new Audio('/src/assets/audio/bgm.mp3');this.bgm.loop = true;this.bgm.volume = 0.5;// 预加载音效const soundFiles = {drop: '/src/assets/audio/drop.mp3',merge: '/src/assets/audio/merge.mp3',levelup: '/src/assets/audio/levelup.mp3'};// 使用Promise.all并行加载所有音效const loadPromises = Object.entries(soundFiles).map(([key, path]) => {return new Promise((resolve, reject) => {const audio = new Audio(path);audio.addEventListener('canplaythrough', () => {this.sounds[key] = audio;resolve();}, { once: true });// 添加错误处理audio.addEventListener('error', (e) => {console.warn(`音频 ${key} 加载失败:`, e);// 即使加载失败也允许继续this.loadFailed = true;resolve();}, { once: true });// 开始加载audio.load();});});// 等待所有音效加载完成return Promise.all(loadPromises).then(() => console.log('所有音频加载完成')).catch(err => {console.error('音频加载过程出错:', err);this.loadFailed = true;});} catch (error) {console.error('音频初始化失败:', error);this.loadFailed = true;return Promise.resolve(); // 返回已解决的Promise以免中断游戏}}// 播放音效的安全方法playSound(name) {if (this.isMuted || this.loadFailed) return;try {const sound = this.sounds[name];if (!sound) return;// 克隆节点以允许重叠播放const soundClone = sound.cloneNode();soundClone.volume = name === 'levelup' ? 0.8 : 0.6;// 播放后自动清理soundClone.addEventListener('ended', () => {soundClone.remove();}, { once: true });soundClone.play().catch(e => {console.warn(`播放音效 ${name} 失败:`, e);});} catch (error) {console.warn('播放音效错误:', error);}}
}
这段代码展示了如何实现健壮的音频加载和播放系统。我们使用Promise并行加载所有音效,并添加了全面的错误处理机制,确保即使音频加载失败也不会影响游戏主体功能。
开发难点:
浏览器音频API的兼容性问题是一大挑战。我们实现了完善的错误捕获机制,确保即使音频加载失败,也不会影响游戏主体功能的运行。另一个挑战是解决自动播放限制,我们通过用户交互触发首次播放来解决这个问题。
// 在main.js中处理自动播放限制
function startMusicOnInteraction() {if (!musicStarted) {try {game.audioManager.playBGM()musicStarted = true} catch (error) {console.warn('播放背景音乐失败:', error)}// 移除所有事件监听器document.removeEventListener('click', startMusicOnInteraction)document.removeEventListener('keydown', startMusicOnInteraction)document.removeEventListener('touchstart', startMusicOnInteraction)}
}// 添加用户交互事件监听器
document.addEventListener('click', startMusicOnInteraction)
document.addEventListener('keydown', startMusicOnInteraction)
document.addEventListener('touchstart', startMusicOnInteraction)
4. IDE风格控制台 (ConsoleManager.js)
这是游戏中最具特色的元素之一,模拟IDE控制台,实时显示游戏事件和调试信息。
核心功能:
- 不同类型消息的格式化显示
- 控制台滚动和历史记录管理
- 程序员幽默元素的随机插入
控制台实现代码:
export class ConsoleManager {constructor() {this.consoleElement = document.querySelector('.console-output');this.messageHistory = [];this.maxMessages = 100;// 初始化控制台this.clear();this.log('程序员合成大西瓜 v1.0.0 初始化中...', 'info');this.log('物理引擎加载完成', 'success');this.log('准备就绪,开始游戏吧!', 'success');}// 添加日志消息log(message, type = 'log') {// 创建新的日志元素const logElement = document.createElement('div');logElement.className = `log ${type}`;// 根据类型添加前缀let prefix = '';switch(type) {case 'error': prefix = '[ERROR] '; break;case 'warning': prefix = '[WARN] '; break;case 'info': prefix = '[INFO] '; break;case 'success': prefix = '[SUCCESS] '; break;default: prefix = '[LOG] ';}// 添加当前时间const time = new Date().toLocaleTimeString();logElement.textContent = `${prefix}${time} - ${message}`;// 添加到控制台并保存到历史记录this.consoleElement.appendChild(logElement);this.messageHistory.push({type,message,time});// 限制历史记录长度if (this.messageHistory.length > this.maxMessages) {this.messageHistory.shift();// 也从DOM中移除最早的消息if (this.consoleElement.children.length > this.maxMessages) {this.consoleElement.removeChild(this.consoleElement.children[0]);}}// 自动滚动到最新消息this.consoleElement.scrollTop = this.consoleElement.scrollHeight;// 添加入场动画logElement.style.opacity = '0';setTimeout(() => {logElement.style.opacity = '1';}, 10);// 随机添加程序员幽默元素this.maybeAddProgrammerHumor();return logElement;}// 随机添加程序员幽默maybeAddProgrammerHumor() {// 每20条消息有约10%概率出现幽默元素if (this.messageHistory.length % 20 === 0 && Math.random() < 0.1) {const jokes = ['又在努力调试了一整天,才发现是少了一个分号...','尝试了99种方法都不行?那就尝试第100种吧!','git commit -m "我也不知道为什么这能运行,但它就是运行了"','当代码运行时,别动它;当代码不运行时,也别动它。','Error 404: 咖啡不足','世界上最遥远的距离不是生与死,而是你我之间的1px偏差'];const randomJoke = jokes[Math.floor(Math.random() * jokes.length)];this.log(randomJoke, 'info');}}// 清空控制台clear() {this.consoleElement.innerHTML = '';this.log('控制台已清空', 'info');}
}
这段代码展示了如何实现一个交互式的模拟IDE控制台。它不仅能显示不同类型的消息,还会自动管理消息历史记录、控制滚动,甚至随机穿插程序员幽默元素,增强游戏的文化氛围。
开发难点:
平衡信息量和游戏体验是最大的挑战。我们精心设计了信息过滤机制,确保玩家既能获得必要的游戏反馈,又不会被过多的技术细节所干扰。
5. 彩蛋系统:游戏点睛之笔
作为一款面向程序员的游戏,彩蛋系统是我们投入心血最多的部分。我们设计了多种彩蛋,在不同条件下触发,为玩家带来意外的惊喜。
游戏通关彩蛋代码:
// 触发游戏通关彩蛋
triggerGameBeatEasterEgg() {console.log("恭喜通关!你已经合成了三个财务自由!");// 暂停游戏this.isPaused = true;// 播放胜利音效序列this.audioManager.playVictoryFanfare();// 计算游戏统计数据const stats = this.calculateGameStats();// 创建通关UIconst eggContainer = document.createElement('div');eggContainer.className = 'game-beat-egg';eggContainer.innerHTML = `<div class="endgame-content"><div class="endgame-title-container"><div class="endgame-banner"></div><h1 class="endgame-title">恭喜通关!</h1></div><div class="endgame-certificate"><div class="certificate-header">程序员成就证书</div><div class="certificate-body"><div class="achievement">✓ 成功实现财务自由</div><div class="achievement">✓ 编程技能达到专家级别</div><div class="achievement">✓ 解锁自由职业者生涯</div><div class="stats-grid"><div class="stat-item"><div class="stat-label">游戏时长</div><div class="stat-value">${stats.playTime} 分钟</div></div><div class="stat-item"><div class="stat-label">总得分</div><div class="stat-value">${this.score}</div></div><div class="stat-item"><div class="stat-label">合成次数</div><div class="stat-value">${stats.totalMerges}</div></div><div class="stat-item"><div class="stat-label">程序员等级</div><div class="stat-value">Lv.${stats.highestLevel}</div></div><div class="stat-item"><div class="stat-label">消耗咖啡</div><div class="stat-value">${stats.coffeeConsumed} 杯</div></div><div class="stat-item"><div class="stat-label">编写代码</div><div class="stat-value">${stats.linesOfCode} 行</div></div></div></div><div class="certificate-footer"><div class="certificate-date">${new Date().toLocaleDateString()}</div><div class="certificate-seal"></div></div></div><div class="endgame-message"><p>成功通关!你已经成为了拥有财务自由的程序员精英!</p><p class="joke">通往成功的唯一捷径,就是把if/else改成switch,这会加速程序运行(笑)</p></div><button class="continue-button">继续游戏</button></div>`;// 添加特效元素for (let i = 0; i < 20; i++) {const particle = document.createElement('div');particle.className = 'endgame-particle';particle.style.left = `${Math.random() * 100}%`;particle.style.top = `${Math.random() * 100}%`;particle.style.animationDelay = `${Math.random() * 5}s`;eggContainer.appendChild(particle);}// 添加流星for (let i = 0; i < 3; i++) {const star = document.createElement('div');star.className = 'shooting-star';star.style.top = `${10 + Math.random() * 30}%`;star.style.left = `${Math.random() * 20}%`;star.style.animationDelay = `${i * 3}s`;eggContainer.appendChild(star);}// 添加到文档document.body.appendChild(eggContainer);// 添加按钮事件const continueButton = eggContainer.querySelector('.continue-button');continueButton.addEventListener('click', () => {eggContainer.classList.add('fade-out');setTimeout(() => {eggContainer.remove();this.isPaused = false;}, 1000);});// 保存通关记录this.saveGameCompletionStats();
}// 计算游戏统计数据
calculateGameStats() {return {playTime: Math.floor((Date.now() - this.gameStartTime) / 60000), // 游戏时长(分钟)totalMerges: this._mergeCount || 0, // 总合成次数highestLevel: this.currentLevel, // 最高等级financialFreedoms: this.financialFreedomCount, // 财务自由数量difficultyLevel: this.difficultyLevel + 1, // 难度级别// 随机生成一些有趣的统计数据coffeeConsumed: Math.floor(Math.random() * 15) + 5, // 5-20杯咖啡linesOfCode: (Math.floor(Math.random() * 2000) + 1000) * this.score, // 基于分数的代码行数bugsFixed: Math.floor(Math.random() * 99) + 1, // 1-100个bugsleepLost: Math.floor(Math.random() * 12) + 4 // 4-16小时};
}
这段代码实现了游戏的通关彩蛋,当玩家成功合成三个"财务自由"物品时触发。彩蛋不仅显示游戏成绩,还生成了一张精美的"程序员成就证书",并添加了流星和粒子特效,为玩家带来视觉盛宴。
主要彩蛋类型:
-
财务自由彩蛋:首次合成"财务自由"物品时触发,模拟终端界面展示玩家的虚拟财富状况。
-
游戏通关彩蛋:成功合成三个"财务自由"物品时触发,展示精美的程序员成就证书,记录游戏统计数据和幽默的成就描述。
-
等级彩蛋:在达到特定程序员等级时触发,解锁特殊能力或游戏机制。
特殊彩蛋触发代码:
// 特殊彩蛋方法
triggerSpecialEasterEgg(type, message) {this.consoleManager.log(message, 'warning')if (type === 'mid_game') {// 在游戏中间触发的彩蛋const warningElement = document.createElement('div')warningElement.className = 'special-easter-egg mid-game'warningElement.innerHTML = `<div class="terminal-window"><div class="terminal-header"><span class="terminal-title">Terminal</span><span class="terminal-controls">×</span></div><div class="terminal-content"><div class="command-line">$ rm -rf node_modules</div><div class="command-output">Deleting... This might take a while</div><div class="command-prompt">_</div></div></div>`document.body.appendChild(warningElement)// 3秒后删除彩蛋元素setTimeout(() => {warningElement.classList.add('fade-out')setTimeout(() => warningElement.remove(), 1000)}, 3000)}else if (type === 'high_level') {// 高等级特殊彩蛋const confetti = document.createElement('div')confetti.className = 'confetti-container'// 创建50个随机彩色纸屑for (let i = 0; i < 50; i++) {const color = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff'][Math.floor(Math.random() * 5)]const piece = document.createElement('div')piece.className = 'confetti-piece'piece.style.backgroundColor = colorpiece.style.left = Math.random() * 100 + '%'piece.style.animationDelay = Math.random() * 3 + 's'piece.style.animationDuration = Math.random() * 2 + 2 + 's'confetti.appendChild(piece)}document.body.appendChild(confetti)// 5秒后删除纸屑setTimeout(() => {confetti.remove()}, 5000)}
}
这段代码展示了如何实现特殊彩蛋,当玩家达到特定等级时触发。这些彩蛋包括模拟终端窗口执行命令和彩色纸屑庆祝效果,为游戏增添了更多惊喜和乐趣。
开发难点与解决方案
1. 物理碰撞的稳定性
问题:使用Matter.js实现物理碰撞时,有时会出现物体穿透或合成判定不准确的问题。
解决方案:
- 优化碰撞参数,增加迭代次数提高精度
- 设计复合判定条件,综合考虑距离、时间和速度
- 添加额外的安全检查,防止边缘情况导致的错误
代码实现:
// 物理引擎参数优化
this.engine = Matter.Engine.create({enableSleeping: true,constraintIterations: 3, // 增加约束迭代次数positionIterations: 8, // 增加位置迭代次数velocityIterations: 6 // 增加速度迭代次数
})
2. 游戏性能优化
问题:当屏幕上物体数量增多时,物理计算会导致性能下降。
解决方案:
- 实现物体睡眠机制,减少静止物体的计算量
- 优化渲染循环,分离物理更新和视觉渲染
- 使用固定时间步长更新物理世界,保证稳定性
代码实现:
gameLoop() {if (this.gameOver) returnconst loop = (currentTime) => {if (!this.isPaused) {try {// 计算时间步长const deltaTime = currentTime - this.lastTimethis.lastTime = currentTimethis.accumulator += deltaTime// 固定时间步长更新物理while (this.accumulator >= this.fixedDeltaTime) {Matter.Engine.update(this.engine, this.fixedDeltaTime)this.accumulator -= this.fixedDeltaTime}this.checkLevelUp()this.checkDifficulty()this.checkWarningLine()this.updateGameState()this.checkCanDrop()} catch (error) {console.error('游戏循环错误:', error)// 尝试恢复游戏状态this.canDropItem = truethis.lastDroppedItem = null}}requestAnimationFrame(loop.bind(this))}requestAnimationFrame(loop.bind(this))
}
这段代码实现了一个高效的游戏循环,使用固定时间步长更新物理世界,确保物理模拟的精确性和一致性,同时避免了过度渲染导致的性能问题。
项目代码:
👉 项目源码点击这里获取👈
写在最后
🎉 到这里,“程序员版合成大西瓜"游戏的开发分享就到这里啦!希望这些内容能帮助到你的日常开发工作,也欢迎你下载游戏体验,看看能否成功合成三个"财务自由”,解锁终极彩蛋!
如果觉得有帮助的话,别忘了点个赞 👍 收藏 ⭐ 关注 🔖 哦!
💡 开发路上,我们都是学习者。如果你有任何问题或更好的想法,欢迎在评论区留言交流!
🤝 一起进步,共同成长~
🎯 我是果冻~,一个热爱技术、乐于分享的开发者
📚 更多精彩内容,请关注我的博客
🌟 我们下期再见!
相关文章:
【HTML5游戏开发教程】零基础入门合成大西瓜游戏实战 | JS物理引擎+Canvas动画+完整源码详解
《从咖啡杯到财务自由:一个程序员的合成之旅——当代码遇上物理引擎的匠心之作》 🌟 这是小游戏开发系列的第四篇送福利文章,感谢一路以来支持和关注这个项目的每一位朋友! 💡 文章力求严谨,但难免有疏漏之…...
【C#语言】深入理解C#多线程编程:从基础到高性能实践
文章目录 ⭐前言⭐一、多线程的本质价值🌟1、现代计算需求🌟2、C#线程演进史 ⭐二、线程实现方案对比🌟1、传统线程模型🌟2、现代任务模型(推荐)🌟3、异步编程范式 ⭐三、线程安全深度解析&…...
短信验证码安全需求设计
背景: 近期发现部分系统再短信充值频繁,发现存在恶意消耗短信额度现象,数据库表排查,发现大量非合法用户非法调用短信接口API导致额度耗尽。由于系统当初设计存在安全缺陷,故被不法分子进行利用,造成损失。…...
selenium实现自动登录项目(5)
1、163邮箱自动登录功能 遇到的问题: 1、登录页面,在定位表单时候,采用id,xpath,css selector都无法定位成功,因为id后面有个随机生成的数字(//*[id"x-URS-iframe1741925838640.6785&quo…...
多 线 程
一.基本知识 线程:线程是操作系统能够运行调度的最小单位 进程:进程是程序执行实体 多线程应用场景:拷贝、迁移大文件,加载大量的资源文件 并发:有多个指令在单个cpu上交替执行 并行:在同一时刻人&…...
C#:类型定义中使用问号(?)
在 C# 中,类型定义中的问号(?)主要用于控制类型的可空性,但具体行为因类型(值类型或引用类型)和 C# 版本而异。以下是清晰分类的说明: 一、可空值类型(T?,适用于所…...
基于飞腾FT2000+服务器主板与DeepSeek大模型的国产化AI算力探索
随着国产化处理器和AI技术的快速发展,自主可控的算力解决方案日益受到关注。国内大模型技术飞速发展,Deepseek等大模型在自然语言处理、计算机视觉等领域展现出强大的能力。面对大模型的计算需求,服务器硬件的国产化成为重要趋势。 飞腾FT20…...
知识篇 | Oracle的 TEMP表空间管理和优化
Oracle临时表空间(TEMP)是数据库中用于存储会话级临时数据的核心组件,主要用于支持需要中间结果集的操作(如排序、哈希连接)。其数据在事务结束或会话终止后自动释放,不持久化存储。 核心特点:…...
鸿蒙进行视频上传,使用 request.uploadFile方法
一.拉起选择器进行视频选择,并且创建文件名称 async getPictureFromAlbum() {// 拉起相册,选择图片let PhotoSelectOptions new photoAccessHelper.PhotoSelectOptions();PhotoSelectOptions.MIMEType photoAccessHelper.PhotoViewMIMETypes.VIDEO_TY…...
如何下载 Postman?快速指南!
Postman 是一款非常受欢迎的 API 测试工具。它最初是作为一个 Chrome 插件发布,后来发展成为一款独立的跨平台软件,支持 Windows、Mac、Linux 等操作系统。 Postman 怎么下载教程(2025最新版)?...
Angular由一个bug说起之十五:自定义基于Overlay的Tooltip
背景 工具提示(tooltip)是一个常见的 UI 组件,用于在用户与页面元素交互时提供额外的信息。由于angular/material/tooltip的matTooltip只能显示纯文本,所以我们可以通过自定义Directive来实现一个灵活且功能丰富的tooltip Overlay…...
M系mac怎么关闭sip
SIP是系统级的权限操作,我们无法直接关闭它。记录一下如何成功关闭SIP。 一. 查看自己mac的sip是否关闭,终端中输入该下命令: csrutil status 未关闭:System Integrity Protection status: enabled. 已关闭:System…...
Kafka 的延迟队列、死信队列和重试队列
总结一下实现的方法: 1、延迟队列,首先kafka是没有延迟队列的,那要实现延迟队列的话,就得使用其他方法。在发送消息的时候加上时间戳,再在时间戳上面加上延迟时间。消费的时候判断一下,有没有到达延迟时间&…...
OpenCV正确安装及环境变量配置
安装OpenCV(v4.6.0)安装Python(3.10.6)安装VS2022的C桌面开发,手动勾选Windows 10 SDK和MSVC安装CMake(3.31.6)在.npmrc配置pnpm config set auto-approve-builds true运行pnpm install 接下来是…...
分布式系统的CAP理论、事务和锁实现
分布式系统核心概念 1. CAP理论 CAP理论指出,分布式系统最多同时满足以下三项中的两项: 一致性(CC):所有节点访问同一份最新数据。可用性(AA):每个请求都能在合理时间内获得非错误…...
JBDev - Theos下一代越狱开发工具
JBDev - Theos下一代越狱开发工具 自越狱诞生以来,Theos一直是越狱开发的主流工具,大多数开发者使用Theos编译代码,再用lldb手动调试。JBDev简化了这个过程,项目地址https://github.com/lich4/JBDev 简介 JBDev用于Xcode越狱开…...
vue3自定义动态锚点列表,实现本页面锚点跳转效果
需求:当前页面存在多个模块且内容很长时,需要提供一个锚点列表,可以快速查看对应模块内容 实现步骤: 1.每个模块添加唯一id,添加锚点列表div <template><!-- 模块A --><div id"modalA">…...
华为、浪潮、华三链路聚合概述
1、华为 链路聚合可以提高链路带宽和链路冗余性。有三种类型,分别是手工链路聚合,静态lacp链路聚合,动态lacp链路聚合。 手工链路模式:也称负载分担模式,需手动指定链路,各链路之间平均分担流量。静态LAC…...
RUBY报告系统
我们常用GFP及其变体如RFP、YFP、mCherry等作为基因表达的报告蛋白——需要荧光显微镜制片观察;此外还有GUS或荧光素酶作为报告酶——需要添加底物。 RUBY报告系统则与众不同,其作用原理是:将酪氨酸转化为鲜艳的红色甜菜碱,无需使…...
HO与OH差异之Navigation三
在上一篇内容中我们介绍了HO与OH差异之Navigator,我们也了解了Navigator的基本概念和大致了解了一下他的基础用法,既然谈到差异肯定就不止这两种差异,今天就让我们来了解第三种差异NavRouter,其中在HO中我们并没有这种路由方式但是…...
PyTorch处理数据--Dataset和DataLoader
在 PyTorch 中,Dataset 和 DataLoader 是处理数据的核心工具。它们的作用是将数据高效地加载到模型中,支持批量处理、多线程加速和数据增强等功能。 一、Dataset:数据集的抽象 Dataset 是一个抽象类,用于表示数据集的接口。你…...
Linux搭建NFS服务
1.概述 Network File System的缩写,它最大的功能是可以通过网络使用挂载的方式,让不同的机器、不同的操作系统可以共享彼此的文件 2.名称 软件名 nfs-utils服务名 nfs或者nfs-server 3.端口 nfs-server tcp/2049 负责建立连接 rpcbind tcp/111 负责…...
ubuntu服务器server版安装,ssh远程连接xmanager管理,改ip网络连接。图文教程
ventoy启动服务器版iso镜像,注意看server名称,跟之前desktop版ubuntu不一样。没有gui界面。好,进入命令行界面。语言彻底没汉化了,选英文吧,别的更看不懂。 跟桌面版ubuntu类似,选择是否精简系统࿰…...
GC overhead limit exceeded---Java 虚拟机 (JVM) 在进行垃圾回收内存量非常少解决
背景: 我正在跑一个数据处理较为复杂的程序。然后调试了很多遍,出现了GC问题,如下图bug. GC overhead limit exceeded-这个bug错误通常表示 Java 虚拟机 (JVM) 在进行垃圾回收时花费了过多的时间,并且回收的内存量非常少。…...
Pytorch学习笔记(十二)Learning PyTorch - NLP from Scratch
这篇博客瞄准的是 pytorch 官方教程中 Learning PyTorch 章节的 NLP from Scratch 部分。 官网链接:https://pytorch.org/tutorials/intermediate/nlp_from_scratch_index.html 完整网盘链接: https://pan.baidu.com/s/1L9PVZ-KRDGVER-AJnXOvlQ?pwdaa2m 提取码: …...
学习日记0327
A cross-domain knowledge tracing model based on graph optimal transport 我们使用gnn来学习这些节点的特征。在此基础上,我们使用显式分布距离度量对齐来自两个不同域的特征向量,旨在最小化域差异,实现最大的跨域知识转移。 AEGOT-CDKT…...
Postman 下载文件指南:如何请求 Excel/PDF 文件?
在 Postman 中进行 Excel/PDF 文件的请求下载和导出,以下是简明的步骤,帮助你轻松完成任务。首先,我们将从新建接口开始,逐步引导你完成整个过程。 Postman 请求下载/导出 excel/pdf 文件教程...
【HTML】验证与调试工具
个人主页:Guiat 归属专栏:HTML CSS JavaScript 文章目录 1. HTML 验证工具概述1.1 验证的重要性1.2 常见 HTML 错误类型 2. W3C 验证服务2.1 W3C Markup Validation Service2.2 使用 W3C 验证器2.3 验证结果解读 3. 浏览器开发者工具3.1 Chrome DevTools…...
头歌实践教学平台--【数据库概论】--SQL
一、表结构与完整性约束的修改(ALTER) 1.修改表名 USE TestDb1; alter table your_table rename TO my_table; 2.添加与删除字段 #语句1:删除表orderDetail中的列orderDate alter table orderDetail drop orderDate; #语句2:添加列unitPrice alter t…...
2025.03.27【基因分析新工具】| MAST:解锁基因表达差异分析与网络构建
文章目录 1. MAST工具简介:探索生物信息分析的新利器1.1 什么是MAST工具?1.2 MAST工具的优势1.3 MAST工具的应用场景 2. MAST的安装方法:轻松入门的第一步2.1 安装R语言环境2.2 安装MAST包2.3 安装依赖库 3. MAST常用命令:掌握数据…...
JVM - 垃圾回收基本问题
通过一些问题来讨论在 JVM 中,垃圾回收的一些基本问题 为什么要有垃圾回收?Java 垃圾回收中是如何判断一个对象死亡的?请简单介绍一下刚才说到了引用计数法,引用计数法存在什么问题?刚才说到了可达性分析,…...
Python 爬虫案例
以下是一些常见的 Python 爬虫案例,涵盖了不同的应用场景和技术点: 1. 简单网页内容爬取 案例:爬取网页标题和简介 import requests from bs4 import BeautifulSoup url "https://www.runoob.com/" response requests.get(url) …...
从零构建大语言模型全栈开发指南:第三部分:训练与优化技术-3.1.3分布式数据加载与并行处理(PyTorch DataLoader优化)
👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 3.1.3 分布式数据加载与并行处理(`PyTorch DataLoader`优化)1. 大规模数据加载的挑战与瓶颈分析1.1 数据加载流程的时间分解2. PyTorch DataLoader的深度优化策略2.1 核心参数调优2.2 分布式数据分片策…...
2025年- G31-Lc105-102. 二叉树层次遍历--java版
1.题目描述 2.思路 思路一: 使用 队列 Queue 来存储当前层的所有节点。关键点在于 levelSize queue.size() 这一行,它决定了当前层的节点数量。 3.代码实现 /*** Definition for a binary tree node.* public class TreeNode {* int val;* Tr…...
Redis 和 MySQL双写一致性的更新策略有哪些?常见面试题深度解答。
目录 一. 业务数据查询,更新顺序简要分析 二. 更新数据库、查询数据库、更新缓存、查询缓存耗时对比 2.1 更新数据库(最慢) 2.2 查询数据库(较慢) 2.3 更新缓存(次快) 2.4 查询缓存&#…...
【DFS】羌笛何须怨杨柳,春风不度玉门关 - 4. 二叉树中的深搜
本篇博客给大家带来的是二叉树深度优先搜索的解法技巧,在后面的文章中题目会涉及到回溯和剪枝,遇到了一并讲清楚. 🐎文章专栏: DFS 🚀若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的…...
【Exception】MybatisPlusException: can not find lambda cache for this entity
文章目录 环境 | Environment复现步骤 | Reproduction steps报错日志 | Error log源码 | Source CodeUserServiceImpl.javaAddressServiceImpl.javaAbstractSubTableBaseServiceImpl.javaUserEntity.javaAddressEntity.javaSubTableBaseEntity.java 原因分析 | Analysis解决方案…...
Spring Security 全面指南:从基础到高级实践
一、Spring Security 概述与核心概念 1.1 Spring Security 简介 Spring Security 是 Spring 生态系统中的安全框架,为基于 Java 的企业应用提供全面的安全服务。它起源于 2003 年的 Acegi Security 项目,2008 年正式成为 Spring 官方子项目,…...
IP组播 C++简单应用
引言 在当今的网络世界中,数据的传输效率和带宽的合理利用是至关重要的。传统的单播和广播通信方式在某些场景下存在着局限性,而IP组播技术的出现为解决这些问题提供了一种有效的方案。本文将详细介绍IP组播的概念、工作原理、应用场景,并通…...
CentOS 7安装 mysql
CentOS 7安装 mysql 1. yum 安装 mysql 配置mysql源 yum -y install mysql57-community-release-el7-10.noarch.rpm安装MySQL服务器 yum -y install mysql-community-server启动MySQL systemctl start mysqld.service查看MySQL运行状态,运行状态如图ÿ…...
“十五五”时期航空弹药发展环境分析
1.“十五五”时期航空弹药发展环境分析 (标题:小二号宋体居中) 一、建言背景介绍 (一级标题:黑体三号,首行空两格) 航空弹药作为现代战争的核心装备,其发展水平直接关乎…...
es6的100个问题
基础概念 解释 let、const 和 var 的区别。什么是块级作用域?ES6 如何实现它?箭头函数和普通函数的主要区别是什么?解释模板字符串(Template Literals)的用途,并举例嵌套变量的写法。解构赋值的语法是什么…...
在直播间如何和观众进行互动
在抖音直播间实现高效互动需要**技术话术工具**的立体化组合,以下是程序员可落地的深度互动方案: --- ### 一、技术驱动型互动策略 #### 1. **实时代码演示(硬核互动)** - **OBS虚拟摄像头屏幕共享** python # 用Flask创建实…...
mysql--用户管理
MySQL 用户管理完整指南 1. 查看用户信息 查看所有用户 SELECT User, Host, authentication_string FROM mysql.user;查看用户详细信息 SELECT * FROM mysql.user \G查看当前登录用户 SELECT CURRENT_USER();查看特定用户的权限 SHOW GRANTS FOR usernamehost;2. 创建用户…...
.NET三层架构详解
.NET三层架构详解 文章目录 .NET三层架构详解引言什么是三层架构表示层(Presentation Layer)业务逻辑层(Business Logic Layer,BLL)数据访问层(Data Access Layer,DAL) .NET三层架构…...
机器学习之回归
1. 引言 回归分析是机器学习中的基本技术之一,广泛用于预测连续型变量。本文调研了线性回归、多项式回归、岭回归、Lasso回归及弹性网络回归,重点分析其数学原理、算法推导、求解方法及应用场景。 2. 线性回归 2.1 概述 线性回归假设因变量与自变量之间存在线性关系,其目…...
危险化合物安全处理,有机反应淬灭操作解析
化学淬灭操作是指在化学反应过程中,通过人为干预快速终止反应的技术。在有机化学反应中,某一反应底物是过量的,当化学反应进行到一定程度,目标产物已经获得,该过量反应底物继续存在会进一步反应生成副产物或者影响后处…...
【前端】使用 HTML、CSS 和 JavaScript 创建一个数字时钟和搜索功能的网页
文章目录 ⭐前言⭐一、项目结构⭐二、HTML 结构⭐三、CSS 样式⭐四、JavaScript 功能⭐五、运行效果⭐总结 标题详情作者JosieBook头衔CSDN博客专家资格、阿里云社区专家博主、软件设计工程师博客内容开源、框架、软件工程、全栈(,NET/Java/Python/C)、数…...
【Linux】调试器——gdb使用
目录 一、预备知识 二、常用指令 三、调试技巧 (一)监视变量的变化指令 watch (二)更改指定变量的值 set var 正文 一、预备知识 程序的发布形式有两种,debug和release模式,Linux gcc/g出来的二进制…...
Windows10清理机器大全集
Windows10清理机器大全集 写在前面先这么个标题,逐渐补充禁止Update移除Microsoft Compatibility Telemetrywindows-defender-remover其它 写在前面 看到标题,读者已经就吐了。 我是说,我非常认可: IT从业者,如果你银子比较充足&…...