Example showcasing how to use the ContactCallback

This commit is contained in:
Lukas Klingsbo
2020-05-01 00:43:13 +02:00
parent fa678cbb2c
commit 6d38f162dc
7 changed files with 282 additions and 0 deletions

2
.gitignore vendored
View File

@ -10,6 +10,8 @@ pubspec.lock
doc/api/
.flutter-plugins
.vscode/
**/.flutter-plugins
**/.flutter-plugins-dependencies
android/
ios/

View File

@ -0,0 +1,70 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# Visual Studio Code related
.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.packages
.pub-cache/
.pub/
/build/
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages

View File

@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 7fc14a55af64462763d28abfb4e610086c6e0f39
channel: dev
project_type: app

View File

@ -0,0 +1,4 @@
# box2d contact callbacks
A Flame game showcasing how to use box2d_game's contact callbacks.
Balls will bounce around and change colour when they come in contact.

View File

@ -0,0 +1,57 @@
import 'dart:ui';
import 'package:box2d_flame/box2d.dart';
import 'package:flame/box2d/box2d_component.dart';
import 'package:flame/box2d/viewport.dart';
import 'package:flame/palette.dart';
List<Wall> createBoundaries(Box2DComponent box) {
final Viewport viewport = box.viewport;
final Vector2 screenSize = Vector2(viewport.width, viewport.height)
*viewport.scale;
final Vector2 topLeft = viewport.getScreenToWorld(Vector2.zero());
final Vector2 bottomRight = viewport.getScreenToWorld(screenSize);
final Vector2 topRight = Vector2(bottomRight.x, topLeft.y);
final Vector2 bottomLeft = Vector2(topLeft.x, bottomRight.y);
return [
Wall(topLeft, topRight, box),
Wall(topRight, bottomRight, box),
Wall(bottomRight, bottomLeft, box),
Wall(bottomLeft, topLeft, box),
];
}
class Wall extends BodyComponent {
Paint paint = BasicPalette.white.paint;
final Vector2 start;
final Vector2 end;
Wall(this.start, this.end, Box2DComponent box) : super(box) {
_createBody(start, end);
}
@override
void renderPolygon(Canvas canvas, List<Offset> coordinates) {
Offset start = coordinates[0];
Offset end = coordinates[1];
canvas.drawLine(start, end, paint);
}
void _createBody(Vector2 start, Vector2 end) {
final PolygonShape shape = PolygonShape();
shape.setAsEdge(start, end);
final fixtureDef = FixtureDef();
fixtureDef.setUserData(this); // To be able to determine object in collision
fixtureDef.shape = shape;
fixtureDef.restitution = 0.0;
fixtureDef.friction = 0.1;
final bodyDef = BodyDef();
bodyDef.position = Vector2.zero();
bodyDef.type = BodyType.STATIC;
body = world.createBody(bodyDef)..createFixtureFromFixtureDef(fixtureDef);
}
}

View File

@ -0,0 +1,122 @@
import 'dart:math' as math;
import 'package:box2d_contact_callbacks/boundaries.dart';
import 'package:flame/box2d/box2d_component.dart';
import 'package:flame/box2d/box2d_game.dart';
import 'package:flame/box2d/contact_listeners.dart';
import 'package:flame/flame.dart';
import 'package:flame/palette.dart';
import 'package:flutter/material.dart';
import 'package:box2d_flame/box2d.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Flame.util.fullScreen();
runApp(GameController().widget);
}
class Ball extends BodyComponent {
Paint originalPaint, currentPaint;
Ball(Vector2 position, Box2DComponent box) : super(box) {
originalPaint = _randomPaint();
currentPaint = originalPaint;
Vector2 worldPosition = viewport.getScreenToWorld(position);
_createBody(5.0, worldPosition);
}
Paint _randomPaint() {
math.Random rng = math.Random();
return PaletteEntry(Color.fromARGB(rng.nextInt(255), rng.nextInt(255),
rng.nextInt(255), rng.nextInt(255))).paint;
}
void _createBody(double radius, Vector2 position) {
final CircleShape shape = CircleShape();
shape.radius = radius;
final fixtureDef = FixtureDef();
// To be able to determine object in collision
fixtureDef.setUserData(this);
fixtureDef.shape = shape;
fixtureDef.restitution = 1.0;
fixtureDef.density = 1.0;
fixtureDef.friction = 0.1;
final bodyDef = BodyDef();
bodyDef.position = position;
bodyDef.type = BodyType.DYNAMIC;
body = world.createBody(bodyDef)..createFixtureFromFixtureDef(fixtureDef);
}
@override
bool destroy() {
// Implement your logic for when the component should be removed
return false;
}
@override
void renderCircle(Canvas c, Offset p, double radius) {
Paint blue = PaletteEntry(Colors.blue).paint;
c.drawCircle(p, radius, currentPaint);
double angle = body.getAngle();
Offset lineRotation =
Offset(math.sin(angle) * radius, math.cos(angle) * radius);
c.drawLine(p, p + lineRotation, blue);
}
}
class BallContactCallback implements ContactCallback {
@override
List<Type> objects = [Ball, Ball];
BallContactCallback();
@override
void begin(Object contact1, Object contact2) {
Ball ball1 = contact1 as Ball;
Ball ball2 = contact2 as Ball;
if (ball1.currentPaint != ball1.originalPaint) {
ball1.currentPaint = ball2.currentPaint;
} else {
ball2.currentPaint = ball1.currentPaint;
}
}
@override
void end(Object ship, Object material) {}
}
class MyGame extends Box2DGame {
MyGame(Box2DComponent box) : super(box) {
final List<BodyComponent> boundaries = createBoundaries(box);
boundaries.forEach(add);
addContactCallback(BallContactCallback());
}
@override
void onTapDown(TapDownDetails details) {
super.onTapDown(details);
final Vector2 position =
Vector2(details.globalPosition.dx, details.globalPosition.dy);
add(Ball(position, box));
}
}
class MyBox2D extends Box2DComponent {
MyBox2D() : super(scale: 4.0, gravity: -10.0);
@override
void initializeWorld() {}
}
class GameController {
MyGame _game;
GameController() {
final MyBox2D box = MyBox2D();
_game = MyGame(box);
}
Widget get widget => _game.widget;
}

View File

@ -0,0 +1,17 @@
name: box2d_contact_callbacks
description: Flame sample game showcasing the structure for box2d games
version: 1.0.0+1
environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flame:
path: ../../../../
dev_dependencies:
flutter_test:
sdk: flutter