JavaScript系列(49)--游戲引擎實現詳解

JavaScript游戲引擎實現詳解 🎮

今天,讓我們深入探討JavaScript的游戲引擎實現。游戲引擎是一個復雜的系統,它需要處理渲染、物理、音頻、輸入等多個方面,讓我們一步步實現一個基礎但功能完整的游戲引擎。

游戲引擎基礎概念 🌟

💡 小知識:游戲引擎是一個為游戲開發提供核心功能的框架,它通常包括渲染系統、物理引擎、音頻系統、輸入處理、資源管理等模塊。通過合理的架構設計,這些模塊可以協同工作,為游戲開發提供強大的支持。

基本實現 📊

// 1. 游戲引擎核心
class GameEngine {constructor(canvas) {this.canvas = canvas;this.context = canvas.getContext('2d');// 核心系統this.renderer = new Renderer(this.context);this.physics = new PhysicsSystem();this.input = new InputManager();this.audio = new AudioSystem();// 游戲狀態this.scenes = new Map();this.currentScene = null;this.isRunning = false;// 時間管理this.lastTime = 0;this.deltaTime = 0;}// 初始化引擎init() {this.input.init();this.audio.init();window.requestAnimationFrame(this.gameLoop.bind(this));}// 游戲主循環gameLoop(timestamp) {// 計算時間增量this.deltaTime = (timestamp - this.lastTime) / 1000;this.lastTime = timestamp;if (this.isRunning && this.currentScene) {this.update();this.render();}window.requestAnimationFrame(this.gameLoop.bind(this));}// 更新游戲狀態update() {this.physics.update(this.deltaTime);this.currentScene.update(this.deltaTime);this.input.update();}// 渲染游戲畫面render() {this.context.clearRect(0, 0,this.canvas.width,this.canvas.height);this.currentScene.render(this.renderer);}// 場景管理addScene(name, scene) {this.scenes.set(name, scene);}loadScene(name) {const scene = this.scenes.get(name);if (scene) {if (this.currentScene) {this.currentScene.onExit();}this.currentScene = scene;scene.onEnter();}}
}// 2. 渲染系統
class Renderer {constructor(context) {this.context = context;this.camera = new Camera();}// 繪制精靈drawSprite(sprite) {const { position, scale, rotation } = sprite.transform;const { texture, width, height } = sprite;this.context.save();// 應用相機變換this.context.translate(-this.camera.position.x,-this.camera.position.y);// 應用精靈變換this.context.translate(position.x, position.y);this.context.rotate(rotation);this.context.scale(scale.x, scale.y);// 繪制精靈this.context.drawImage(texture,-width / 2,-height / 2,width,height);this.context.restore();}// 繪制圖元drawPrimitive(primitive) {this.context.save();this.context.fillStyle = primitive.color;this.context.beginPath();switch (primitive.type) {case 'rectangle':this.context.fillRect(primitive.x,primitive.y,primitive.width,primitive.height);break;case 'circle':this.context.arc(primitive.x,primitive.y,primitive.radius,0,Math.PI * 2);this.context.fill();break;}this.context.restore();}
}// 3. 物理系統
class PhysicsSystem {constructor() {this.bodies = [];this.gravity = new Vector2(0, 9.81);}addBody(body) {this.bodies.push(body);}removeBody(body) {const index = this.bodies.indexOf(body);if (index !== -1) {this.bodies.splice(index, 1);}}update(deltaTime) {// 更新物理體for (const body of this.bodies) {if (!body.isStatic) {// 應用重力body.velocity.add(Vector2.multiply(this.gravity, deltaTime));// 更新位置body.position.add(Vector2.multiply(body.velocity, deltaTime));}}// 碰撞檢測和處理this.detectCollisions();}detectCollisions() {for (let i = 0; i < this.bodies.length; i++) {for (let j = i + 1; j < this.bodies.length; j++) {const bodyA = this.bodies[i];const bodyB = this.bodies[j];if (this.checkCollision(bodyA, bodyB)) {this.resolveCollision(bodyA, bodyB);}}}}
}

高級功能實現 🚀

// 1. 實體組件系統
class Entity {constructor() {this.components = new Map();this.id = Entity.nextId++;}addComponent(component) {component.entity = this;this.components.set(component.constructor, component);}getComponent(componentClass) {return this.components.get(componentClass);}removeComponent(componentClass) {const component = this.components.get(componentClass);if (component) {component.entity = null;this.components.delete(componentClass);}}update(deltaTime) {for (const component of this.components.values()) {if (component.update) {component.update(deltaTime);}}}
}// 2. 組件系統
class Component {constructor() {this.entity = null;}// 生命周期方法onAdd() {}onRemove() {}update(deltaTime) {}
}class TransformComponent extends Component {constructor() {super();this.position = new Vector2();this.rotation = 0;this.scale = new Vector2(1, 1);}
}class SpriteComponent extends Component {constructor(texture) {super();this.texture = texture;this.width = texture.width;this.height = texture.height;}render(renderer) {const transform = this.entity.getComponent(TransformComponent);if (transform) {renderer.drawSprite({texture: this.texture,width: this.width,height: this.height,transform});}}
}// 3. 場景管理
class Scene {constructor() {this.entities = new Set();this.systems = new Map();}addEntity(entity) {this.entities.add(entity);}removeEntity(entity) {this.entities.delete(entity);}addSystem(system) {system.scene = this;this.systems.set(system.constructor, system);}update(deltaTime) {// 更新所有系統for (const system of this.systems.values()) {system.update(deltaTime);}// 更新所有實體for (const entity of this.entities) {entity.update(deltaTime);}}render(renderer) {for (const entity of this.entities) {const sprite = entity.getComponent(SpriteComponent);if (sprite) {sprite.render(renderer);}}}// 場景生命周期onEnter() {}onExit() {}
}

實際應用場景 💼

// 1. 游戲對象實現
class GameObject extends Entity {constructor(x = 0, y = 0) {super();// 添加基本組件const transform = new TransformComponent();transform.position.set(x, y);this.addComponent(transform);}// 便捷方法setPosition(x, y) {const transform = this.getComponent(TransformComponent);transform.position.set(x, y);}setRotation(angle) {const transform = this.getComponent(TransformComponent);transform.rotation = angle;}setScale(x, y) {const transform = this.getComponent(TransformComponent);transform.scale.set(x, y);}
}// 2. 游戲角色實現
class Player extends GameObject {constructor(x, y) {super(x, y);// 添加精靈組件const sprite = new SpriteComponent(ResourceManager.getTexture('player'));this.addComponent(sprite);// 添加物理組件const physics = new PhysicsComponent();physics.mass = 1;physics.friction = 0.1;this.addComponent(physics);// 添加輸入組件const input = new InputComponent();input.bindKey('ArrowLeft', this.moveLeft.bind(this));input.bindKey('ArrowRight', this.moveRight.bind(this));input.bindKey('Space', this.jump.bind(this));this.addComponent(input);}moveLeft() {const physics = this.getComponent(PhysicsComponent);physics.applyForce(new Vector2(-100, 0));}moveRight() {const physics = this.getComponent(PhysicsComponent);physics.applyForce(new Vector2(100, 0));}jump() {const physics = this.getComponent(PhysicsComponent);if (physics.isGrounded) {physics.applyImpulse(new Vector2(0, -200));}}
}// 3. 游戲關卡實現
class GameLevel extends Scene {constructor() {super();// 創建玩家const player = new Player(100, 100);this.addEntity(player);// 創建平臺this.createPlatform(0, 500, 800, 20);this.createPlatform(300, 400, 200, 20);this.createPlatform(100, 300, 200, 20);// 添加系統this.addSystem(new PhysicsSystem());this.addSystem(new CollisionSystem());this.addSystem(new RenderSystem());}createPlatform(x, y, width, height) {const platform = new GameObject(x, y);const sprite = new SpriteComponent(ResourceManager.getTexture('platform'));sprite.width = width;sprite.height = height;platform.addComponent(sprite);const physics = new PhysicsComponent();physics.isStatic = true;physics.setBox(width, height);platform.addComponent(physics);this.addEntity(platform);}
}

性能優化技巧 ?

// 1. 對象池系統
class ObjectPool {constructor(factory, initialSize = 10) {this.factory = factory;this.activeObjects = new Set();this.inactiveObjects = [];// 預創建對象for (let i = 0; i < initialSize; i++) {this.inactiveObjects.push(this.factory());}}spawn(x, y) {let object;if (this.inactiveObjects.length > 0) {object = this.inactiveObjects.pop();} else {object = this.factory();}object.setPosition(x, y);this.activeObjects.add(object);return object;}despawn(object) {if (this.activeObjects.has(object)) {this.activeObjects.delete(object);this.inactiveObjects.push(object);}}update(deltaTime) {for (const object of this.activeObjects) {object.update(deltaTime);}}
}// 2. 四叉樹空間分區
class QuadTree {constructor(bounds, maxObjects = 10, maxLevels = 4, level = 0) {this.bounds = bounds;this.maxObjects = maxObjects;this.maxLevels = maxLevels;this.level = level;this.objects = [];this.nodes = [];}clear() {this.objects = [];for (let i = 0; i < this.nodes.length; i++) {if (this.nodes[i]) {this.nodes[i].clear();this.nodes[i] = null;}}}split() {const subWidth = this.bounds.width / 2;const subHeight = this.bounds.height / 2;const x = this.bounds.x;const y = this.bounds.y;this.nodes[0] = new QuadTree({x: x + subWidth,y: y,width: subWidth,height: subHeight}, this.maxObjects, this.maxLevels, this.level + 1);this.nodes[1] = new QuadTree({x: x,y: y,width: subWidth,height: subHeight}, this.maxObjects, this.maxLevels, this.level + 1);this.nodes[2] = new QuadTree({x: x,y: y + subHeight,width: subWidth,height: subHeight}, this.maxObjects, this.maxLevels, this.level + 1);this.nodes[3] = new QuadTree({x: x + subWidth,y: y + subHeight,width: subWidth,height: subHeight}, this.maxObjects, this.maxLevels, this.level + 1);}getIndex(rect) {const verticalMidpoint = this.bounds.x + (this.bounds.width / 2);const horizontalMidpoint = this.bounds.y + (this.bounds.height / 2);const topQuadrant = (rect.y < horizontalMidpoint && rect.y + rect.height < horizontalMidpoint);const bottomQuadrant = (rect.y > horizontalMidpoint);if (rect.x < verticalMidpoint && rect.x + rect.width < verticalMidpoint) {if (topQuadrant) {return 1;} else if (bottomQuadrant) {return 2;}} else if (rect.x > verticalMidpoint) {if (topQuadrant) {return 0;} else if (bottomQuadrant) {return 3;}}return -1;}
}// 3. 渲染優化
class RenderOptimizer {constructor(renderer) {this.renderer = renderer;this.visibleObjects = new Set();this.frustum = new Frustum();}updateVisibility(camera, objects) {this.visibleObjects.clear();this.frustum.updateFromCamera(camera);for (const object of objects) {if (this.frustum.intersectsBox(object.getBoundingBox())) {this.visibleObjects.add(object);}}}render() {// 按材質排序const sortedObjects = Array.from(this.visibleObjects).sort((a, b) => a.material.id - b.material.id);// 批量渲染let currentMaterial = null;for (const object of sortedObjects) {if (object.material !== currentMaterial) {currentMaterial = object.material;this.renderer.setMaterial(currentMaterial);}this.renderer.renderObject(object);}}
}

最佳實踐建議 💡

  1. 游戲引擎架構設計
// 1. 模塊化設計
class GameModule {constructor(engine) {this.engine = engine;}init() {}update(deltaTime) {}destroy() {}
}// 2. 事件系統
class EventSystem extends GameModule {constructor(engine) {super(engine);this.listeners = new Map();}on(event, callback) {if (!this.listeners.has(event)) {this.listeners.set(event, new Set());}this.listeners.get(event).add(callback);}off(event, callback) {const callbacks = this.listeners.get(event);if (callbacks) {callbacks.delete(callback);}}emit(event, data) {const callbacks = this.listeners.get(event);if (callbacks) {for (const callback of callbacks) {callback(data);}}}
}// 3. 資源管理
class ResourceManager extends GameModule {constructor(engine) {super(engine);this.resources = new Map();this.loading = new Map();}async load(url, type) {if (this.resources.has(url)) {return this.resources.get(url);}if (this.loading.has(url)) {return this.loading.get(url);}const loadPromise = this.loadResource(url, type);this.loading.set(url, loadPromise);try {const resource = await loadPromise;this.resources.set(url, resource);this.loading.delete(url);return resource;} catch (error) {this.loading.delete(url);throw error;}}async loadResource(url, type) {switch (type) {case 'image':return this.loadImage(url);case 'audio':return this.loadAudio(url);case 'json':return this.loadJSON(url);default:throw new Error(`Unsupported resource type: ${type}`);}}
}

結語 📝

JavaScript游戲引擎的實現是一個復雜但有趣的主題。通過本文,我們學習了:

  1. 游戲引擎的基本架構和核心系統
  2. 實體組件系統的實現
  3. 場景管理和游戲對象
  4. 性能優化技巧
  5. 最佳實踐和設計模式

💡 學習建議:在實現游戲引擎時,要注意模塊之間的解耦和性能優化。合理使用設計模式和優化策略,可以顯著提升游戲的運行效率。


如果你覺得這篇文章有幫助,歡迎點贊收藏,也期待在評論區看到你的想法和建議!👇

終身學習,共同成長。

咱們下一期見

💻

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67405.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67405.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67405.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

安裝zsh并美化

0 Zsh 是一種功能強大的 shell&#xff0c;通常用于替代默認的 Bash shell。它為命令行提供了更多的功能&#xff0c;例如自動補全、強大的模式匹配和主題支持等。 Oh My Zsh 是用于管理 Zsh 配置的框架。 powerlevel10k是樣式&#xff0c;通過p10k configure腳本可以調節自己…

GMSL 明星產品之 MAX96717

在上一篇文章中&#xff0c;我們詳細介紹了車載市場中爆火的 GMSL 到底是個啥 &#xff1a; 揭開 GMSL 的面紗&#xff1a;自動駕駛背后的隱藏技術。今天我們就來詳細了解下如今在攝像頭側超級火爆的加串器&#xff1a;MAX96717。 MAX96717 系列有三款產品&#xff1a; MAX967…

線段樹 算法

文章目錄 基礎知識適用場景小結 題目概述題目詳解300.最長遞增子序列2407.最長遞增子序列 II 基礎知識 線段樹和樹狀數組都只是一個工具來的&#xff0c;題目并不會一下子就告訴你這個題目用到線段樹和樹狀數組&#xff0c;這個取決于你想使用的數據結構以及所要優化的方向 線…

MATLAB提供的顏色映射表colormap——偽彩色

圖像處理領域的一個習慣&#xff1a;不是真實的顏色&#xff0c;一般用偽彩色。一是說明不是物體本身的顏色&#xff0c;二是彩色更容易分辨。 MATLAB陸續提供了16種顏色映射表colormap。 之前的都很丑&#xff0c;近5年新增的4種還可以。總的說來還是丑。 這是一種鳥的名字。…

20.Word:小謝-病毒知識的科普文章?【38】

目錄 題目? NO1.2.3文檔格式 NO4.5 NO6.7目錄/圖表目錄/書目 NO8.9.10 NO11索引 NO12.13.14 每一步操作完&#xff0c;確定之后記得保存最后所有操作完記得再次刪除空行 題目 NO1.2.3文檔格式 樣式的應用 選中應用段落段落→開始→選擇→→檢查→應用一個一個應用ctr…

【16屆藍橋杯寒假刷題營】第2期DAY4

【16屆藍橋杯寒假刷題營】第2期DAY4 - 藍橋云課 問題描述 幼兒園小班的浩楠同學有一個序列 a。 他想知道有多少個整數三元組 (i,j,k) 滿足 1≤i,j,k≤n 且 ai?aj?ak?。 輸入格式 共2行&#xff0c;第一行一個整數 n&#xff0c;表示序列的長度。 第二行 n 個整數&#x…

MySQL查詢優化(三):深度解讀 MySQL客戶端和服務端協議

如果需要從 MySQL 服務端獲得很高的性能&#xff0c;最佳的方式就是花時間研究 MySQL 優化和執行查詢的機制。一旦理解了這些&#xff0c;大部分的查詢優化是有據可循的&#xff0c;從而使得整個查詢優化的過程更有邏輯性。下圖展示了 MySQL 執行查詢的過程&#xff1a; 客戶端…

Van-Nav:新年,將自己學習的項目地址統一整理搭建自己的私人導航站,供自己后續查閱使用,做技術的同學應該都有一個自己網站的夢想

嗨&#xff0c;大家好&#xff0c;我是小華同學&#xff0c;關注我們獲得“最新、最全、最優質”開源項目和高效工作學習方法 Van-Nav是一個基于Vue.js開發的導航組件庫&#xff0c;它提供了多種預設的樣式和靈活的配置選項&#xff0c;使得開發者可以輕松地定制出符合項目需求…

VSCode+Continue實現AI輔助編程

Continue是一款功能強大的AI輔助編程插件&#xff0c;可連接多種大模型&#xff0c;支持代碼設計優化、錯誤修正、自動補全、注釋編寫等功能&#xff0c;助力開發人員提高工作效率與代碼質量。以下是其安裝和使用方法&#xff1a; 一、安裝VSCode 參見&#xff1a; vscode安…

【hot100】刷題記錄(6)-輪轉數組

題目描述&#xff1a; 給定一個整數數組 nums&#xff0c;將數組中的元素向右輪轉 k 個位置&#xff0c;其中 k 是非負數。 示例 1: 輸入: nums [1,2,3,4,5,6,7], k 3 輸出: [5,6,7,1,2,3,4] 解釋: 向右輪轉 1 步: [7,1,2,3,4,5,6] 向右輪轉 2 步: [6,7,1,2,3,4,5] 向右輪轉…

FPGA 使用 CLOCK_DEDICATED_ROUTE 約束

使用 CLOCK_DEDICATED_ROUTE 約束 CLOCK_DEDICATED_ROUTE 約束通常在從一個時鐘區域中的時鐘緩存驅動到另一個時鐘區域中的 MMCM 或 PLL 時使 用。默認情況下&#xff0c; CLOCK_DEDICATED_ROUTE 約束設置為 TRUE &#xff0c;并且緩存 /MMCM 或 PLL 對必須布局在相同…

阿里:基于路由和規劃的多agent系統

&#x1f4d6;標題&#xff1a;Talk to Right Specialists: Routing and Planning in Multi-agent System for Question Answering &#x1f310;來源&#xff1a;arXiv, 2501.07813 &#x1f31f;摘要 &#x1f538;利用大型語言模型&#xff08;LLM&#xff09;&#xff0c…

數論問題77一一3x+1問題

3X 1問題&#xff0c;也被稱為考拉茲猜想、角谷猜想等&#xff0c;是數學領域一個著名的未解決問題&#xff0c;以下是關于它的介紹&#xff1a; 問題表述 對于任意一個正整數X&#xff0c;如果X是奇數&#xff0c;則將其變為3X 1&#xff1b;如果X是偶數&#xff0c;則將其變…

【Unity3D】實現2D角色/怪物死亡消散粒子效果

核心&#xff1a;這是一個Unity粒子系統自帶的一種功能&#xff0c;可將粒子生成控制在一個Texture圖片網格范圍內&#xff0c;并且粒子顏色會自動采樣圖片的像素點顏色&#xff0c;之后則是粒子編輯出消散效果。 Particle System1物體&#xff08;爆發式隨機速度擴散10000個粒…

Synology 群輝NAS安裝(10)安裝confluence

Synology 群輝NAS安裝&#xff08;10&#xff09;安裝confluence 寫在前面本著一朝鮮吃遍天的原則&#xff0c;我又去了這個github的作者那里翻車的第一次嘗試手工創建數據庫制作一個新的docker-compose of confluence 不折騰但成功啟動的版本 寫在前面 在裝完jira之后&#x…

萬字長文總結前端開發知識---JavaScriptVue3Axios

JavaScript學習目錄 一、JavaScript1. 引入方式1.1 內部腳本 (Inline Script)1.2 外部腳本 (External Script) 2. 基礎語法2.1 聲明變量2.2 聲明常量2.3 輸出信息 3. 數據類型3.1 基本數據類型3.2 模板字符串 4. 函數4.1 具名函數 (Named Function)4.2 匿名函數 (Anonymous Fun…

DeepSeek R1有什么不同

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

年度總結(盡量簡短)

一.成長 1.對于U使用更熟練&#xff0c;能應付基本的開發。幾個項目的練習和磨練&#xff0c;基本達到了我今年的目標&#xff0c;自己可以應付項目。可以過度到底層的學習。 2.堅持寫帖子&#xff0c;雖然后半年的帖子發的沒有上半年勤快。但是也在堅持學東西 3.對于職場上…

多頭潛在注意力(MLA):讓大模型“輕裝上陣”的技術革新——從DeepSeek看下一代語言模型的高效之路

多頭潛在注意力&#xff08;MLA&#xff09;&#xff1a;讓大模型“輕裝上陣”的技術革新 ——從DeepSeek看下一代語言模型的高效之路 大模型的“內存焦慮” 當ChatGPT等大語言模型&#xff08;LLM&#xff09;驚艷世界時&#xff0c;很少有人意識到它們背后隱藏的“內存焦慮”…

淺談Linux 權限、壓縮、進程與服務

概述 放假回家&#xff0c;對Linux系統的一些知識進行重新的整理&#xff0c;做到溫故而知新&#xff0c;對用戶權限管理、文件賦權、壓縮文件、進程與服務的知識進行了一次梳理和總結。 權限管理 Linux最基礎的權限是用戶和文件&#xff0c;先了解基礎的用戶權限和文件權限…