Skip to content

Commit

Permalink
add collision detection
Browse files Browse the repository at this point in the history
  • Loading branch information
hamed-rezaee committed Sep 3, 2023
1 parent 0241231 commit 27a0530
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 24 deletions.
11 changes: 6 additions & 5 deletions lib/asteroid.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ class Asteroid {
required this.size,
required this.position,
this.speed = 0.5,
double radius = 50,
this.radius = 50,
}) {
_radius = Random().nextDouble() * radius / 2 + radius / 2;
radius = Random().nextDouble() * radius / 2 + radius / 2;

for (int i = 0; i < _totalVertices; i++) {
_verticesOffset.add(Random().nextInt(radius ~/ 2) - radius / 4);
Expand All @@ -25,14 +25,15 @@ class Asteroid {
Vector position;

Vector _velocity = Vector.zero();
late final double _radius;
double radius;

final int _totalVertices = Random().nextInt(10) + 5;
final List<double> _verticesOffset = <double>[];

void update() {
position += _velocity;

position = wrapEdges(position, _radius, size);
position = wrapEdges(position, radius, size);
}

void render(Canvas canvas) {
Expand All @@ -56,7 +57,7 @@ class Asteroid {
for (int i = 0; i < _totalVertices; i++) {
final double angle = 2 * pi * i / _totalVertices;
final Vector vertex =
Vector.fromAngle(angle) * (_radius + _verticesOffset[i]);
Vector.fromAngle(angle) * (radius + _verticesOffset[i]);

points.add(vertex.toOffset);
}
Expand Down
11 changes: 11 additions & 0 deletions lib/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,14 @@ bool isOffScreen(Vector position, double radius, Size size) =>
position.x > size.width + radius ||
position.y < -radius ||
position.y > size.height + radius;

bool isColliding({
required Vector positionA,
required double radiusA,
required Vector positionB,
required double radiusB,
}) {
final double distance = (positionA - positionB).magnitude;

return distance < radiusA + radiusB;
}
98 changes: 88 additions & 10 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_asteroids/asteroid.dart';
import 'package:flutter_asteroids/helpers.dart';
import 'package:flutter_asteroids/playground.dart';
import 'package:flutter_asteroids/ship.dart';
import 'package:flutter_asteroids/vector.dart';
Expand All @@ -20,49 +21,71 @@ class MainApp extends StatefulWidget {
}

class _MainAppState extends State<MainApp> {
int score = 0;
final List<Asteroid> asteroids = <Asteroid>[];

final Ship ship = Ship(
size: size,
position: Vector(size.width / 2, size.height / 2),
);
late final Ship ship;

final List<Asteroid> asteroids = <Asteroid>[];
int score = 0;
bool isGameOver = false;

@override
void initState() {
super.initState();

_generateAstroids();

ship = Ship(
size: size,
position: Vector(size.width / 2, size.height / 2),
asteroids: asteroids,
);

Timer.periodic(const Duration(milliseconds: 16), (_) {
ship.update();
if (!isGameOver) {
ship.update();
}

for (final Asteroid asteroid in asteroids) {
asteroid.update();
}

_checkShipCollision();
_checkLaserCollision();

setState(() {});
});
}

@override
Widget build(BuildContext context) => RawKeyboardListener(
focusNode: FocusNode(),
onKey: _onKeyEventHandler,
onKey: isGameOver ? null : _onKeyEventHandler,
child: MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
body: Stack(
children: <Widget>[
_buildScore(),
_buildPlayground(),
if (isGameOver) _buildGameOver(),
],
),
),
),
);

Widget _buildGameOver() => Align(
child: Text(
'Game Over\nScore: $score\n🙁',
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.white,
fontSize: 54,
fontWeight: FontWeight.bold,
),
),
);

Widget _buildScore() => Align(
alignment: Alignment.topLeft,
child: Padding(
Expand All @@ -81,12 +104,16 @@ class _MainAppState extends State<MainApp> {
Widget _buildPlayground() => Center(
child: CustomPaint(
size: size,
painter: Playground(ship: ship, asteroids: asteroids),
painter: Playground(
ship: ship,
asteroids: asteroids,
gameOver: isGameOver,
),
),
);

void _generateAstroids() {
for (int i = 0; i < 5; i++) {
for (int i = 0; i < 8; i++) {
asteroids.add(
Asteroid(
size: size,
Expand All @@ -99,6 +126,57 @@ class _MainAppState extends State<MainApp> {
}
}

void _checkShipCollision() {
for (final Asteroid asteroid in asteroids) {
if (isColliding(
positionA: ship.position,
radiusA: ship.radius,
positionB: asteroid.position,
radiusB: asteroid.radius,
)) {
isGameOver = true;

break;
}
}
}

void _checkLaserCollision() {
for (int i = ship.lasers.length - 1; i >= 0; i--) {
for (final Asteroid asteroid in asteroids) {
if (isColliding(
positionA: ship.lasers[i].position,
radiusA: ship.lasers[i].radius,
positionB: asteroid.position,
radiusB: asteroid.radius,
)) {
score += 10;

ship.lasers.remove(ship.lasers[i]);

final double newRadius = asteroid.radius / 2;

if (newRadius > 5) {
for (int i = 0; i < 2; i++) {
asteroids.add(
Asteroid(
size: size,
position: asteroid.position,
speed: asteroid.speed * 2,
radius: newRadius,
),
);
}
}

asteroids.remove(asteroid);

break;
}
}
}
}

void _onKeyEventHandler(RawKeyEvent event) {
switch (event.runtimeType) {
case RawKeyDownEvent:
Expand Down
10 changes: 8 additions & 2 deletions lib/playground.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ class Playground extends CustomPainter {
Playground({
required this.ship,
required this.asteroids,
required this.gameOver,
this.drawDebug = false,
});

final bool drawDebug;
final Ship ship;
final List<Asteroid> asteroids;
final bool gameOver;
final bool drawDebug;

@override
void paint(Canvas canvas, Size size) {
Expand All @@ -23,7 +25,11 @@ class Playground extends CustomPainter {
asteroid.render(canvas);
}

ship.render(canvas);
if (gameOver) {
ship.explode(canvas);
} else {
ship.render(canvas);
}
}

void _drawBorder(Canvas canvas, Size size) {
Expand Down
37 changes: 30 additions & 7 deletions lib/ship.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_asteroids/asteroid.dart';
import 'package:flutter_asteroids/enums.dart';
import 'package:flutter_asteroids/helpers.dart';
import 'package:flutter_asteroids/laser.dart';
Expand All @@ -10,26 +11,29 @@ class Ship {
Ship({
required this.size,
required this.position,
required this.asteroids,
this.speed = 0.2,
this.rotationSpeed = 0.1,
this.drag = 0.98,
});

final double radius = 10;
final List<Asteroid> asteroids;

Size size;
Vector position;
double speed;
double rotationSpeed;
double drag;

final double radius = 10;
final List<Laser> lasers = <Laser>[];

bool isTurningLeft = false;
bool isTurningRight = false;
bool isThrusting = false;

double _rotation = 0;
Vector _velocity = Vector.zero();
final List<Laser> _lasers = <Laser>[];

void update() {
if (isTurningLeft) {
Expand Down Expand Up @@ -64,7 +68,7 @@ class Ship {
canvas.restore();
}

void shoot() => _lasers.add(
void shoot() => lasers.add(
Laser(
size: size,
position: position,
Expand All @@ -73,6 +77,25 @@ class Ship {
),
);

void explode(Canvas canvas) {
final List<Color> colors = <Color>[
Colors.red,
Colors.orange,
Colors.yellow,
];

final Paint paint = Paint()
..strokeWidth = 2
..color = colors[Random().nextInt(colors.length)]
..style = PaintingStyle.fill;

canvas.drawCircle(
position.toOffset,
Random().nextDouble() * radius + radius,
paint,
);
}

void _turn(Rotation rotation) =>
_rotation += (rotation == Rotation.left ? -1 : 1) * rotationSpeed;

Expand Down Expand Up @@ -113,13 +136,13 @@ class Ship {
}

void _drawLaser(Canvas canvas) {
for (int i = 0; i < _lasers.length; i++) {
_lasers[i]
for (int i = 0; i < lasers.length; i++) {
lasers[i]
..render(canvas)
..update();

if (isOffScreen(_lasers[i].position, _lasers[i].radius, size)) {
_lasers.removeAt(i);
if (isOffScreen(lasers[i].position, lasers[i].radius, size)) {
lasers.removeAt(i);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions lib/vector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class Vector {

Vector operator +(Vector other) => Vector(x + other.x, y + other.y);

Vector operator -(Vector other) => Vector(x - other.x, y - other.y);

Vector operator *(double scalar) => Vector(x * scalar, y * scalar);

@override
Expand Down

0 comments on commit 27a0530

Please sign in to comment.