Skip to content

Commit

Permalink
exercise 3.4: simulating a vehicle with controls
Browse files Browse the repository at this point in the history
  • Loading branch information
CoderNamedHendrick committed Jan 29, 2024
1 parent 7c7f3ba commit d73f1df
Show file tree
Hide file tree
Showing 9 changed files with 659 additions and 14 deletions.
9 changes: 0 additions & 9 deletions lib/chapters/one_vectors/mover.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ class Mover {
late Vector velocity;
final Size canvasSize;
late Vector acceleration;
late double topSpeed;
late double mass;

Mover._(
this.position,
this.velocity,
this.canvasSize,
this.acceleration,
this.topSpeed,
this.mass,
);

Expand All @@ -28,15 +26,13 @@ class Mover {
// constant acceleration initialisation
acceleration = const Vector(0, 0);

topSpeed = 10;
mass = 10;
}

void updateRandomAcceleration() {
acceleration = Vector.random();
acceleration *= (Random().nextDouble() * 4) - 2;
velocity += acceleration;
velocity = velocity.limit(topSpeed);
position += velocity;
}

Expand All @@ -48,7 +44,6 @@ class Mover {

void update() {
velocity += acceleration;
velocity = velocity.limit(topSpeed);
position += velocity;

acceleration *= 0; // reset acceleration
Expand Down Expand Up @@ -79,15 +74,13 @@ class Mover {
Vector? velocity,
Size? canvasSize,
Vector? acceleration,
double? topSpeed,
double? mass,
}) {
return Mover._(
position ?? this.position,
velocity ?? this.velocity,
canvasSize ?? this.canvasSize,
acceleration ?? this.acceleration,
topSpeed ?? this.topSpeed,
mass ?? this.mass,
);
}
Expand All @@ -98,7 +91,6 @@ class Mover {
velocity.hashCode ^
canvasSize.hashCode ^
acceleration.hashCode ^
topSpeed.hashCode ^
mass.hashCode;

@override
Expand All @@ -109,7 +101,6 @@ class Mover {
velocity == other.velocity &&
canvasSize == other.canvasSize &&
acceleration == other.acceleration &&
topSpeed == other.topSpeed &&
mass == other.mass;
}
}
5 changes: 5 additions & 0 deletions lib/chapters/one_vectors/vector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ class Vector {
return newVector * newMag;
}

/// returns the angle of the vector in radians
double heading() {
return atan2(y, x);
}

Vector operator +(covariant Vector v) {
return Vector(x + v.x, y + v.y);
}
Expand Down
10 changes: 7 additions & 3 deletions lib/chapters/one_vectors/vehicle_mover.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import 'vector.dart';

class VehicleMover extends Mover {
bool isBreaking = false;
late double topSpeed;
static const Vector _deceleration = Vector(0.01, 0);

VehicleMover(super.canvasSize, double topSpeed) {
VehicleMover(super.canvasSize, this.topSpeed) {
acceleration = const Vector(0, 0);
this.topSpeed = topSpeed;
}

void brake() {
Expand All @@ -25,7 +25,11 @@ class VehicleMover extends Mover {

@override
void update() {
super.update();
velocity += acceleration;
velocity = velocity.limit(topSpeed);
position += velocity;

acceleration *= 0; // reset acceleration

if (isBreaking && velocity.mag() < 1) {
velocity = Vector.zero;
Expand Down
100 changes: 100 additions & 0 deletions lib/chapters/three_oscillation/baton_challenge.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import 'package:flutter/material.dart';
import 'package:the_nature_of_code/chapters/three_oscillation/mover.dart';

class BatonOscillation extends StatefulWidget {
const BatonOscillation({super.key});

@override
State<BatonOscillation> createState() => _BatonOscillationState();
}

class _BatonOscillationState extends State<BatonOscillation>
with SingleTickerProviderStateMixin {
late AnimationController controller;

Mover? mover;

@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 100),
)..repeat();

controller.addListener(() {
setState(() {
mover?.update();
});
});
}

@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
mover ??= Mover(constraints.biggest);
return Center(
child: Transform.rotate(
angle: mover?.angle ?? 0,
child: _box(80),
),
);
},
);
}

Widget _box(double size) {
return Container(
width: size,
height: size,
color: Colors.red,
);
}
}

class BatonPainter extends CustomPainter {
final double angle;

const BatonPainter(this.angle);

@override
void paint(Canvas canvas, Size size) {
canvas.translate(size.width / 2, size.height / 2);
canvas.rotate(angle);

const center =
Offset(0, 0); // center is zero offset since origin is now at the center
const halfOfLengthOffset = Offset(80, 0);
canvas.drawLine(
center - halfOfLengthOffset,
center + halfOfLengthOffset, // length of 120
Paint()
..color = Colors.green
..strokeWidth = 3,
);

canvas.drawCircle(
center - halfOfLengthOffset,
16,
Paint()
..color = Colors.blue
..strokeWidth = 2,
);
canvas.drawCircle(
center + halfOfLengthOffset,
16,
Paint()
..color = Colors.blue
..strokeWidth = 2,
);
}

@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
if (oldDelegate is! BatonPainter) return false;

if (oldDelegate.angle != angle) return true;
return false;
}
}
Loading

0 comments on commit d73f1df

Please sign in to comment.