Skip to content

A TypeScript engine for pixel art browser games

License

Notifications You must be signed in to change notification settings

beetrootpaul/beetpx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BeetPx

BeetP logo

A TypeScript engine for pixel art browser games.



Getting Started

In your terminal navigate to the parent folder in which you want to create your BeetPx game. Then run:

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:

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
Dart-07 beetrootpaul/dart-07-beetpx
Towers of Survival beetrootpaul/towers-of-survival-beetpx
Avoid Your Past beetrootpaul/avoid-your-past-beetpx

Game Controls

The BeetPx engine 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 engine 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 engine 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 18.

You might find it helpful to use nvm 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. 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 engine, 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, 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 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

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.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 by returning the (0,0).