diff --git a/assets/images/wall-frames.png b/assets/images/wall-frames.png new file mode 100644 index 0000000..da38cad Binary files /dev/null and b/assets/images/wall-frames.png differ diff --git a/lib/main.dart b/lib/main.dart index 83bab5c..b77b31b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,6 +9,7 @@ import 'package:firo_runner/game_state.dart'; import 'package:firo_runner/moving_object.dart'; import 'package:firo_runner/platform.dart'; import 'package:firo_runner/platform_holder.dart'; +import 'package:firo_runner/wall_holder.dart'; import 'package:firo_runner/wire.dart'; import 'package:firo_runner/wire_holder.dart'; import 'package:flame/components.dart'; @@ -36,6 +37,7 @@ const RUNNER_PRIORITY = 100; const BUG_PRIORITY = 75; const COIN_PRIORITY = 70; const PLATFORM_PRIORITY = 50; +const WALL_PRIORITY = 40; const DEBRIS_PRIORITY = 30; const WIRE_PRIORITY = 25; const FIREWORK_PRIORITY = 15; @@ -72,6 +74,7 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { late BugHolder bugHolder; late Firework fireworks; late DebrisHolder debrisHolder; + late WallHolder wallHolder; Random random = Random(); bool playingMusic = false; @@ -106,6 +109,8 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { await bugHolder.load(); debrisHolder = DebrisHolder(); await debrisHolder.load(); + wallHolder = WallHolder(); + await wallHolder.load(); fireworks = Firework(this); await fireworks.load(); @@ -154,14 +159,19 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { if (choseCoinLevel % 3 != 2 && choseCoinLevel != 6) { coinHolder.generateCoin(this, choseCoinLevel, false); } + + int wallChosenRegion = random.nextInt(9); + if (wallChosenRegion % 3 == 1 && wallChosenRegion != 7) { + wallHolder.generateWall(this, wallChosenRegion, false); + } } bool isTooNearOtherObstacles(Rect rect) { Rect obstacleBounds = Rect.fromLTRB( - 3 * rect.left - 2 * rect.right - 1, - 3 * rect.top - 2 * rect.bottom - 1, - 3 * rect.right - 2 * rect.left + 1, - 3 * rect.bottom - 2 * rect.top + 1); + 3 * rect.left - 2 * (rect.left + blockSize) - 1, + 3 * rect.top - 2 * (rect.top + blockSize) - 1, + 3 * (rect.left + blockSize) - 2 * rect.left + 1, + 3 * (rect.top + blockSize) - 2 * rect.top + 1); for (List wireLevel in wireHolder.objects) { for (MovingObject wire in wireLevel) { if (wire.intersect(obstacleBounds) != "none") { @@ -194,6 +204,14 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { } } + for (List wallLevel in wallHolder.objects) { + for (MovingObject wall in wallLevel) { + if (wall.intersect(obstacleBounds) != "none") { + return true; + } + } + } + return false; } @@ -226,6 +244,7 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { wireHolder.setUp(); bugHolder.setUp(); debrisHolder.setUp(); + wallHolder.setUp(); gameState.setUp(this); @@ -257,6 +276,7 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { wireHolder.removePast(this); bugHolder.removePast(this); debrisHolder.removePast(this); + wallHolder.removePast(this); fillScreen(); super.update(dt); circuitBackground.update(dt); @@ -266,6 +286,7 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { wireHolder.update(dt); bugHolder.update(dt); debrisHolder.update(dt); + wallHolder.update(dt); if (shouldReset) { reset(); } @@ -286,6 +307,7 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents { wireHolder.resize(canvasSize, xRatio, yRatio); bugHolder.resize(canvasSize, xRatio, yRatio); debrisHolder.resize(canvasSize, xRatio, yRatio); + wallHolder.resize(canvasSize, xRatio, yRatio); fireworks.resize(canvasSize, xRatio, yRatio); } } diff --git a/lib/runner.dart b/lib/runner.dart index 67e6872..df6fa2b 100644 --- a/lib/runner.dart +++ b/lib/runner.dart @@ -412,8 +412,23 @@ class Runner extends Component with HasGameRef { String intersectState = debrisLevel[i].intersect(slim); if (intersectState == "none") { continue; - } else if ((runnerState == "duck" || runnerState == "float") && - intersectState != "above") { + } else if (runnerState == "duck" && intersectState != "above") { + continue; + } else { + event("die"); + } + } + } + + for (List debrisLevel in gameRef.wallHolder.objects) { + for (int i = 0; i < debrisLevel.length; i++) { + Rect slim = Rect.fromLTRB( + runnerRect.left + sprite.width / 3, + runnerRect.top + sprite.height / (runnerState == "duck" ? 3 : 6), + runnerRect.right - sprite.width / 3, + runnerRect.bottom - sprite.height / 3); + String intersectState = debrisLevel[i].intersect(slim); + if (intersectState == "none") { continue; } else { event("die"); diff --git a/lib/wall.dart b/lib/wall.dart new file mode 100644 index 0000000..6b7e9e8 --- /dev/null +++ b/lib/wall.dart @@ -0,0 +1,54 @@ +import 'package:firo_runner/moving_object.dart'; +import 'package:firo_runner/main.dart'; +import 'package:flame/components.dart'; + +enum WallState { normal } + +class Wall extends MovingObject { + int direction = -1; + late int bottomPlatformLevel; + Wall(MyGame gameRef) : super(gameRef) { + var wall = gameRef.wallHolder.getWall(); + SpriteAnimation normal = SpriteAnimation.fromFrameData( + wall, + SpriteAnimationData.sequenced( + amount: 5, + stepTime: 0.1, + textureSize: Vector2(163, 1000), + ), + ); + + sprite = SpriteAnimationGroupComponent( + animations: { + WallState.normal: normal, + }, + current: WallState.normal, + ); + + sprite.changePriorityWithoutResorting(WALL_PRIORITY); + + setSize( + gameRef.blockSize * + (gameRef.wallHolder.wall.width / gameRef.wallHolder.wall.height / 5) * + 2.0, + gameRef.blockSize * 0.5, + ); + } + + @override + void update(double dt) { + super.update(dt); + int nearestPlatform = + getNearestPlatform((sprite.x / gameRef.blockSize).round()); + nearestPlatform = nearestPlatform == 0 ? -1 : nearestPlatform; + if (sprite.y + sprite.height > bottomPlatformLevel * gameRef.blockSize) { + direction = -1; + } else if ((bottomPlatformLevel - 2) * gameRef.blockSize - + 2 * gameRef.blockSize / 7 > + sprite.y) { + direction = 1; + } + double velocity = gameRef.gameState.getVelocity() / 10.0; + sprite.position = sprite.position + Vector2(0, direction * velocity * dt); + } +} diff --git a/lib/wall_holder.dart b/lib/wall_holder.dart new file mode 100644 index 0000000..c9ad35d --- /dev/null +++ b/lib/wall_holder.dart @@ -0,0 +1,65 @@ +import 'package:firo_runner/holder.dart'; +import 'package:firo_runner/platform.dart'; +import 'package:flame/extensions.dart'; +import 'package:flame/flame.dart'; + +import 'package:firo_runner/wall.dart'; +import 'package:firo_runner/main.dart'; + +class WallHolder extends Holder { + late Image wall; + + @override + Future load() async { + wall = await Flame.images.load("wall-frames.png"); + } + + getWall() { + return wall; + } + + bool generateWall(MyGame gameRef, int level, bool force) { + if (objects[level].isNotEmpty) { + return false; + } + + if (random.nextInt(100) > 25) { + return true; + } else { + int nearestPlatform = getNearestPlatform(level); + + Platform? platform = + gameRef.platformHolder.getPlatformOffScreen(nearestPlatform); + if (platform != null && platform.prohibitObstacles) { + return false; + } + double xCoordinate = -100; + + if (level == 0) { + xCoordinate = gameRef.size.x; + } else if (platform != null) { + xCoordinate = platform.sprite.x; + } else { + return false; + } + + Wall wall = Wall(gameRef); + wall.setPosition(xCoordinate, gameRef.blockSize * level); + wall.bottomPlatformLevel = level + 1; + + if (gameRef.isTooNearOtherObstacles(wall.sprite.toRect())) { + return false; + } + + objects[level].add(wall); + gameRef.add(wall.sprite); + if (platform != null) { + platform.removeChildren.add(() { + objects[level].remove(wall); + wall.remove(); + }); + } + return false; + } + } +}