Added level scaling and animations as Firo coins are gathered #4. Also Tightened the controls on mobile to make user input faster.

This commit is contained in:
Marco Salazar 2021-10-01 20:46:44 -06:00
parent e8455500da
commit 91e5554105
6 changed files with 267 additions and 84 deletions

View File

@ -50,7 +50,7 @@ class CoinHolder extends Holder {
} }
void renderCoinScore(Canvas c) { void renderCoinScore(Canvas c) {
sprite.position = Vector2(personalGameRef.size.x - 33, 10); sprite.position = Vector2(personalGameRef.size.x - 70, 10);
sprite.render(c); sprite.render(c);
} }

View File

@ -87,6 +87,23 @@ class GameState extends Component {
} }
} }
int getDangerLevel() {
int score = getScore();
if (score > LEVEL2 / 2 + LEVEL2 / (2 * 4)) {
return 5;
} else if (score > LEVEL2 / 2) {
return 4;
} else if (score > LEVEL2 / 2 - LEVEL2 / (2 * 4)) {
return 3;
} else if (score > LEVEL2 / 2 - 2 * LEVEL2 / (2 * 4)) {
return 2;
} else if (score > LEVEL2 / 2 - 3 * LEVEL2 / (2 * 4)) {
return 1;
} else {
return 0;
}
}
int getScore() { int getScore() {
return distance ~/ 10 + numCoins * 1000000; return distance ~/ 10 + numCoins * 1000000;
} }
@ -103,22 +120,32 @@ class GameState extends Component {
if (!isPaused) { if (!isPaused) {
switch (getLevel()) { switch (getLevel()) {
case 7: case 7:
return gameRef.viewport.canvasSize.x * 0.25; return gameRef.viewport.canvasSize.x * 0.28;
case 6: case 6:
return gameRef.viewport.canvasSize.x * 0.20; return gameRef.viewport.canvasSize.x * 0.26;
case 5: case 5:
return gameRef.viewport.canvasSize.x * 0.18; return gameRef.viewport.canvasSize.x * 0.24;
case 4: case 4:
return gameRef.viewport.canvasSize.x * 0.16; return gameRef.viewport.canvasSize.x * 0.22;
case 3: case 3:
return gameRef.viewport.canvasSize.x * 0.14; return gameRef.viewport.canvasSize.x * 0.20;
case 2: case 2:
return gameRef.viewport.canvasSize.x * 0.12; return gameRef.viewport.canvasSize.x * 0.18;
default: default:
return gameRef.viewport.canvasSize.x * 0.1; return gameRef.viewport.canvasSize.x * 0.16;
} }
} else { } else {
return 0; return 0;
} }
} }
int getRobotLevel() {
if (numCoins > COINS_ROBOT_UPGRADE2) {
return 3;
} else if (numCoins > COINS_ROBOT_UPGRADE1) {
return 2;
} else {
return 1;
}
}
} }

View File

@ -53,9 +53,9 @@ class LoseMenuOverlay extends StatelessWidget {
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
" Main Menu ", " MAIN MENU ",
style: TextStyle( style: TextStyle(
color: Colors.white, color: Colors.cyan,
fontSize: width * 0.03, fontSize: width * 0.03,
), ),
), ),
@ -83,9 +83,9 @@ class LoseMenuOverlay extends StatelessWidget {
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
" Replay ", " REPLAY ",
style: TextStyle( style: TextStyle(
color: Colors.white, color: Colors.cyan,
fontSize: width * 0.03, fontSize: width * 0.03,
), ),
), ),

View File

@ -34,12 +34,15 @@ import 'package:firo_runner/main_menu_overlay.dart';
const COLOR = Color(0xFFDDC0A3); const COLOR = Color(0xFFDDC0A3);
const int LOADING_TIME = 2000000; const int LOADING_TIME = 2000000;
const LEVEL2 = 10000000; const LEVEL2 = 25000000;
const LEVEL3 = 20000000; const LEVEL3 = 50000000;
const LEVEL4 = 30000000; const LEVEL4 = 75000000;
const LEVEL5 = 40000000; const LEVEL5 = 100000000;
const LEVEL6 = 50000000; const LEVEL6 = 125000000;
const LEVEL7 = 60000000; const LEVEL7 = 150000000;
const COINS_ROBOT_UPGRADE1 = 50;
const COINS_ROBOT_UPGRADE2 = 100;
const OVERLAY_PRIORITY = 110; const OVERLAY_PRIORITY = 110;
const RUNNER_PRIORITY = 100; const RUNNER_PRIORITY = 100;
@ -170,12 +173,12 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
await runner.load(loadSpriteAnimation); await runner.load(loadSpriteAnimation);
loaded = true; loaded = true;
_distance = TextComponent("Distance: 0", _distance = TextComponent("Time: 0",
position: Vector2(size.x - 100, 10), textRenderer: scoresPaint) position: Vector2(size.x - 100, 10), textRenderer: scoresPaint)
..anchor = Anchor.topRight; ..anchor = Anchor.topRight;
_distance.changePriorityWithoutResorting(OVERLAY_PRIORITY); _distance.changePriorityWithoutResorting(OVERLAY_PRIORITY);
_coins = TextComponent(": 0", _coins = TextComponent(": 0",
position: Vector2(size.x - 35, 10), textRenderer: scoresPaint) position: Vector2(size.x - 20, 10), textRenderer: scoresPaint)
..anchor = Anchor.topRight; ..anchor = Anchor.topRight;
_coins.changePriorityWithoutResorting(OVERLAY_PRIORITY); _coins.changePriorityWithoutResorting(OVERLAY_PRIORITY);
overlays.add("gameOver"); overlays.add("gameOver");
@ -196,24 +199,31 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
if (shouldReset) { if (shouldReset) {
return; return;
} }
int dangerLevel = gameState.getDangerLevel();
platformHolder.generatePlatforms(this); platformHolder.generatePlatforms(this);
int wireChosenRegion = random.nextInt(9); if (dangerLevel > 2) {
if (wireChosenRegion % 3 != 2 && int wireChosenRegion = random.nextInt(9);
wireChosenRegion != 6 && if (wireChosenRegion % 3 != 2 &&
wireChosenRegion != 7) { wireChosenRegion != 6 &&
wireHolder.generateWire(this, wireChosenRegion); wireChosenRegion != 7) {
wireHolder.generateWire(this, wireChosenRegion);
}
} }
int bugChosenRegion = random.nextInt(9); if (dangerLevel > 0) {
if (bugChosenRegion % 3 != 2 && bugChosenRegion % 3 != 0) { int bugChosenRegion = random.nextInt(9);
bugHolder.generateBug(this, bugChosenRegion); if (bugChosenRegion % 3 != 2 && bugChosenRegion % 3 != 0) {
bugHolder.generateBug(this, bugChosenRegion);
}
} }
int debrisChosenRegion = random.nextInt(9); if (dangerLevel > 1) {
if (debrisChosenRegion % 3 == 0 && debrisChosenRegion != 6) { int debrisChosenRegion = random.nextInt(9);
debrisHolder.generateDebris(this, debrisChosenRegion); if (debrisChosenRegion % 3 == 0 && debrisChosenRegion != 6) {
debrisHolder.generateDebris(this, debrisChosenRegion);
}
} }
int choseCoinLevel = random.nextInt(9); int choseCoinLevel = random.nextInt(9);
@ -221,9 +231,11 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
coinHolder.generateCoin(this, choseCoinLevel); coinHolder.generateCoin(this, choseCoinLevel);
} }
int wallChosenRegion = random.nextInt(9); if (dangerLevel > 4) {
if (wallChosenRegion % 3 == 1 && wallChosenRegion != 7) { int wallChosenRegion = random.nextInt(9);
wallHolder.generateWall(this, wallChosenRegion); if (wallChosenRegion % 3 == 1 && wallChosenRegion != 7) {
wallHolder.generateWall(this, wallChosenRegion);
}
} }
} }
@ -389,12 +401,12 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
circuitBackground.render(canvas); circuitBackground.render(canvas);
fireworks.renderText(canvas); fireworks.renderText(canvas);
super.render(canvas); super.render(canvas);
final fpsCount = fps(10000); // final fpsCount = fps(10000);
fireworksPaint.render( // fireworksPaint.render(
canvas, // canvas,
fpsCount.toString(), // fpsCount.toString(),
Vector2(0, 0), // Vector2(0, 0),
); // );
coinHolder.renderCoinScore(canvas); coinHolder.renderCoinScore(canvas);
} }
} }
@ -426,7 +438,7 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
debrisHolder.update(dt); debrisHolder.update(dt);
wallHolder.update(dt); wallHolder.update(dt);
_distance.text = "Distance: ${gameState.getPlayerDistance()}"; _distance.text = "Time: ${gameState.getPlayerDistance()}";
_coins.text = " ${gameState.numCoins}"; _coins.text = " ${gameState.numCoins}";
if (shouldReset && if (shouldReset &&
!overlays.isActive('gameOver') && !overlays.isActive('gameOver') &&
@ -464,36 +476,46 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
yDeltas = List.empty(growable: true); yDeltas = List.empty(growable: true);
} }
bool action = false;
@override @override
void onPanUpdate(DragUpdateInfo info) { void onPanUpdate(DragUpdateInfo info) {
xDeltas.add(info.delta.game.x); xDeltas.add(info.delta.game.x);
yDeltas.add(info.delta.game.y); yDeltas.add(info.delta.game.y);
if (xDeltas.length > 2 && !action) {
action = true;
if (!playingMusic && kIsWeb) {
playMusic();
}
double xDelta = xDeltas.isEmpty
? 0
: xDeltas.reduce((value, element) => value + element);
double yDelta = yDeltas.isEmpty
? 0
: yDeltas.reduce((value, element) => value + element);
if (xDelta.abs() > yDelta.abs()) {
if (xDelta > 0) {
runner.control("right");
} else {
runner.control("left");
}
} else if (xDelta.abs() < yDelta.abs()) {
if (yDelta > 0) {
runner.control("down");
} else {
runner.control("up");
}
}
xDeltas = List.empty(growable: true);
yDeltas = List.empty(growable: true);
}
} }
@override @override
void onPanEnd(DragEndInfo info) { void onPanEnd(DragEndInfo info) {
if (!playingMusic && kIsWeb) { action = false;
playMusic(); xDeltas = List.empty(growable: true);
} yDeltas = List.empty(growable: true);
double xDelta = xDeltas.isEmpty
? 0
: xDeltas.reduce((value, element) => value + element);
double yDelta = yDeltas.isEmpty
? 0
: yDeltas.reduce((value, element) => value + element);
if (xDelta.abs() > yDelta.abs()) {
if (xDelta > 0) {
runner.control("right");
} else {
runner.control("left");
}
} else if (xDelta.abs() < yDelta.abs()) {
if (yDelta > 0) {
runner.control("down");
} else {
runner.control("up");
}
}
} }
@override @override

View File

@ -54,9 +54,9 @@ class MainMenuOverlay extends StatelessWidget {
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
" Start ", " START ",
style: TextStyle( style: TextStyle(
color: Colors.white, color: Colors.cyan,
fontSize: width * 0.03, fontSize: width * 0.03,
), ),
), ),
@ -81,9 +81,9 @@ class MainMenuOverlay extends StatelessWidget {
// child: Padding( // child: Padding(
// padding: EdgeInsets.all(8.0), // padding: EdgeInsets.all(8.0),
// child: Text( // child: Text(
// " Deposit ", // " DEPOSIT ",
// style: TextStyle( // style: TextStyle(
// color: Colors.white, // color: Colors.cyan,
// fontSize: width * 0.03, // fontSize: width * 0.03,
// ), // ),
// ), // ),
@ -107,9 +107,9 @@ class MainMenuOverlay extends StatelessWidget {
// child: Padding( // child: Padding(
// padding: EdgeInsets.all(8.0), // padding: EdgeInsets.all(8.0),
// child: Text( // child: Text(
// " Leader Boards ", // " LEADER BOARD ",
// style: TextStyle( // style: TextStyle(
// color: Colors.white, // color: Colors.cyan,
// fontSize: width * 0.03, // fontSize: width * 0.03,
// ), // ),
// ), // ),

View File

@ -14,8 +14,14 @@ enum RunnerState {
run, run,
jump, jump,
duck, duck,
duck2,
duck3,
kick, kick,
kick2,
kick3,
float, float,
float2,
float3,
fall, fall,
die, die,
electrocute, electrocute,
@ -78,6 +84,7 @@ class Runner extends Component with HasGameRef<MyGame> {
if (gameRef.gameState.isPaused) { if (gameRef.gameState.isPaused) {
return; return;
} }
sprite.animation!.reset();
switch (event) { switch (event) {
case "jump": case "jump":
previousState = runnerState; previousState = runnerState;
@ -88,7 +95,7 @@ class Runner extends Component with HasGameRef<MyGame> {
// sprite.position, // sprite.position,
Vector2(sprite.x, (level - 1) * gameRef.blockSize), Vector2(sprite.x, (level - 1) * gameRef.blockSize),
], ],
duration: 0.25, duration: 0.15,
curve: Curves.bounceIn, curve: Curves.bounceIn,
onComplete: () { onComplete: () {
updateLevel(); updateLevel();
@ -106,12 +113,22 @@ class Runner extends Component with HasGameRef<MyGame> {
break; break;
} }
runnerState = event; runnerState = event;
sprite.current = RunnerState.float; switch (gameRef.gameState.getRobotLevel()) {
case 3:
sprite.current = RunnerState.float3;
break;
case 2:
sprite.current = RunnerState.float2;
break;
default:
sprite.current = RunnerState.float;
break;
}
sprite.addEffect(MoveEffect( sprite.addEffect(MoveEffect(
path: [ path: [
Vector2(sprite.x, (level - 2) * gameRef.blockSize), Vector2(sprite.x, (level - 2) * gameRef.blockSize),
], ],
duration: 0.5, duration: 0.20,
curve: Curves.ease, curve: Curves.ease,
onComplete: () { onComplete: () {
updateLevel(); updateLevel();
@ -133,7 +150,17 @@ class Runner extends Component with HasGameRef<MyGame> {
case "kick": case "kick":
previousState = runnerState; previousState = runnerState;
runnerState = event; runnerState = event;
sprite.current = RunnerState.kick; switch (gameRef.gameState.getRobotLevel()) {
case 3:
sprite.current = RunnerState.kick3;
break;
case 2:
sprite.current = RunnerState.kick2;
break;
default:
sprite.current = RunnerState.kick;
break;
}
break; break;
case "run": case "run":
previousState = runnerState; previousState = runnerState;
@ -143,7 +170,17 @@ class Runner extends Component with HasGameRef<MyGame> {
case "float": case "float":
previousState = runnerState; previousState = runnerState;
runnerState = event; runnerState = event;
sprite.current = RunnerState.float; switch (gameRef.gameState.getRobotLevel()) {
case 3:
sprite.current = RunnerState.float3;
break;
case 2:
sprite.current = RunnerState.float2;
break;
default:
sprite.current = RunnerState.float;
break;
}
sprite.addEffect(MoveEffect( sprite.addEffect(MoveEffect(
path: [sprite.position], path: [sprite.position],
duration: 1.5, duration: 1.5,
@ -161,7 +198,17 @@ class Runner extends Component with HasGameRef<MyGame> {
case "duck": case "duck":
previousState = runnerState; previousState = runnerState;
runnerState = event; runnerState = event;
sprite.current = RunnerState.duck; switch (gameRef.gameState.getRobotLevel()) {
case 3:
sprite.current = RunnerState.duck3;
break;
case 2:
sprite.current = RunnerState.duck2;
break;
default:
sprite.current = RunnerState.duck;
break;
}
sprite.addEffect(MoveEffect( sprite.addEffect(MoveEffect(
path: [sprite.position], path: [sprite.position],
duration: 1.5, duration: 1.5,
@ -529,6 +576,36 @@ class Runner extends Component with HasGameRef<MyGame> {
SpriteAnimation ducking = SpriteAnimation ducking =
SpriteAnimation.spriteList(ducks, stepTime: 0.02, loop: true); SpriteAnimation.spriteList(ducks, stepTime: 0.02, loop: true);
List<Sprite> ducks2 = [];
for (int i = 1; i <= 38; i++) {
final composition = ImageComposition()
..add(satellites.elementAt(i - 1), Vector2(0, 0))
..add(
await Flame.images.load(
'runner/duck2/duck200${i < 10 ? "0" + i.toString() : i.toString()}.png'),
Vector2(0, 0));
ducks2.add(Sprite(await composition.compose()));
}
SpriteAnimation ducking2 =
SpriteAnimation.spriteList(ducks2, stepTime: 0.02, loop: true);
List<Sprite> ducks3 = [];
for (int i = 1; i <= 38; i++) {
final composition = ImageComposition()
..add(satellites.elementAt(i - 1), Vector2(0, 0))
..add(
await Flame.images.load(
'runner/duck3/duck300${i < 10 ? "0" + i.toString() : i.toString()}.png'),
Vector2(0, 0));
ducks3.add(Sprite(await composition.compose()));
}
SpriteAnimation ducking3 =
SpriteAnimation.spriteList(ducks3, stepTime: 0.02, loop: true);
List<Sprite> kicks = []; List<Sprite> kicks = [];
for (int i = 1; i <= 38; i++) { for (int i = 1; i <= 38; i++) {
final composition = ImageComposition() final composition = ImageComposition()
@ -544,6 +621,36 @@ class Runner extends Component with HasGameRef<MyGame> {
SpriteAnimation kicking = SpriteAnimation kicking =
SpriteAnimation.spriteList(kicks, stepTime: 0.02, loop: false); SpriteAnimation.spriteList(kicks, stepTime: 0.02, loop: false);
List<Sprite> kicks2 = [];
for (int i = 1; i <= 38; i++) {
final composition = ImageComposition()
..add(satellites.elementAt(i - 1), Vector2(0, 0))
..add(
await Flame.images.load(
'runner/attack2/attack200${i < 10 ? "0" + i.toString() : i.toString()}.png'),
Vector2(0, 0));
kicks2.add(Sprite(await composition.compose()));
}
SpriteAnimation kicking2 =
SpriteAnimation.spriteList(kicks2, stepTime: 0.02, loop: false);
List<Sprite> kicks3 = [];
for (int i = 1; i <= 38; i++) {
final composition = ImageComposition()
..add(satellites.elementAt(i - 1), Vector2(0, 0))
..add(
await Flame.images.load(
'runner/attack3/attack300${i < 10 ? "0" + i.toString() : i.toString()}.png'),
Vector2(0, 0));
kicks3.add(Sprite(await composition.compose()));
}
SpriteAnimation kicking3 =
SpriteAnimation.spriteList(kicks3, stepTime: 0.02, loop: false);
List<Sprite> floats = []; List<Sprite> floats = [];
for (int i = 1; i <= 44; i++) { for (int i = 1; i <= 44; i++) {
final composition = ImageComposition() final composition = ImageComposition()
@ -559,6 +666,36 @@ class Runner extends Component with HasGameRef<MyGame> {
SpriteAnimation floating = SpriteAnimation floating =
SpriteAnimation.spriteList(floats, stepTime: 0.02, loop: true); SpriteAnimation.spriteList(floats, stepTime: 0.02, loop: true);
List<Sprite> floats2 = [];
for (int i = 1; i <= 44; i++) {
final composition = ImageComposition()
..add(satellites.elementAt(((i - 1) % 38)), Vector2(0, 0))
..add(
await Flame.images.load(
'runner/hover2/hover200${i < 10 ? "0" + i.toString() : i.toString()}.png'),
Vector2(0, 0));
floats2.add(Sprite(await composition.compose()));
}
SpriteAnimation floating2 =
SpriteAnimation.spriteList(floats2, stepTime: 0.02, loop: true);
List<Sprite> floats3 = [];
for (int i = 1; i <= 44; i++) {
final composition = ImageComposition()
..add(satellites.elementAt(((i - 1) % 38)), Vector2(0, 0))
..add(
await Flame.images.load(
'runner/hover3/hover300${i < 10 ? "0" + i.toString() : i.toString()}.png'),
Vector2(0, 0));
floats3.add(Sprite(await composition.compose()));
}
SpriteAnimation floating3 =
SpriteAnimation.spriteList(floats3, stepTime: 0.02, loop: true);
List<Sprite> falls = []; List<Sprite> falls = [];
for (int i = 1; i <= 38; i++) { for (int i = 1; i <= 38; i++) {
final composition = ImageComposition() final composition = ImageComposition()
@ -574,15 +711,6 @@ class Runner extends Component with HasGameRef<MyGame> {
SpriteAnimation falling = SpriteAnimation falling =
SpriteAnimation.spriteList(falls, stepTime: 0.02, loop: false); SpriteAnimation.spriteList(falls, stepTime: 0.02, loop: false);
// SpriteAnimation falling = await loadSpriteAnimation(
// 'fall-frames.png',
// SpriteAnimationData.sequenced(
// amount: 7,
// stepTime: 0.1,
// textureSize: Vector2(512, 512),
// ),
// );
List<Sprite> dies = []; List<Sprite> dies = [];
for (int i = 1; i <= 57; i++) { for (int i = 1; i <= 57; i++) {
dies.add(Sprite(await Flame.images.load( dies.add(Sprite(await Flame.images.load(
@ -606,8 +734,14 @@ class Runner extends Component with HasGameRef<MyGame> {
RunnerState.run: running, RunnerState.run: running,
RunnerState.jump: jumping, RunnerState.jump: jumping,
RunnerState.duck: ducking, RunnerState.duck: ducking,
RunnerState.duck2: ducking2,
RunnerState.duck3: ducking3,
RunnerState.kick: kicking, RunnerState.kick: kicking,
RunnerState.kick2: kicking2,
RunnerState.kick3: kicking3,
RunnerState.float: floating, RunnerState.float: floating,
RunnerState.float2: floating2,
RunnerState.float3: floating3,
RunnerState.fall: falling, RunnerState.fall: falling,
RunnerState.die: dying, RunnerState.die: dying,
RunnerState.electrocute: dying, RunnerState.electrocute: dying,