Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
9 changes: 0 additions & 9 deletions packages/flame_3d/example/lib/commands/commands.dart

This file was deleted.

60 changes: 0 additions & 60 deletions packages/flame_3d/example/lib/commands/destroy_command.dart

This file was deleted.

17 changes: 0 additions & 17 deletions packages/flame_3d/example/lib/commands/reset_command.dart

This file was deleted.

29 changes: 0 additions & 29 deletions packages/flame_3d/example/lib/commands/setup_command.dart

This file was deleted.

8 changes: 3 additions & 5 deletions packages/flame_3d/example/lib/components/crate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,16 @@ class Crate extends MeshComponent {
super.position,
}) : super(mesh: CuboidMesh(size: size));

double direction = 0.1;

@override
FutureOr<void> onLoad() async {
final crateTexture = await Flame.images.loadTexture('crate.jpg');
mesh.updateSurfaces((surfaces) {
surfaces[0].material = SpatialMaterial(
albedoTexture: crateTexture,
);
surfaces[0].material = SpatialMaterial(albedoTexture: crateTexture);
});
}

double direction = 0.1;

@override
void update(double dt) {
if (scale.x >= 1.19 || scale.x <= 0.99) {
Expand Down
81 changes: 52 additions & 29 deletions packages/flame_3d/example/lib/components/player.dart
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import 'dart:math';

import 'package:flame/components.dart' show HasGameReference, KeyboardHandler;
import 'package:flame/components.dart' show KeyboardHandler;
import 'package:flame/geometry.dart';
import 'package:flame/input.dart';
import 'package:flame/palette.dart';
import 'package:flame_3d/components.dart';
import 'package:flame_3d/game.dart';
import 'package:flame_3d/resources.dart';
import 'package:flame_3d_example/example_game_3d.dart';
import 'package:flame_3d_example/keyboard_utils.dart';
import 'package:flutter/services.dart';

class Player extends MeshComponent
with HasGameReference<ExampleGame3D>, KeyboardHandler {
class Player extends MeshComponent with KeyboardHandler {
final Vector2 _input = Vector2.zero();

bool isRunning = false;
double speedY = 0.0;

final LogicalKeyboardKey upKey;
final LogicalKeyboardKey downKey;
final LogicalKeyboardKey leftKey;
final LogicalKeyboardKey rightKey;
final LogicalKeyboardKey jumpKey;
final Set<LogicalKeyboardKey> runKeys;

double _lookAngle = 0.0;
double get lookAngle => _lookAngle;
set lookAngle(double value) {
Expand All @@ -27,40 +32,58 @@ class Player extends MeshComponent

Vector3 get lookAt => Vector3(sin(_lookAngle), 0.0, cos(_lookAngle));

Player({required Vector3 position})
: super(
position: position,
mesh: CuboidMesh(
size: Vector3(1, 2, 1),
material: SpatialMaterial(
albedoTexture: ColorTexture(BasicPalette.yellow.color),
),
),
children: [
LightComponent.point(
position: Vector3(0, 1.5, 0.8),
color: BasicPalette.white.color,
intensity: 10,
),
],
);
Player({
required Vector3 position,
this.upKey = LogicalKeyboardKey.keyW,
this.downKey = LogicalKeyboardKey.keyS,
this.leftKey = LogicalKeyboardKey.keyA,
this.rightKey = LogicalKeyboardKey.keyD,
this.jumpKey = LogicalKeyboardKey.space,
Set<LogicalKeyboardKey>? runKeys,
Color color = const Color(0xFFFFFF00),
}) : runKeys =
runKeys ??
{
LogicalKeyboardKey.shift,
LogicalKeyboardKey.shiftLeft,
LogicalKeyboardKey.shiftRight,
},
super(
position: position,
mesh: CuboidMesh(
size: Vector3(1, 2, 1),
material: SpatialMaterial(
albedoTexture: ColorTexture(color),
),
),
children: [
LightComponent.point(
position: Vector3(0, 1.5, 0.8),
color: BasicPalette.white.color,
intensity: 10,
),
],
);

@override
bool onKeyEvent(KeyEvent event, Set<LogicalKeyboardKey> keysPressed) {
final shiftKeys = {
LogicalKeyboardKey.shift,
LogicalKeyboardKey.shiftLeft,
LogicalKeyboardKey.shiftRight,
};
isRunning = shiftKeys.any(keysPressed.contains);
isRunning = runKeys.any(keysPressed.contains);

final isDown = event is KeyDownEvent || event is KeyRepeatEvent;
if (isDown && event.logicalKey == LogicalKeyboardKey.space) {
if (isDown && event.logicalKey == jumpKey) {
jump();
return false;
}

return readArrowLikeKeysIntoVector2(event, keysPressed, _input);
return readArrowLikeKeysIntoVector2(
event,
keysPressed,
_input,
up: upKey,
down: downKey,
left: leftKey,
right: rightKey,
);
}

@override
Expand Down
24 changes: 0 additions & 24 deletions packages/flame_3d/example/lib/components/simple_hud.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,36 +27,12 @@ class SimpleHud extends Component with HasGameReference<ExampleGame3D> {
String get fps =>
children.query<FpsComponent>().firstOrNull?.fps.toStringAsFixed(2) ?? '0';

final _textLeft = TextPaint(style: _style);

final _textCenter = TextPaint(style: _style.copyWith(fontSize: 20));

final _textRight = TextPaint(style: _style, textDirection: TextDirection.rtl);

@override
void render(Canvas canvas) {
final CameraComponent3D(:position, :target, :up) = game.camera;

_textLeft.render(
canvas,
'''
Camera controls:
- Move using W, A, S, D, Space, Left-Ctrl
- Look around with arrow keys or mouse
- Change camera mode with 1, 2, 3 or 4
- Change camera projection with P
- Zoom in and out with scroll
''',
Vector2.all(8),
);

_textCenter.render(
canvas,
'Welcome to the 3D world',
Vector2(game.size.x / 2, game.size.y - 8),
anchor: Anchor.bottomCenter,
);

_textRight.render(
canvas,
'''
Expand Down
87 changes: 87 additions & 0 deletions packages/flame_3d/example/lib/components/split_viewport.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import 'dart:math';

import 'package:flame/camera.dart';
import 'package:flame/extensions.dart';

enum SplitSide { left, right }

/// A viewport that occupies one half of the screen while maintaining a fixed
/// virtual resolution, similar to [FixedResolutionViewport] but positioned in
/// the left or right half for split-screen setups.
class SplitViewport extends Viewport {
SplitViewport({
required this.resolution,
required this.side,
super.children,
});

final Vector2 resolution;
final SplitSide side;

Rect _clipRect = Rect.zero;
final Vector2 _scale = Vector2.zero();

@override
Vector2 get virtualSize => resolution;

@override
void onLoad() {
_handleResize(findGame()!.canvasSize);
}

@override
void onGameResize(Vector2 canvasSize) {
super.onGameResize(canvasSize);
_handleResize(canvasSize);
}

void _handleResize(Vector2 canvasSize) {
final halfWidth = canvasSize.x / 2;
final availableHeight = canvasSize.y;
final aspectRatio = resolution.x / resolution.y;

// Fit within the half while maintaining aspect ratio.
if (availableHeight * aspectRatio > halfWidth) {
size = Vector2(halfWidth, halfWidth / aspectRatio);
} else {
size = Vector2(availableHeight * aspectRatio, availableHeight);
}

// Center within the assigned half.
final yOffset = (availableHeight - size.y) / 2;
final xOffset = switch (side) {
SplitSide.left => (halfWidth - size.x) / 2,
SplitSide.right => halfWidth + (halfWidth - size.x) / 2,
};
position.setValues(
xOffset + anchor.x * size.x,
yOffset + anchor.y * size.y,
);

_clipRect = Rect.fromLTRB(0, 0, size.x, size.y);

// Scale from pixel size to virtual resolution.
final s = min(size.x / resolution.x, size.y / resolution.y);
_scale.setAll(s);
}

@override
void clip(Canvas canvas) => canvas.clipRect(_clipRect, doAntiAlias: false);

@override
bool containsLocalPoint(Vector2 point) {
final x = point.x;
final y = point.y;
return x >= 0 && y >= 0 && x <= virtualSize.x && y <= virtualSize.y;
}

@override
void onViewportResize() {}

@override
void transformCanvas(Canvas canvas) {
canvas.translate(size.x / 2, size.y / 2);
canvas.scale(_scale.x, _scale.y);
canvas.translate(-resolution.x / 2, -resolution.y / 2);
}
}
Loading
Loading