forked from marco/firo_runner
User input can move the character. Implemented the background and moving objects. Implmented platforms.
This commit is contained in:
parent
05b3891cbe
commit
383b302c71
BIN
assets/images/bug-break-frames.png
Normal file
BIN
assets/images/bug-break-frames.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 249 KiB |
BIN
assets/images/bug-frames.png
Normal file
BIN
assets/images/bug-frames.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 172 KiB |
BIN
assets/images/p1-frames.png
Normal file
BIN
assets/images/p1-frames.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 372 KiB |
BIN
assets/images/p2-frames.png
Normal file
BIN
assets/images/p2-frames.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 395 KiB |
BIN
assets/images/p3-frames.png
Normal file
BIN
assets/images/p3-frames.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 397 KiB |
BIN
assets/images/wire-frames.png
Normal file
BIN
assets/images/wire-frames.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 175 KiB |
55
lib/GameState.dart
Normal file
55
lib/GameState.dart
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flame/components.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class GameState extends Component {
|
||||||
|
int numCoins = 0;
|
||||||
|
int distance = 0;
|
||||||
|
late Rect square;
|
||||||
|
late Color color = Colors.white;
|
||||||
|
int start = 0;
|
||||||
|
late ColorTween tween;
|
||||||
|
static const int CIRCUIT_PERIOD = 500000;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(double dt) {
|
||||||
|
super.update(dt);
|
||||||
|
distance = DateTime.now().microsecondsSinceEpoch - start;
|
||||||
|
color = tween.lerp(sin(distance.toDouble() / CIRCUIT_PERIOD))!;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCoin() {
|
||||||
|
numCoins++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void render(Canvas c) {
|
||||||
|
super.render(c);
|
||||||
|
c.drawRect(square, Paint()..color = color);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future load(Vector2 size) async {
|
||||||
|
square = Rect.fromLTWH(0, 0, size.x, size.y);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSize(Vector2 size) {
|
||||||
|
square = Rect.fromLTWH(0, 0, size.x, size.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
start = DateTime.now().microsecondsSinceEpoch;
|
||||||
|
tween = ColorTween(begin: Colors.yellow, end: Colors.yellowAccent);
|
||||||
|
}
|
||||||
|
|
||||||
|
double getVelocity() {
|
||||||
|
if (distance > 50000000) {
|
||||||
|
return 250.0;
|
||||||
|
} else if (distance > 10000000)
|
||||||
|
return 175.0;
|
||||||
|
else {
|
||||||
|
return 100.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
lib/MovingObject.dart
Normal file
41
lib/MovingObject.dart
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:firo_runner/main.dart';
|
||||||
|
import 'package:flame/components.dart';
|
||||||
|
|
||||||
|
class MovingObject extends Component {
|
||||||
|
late SpriteAnimationGroupComponent sprite;
|
||||||
|
MyGame gameRef;
|
||||||
|
|
||||||
|
MovingObject(this.gameRef);
|
||||||
|
|
||||||
|
void setPosition(double x, double y) {
|
||||||
|
sprite.position = Vector2(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSize(double x, double y) {
|
||||||
|
sprite.size = Vector2(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sprite getSprite() {
|
||||||
|
return sprite.animation!.getSprite();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void render(Canvas c) {
|
||||||
|
super.render(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(double dt) {
|
||||||
|
super.update(dt);
|
||||||
|
sprite.update(dt);
|
||||||
|
double velocity = gameRef.gameState.getVelocity();
|
||||||
|
sprite.position = sprite.position - Vector2(velocity * dt, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void remove() {
|
||||||
|
super.remove();
|
||||||
|
}
|
||||||
|
}
|
45
lib/Platform.dart
Normal file
45
lib/Platform.dart
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:firo_runner/MovingObject.dart';
|
||||||
|
import 'package:firo_runner/main.dart';
|
||||||
|
import 'package:flame/components.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
enum PlatformState { normal }
|
||||||
|
|
||||||
|
class Platform extends MovingObject {
|
||||||
|
Platform(MyGame gameRef) : super(gameRef) {
|
||||||
|
var random = Random();
|
||||||
|
int version = random.nextInt(3) + 1;
|
||||||
|
var platform = gameRef.platformHolder.getPlatform(version);
|
||||||
|
SpriteAnimation normal = SpriteAnimation.fromFrameData(
|
||||||
|
platform,
|
||||||
|
SpriteAnimationData.sequenced(
|
||||||
|
amount: 7,
|
||||||
|
stepTime: 0.1,
|
||||||
|
textureSize: Vector2(800, 510),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
sprite = SpriteAnimationGroupComponent(
|
||||||
|
animations: {
|
||||||
|
PlatformState.normal: normal,
|
||||||
|
},
|
||||||
|
current: PlatformState.normal,
|
||||||
|
);
|
||||||
|
|
||||||
|
setSize(
|
||||||
|
gameRef.blockSize * (platform!.width / platform!.height / 7),
|
||||||
|
gameRef.blockSize,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
double getRightEnd() {
|
||||||
|
return sprite.position.x + sprite.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void render(Canvas c) {
|
||||||
|
getSprite().render(c, position: sprite.position, size: sprite.size);
|
||||||
|
}
|
||||||
|
}
|
91
lib/PlatformLoader.dart
Normal file
91
lib/PlatformLoader.dart
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:firo_runner/main.dart';
|
||||||
|
import 'package:flame/flame.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'Platform.dart';
|
||||||
|
|
||||||
|
class PlatformHolder {
|
||||||
|
var platform1;
|
||||||
|
var platform2;
|
||||||
|
var platform3;
|
||||||
|
late List<List<Platform>> platforms = [];
|
||||||
|
Random random = Random();
|
||||||
|
|
||||||
|
Future loadPlatforms() async {
|
||||||
|
platform1 = await Flame.images.load('p1-frames.png');
|
||||||
|
platform2 = await Flame.images.load('p2-frames.png');
|
||||||
|
platform3 = await Flame.images.load('p3-frames.png');
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
platforms.add([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getPlatform(int imageNumber) {
|
||||||
|
switch (imageNumber) {
|
||||||
|
case 1:
|
||||||
|
return platform1;
|
||||||
|
case 2:
|
||||||
|
return platform2;
|
||||||
|
default:
|
||||||
|
return platform3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool generatePlatform(MyGame gameRef, int level, bool force) {
|
||||||
|
double xCordinate = 0;
|
||||||
|
if (platforms[level].isNotEmpty) {
|
||||||
|
xCordinate = platforms[level].last.getRightEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xCordinate > gameRef.size.x + 1000) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Platform platform = Platform(gameRef);
|
||||||
|
platform.setPosition(xCordinate, gameRef.blockSize * level);
|
||||||
|
platforms[level].add(platform);
|
||||||
|
print(platforms[0].length);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render(Canvas canvas) {
|
||||||
|
for (List<Platform> platformLevel in platforms) {
|
||||||
|
for (Platform p in platformLevel) {
|
||||||
|
p.render(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(double dt) {
|
||||||
|
for (List<Platform> platformLevel in platforms) {
|
||||||
|
for (Platform p in platformLevel) {
|
||||||
|
p.update(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void removePast(MyGame gameRef) {
|
||||||
|
for (List<Platform> platformLevel in platforms) {
|
||||||
|
int removed = 0;
|
||||||
|
while (platformLevel.isNotEmpty &&
|
||||||
|
platformLevel[0].sprite.position.x + platformLevel[0].sprite.width <
|
||||||
|
0) {
|
||||||
|
platformLevel.removeAt(0);
|
||||||
|
removed++;
|
||||||
|
}
|
||||||
|
if (platformLevel.isNotEmpty &&
|
||||||
|
platformLevel.length > 3 &&
|
||||||
|
random.nextInt(100) > 65 &&
|
||||||
|
removed > 0) {
|
||||||
|
int secondToLast = platformLevel.length - 3;
|
||||||
|
double secondToLastPosition =
|
||||||
|
platformLevel.elementAt(secondToLast).sprite.x;
|
||||||
|
if (secondToLastPosition > gameRef.size.x) {
|
||||||
|
platformLevel.removeAt(secondToLast);
|
||||||
|
platformLevel.removeAt(secondToLast + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -70,10 +70,10 @@ class Runner extends Component with HasGameRef<MyGame> {
|
|||||||
sprite.addEffect(MoveEffect(
|
sprite.addEffect(MoveEffect(
|
||||||
path: [
|
path: [
|
||||||
sprite.position,
|
sprite.position,
|
||||||
Vector2(sprite.x, (level - 2) * gameRef.blockSize),
|
Vector2(sprite.x, (level - 3) * gameRef.blockSize),
|
||||||
],
|
],
|
||||||
speed: 50,
|
speed: 50,
|
||||||
curve: Curves.bounceIn,
|
curve: Curves.ease,
|
||||||
onComplete: () {
|
onComplete: () {
|
||||||
updateLevel();
|
updateLevel();
|
||||||
runnerState = "run";
|
runnerState = "run";
|
||||||
@ -245,7 +245,7 @@ class Runner extends Component with HasGameRef<MyGame> {
|
|||||||
'death-normal-frames.png',
|
'death-normal-frames.png',
|
||||||
SpriteAnimationData.sequenced(
|
SpriteAnimationData.sequenced(
|
||||||
amount: 20,
|
amount: 20,
|
||||||
stepTime: 0.1,
|
stepTime: 0.05,
|
||||||
textureSize: Vector2(512, 512),
|
textureSize: Vector2(512, 512),
|
||||||
loop: false,
|
loop: false,
|
||||||
),
|
),
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
import 'package:firo_runner/GameState.dart';
|
||||||
|
import 'package:firo_runner/MovingObject.dart';
|
||||||
|
import 'package:firo_runner/Platform.dart';
|
||||||
|
import 'package:firo_runner/PlatformLoader.dart';
|
||||||
import 'package:flame/components.dart';
|
import 'package:flame/components.dart';
|
||||||
import 'package:flame/extensions.dart';
|
import 'package:flame/extensions.dart';
|
||||||
import 'package:flame/flame.dart';
|
import 'package:flame/flame.dart';
|
||||||
@ -29,10 +33,13 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
config: TextPaintConfig(fontSize: 48.0),
|
config: TextPaintConfig(fontSize: 48.0),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
late PlatformHolder platformHolder;
|
||||||
|
|
||||||
late Sprite background1;
|
late Sprite background1;
|
||||||
late Sprite background2;
|
late Sprite background2;
|
||||||
late Runner runner;
|
late Runner runner;
|
||||||
late var background;
|
late GameState gameState;
|
||||||
|
var background;
|
||||||
late var platform1;
|
late var platform1;
|
||||||
late var platform2;
|
late var platform2;
|
||||||
late var platform3;
|
late var platform3;
|
||||||
@ -47,12 +54,16 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
var background2Position;
|
var background2Position;
|
||||||
late double blockSize;
|
late double blockSize;
|
||||||
|
|
||||||
|
bool loaded = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onLoad() async {
|
Future<void> onLoad() async {
|
||||||
|
debugMode = true;
|
||||||
print("load");
|
print("load");
|
||||||
FlameAudio.bgm.initialize();
|
FlameAudio.bgm.initialize();
|
||||||
background = await Flame.images.load('bg.png');
|
background = await Flame.images.load('bg.png');
|
||||||
background1 = Sprite(background);
|
background1 = Sprite(background);
|
||||||
|
print(background.height.toString() + " " + background.width.toString());
|
||||||
background2 = Sprite(background);
|
background2 = Sprite(background);
|
||||||
platform1 = await Flame.images.load('platform1.png');
|
platform1 = await Flame.images.load('platform1.png');
|
||||||
platform2 = await Flame.images.load('platform2.png');
|
platform2 = await Flame.images.load('platform2.png');
|
||||||
@ -61,6 +72,12 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
bug = await Flame.images.load('bug.png');
|
bug = await Flame.images.load('bug.png');
|
||||||
coin = await Flame.images.load('coin.png');
|
coin = await Flame.images.load('coin.png');
|
||||||
|
|
||||||
|
platformHolder = PlatformHolder();
|
||||||
|
await platformHolder.loadPlatforms();
|
||||||
|
|
||||||
|
gameState = GameState();
|
||||||
|
await gameState.load(size);
|
||||||
|
|
||||||
runner = Runner();
|
runner = Runner();
|
||||||
await runner.load(loadSpriteAnimation);
|
await runner.load(loadSpriteAnimation);
|
||||||
runner.setSize(runnerSize, blockSize);
|
runner.setSize(runnerSize, blockSize);
|
||||||
@ -68,28 +85,48 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
runner.setPosition(runnerPosition);
|
runner.setPosition(runnerPosition);
|
||||||
add(runner);
|
add(runner);
|
||||||
|
|
||||||
|
// Generate the first 4 Platforms that will always be there at the start.
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
platformHolder.generatePlatform(this, 8, true);
|
||||||
|
}
|
||||||
|
fillScreen();
|
||||||
|
|
||||||
FlameAudio.bgm.play('Infinite_Spankage_M.mp3');
|
FlameAudio.bgm.play('Infinite_Spankage_M.mp3');
|
||||||
|
loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillScreen() {
|
||||||
|
for (int i = 2; i < 9; i = i + 3) {
|
||||||
|
while (!platformHolder.generatePlatform(this, i, false));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void render(Canvas canvas) {
|
void render(Canvas canvas) {
|
||||||
|
gameState.render(canvas);
|
||||||
background1.render(
|
background1.render(
|
||||||
canvas,
|
canvas,
|
||||||
position: Vector2(0, 0),
|
position: Vector2(0, 0),
|
||||||
size: backgroundSize,
|
size: Vector2(size.y * (background!.width / background!.height), size.y),
|
||||||
);
|
);
|
||||||
super.render(canvas);
|
super.render(canvas);
|
||||||
|
platformHolder.render(canvas);
|
||||||
final fpsCount = fps(1);
|
final fpsCount = fps(1);
|
||||||
// textPaint.render(
|
textPaint.render(
|
||||||
// canvas,
|
canvas,
|
||||||
// fpsCount.toString(),
|
fpsCount.toString(),
|
||||||
// Vector2(0, 0),
|
Vector2(0, 0),
|
||||||
// );
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void update(double dt) {
|
void update(double dt) {
|
||||||
|
platformHolder.removePast(this);
|
||||||
|
fillScreen();
|
||||||
super.update(dt);
|
super.update(dt);
|
||||||
|
gameState.update(dt);
|
||||||
|
platformHolder.update(dt);
|
||||||
|
// print(gameState.distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -102,7 +139,11 @@ class MyGame extends BaseGame with PanDetector, TapDetector, KeyboardEvents {
|
|||||||
size.y / 9,
|
size.y / 9,
|
||||||
);
|
);
|
||||||
|
|
||||||
backgroundSize = Vector2(size.x * 2, size.y);
|
if (loaded) {
|
||||||
|
backgroundSize =
|
||||||
|
Vector2(size.y * (background!.width / background!.height), size.y);
|
||||||
|
gameState.setSize(size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mobile controls
|
// Mobile controls
|
||||||
|
Loading…
Reference in New Issue
Block a user