Excalibur

excaliburjsBSD-2-Clause活跃维护

用 TypeScript 编写的 2D 网页游戏引擎,提供开箱即用的渲染、物理和输入处理,让开发者专注写游戏逻辑而不是搭底层。

🎮 Your friendly TypeScript 2D game engine for the web 🗡️

v1.0.0发布于 2026-11-08 05:21 UTC2,365star +3 / 7 天230fork同步于 2026-11-10 17:46 UTC

怎么上手

由 README 提炼,执行前请确认
npm install
npx playwright install --with-deps
硬件要求按 README 说明

README 未说明;引擎运行于浏览器 HTML5 Canvas,开发环境需要 Node.js LTS 版本

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

用 TypeScript 编写、运行在 HTML5 Canvas 上的免费 2D 游戏引擎,帮你省去引擎样板代码

用 TypeScript 编写的 2D 网页游戏引擎,提供开箱即用的渲染、物理和输入处理,让开发者专注写游戏逻辑而不是搭底层。

核心能力

  • 用 TypeScript 编写,面向 HTML5 Canvas 制作 2D 游戏
  • 封装引擎样板代码,可只取所需部分使用
  • 借助 BrowserStack 做跨平台浏览器兼容测试
  • 提供 API 文档、入门指南与在线示例集
  • 采用 BSD 2-clause 许可,可用于商业项目

容易踩的坑

项目仍处于 0.x 版本,新版本中会出现破坏性 API 变更;从源码贡献需先装 Node.js LTS 并执行 npx playwright install --with-deps 安装系统依赖;README 未给出引擎本身的安装命令,需按官网 Installation 指南操作

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v1.0.0
  1. v1.0.0Excalibur v1.0.0 Release最新正式版2026-11-08 · 2026-11-08 05:21 UTC

    excalibur logo

    Thirteen years, nearly 4,000 commits, and over 120 contributors later: Excalibur.js is v1.0.0!

    Highlights new in v1

    • 2D Lighting
    • Pause System
    • Serialization System
    • Faster Realistic Physics
    • MULTI-pass Materials & Post-processors
    • Sound: a real Web Audio mixer and sound manager
    • Plugin API
    • Excalibur CLI for doing upgrades and codemods!

    Breaking Changes

    We have done our best to write codemods to auto-upgrade everything https://github.com/excaliburjs/create-excalibur

    • ESM Only output

    • Time units are implicitly milliseconds everywhere, with no Ms suffix on public API:

      • Engine.currentFrameElapsedMs -> currentFrameElapsed, Engine.currentFrameLagMs -> currentFrameLag, FrameStats.elapsedMs -> elapsed, GifFrame.delayMs -> delay, ClockOptions.defaultUpdateMs -> defaultUpdate
      • Sound, SoundTrack and PlayOptions position/duration, seek(), getPlaybackPosition(), getTotalPlaybackDuration() and SoundTrack.scheduledStartTime are now in milliseconds (previously seconds). sound.play({ duration: 500 }) now plays for half a second.
    • API naming is now consistent: synchronous boolean state is always a getter (isX), side-effecting calls are verb methods, and async state is a Promise property that never has an isX() form. Zero-arg isX()/hasX() methods became getters, drop the parentheses:

      • Entity.isKilled (and Actor), Engine.isRunning, Engine.isDisposed, Clock.isRunning, Scene.isCurrentScene, CollisionContact.isCanceled, CoroutineInstance.isRunning/isComplete
      • Sound and SoundTrack: isPlaying, isPaused, isStopped
      • Loadable.isLoaded (Resource, ImageSource, Font, Gif, Sound, SoundManager, DefaultLoader)
      • Matrix/AffineMatrix.isIdentity, Transform.isMirrored, BoundingBox.hasZeroDimensions, Camera.hasChanged, ActionQueue.hasNext/isComplete, Graphic.isStale, RendererPlugin.hasPendingDraws, WebAudio.isUnlocked, Serializer.isInitialized
      • Methods that mutate or do real work stay verbs: PolygonCollider.isConvex -> checkConvex() (O(n)), the mutating hasChanged getter on SparseHashGrid and its collision processor -> refreshAndCheckChanged(), and every toggleEnabled(enabled) on the input classes -> setEnabled(enabled) (it takes an explicit value, it never toggled)
      • Settable booleans follow the same isX naming as the already-shipped isVisible: the visible option on ActorOptions, TriggerOptions and GraphicsComponentOptions is now isVisible, and Particle.visible is now Particle.isVisible
      • Tile.solid (TileMap and IsometricMap tiles) and the solid tile option are now isSolid
      • GarbageCollector.running() is now the getter isRunning; FontTextInstance.disposed is now isDisposed
      • Slide({ easingFunction }) is now Slide({ easing }), matching every other transition; previously easing was silently ignored by Slide
      • Pausing: Actor.paused (a PauseComponent, not a boolean) and Particle.paused are now the read-only pauseComponent, PauseComponent.paused is now the read-only isPaused, and PauseComponentInterface is now PauseComponentOptions. Use Actor.canPause and Actor.isPaused for everyday code
      • Spelling: isOffScreen -> isOffscreen (one word, like the web platform's OffscreenCanvas; "on screen" stays split: forceOnScreen, onScreenOnly, getOnScreenTiles()), isHiDpi -> isHiDPI on Engine and Screen, and Future.isCompleted -> isComplete
      • Renamed: Color.equal -> Color.equals
      • Renamed: Engine.loadingComplete -> Engine.isLoaded; Engine.ready (boolean) -> Engine.isReady; Engine.isReady() (Promise) -> await engine.ready; Animation.done -> Animation.isComplete; Timer.complete and Transition.complete -> isComplete; `Gamepad.con
  2. v0.32.0Excalibur v0.32.0 Release2025-12-23 · 2025-12-23 15:14 UTC
    查看更新说明

    excalibur logo

    The theme of this release is developer experience and performance. We've removed a lot of paper cuts in the api with quick and easy ways to do what you want.

    • Actors can now have a default graphic and/or material set in their constructor!
    • Debug Draw has had a huge improvement, both in performance, and visual fidelity through the browser extension!
    • Offscreen, Tilemaps, Realistic Collisions, and more all got big performance increases
    • Realistic Physics Bodies now sleep consistently giving a huge perf boost to physics games
    • Easing functions are now the good ol' 0 -> 1 style you see all over the internet, BYOF easily!

    Did you know we have a playground now?

    https://github.com/user-attachments/assets/4833c259-f1e7-42e4-bb9f-c9fbf63f1f6c

    https://excaliburjs.com/playground

    [Puyo Puyo Clone in Playground](https://excaliburjs.com/playground/?autoplay=true&code=FASwtgDg9gTgLgAgFQIIYGcEFMAeCBmMUYCA5LgMaoA2IARgK4ykDcwwFUAduogOIAlAJIARAPoB1UQBUAEggC8CAGxtOPfsPGyAokL6zpihAEYATGu68EAYR0AZe2IDKQgFo7jAFgAMljbYA8vaBAs7GANq4AHQ2UNSw0QJYACYANNg4sfGJAELUDFgZMXEJMNF8MFhYXMVZpYkAmljUCQDuALr+1gCyAILSNrJiNoEAqgByRkpebMAA9PMIAAoMAJ5QCBTUGOgcO+iYqxuZcDUpmDF9FHCwCADewAgIAOYwICkAGgBcCFwMYDoWBgbGebw+jV+-0BwNBCAg6ygDRgvxKORB7Ge6l4MAYN1gAAocFCAUCYBk1iSYeStujUfV0QBKB5PZ4IdAMCDAgmPNls6DoKFYNqZaIANSw+JgROQtgcTlcHgQAGo5Y4XO5PEszBTZXZ1YrPKr9QrNQhtYy0qy+W0PnAABa-E0apUAWgQXitfOe9qwIBe9rgTvlLs87s91rZnDKv2jsC9bIAvoy4c8HSB0NFwV9jDhUwh05ns41jGt84XogiNsjjHGMXyK29UBB7SAKJmGOgsASuMLRTYQDBtt3ed6YKgUiBO8GDWbtQh3TrI1i6bSygnnsmU6zE5iEJyUqgzssoOgQHAQNwCczR2nW5mBcZeyKYhKpQTlwX71n3jmUM7DRVNVTSVbUNzZRtfxLf8Q0A41YLnBAzEjbdN2AXcFiWAAxGhaC4F54VQQcECgfB4URPZtl2BAcNaEB8OWIiYBZZ4qygExfmOKA4TYsxOMROEiDgI9Ly4KkyWMPxzSWHxfk5DIOIQd4AzgDI+IQFIoDaWoEAAZl+agsHwOA92xOBcXfdAKBqLB6WiZxrN7G9IzMtdYBMYxRhCMIIh6I97WifAEkJPyHWiccuE0sBrz1YJQmcaJDPwh1GS6FyrEQOszE8uKfNCgKgqgEL-PC1BIuIGL-1yhKkpeFK0r5SMKzYjylGfFZEQJHUEB8DI6xMVCIO-Xinz7LiuoyV0TD69EzEG55IysmzognFICWaxEBvzJbexWlI1o2jY5rhDDnjAKAADcsBELSuGvX46CKwyypYoaM0rTafwhZVlXLYbETML6UkaH6-velrogPI8sBPM8Lyveav3BgHIYgQ9j1Pc9ROvfMqjgJguALXEsBOvdzqu+wjLgAls1+AkuIQAAfP4GFaRkIg6DnGQep6sBe29aQCZ9PlapGH0+7NPgXUx81c4XsqUQ6oEByXpZMfNIxAMie2FEWEAAPiUHwEAAMhNv5deyw2etN83P2eABCbMIiVkwgcaDoAH5ogiYWTA6W2EHthAnd-F3-qO92vZ9+WOmc70xY+jY3cl11XXzO9kcj1P08-V3UfRmHMfhu7Ecz8XI6hjG4exsulKwfGYEJ8zCnzXc+TxgmCBoLtSdZcmsAEf1Axp386YZ5n-jZjmuZ5+I+cJgW5d10X89V1V1fSoXLeMJWVd-KWN41vktYQHW2j1gAeBBBFESQZHkM2LYv7Lr9v8QpBEORA+D0OPnDrO7Eo7e19ivAOT9f7Oz3sAmOls46vQbBHIBktQZ5yQfvD4nxUEJ3zlXIuNcEYZ0TrxAu0NYZY0IZ+TuTciat0jO3Nk1DCb4B7iTHce4hLQ1Hh8ceiImYs2npzOOc9nqLy3tYFIeBFboKBlLd0a8D6ywyhpNYu8ZHFmlgoiEx82SLAQBMPsAoKGE1QMZYESkoDCRLmfAAnMbFIWA3jVEwNsKAFAADWtouyMnEYgZ8IgpELhSGWXxz8RCqKUJIpR28L5qMASnA+QF-F5lCc+Es0j4nuyScKcJOjnh6JsL6DxCBHoMEipgMqKQ1y0DPNwTW2thYGyNoHRpb8tD3y-o-c2aSmk2yfj0tpd9dD6EMIHP+KRQFtA9iA4W8CBblyTsrWRo0L5EOgRotqwpGhrJkXg8hJccZoPepw6xSh1rfhOaJICA0EAAFIPREKYbQthfIGHPCeSw6gvd2GsioFwHol1rq3W4SkXhJxJ6s2oOzIR3MSm835qkrZq8kEJIhNc6J1g0kK2ISjDRR9Iz1LPmkjy1t35iGGQYIwjNJ5bKtkoMlFLDDMg+aw-Mp8QWTMaP7EBWivgB2pa8MOWLo4AIrksyW8CWVfJeWySMTyW4ytOggBIHiQVgs2BCwRXMEEIHZbyks1sfDx29FAlFUdRWLNRXyuJYrN6vMJecwBGDga9KNTqsEYd1lQU5l6zBAcMliosPQ9hGE9F+Xoq8VAYAsDskclgfY1E+BRqwA5GypxziXCyKm3sr1aZnwngIqFM9-UIA5nCT5eEXiMUHL8Wilbq3MU1dQJ8kLy24WkOAYE4lzFGzba0ZwXJUjduYkoAArD4KSeiwB7GeBmZYRBrKHHoi8ERC9jCfO+c8KysBbIs2pJJOE26qjSFwEGUU9hUBAmoHMFcGgLK3GlMardnJuSI0jHooQXAsY0BAAALxjdmSM+A7gEkMogCJPUWAIFUYM7QehKVQbWD9J9b0ixhzWCW9qfQYDjjWASMln85CMkCiAVoPZIWIyVfkpYDkd0aQzBAHYawmrfiPVgE9OBECbJfFkC9V6eR51Pb8UgtGqi-B8KQcCrFTxCh4+KSUD6CQmF6jfdpjKjAwVnEqDeRqpMEG4Ge9qMQsIGZ5OyP9u6zAqbrHZZE0QJCtjOAgZM4Fkxg0zKtR1mY2McbgINJV3BP3ftoP+mKAsKzoAgKgbSBi2gNsOWhVkkXotcFi-FlDervzOx8JzMw-LmaQX-v7CIeWUPUZvsmkiV0YCflci8ZNgRqu+ZWeey9LQBMJzTEJsgfA+g9E8IEMUOgBCSeDgKWToo3yKYIw-PUCFQJIQyAy+DozNMgS1EhS0wdgNcEM32Yzpn7hB06xBU9fRaAvDEqKXz53-RcFiDUM45Jg5bos78XS3UbP9nRPZxzMbg4uc-G5

  3. v0.31.0Excalibur v0.31.0 Release2025-09-26 · 2025-09-26 14:52 UTC
    查看更新说明

    excalibur logo

    Added

    • Added new ex.Camera.setStrategies() and ex.Camera.strategies for additional control of strategy order
    • Fixed ex.Font measureText always using 10px sans-serif on the first call on some browsers
    • Added a new ex.Sound({...}) option back constructor to set all the same props available on sound
    • Added a new ex.SoundManager type for managing groups of audio/sound effects/music volume in an easier way
    const soundManager = new ex.SoundManger({
      channels: ['fx', 'music', 'background'],
      sounds: {
        jumpSnd: { sound: jumpSnd, volume: 0.4, channels: ['fx'] },
        forestSnd: { sound: forestSnd, volume: 0.2, channels: ['music', 'background'] },
        challengeMusic: { sound: challengeMusic, volume: 0.2, channels: ['music'] },
        guitarLoop: { sound: guitarLoop, volume: 0.2, channels: ['music'] }
      }
    });
    
    // play a specific sound
    soundManager.play('jumpSnd');
    
    // mute a specific channel with all member sounds
    soundManager.channel.mute('music');
    
    // mute all sound
    soundManager.mute();
    // unmute all sound that was previously muted, and resume playing from the current location
    soundManager.unmute();
    
    // unmute a specific channel that was muted
    soundManager.channel.unmute('music');
    
    // play a specific channel
    soundManager.channel.play('music');
    
    // set the max volume of an entire channel
    soundManager.channel.setVolume('music', 0.9);
    
    • Added ex.Animation.data to store arbitrary meta data for an animation. Data can be directly added in the constructor as an option, by using the optional data argument in fromSpriteSheet(...) and as an option in fromSpriteSheetCoordinates({...})
    • Added a new configuration option to ex.Engine({global: ...}) where you can provide a keyboard global to override if iframe detection fails for anyway.
    • Added new way to output data from scenes onDeactivate(), returning data will be passed to the next SceneActivationContext in the previousSceneData property!
    • Added new transitionstart and transitionend events to ex.Scenes
    • Pipe navigation* events to ex.Engine
    • Added ability to use ex.Vector to specify offset and margin in SpriteSheet.fromImageSource({..})
    • New PostProcessor.onDraw() hook to handle uploading textures
    • Adds contact solve bias to RealisticSolver, this allows customization on which direction contacts are solved first. By default there is no bias set to 'none'.
    • Queries can now take additional options to filter in/out by components or tags.
    const query = new Query({
      // all fields are optional
      components: {
        all: [ComponentA, ComponentB] as const, // important for type safety!
        any: [ComponentC, ComponentD] as const, // important for type safety!
        not: [ComponentE]
      },
      tags: {
        all: ['tagA', 'tagB'],
        any: ['tagC', 'tagD'],
        not: ['tagE']
      }
    })
    
    // previous constructor type still works and is shorthand for components.all
    new Query([ComponentA, ComponentB] as const)
    
    • Queries can now match all entities by specifying no filters
    const query = new Query({})
    
    • Adds maxVel attribute to MotionComponent, which clamps velocity on separated X and Y axes
    • Add Clock.clearSchedule(id) and have Clock.schedule return an ID so you can clear a scheduled callback before it fires

    Fixed

    • Fixed issue where ParticleEmitter Particle did not receive z index value from emitter when in World space
    • Fixed issue where an animation that was anim.reset() inside of an animation event handler like anim.once('end', () => anim.reset()) would not work correctly
    • Fixed issue where GpuParticleEmitter did not rotate with their parents
    • Fixed issue where Cpu ParticleEmitter did not respect ParticleTransform.Local
    • Fixed issue where same origin iframes did not work properly with keyboard & pointer events
    • Fixed is
  4. v0.30.3Excalibur v0.30.3 Release2025-01-02 · 2025-01-02 01:41 UTC
    查看更新说明

    excalibur logo

    Added

    • Adds contact solve bias to RealisticSolver, this allows customization on which direction contacts are solved first. By default there is no bias set to 'none'.

    Fixed

    • Fixed false positive warning when adding timers
    • Fixed issue where gamepad buttons wouldn't progress the default loader play button
    • Add defense around middling Safari fullscreen support and update documentation
    • Fixed issue where non-standard gamepad buttons would not be emitted by Excalibur
      • Added an additional param to the ex.GamepadButtonEvent indexto disabiguate between ex.Buttons.Unknown
    • Fixed issue where Realistic solver would not sort contacts by distance causing some artifacts on seams
    • Fixed issue with CompositeCollider where large TileMaps would sometimes causes odd collision behavior in the Realistic Solver when the body & collider components are far apart in a TileMap.

    What's Changed

    New Contributors

    Full Changelog: https://github.com/excaliburjs/Excalibur/compare/v0.30.2...v0.30.3

  5. v0.30.2Excalibur v0.30.2 Release2024-12-26 · 2024-12-26 02:49 UTC
    查看更新说明

    excalibur logo

    Added

    • New PostProcessor.onDraw() hook to handle uploading textures

    Fixed

    • Fixed crash on Xiaomi Redmi Phones by lazy loading the GPU particle renderer, GPU particles still do not work on these phones
    • Add warning if World.add() falls through! This is caused by multiple versions of Excalibur usually
    • Fixed CollidePolygonPolygon crash with some defense against invalid separation
    • Fixed issue with PostProcessor where it would not run correctly if no actors present

    Full Changelog: https://github.com/excaliburjs/Excalibur/compare/v0.30.1...v0.30.2

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Logo

    CI Coverage Status npm version npm downloads NuGet version Discord

    Sweep Stacks

    Excalibur is a free game engine written in TypeScript for making 2D games in HTML5 canvas. Our goal is to make it easier for you to create 2D HTML/JS games, whether you're new to game development or you're an experienced game developer. We take care of all of the boilerplate engine code, cross-platform targeting (using browserstack 😎), and more! Use as much or as little as you need!

    Excalibur is an open source project licensed under the 2-clause BSD license (this means you can use it in commercial projects!). It's free and always will be. We welcome any feedback or contributions! If you make something with Excalibur, please let us know!

    Get Started

    Our user documentation is at https://excaliburjs.com/docs (and you can contribute to the docs at https://github.com/excaliburjs/Excalibur/tree/main/site)

    :exclamation: Note: Excalibur is still in version 0.x, which means this project and its associated plugins may be a little rough around the edges. We try to minimize API changes, but breaking changes will occur in new released versions. Excalibur is a labor of love and the product of many hours of spare time. Thanks for checking it out!

    API Reference

    Visit the API Reference section for fully-annotated documentation of the API.

    Questions

    Samples

    Compiled examples can be found in the Excalibur Samples collection.

    Contributing

    Please read our Contributing Guidelines and our Code of Conduct. Whether you've spotted a bug, have a question, or think of a new feature, we thank you for your help!

    Writing Documentation

    We love when people help improve our documentation. You can contribute to the docs in this repo under /site

    Environment Setup

    The Excalibur.js team primarily uses Visual Studio Code as a platform agnostic editor to allow the widest contributions possible. However, you can always use your own preferred editor.

    Dev Container Support

    In supported editors, you may be prompted to Open in a Dev Container. This is a great way to contribute if you don't want to install Playwright and its dependencies on your machine and keep everything isolated.

    Dev Containers require Docker (or Podman) to be installed and should work across all platforms.

    Supported Editors

    Testing

    Browserstack

    Excalibur is committed to supporting the latest 2 versions of popular desktop and mobile browsers. We leverage browserstack automated testing to ensure that Excalibur is automatically tested as thoroughly as possible on all our supported platforms.

    Prerequisites

    After cloning the repository, run:

    npm install
    npx playwright install --with-deps
    

    [!TIP] If you are using a Dev Container, this is handled for you automatically! The --with-deps flag installs system dependencies, which may be needed depending on your OS.

    You can then run the npm tasks for various purposes:

    # Run compilation, linting, and all unit & visual tests
    # Recommend to do this before finalizing pull requests
    npm run all
    
    # Run engine core compilation only
    # Useful for quick checks to ensure everything compiles
    npm run build
    
    # Run engine tests only (does not run compile task)
    # Useful to run tests ad-hoc
    npm test
    npm run test
    
    # Start Storybook-based sandbox
    # Used for creating interactive visual tests and examples for docs
    npm run sandbox
    
    # Build a nuget package and specify a version
    npm run nuget -- 1.1.1
    

    License

    Excalibur is open source and operates under the 2-clause BSD license:

    BSD 2-Clause License
    
    Copyright (c) 2014, Erik Onarheim
    All rights reserved.
    
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:
    
    * Redistributions of source code must retain the above copyright notice, this
      list of conditions and the following disclaimer.
    
    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
    
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.