Skip to content

Commit

Permalink
docs: bootstrapping the docs for initial release (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
kurtome authored Sep 12, 2022
1 parent eaf857a commit 7ecdedc
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 135 deletions.
167 changes: 145 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,162 @@
<!--
This README describes the package. If you publish this package to pub.dev,
this README's contents appear on the landing page for your package.
# Leap

For information about how to write a good package README, see the guide for
[writing package pages](https://dart.dev/guides/libraries/writing-package-pages).
An opinionated toolkit for creating 2D platformers on top of
the [Flame engine](https://flame-engine.org/).

For general information about developing packages, see the Dart guide for
[creating packages](https://dart.dev/guides/libraries/create-library-packages)
and the Flutter guide for
[developing packages and plugins](https://flutter.dev/developing-packages).
-->
## WARNING library under development

TODO: Put a short description of the package here that helps potential users
know whether this package might be useful for them.
Be aware that this is still under development and is likely to change frequently, every release
could introduce breaking changes up until a `v1.0.0` release (which may never happen as this
is a solo endeavour currently).

## Features

TODO: List what your package can do. Maybe include images, gifs, or videos.
### Level creation via Tiled

Leap uses Tiled tile maps not just for visually rendering the level, but also for imbuing behavior
and terrain in the level by creating corresponding Flame components automatically from the map's
layers.

### Physics

The crux of this physics engine is based on this post
[The guide to implementing 2D platformers](http://higherorderfun.com/blog/2012/05/20/the-guide-to-implementing-2d-platformers/)

The "Type #2: Tile Based (Smooth)" section outlines the overall algorithm.

Note that Leap doesn't use Flame's collision detection system in favor of one that is more
specialized and efficient for tile based platformers where every hitbox is an axis-aligned bounding
box, and special handling can be done for tile grid aligned components (such as ground terrain).

#### Efficient collision detection

[!image](http://higherorderfun.com/blog/wp-content/uploads/2012/05/Mega_Man_X_tiles.png)

Essentially all physical objects (`PhsyicalComponent`) in the game have axis-aligned bounding boxes
(AABBs) for hitboxes, determined by their `size` and `position`. The hitbox doesn't necessarily need
to match the visual size of the component.

✅ Supported tile platformer features:

- Ground terrain
- One way platforms
- Slopes

🚧 Future tile platformer features:

- Moving platforms
- Ladders

#### Simple physics designed for 2D platformers

Long story short, physics engines like `box2d` are great for emulating realistic physics and
terrible for implementing retro-style 2d platformers which are not remotely realistic. In order to
get the snappy jumps and controls required for a responsive platformer a much more rudimentary
physics engine is required.

In Leap, physical entities have a `velocity` attribute for storing the current `x` and `y` velocity,
which will automatically update the entity's position. A moving entity colliding with the level
terrain will automatically have its velocity set to `0` and position updated to be kept outside the
terrain to prevent overlap. There is also a global `gravity` rate applied to the `y` velocity every
game tick. Static entities will never be moved by velocity or gravity.

## Getting started

TODO: List prerequisites and provide or point to information on how to
start using the package.
Before using Leap, you should be familiar with the following Flame components:

- FlameGame
- Camera
- PositionComponent
- TiledComponent

## Usage

TODO: Include short and useful examples for package users. Add longer examples
to `/example` folder.
### LeapGame

To use Leap, your game instance must extend `LeapGame` (which in turn extends `FlameGame`). It's
recommended to use `game.loadWorldAndMap` to initialize the game's `world` and `map`.

### LeapWorld

Accessible via `LeapGame.world`, this component manages any global logic necessary for the physics
engine.

### LeapMap

Accessible via `LeapGame.map`, this component manages the Tiled map and automatically constructs the
tiles with proper collision detection for the ground terrain.
See [Tiled map integration](#Tiled map integration) below

### Game code snippet

See [the standard_platformer example](examples/standard_platformer) for complete game code.

```dart
const like = 'sample';
void main() {
runApp(GameWidget(game: MyLeapGame()));
}
class MyLeapGame extends LeapGame with HasTappables, HasKeyboardHandlerComponents {
late final Player player;
@override
Future<void> onLoad() async {
await super.onLoad();
// "map.tmx" should be a Tiled map the meets the Leap requirements defined below
await loadWorldAndMap('map.tmx', 16);
setFixedViewportInTiles(32, 16);
player = Player();
add(player);
camera.followComponent(player);
}
}
```

## Additional information
### Tiled map integration

Leap automatically parses specific features out of specific Tiled layers.

#### Ground layer

Layer must be a Tile Layer named "Ground", by default all tiles placed in this layer are assumed to
be ground terrain in the physics of the game. This means these tiles will be statically positioned
and have a hitbox that matches the width and height of the tile.

Specialized ground tiles:

- **Slopes** for terrain the physical can walk up/down like a hill. These tiles must have
their `class` property set to `"Slope"` and two custom `int` properties `LeftTop` and `RightTop`.
For example, a 16x16 pixel tile with `LeftTop = 0` and `RightTop = 8` indicates slope that is
ascending when moving from left-to-right.
- **Platforms** (name may change) for terrain the physical entities can move up (e.g. jump) through
from below but still land on. These tiles must have their `class` property set to `"Platform"`.

#### Metadata layer

Layer must be an Object Group named "Metadata", used to place any objects to be used in your game
like level start/end, enemy spawn points, anything you want.

#### Other layer

Any other layers will be rendered visually but have no impact on the game automatically. You can add
additional custom behavior by accessing the layers via `LeapGame.map.tiledMap` and integrating your
own special behavior for tiles or objects.

## Roadmap 🚧

- Improved collision detection API.
- The current API is fairly awkward, see `CollisionInfo`.
- There is no great way to detect collision start or collision end.
- Add support for moving platforms and ladders.
- Add more robust and reusable base class for players/enemies/etc. (`Character` class).
- Integrated with sprite animations based on character state
- Improved API for `PhysicalEntity`, `addImpulse` etc.
- Lots of code clean-up to make usage of Leap more ergonomic and configurable.

## Contributing

TODO: Tell users more about the package: where to find more information, how to
contribute to the package, how to file issues, what response they can expect
from the package authors, and more.
1. Ensure any changes pass `melos analyze` and `melos test`.
2. Start your PR title with a [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/)
type (feat:, fix: etc).
2 changes: 1 addition & 1 deletion examples/standard_platformer/lib/player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class Player extends JumperCharacter {

resetPosition();

walkSpeed = map.tileSizePx * 7;
walkSpeed = map.tileSize * 7;
minJumpImpulse = world.gravity * 0.6;

return super.onLoad();
Expand Down
39 changes: 0 additions & 39 deletions packages/leap/README.md

This file was deleted.

1 change: 1 addition & 0 deletions packages/leap/README.md
1 change: 1 addition & 0 deletions packages/leap/lib/src/input.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flame/input.dart';
import 'package:flutter/services.dart';
import 'package:leap/leap.dart';

/// Combines touch screen and keyboard input into one API.
class SimpleCombinedInput extends Component with HasGameRef<LeapGame> {
late final SimpleTapInput _tapInput;
late final SimpleKeyboardInput _keyboardInput;
Expand Down
1 change: 1 addition & 0 deletions packages/leap/lib/src/leap_game.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class LeapGame extends FlameGame with HasTrackedComponents {
world.input.appStateChanged();
}

/// Tile size (width and height) in pixels
double get tileSize => world.tileSize;

/// Initializes and loads the [world] and [map] components with a Tiled map,
Expand Down
Loading

0 comments on commit 7ecdedc

Please sign in to comment.