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. 模块化设计
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游戏引擎的实现是一个复杂但有趣的主题。通过本文,我们学习了:
- 游戏引擎的基本架构和核心系统
- 实体组件系统的实现
- 场景管理和游戏对象
- 性能优化技巧
- 最佳实践和设计模式
💡 学习建议:在实现游戏引擎时,要注意模块之间的解耦和性能优化。合理使用设计模式和优化策略,可以显著提升游戏的运行效率。
如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇
终身学习,共同成长。
咱们下一期见
💻
相关文章:
JavaScript系列(49)--游戏引擎实现详解
JavaScript游戏引擎实现详解 🎮 今天,让我们深入探讨JavaScript的游戏引擎实现。游戏引擎是一个复杂的系统,它需要处理渲染、物理、音频、输入等多个方面,让我们一步步实现一个基础但功能完整的游戏引擎。 游戏引擎基础概念 &am…...
20【变量的深度理解】
一说起变量,懂点编程的都知道,但是在理解上可能还不够深 变量就是存储空间,电脑上的存储空间有永久(硬盘)和临时(内存条)两种,永久数据重启电脑后依旧存在,临时数据只…...
19.Word:小马-校园科技文化节❗【36】
目录 题目 NO1.2.3 NO4.5.6 NO7.8.9 NO10.11.12索引 题目 NO1.2.3 布局→纸张大小→页边距:上下左右插入→封面:镶边→将文档开头的“黑客技术”文本移入到封面的“标题”控件中,删除其他控件 NO4.5.6 标题→原文原文→标题 正文→手…...
DeepSeek回答量化策略对超短线资金的影响
其实最近很长一段时间我在盘中的感受就是量化策略的触发信号都是超短线选手经常用到的,比如多个题材相互卡位,近期小红书-消费,好想你,来伊份 跟 算力 电光科技,机器人 金奥博 冀凯股份 五洲新春 建设工业 ,这些票的波动其实都是被量化策略锚定了,做成了策略异动。特别…...
2.3.1 基本数据类型
ST(Structured Text)语言支持多种基本数据类型,用于定义变量、常量以及函数参数等。这些数据类型涵盖了布尔值、整数、浮点数、字符和字符串等常见类型。以下是ST语言中基本数据类型的详细说明: 布尔类型(BOOL…...
探秘 TCP TLP:从背景到实现
回家的路上还讨论了个关于 TCP TLP 的问题,闲着无事缕一缕。本文内容参考自 Tail Loss Probe (TLP): An Algorithm for Fast Recovery of Tail Losses 以及 Linux 内核源码。 TLP,先说缘由。自 TCP 引入 Fast retrans 机制就是为了尽力避免 RTO…...
解锁豆瓣高清海报:深度爬虫与requests进阶之路
前瞻 PosterBandit 这个脚本能够根据用户指定的日期,爬取你看过的影视最高清的海报,并自动拼接成指定大小的长图。 你是否发现直接从豆瓣爬取下来的海报清晰度很低? 使用 .pic .nbg img CSS 选择器,在 我看过的影视 界面找到图片…...
无耳科技 Solon v3.0.7 发布(2025农历新年版)
Solon 框架! Solon 框架由杭州无耳科技有限公司(下属 Noear 团队)开发并开源。是新一代,面向全场景的 Java 企业级应用开发框架。从零开始构建(非 java-ee 架构),有灵活的接口规范与开放生态。…...
常见的多媒体框架(FFmpeg GStreamer DirectShow AVFoundation OpenMax)
1.FFmpeg FFmpeg是一个非常强大的开源多媒体处理框架,它提供了一系列用于处理音频、视频和多媒体流的工具和库。它也是最流行且应用最广泛的框架! 官方网址:https://ffmpeg.org/ FFmpeg 的主要特点和功能: 编解码器支持: FFmpe…...
本地部署Deepseek R1
最近Deepseek R1模型也是彻底火出圈了, 但是线上使用经常会受到各种限制,有时候还会连不上,这里我尝试本地部署了Deepseek 的开源R1模型,具体的操作如下: 首先登陆ollama平台,Ollama.ollama平台是一个开源…...
深入解析 .NET 命名管道技术, 通过 Sharp4Tokenvator 实现本地权限提升
01. 管道访问配置 在 .NET 中通常使用 PipeSecurity 类为管道设置访问控制规则,用于管理命名管道的访问控制列表(ACL)。通过这个类,可以为命名管道配置精细化的安全权限,从而控制哪些用户或用户组能够访问管道&#x…...
Cesium ArcGisMapServerImageryProvider API 介绍
作为一名GIS研究生,WebGIS 技术无疑是我们必学的核心之一。说到WebGIS,要提的就是 Cesium —— 这个让3D地球可视化变得简单又强大的工具。为了帮助大家更好地理解和使用 Cesium,我决定把我自己在学习 Cesium 文档过程中的一些心得和收获分享…...
登录授权流程
发起一个网络请求需要:1.请求地址 2.请求方式 3.请求参数 在检查中找到request method,在postman中设置同样的请求方式将登录的url接口复制到postman中(json类型数据)在payload中选择view parsed,将其填入Body-raw中 …...
Python设计模式 - 组合模式
定义 组合模式(Composite Pattern) 是一种结构型设计模式,主要意图是将对象组织成树形结构以表示"部分-整体"的层次结构。这种模式能够使客户端统一对待单个对象和组合对象,从而简化了客户端代码。 组合模式有透明组合…...
【深度学习】图像分类数据集
图像分类数据集 MNIST数据集是图像分类中广泛使用的数据集之一,但作为基准数据集过于简单。 我们将使用类似但更复杂的Fashion-MNIST数据集。 %matplotlib inline import torch import torchvision from torch.utils import data from torchvision import transfo…...
【四川乡镇界面】图层shp格式arcgis数据乡镇名称和编码2020年wgs84无偏移内容测评
本文将详细解析标题和描述中提到的IT知识点,主要涉及GIS(Geographic Information System,地理信息系统)技术,以及与之相关的文件格式和坐标系统。 我们要了解的是"shp"格式,这是一种广泛用于存储…...
ubuntu解决普通用户无法进入root
项目场景: 在RK3566上移植Ubuntu20.04之后普通用户无法进入管理员模式 问题描述 在普通用户使用sudo su试图进入管理员模式的时候报错 解决方案: 1.使用 cat /etc/passwd 查看所有用户.最后一行是 若无用户,则使用 sudo useradd -r -m -s /…...
数据结构选讲 (更新中)
参考 smWCDay7 数据结构选讲2 by yyc 。 可能会补充的: AT_cf17_final_j TreeMST 的 F2 Boruvka算法 目录 AT_cf17_final_j Tree MST AT_cf17_final_j Tree MST link 题意 给定一棵 n n n 个点的树,点有点权 w i w_i wi,边有边权。建立…...
freeswtch目录下modules.conf各个模块的介绍【freeswitch版本1.6.8】
应用模块(applications) mod_abstraction: 为其他模块提供抽象层,有助于简化模块开发,让开发者能在统一框架下开发新功能,减少与底层系统的直接交互,提高代码可移植性和可维护性。 mod_av&#…...
第3章 基于三电平空间矢量的中点电位平衡策略
0 前言 在NPC型三电平逆变器的直流侧串联有两组参数规格完全一致的电解电容,由于三电平特殊的中点钳位结构,在进行SVPWM控制时,在一个完整开关周期内,直流侧电容C1、C2充放电不均匀,各自存储的总电荷不同,电容电压便不均等,存在一定的偏差。在不进行控制的情况下,系统无…...
网络工程师 (8)存储管理
一、页式存储基本原理 (一)内存划分 页式存储首先将内存物理空间划分成大小相等的存储块,这些块通常被称为“页帧”或“物理页”。每个页帧的大小是固定的,例如常见的页帧大小有4KB、8KB等,这个大小由操作系统决定。同…...
Shell特殊位置变量以及常用内置变量总结
目录 1. 特殊的状态变量 1.1 $?(上一个命令的退出状态) 1.2 $$(当前进程的 PID) 1.3 $!(后台进程的 PID) 1.4 $_(上一条命令的最后一个参数) 2.常用shell内置变量 2.1 echo&…...
实验一---典型环节及其阶跃响应---自动控制原理实验课
一 实验目的 1.掌握典型环节阶跃响应分析的基本原理和一般方法。 2. 掌握MATLAB编程分析阶跃响应方法。 二 实验仪器 1. 计算机 2. MATLAB软件 三 实验内容及步骤 利用MATLAB中Simulink模块构建下述典型一阶系统的模拟电路并测量其在阶跃响应。 1.比例环节的模拟电路 提…...
基于 WEB 开发的在线考试系统设计与实现
标题:基于 WEB 开发的在线考试系统设计与实现 内容:1.摘要 基于 WEB 开发的在线考试系统旨在提供一个便捷、高效、公平的考试环境。本文详细介绍了该系统的设计与实现过程,包括系统架构、功能模块、数据库设计等方面。通过实际应用,证明了该系统具有良好…...
【linux】linux缺少tar命令/-bash: tar:未找到命令
问题: -bash: tar:未找到命令 原因 这错误信息"-bash: tar:未找到命令"表示系统无法找到tar命令。tar命令是一个Linux/Unix系统下的打包压缩工具,它用于将多个文件合并为一个文件。如果系统报错找不到tar命令,可能是…...
ERP革新:打破数据壁垒,重塑市场竞争
标题:ERP革新:打破数据壁垒,重塑市场竞争 文章信息摘要: Operator和Computer Use等工具通过模拟用户交互和自动化数据提取,绕过了传统ERP系统的API限制,打破了其数据护城河。这种技术革新降低了企业切换软…...
【BQ3568HM开发板】如何在OpenHarmony上通过校园网的上网认证
引言 前面已经对BQ3568HM开发板进行了初步测试,后面我要实现MQTT的工作,但是遇到一个问题,就是开发板无法通过校园网的认证操作。未认证的话会,学校使用的深澜软件系统会屏蔽所有除了认证用的流量。好在我们学校使用的认证系统和…...
PythonFlask框架
文章目录 处理 Get 请求处理 POST 请求应用 app.route(/tpost, methods[POST]) def testp():json_data request.get_json()if json_data:username json_data.get(username)age json_data.get(age)return jsonify({username: username测试,age: age})从 flask 中导入了 Flask…...
【电工基础】1.电能来源,触电伤害,触电预防,触电急救
一。电能来源 1.电能来源 发电-》输电-》变电-》配电 2.分配电 一类负荷 如果供电中断会造成生命危险,造成国民经济的重大损失,损坏生产的重要设备以致使生产长期不能恢复或产生大量废品,破坏复杂的工艺过程,以及破坏大…...
大数据学习之Kafka消息队列、Spark分布式计算框架一
Kafka消息队列 章节一.kafka入门 4.kafka入门_消息队列两种模式 5.kafka入门_架构相关名词 Kafka 入门 _ 架构相关名词 事件 记录了世界或您的业务中 “ 发生了某事 ” 的事实。在文档中 也称为记录或消息。当您向 Kafka 读取或写入数据时,您以事件的 形式执行…...
