@ -1,7 +1,9 @@
import ' dart:math ' as math ;
import ' package:flame/extensions.dart ' ;
import ' package:flame_forge2d/flame_forge2d.dart ' ;
import ' package:flutter/material.dart ' ;
import ' package:geometry/geometry.dart ' show centroid ;
import ' package:geometry/geometry.dart ' as geometry show centroid ;
import ' package:pinball/game/game.dart ' ;
/ / / { @ template sling_shot }
@ -31,54 +33,88 @@ class SlingShot extends BodyComponent with InitialPosition {
/ / / The size of the [ SlingShot ] body .
/ / TODO ( alestiago ) : Use size from PositionedBodyComponent instead ,
/ / once a sprite is given .
static final Vector2 size = Vector2 ( 6, 8 ) ;
static final Vector2 size = Vector2 ( 4, 10 ) ;
List < FixtureDef > _createFixtureDefs ( ) {
final fixturesDef = < FixtureDef > [ ] ;
/ / TODO ( alestiago ) : This magic number can be deduced by specifying the
/ / angle and using polar coordinate system to place the bottom right
/ / vertex .
/ / Something as : y = - size . y * math . cos ( angle )
const additionalIncrement = 3 ;
final triangleVertices = _side . isLeft
? [
Vector2 ( 0 , 0 ) ,
Vector2 ( 0 , - size . y ) ,
Vector2 (
size . x ,
- size . y - additionalIncrement ,
) ,
]
: [
Vector2 ( size . x , 0 ) ,
Vector2 ( size . x , - size . y ) ,
final fixturesDefs = < FixtureDef > [ ] ;
final direction = _side . direction ;
const quarterPi = math . pi / 4 ;
final upperCircle = CircleShape ( ) . . radius = 1.45 ;
upperCircle . position . setValues ( 0 , - upperCircle . radius / 2 ) ;
final upperCircleFixtureDef = FixtureDef ( upperCircle ) . . friction = 0 ;
fixturesDefs . add ( upperCircleFixtureDef ) ;
final lowerCircle = CircleShape ( ) . . radius = 1.45 ;
lowerCircle . position . setValues (
size . x * - direction ,
- size . y ,
) ;
final lowerCircleFixtureDef = FixtureDef ( lowerCircle ) . . friction = 0 ;
fixturesDefs . add ( lowerCircleFixtureDef ) ;
final wallFacingEdge = EdgeShape ( )
. . set (
upperCircle . position +
Vector2 (
upperCircle . radius * direction ,
0 ,
- size . y - additionalIncrement ,
) ,
] ;
final triangleCentroid = centroid ( triangleVertices ) ;
for ( final vertex in triangleVertices ) {
vertex . setFrom ( vertex - triangleCentroid ) ;
}
/ / TODO ( alestiago ) : Use values from design .
Vector2 ( 2.0 * direction , - size . y + 2 ) ,
) ;
final wallFacingLineFixtureDef = FixtureDef ( wallFacingEdge ) . . friction = 0 ;
fixturesDefs . add ( wallFacingLineFixtureDef ) ;
final triangle = PolygonShape ( ) . . set ( triangleVertices ) ;
final triangleFixtureDef = FixtureDef ( triangle ) . . friction = 0 ;
fixturesDef . add ( triangleFixtureDef ) ;
final bottomEdge = EdgeShape ( )
. . set (
wallFacingEdge . vertex2 ,
lowerCircle . position +
Vector2 (
lowerCircle . radius * math . cos ( quarterPi ) * direction ,
- lowerCircle . radius * math . sin ( quarterPi ) ,
) ,
) ;
final bottomLineFixtureDef = FixtureDef ( bottomEdge ) . . friction = 0 ;
fixturesDefs . add ( bottomLineFixtureDef ) ;
final kicker = EdgeShape ( )
final kicker Edge = EdgeShape ( )
. . set (
triangleVertices . first ,
triangleVertices . last ,
upperCircle . position +
Vector2 (
upperCircle . radius * math . cos ( quarterPi ) * - direction ,
upperCircle . radius * math . sin ( quarterPi ) ,
) ,
lowerCircle . position +
Vector2 (
lowerCircle . radius * math . cos ( quarterPi ) * - direction ,
lowerCircle . radius * math . sin ( quarterPi ) ,
) ,
) ;
/ / TODO ( alestiago ) : Play with restitution value once game is bundled .
final kickerFixtureDef = FixtureDef ( kicker )
final kickerFixtureDef = FixtureDef ( kickerEdge )
/ / TODO ( alestiago ) : Play with restitution value once game is bundled .
. . restitution = 10.0
. . friction = 0 ;
fixturesDef . add ( kickerFixtureDef ) ;
fixturesDef s . add ( kickerFixtureDef ) ;
return fixturesDef ;
/ / TODO ( alestiago ) : Evaluate if there is value on centering the fixtures .
final centroid = geometry . centroid (
[
upperCircle . position + Vector2 ( 0 , - upperCircle . radius ) ,
lowerCircle . position +
Vector2 (
lowerCircle . radius * math . cos ( quarterPi ) * - direction ,
- lowerCircle . radius * math . sin ( quarterPi ) ,
) ,
wallFacingEdge . vertex2 ,
] ,
) ;
for ( final fixtureDef in fixturesDefs ) {
fixtureDef . shape . moveBy ( - centroid ) ;
}
return fixturesDefs ;
}
@ override
@ -90,3 +126,17 @@ class SlingShot extends BodyComponent with InitialPosition {
return body ;
}
}
/ / TODO ( alestiago ) : Evaluate if there ' s value on generalising this to
/ / all shapes .
extension on Shape {
void moveBy ( Vector2 offset ) {
if ( this is CircleShape ) {
final circle = this as CircleShape ;
circle . position . setFrom ( circle . position + offset ) ;
} else if ( this is EdgeShape ) {
final edge = this as EdgeShape ;
edge . set ( edge . vertex1 + offset , edge . vertex2 + offset ) ;
}
}
}