Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding custom classes and types #14

Merged
merged 9 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,27 @@ Any other layers will be rendered visually but have no impact on the game automa
additional custom behavior by accessing the layers via `LeapGame.map.tiledMap` and integrating your
own special behavior for tiles or objects.

#### Customizing layer names and classes

Even though the structure explained above should always be followed, the developer can ask Leap
to use different classes, types, names.

In order to do so, set a new `LeapOptions` to `LeapOptions.defaults` before loading a map:

```dart
LeapOptions.defaults = const LeapOptions(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only qualm with this PR is the API to set the values...

Setting LeapOptions.defaults feels awkward, especially because if you are changing the defaults, does that mean the original values are the "default defaults"?

Anyways, maybe a function instead would be better, like LeapOptions.changeTiledConstants(...) ? Or LeapOptions could be a value on LeapGame, and you just set LeapGame.options to a new instance? Leaning towards the second option since the game ref is everywhere anyways

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it might be good to differentiate between Leap Tiled options and other options (like physics etc), but that's probably premature

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was on the fence about the naming, I tried a different approach now, let me know what you think of it, I have also prepared for the future in case we want to have multiple type of configurations, not only about tiled.

groundLayerName: 'Ground',
metadataLayerName: 'Metadata',
playerSpawnClass: 'PlayerSpawn',
hazardClass: 'Hazard',
damageProperty: 'Damage',
platformClass: 'Platform',
slopeType: 'Slope',
slopeRightTopProperty: 'RightTop',
slopeLeftTopProperty: 'LeftTop',
);
```

## Roadmap 🚧

- Improved collision detection API.
Expand All @@ -162,4 +183,4 @@ own special behavior for tiles or objects.
- `melos analyze`
- `melos test`
2. Start your PR title with a [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/)
type (feat:, fix: etc).
type (feat:, fix: etc).
2 changes: 1 addition & 1 deletion examples/standard_platformer/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ packages:
path: "../../packages/leap"
relative: true
source: path
version: "0.1.0"
version: "0.2.0"
material_color_utilities:
dependency: transitive
description:
Expand Down
4 changes: 2 additions & 2 deletions examples/standard_platformer/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ environment:
flutter: 3.13.2

dependencies:
flame: ^1.9.1
flame: ^1.10.0
flame_audio: ^2.1.1
flame_tiled: ^1.14.1
flame_tiled: ^1.15.0
flutter:
sdk: flutter
leap:
Expand Down
1 change: 1 addition & 0 deletions packages/leap/lib/leap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export 'src/entities/entities.dart';
export 'src/input.dart';
export 'src/leap_game.dart';
export 'src/leap_map.dart';
export 'src/leap_options.dart';
export 'src/leap_world.dart';
32 changes: 21 additions & 11 deletions packages/leap/lib/src/leap_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import 'package:flame/cache.dart';
import 'package:flame/components.dart';
import 'package:flame_tiled/flame_tiled.dart';
import 'package:flutter/services.dart';
import 'package:leap/src/entities/entities.dart';
import 'package:leap/src/leap_game.dart';
import 'package:leap/leap.dart';

/// This component encapsulates the Tiled map, and in particular builds the
/// grid of ground tiles that make up the terrain of the game.
class LeapMap extends PositionComponent with HasGameRef<LeapGame> {
LeapMap({required this.tileSize, required this.tiledMap}) {
groundLayer = getTileLayer<TileLayer>('Ground');
groundLayer = getTileLayer<TileLayer>(
LeapOptions.defaults.groundLayerName,
);

// Size of the map component is based on the tile map's grid.
width = tiledMap.tileMap.map.width * tileSize;
Expand Down Expand Up @@ -63,10 +64,12 @@ class LeapMap extends PositionComponent with HasGameRef<LeapGame> {

/// Spawn location for the player.
Vector2 get playerSpawn {
final metadataLayer = tiledMap.tileMap.getLayer<ObjectGroup>('Metadata');
final metadataLayer = tiledMap.tileMap.getLayer<ObjectGroup>(
LeapOptions.defaults.metadataLayerName,
);
if (metadataLayer != null) {
final spawn = metadataLayer.objects.firstWhere(
(obj) => obj.class_ == 'PlayerSpawn',
(obj) => obj.class_ == LeapOptions.defaults.playerSpawnClass,
);
return Vector2(spawn.x, spawn.y);
} else {
Expand Down Expand Up @@ -120,25 +123,32 @@ class LeapMapGroundTile extends PhysicalEntity {
late bool isSlope;

/// Hazards (like spikes) damage on collision.
bool get isHazard => tile.class_ == 'Hazard';
bool get isHazard => tile.class_ == LeapOptions.defaults.hazardClass;

/// Platforms only collide from above so the player can jump through them
/// and land on top.
bool get isPlatform => tile.class_ == 'Platform';
bool get isPlatform => tile.class_ == LeapOptions.defaults.platformClass;

/// Damage to apply when colliding and [isHazard].
int get hazardDamage {
return tile.properties.getValue<int>('Damage') ?? 0;
final damage = tile.properties.getValue<int>(
LeapOptions.defaults.damageProperty,
);
return damage ?? 0;
}

LeapMapGroundTile(
this.tile,
this.gridX,
this.gridY,
) : super(static: true, collisionType: CollisionType.tilemapGround) {
isSlope = tile.type == 'Slope';
rightTop = tile.properties.getValue<int>('RightTop');
leftTop = tile.properties.getValue<int>('LeftTop');
isSlope = tile.type == LeapOptions.defaults.slopeType;
rightTop = tile.properties.getValue<int>(
LeapOptions.defaults.slopeRightTopProperty,
);
leftTop = tile.properties.getValue<int>(
LeapOptions.defaults.slopeLeftTopProperty,
);
}

@override
Expand Down
49 changes: 49 additions & 0 deletions packages/leap/lib/src/leap_options.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/// A configurable class that allows the developer to
/// customize names and classes that Leap will look for
/// when reading the map.
class LeapOptions {
const LeapOptions({
this.groundLayerName = 'Ground',
this.metadataLayerName = 'Metadata',
this.playerSpawnClass = 'PlayerSpawn',
this.hazardClass = 'Hazard',
this.damageProperty = 'Damage',
this.platformClass = 'Platform',
this.slopeType = 'Slope',
this.slopeRightTopProperty = 'RightTop',
this.slopeLeftTopProperty = 'LeftTop',
});

/// The default options for Leap.
static LeapOptions defaults = const LeapOptions();

/// Which layer name should be used for the player, defaults to "Ground".
final String groundLayerName;

/// Which layer name should be used for the metadata, defaults to "Metadata".
final String metadataLayerName;

/// Which class name should be used for the player spawn point,
/// defaults to "PlayerSpawn".
final String playerSpawnClass;

/// Whick class name represents hazard objects, defaults to "Hazard".
final String hazardClass;

/// Which property name represents damage, defaults to "Damage".
final String damageProperty;

/// Which class name represents platform objects, defaults to "Platform".
final String platformClass;

/// Which property name represents the slope type, defaults to "Slope".
final String slopeType;

/// Which property name represents the slope left bottom, defaults to
/// "RightTop".
final String slopeRightTopProperty;

/// Which property name represents the slope right bottom, defaults to
/// "LeftTop".
final String slopeLeftTopProperty;
}
Loading