UNPKG

@beetpx/beetpx

Version:

A TypeScript framework for pixel art browser games.

282 lines (211 loc) 12 kB
# BeetPx <img src="logo/BeetPx_logo_x5.png" width="80" alt="BeetP logo"> > A TypeScript framework for pixel art browser games. --- <!-- TOC --> * [BeetPx](#beetpx) * [Getting Started](#getting-started) * [Examples](#examples) * [Game Controls](#game-controls) * [API](#api) * [Development Setup](#development-setup) * [The Origin](#the-origin) * [Credits](#credits) * [Fonts](#fonts) * [Color Palettes](#color-palettes) * [Bresenham's Algorithm implementation](#bresenhams-algorithm-implementation) * [Known Issues](#known-issues) * [Release Notes](#release-notes) * [v0.56.1](#v0561) * [v0.56.0](#v0560) * [v0.55.0](#v0550) * [v0.54.0](#v0540) * [v0.53.0](#v0530) * [v0.52.1](#v0521) * [v0.52.0](#v0520) * [v0.51.3](#v0513) * [v0.51.2](#v0512) * [v0.51.1](#v0511) <!-- TOC --> --- ## Getting Started In your terminal navigate to the parent folder in which you want to create your BeetPx game. Then run: ```shell npm init @beetpx/beetpx-game@latest my-game cd my-game npm install ``` where `my-game` is your desired directory/project name. To make sure things are working correctly, continue with: ```shell npm run tsc npm start ``` ### Examples To see how to use the API, check out the examples: https://github.com/beetrootpaul/beetpx-examples/ Also, you might want to take a look at how following projects are using BeetPx: | game | GitHub repository | screenshot | |------------------------|-----------------------------------------------------------------------------------------------------|------------------------------------------------------------------| | **Hat Escape** | [beetrootpaul/hat-escape](https://github.com/beetrootpaul/hat-escape) | <img src="misc/game-example-hat-escape.png" width="192"> | | **Dart-07** | [beetrootpaul/dart-07-beetpx](https://github.com/beetrootpaul/dart-07-beetpx) | <img src="misc/game-example-dart-07.gif" width="192"> | | **Towers of Survival** | [beetrootpaul/towers-of-survival-beetpx](https://github.com/beetrootpaul/towers-of-survival-beetpx) | <img src="misc/game-example-towers-of-survival.png" width="192"> | | **Avoid Your Past** | [beetrootpaul/avoid-your-past-beetpx](https://github.com/beetrootpaul/avoid-your-past-beetpx) | <img src="misc/game-example-avoid-your-past.png" width="192"> | ## Game Controls <img src="misc/beetpx_controls.png" width="640"> The BeetPx framework supports a following sets of game buttons and their mappings from physical devices: | game button | keyboard | DualSense controller | Xbox controller | |-------------------------------------|------------------------|----------------------|-----------------| | **O** (Maru) | `C` / `J` / `O` | circle / square | `A` / `Y` | | **X** (Batsu) | `X` / `K` | cross / triangle | `B` / `X` | | **menu** | `P` / `return` / `esc` | menu | menu | | **directions** | arrows / `WSAD` | D-pad / sticks | D-pad / sticks | | **mute/unmute** | `M` | | | | **full screen** | `F` | | | | **take screenshot** (if enabled) | `]` | | | | **browse screenshots** (if enabled) | `}` | | | Regarding the main game buttons on a keyboard, the intention is basically to either play with left hand on `X`+`C` and right hand on arrows, or to place the left hand on `WSAD`, then used `J`+`K` with the right hand. The `O` support is added in order to reduce to entry barrier for a situation when the game author uses the "⭕️" and "❌" on their sprites and a player doesn't realize what keys should they use – there is a chance they would try with just `O`+`X` on their keyboard. Regarding th game controllers – other controllers might works as well. For example, this framework has an implemented support for **8BitDo Lite 2**. There are also **touch controls** in form of GUI buttons resembling a physical ones. You can see and use them on touch devices like e.g. an iPhone. Dev controls meant to be used by the game developer themselves and gated behind related framework config fields: - **toggle debug**: - on keyboard: `;` - **toggle frame-by-frame**: - on keyboard: `,` - **jump to the next frame** (only while in frame-by-frame mode): - on keyboard: `.` ℹ️ To check if your controls work as expected, go to https://beetrootpaul.itch.io/beetpx-input-tester . ## API You can find docs at https://beetpx.dev . ℹ️ For a quick start you can start by typing either `BeetPx.` and checking what your IDE suggests. Same for `BeetPxDraw.`, and `BeetPxUtils.`. Their shorthands are respectively: `$`, `$d`, and `$u`. ## Development Setup This projects is developed on [Node.js 22](https://nodejs.org/docs/latest-v22.x/api/index.html). You might find it helpful to use [nvm](https://github.com/nvm-sh/nvm#installing-and-updating) in order to make sure you use the same Node.js version as which is specified in `.nvmrc` file. There is no CI configured for this project. For now, it is developed by me only, and all tests as well as the compilation happen in a pre-commit hook. ## The Origin My idea for BeetPx came from a good time I had working on mini games in [PICO-8](https://www.lexaloffle.com/pico-8.php). That fantasy console hit a very sweet spot for me: in PICO-8 you are creating low resolution pixel art games, to do so you use a globally available simple API, and all your creations can easily run in a desktop browser or a mobile one. There are though some areas I would like differently: - I prefer to use a typed language and a one which follows a standard. In PICO-8 I had to use a custom version of Lua, which meant difficulties in finding a decent extension for an IDE of my choice. - PICO-8 has a token limit, which generally means a limit on how much code you are allowed to write and an incentive to use a shorter language constructs rather than optimizing for a code maintenance. I understand this is a heated topic in PICO-8 community and I also see advantages of the limited approach – e.g. it helps to keep games low scoped and, in result finish them! Also, it is sometimes a real fun to come with clever solutions for hunting tokens down 😄. But, when it comes to my personal preferences, I more often was frustrated by the token limit rather then enjoying it. - There is (was?) a minor issue with a browser build of PICO-8 games, where the long press of a in-game button on iOS Safari makes a system text selection to appear and prevents user from playing a game in a smoothly manner. Of course, this is something I could work around by adjusting an HTML template exported from PICO-8. But since I decided to create my own framework, I am able to take care of browser iOS experience and do it the way I like. - Last but not least: I just wanted to have something created for public, [available on npm](https://www.npmjs.com/package/@beetpx/beetpx), something I feel I am capable to do and can be proud of later on ☺️ That being said, I am very grateful that PICO-8 exists and there is a big and helpful community around it. If not for PICO-8, BeetPx would never be created 💛 ## Credits ### Fonts While you are able (and encouraged) to define your own font (as an implementation of `BpxFont` interface), there are 3 fonts ready to use in BeetPx out of the box: - `$font_pico8` (the default one) - `$font_saint11Minimal4` - `$font_saint11Minimal5` The first one is a font from PICO-8 fantasy console, available under a CC-0 license (public domain, free to use). For more info see: https://www.lexaloffle.com/pico-8.php?page=faq Two other fonts are created by [Saint11](https://saint11.org/about/) and available on https://saint11.org/blog/fonts/ under a CC-0 license (public domain, free to use). ### Color Palettes There is a PICO-8 color palette ready to use, exported as `$rgb_p8`. That palette is created by zep and available under a CC-0 license (public domain, free to use). For more info see: https://www.lexaloffle.com/pico-8.php?page=faq ### Bresenham's Algorithm implementation I based the line and ellipse drawing methods on a Bresenham's Algorithm implementation by Alois Zingl: http://members.chello.at/easyfilter/bresenham.html and https://github.com/zingl/Bresenham ## Known Issues - Gamepad input seems to be laggy (at least on Firefox), unsuitable for fast paced games. - In iOS web browsers (Safari, Firefox, etc.) it is possible to go to the previous page by swiping the finger from the left edge. Which means, it is possible to accidentally close the game (while playing it on e.g. itch.io) when trying to use game touch buttons. ## Release Notes ### v0.56.1 - Fixed region clipping for sprite drawing. ### v0.56.0 - Updated Node.js used by the project from v18 to v22. - Updated TypeScript version used by the project from 5.5.3 to 5.8.2. ### v0.55.0 - Renamed `BpxEngineConfig` to `BpxFrameworkConfig`. - `BeetPx:`: Fixed `wasJustPaused()` and `wasJustResumed()`. - `BeetPxDraw`: Added `cameraXy`. - `BpxCanvasSnapshotColorMapping`: Added `from(colorMappingEntries: Array<[BpxRgbColor, BpxRgbColor]>` factory method. - `BpxColorMapper`: Made `x` and `y` optional. - `BpxEasing`: Added more easing functions. - `BpxPersistedStateValueConstraints`: `undefined` values are now valid. - `BpxTimer`: Added `isPaused()`. - `BpxTimerSequence`: Added `isPaused()`. - `BpxUtils`: Added `rand(…)` and `randInt(…)`, rename `randomElementOf(…)` to `randOf(…)`. ### v0.54.0 - CLI: Added `--htmlDeviceColor` option. - `BeetPx:`: Added `isTouchInputMethodAvailable()`. ### v0.53.0 - Renamed `$` to `$x` for a better auto-import experience in WebStorm IDE. - Drawing: Transparent (`null`) sprite pixels are now passed to the `BpxSpriteColorMapping` as well. - `BeetPxUtils`: Fixed `offset4Directions()` to return left/up/right/down instead of diagonals. - `BeetPxUtils`: Renamed `offset4Directions()` to `adjacent4()`. - `BeetPxUtils`: Renamed `offset8Directions()` to `adjacent8()`. - `BpxVector2d`: Renamed `min(…)` to `minOf(…)`. - `BpxVector2d`: Renamed `max(…)` to `maxOf(…)`. - `BpxVector2d`: Renamed `minMax(…)` to `minMaxOf(…)`. - `BpxVector2d`: Added `(x: number, y: number): boolean` overload to `eq(…)`. - `BpxVector2d`: Added `(x: number, y: number): boolean` overload to `gt(…)`. - `BpxVector2d`: Added `(x: number, y: number): boolean` overload to `gte(…)`. - `BpxVector2d`: Added `(x: number, y: number): boolean` overload to `lt(…)`. - `BpxVector2d`: Added `(x: number, y: number): boolean` overload to `lte(…)`. ### v0.52.1 - Game input: Fixed an issue of `"touch"` input method not being listed among others in a set returned by `BeetPx.getRecentInputMethods()`. ### v0.52.0 - Game loop: Fixed an issue of timers and animations behaving in the draw callback like if the next frame has already happened, even though its update callback was not called yet. ### v0.51.3 - `BpxAnimatedSprite`: Added `t` computed property. ### v0.51.2 - Console GUI on touch devices: Fixed the "O" button's press animation. - `BpxVector2d`: Added `neg()` method. - `BpxVector2d`: Added `$v_0_1` shorthand. - `BpxVector2d`: Added `$v_1_0` shorthand. ### v0.51.1 - `BpxVector2d`: Fixed `normalize()` method so it treats `(0,0)` vector in a special way by returning the `(0,0)`.