User input can move the character. Implemented the background and moving objects. Implmented platforms.

This commit is contained in:
Marco Salazar 2021-09-03 17:29:18 -06:00
parent 05b3891cbe
commit 383b302c71
12 changed files with 284 additions and 11 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 KiB

BIN
assets/images/p3-frames.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

55
lib/GameState.dart Normal file
View 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
View 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
View 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
View 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);
}
}
}
}
}

View File

@ -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,
), ),

View File

@ -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