Version 0.1.0

This commit is contained in:
Elias Projahn 2020-01-15 19:04:40 +01:00
commit 5dda59a6cd
73 changed files with 5741 additions and 0 deletions

91
lib/components/cat.dart Normal file
View file

@ -0,0 +1,91 @@
import 'dart:math';
import 'dart:ui';
import 'package:flame/anchor.dart';
import 'package:flame/components/component.dart';
import 'package:flame/sprite.dart';
import 'package:vector_math/vector_math_64.dart';
final random = Random(DateTime.now().millisecondsSinceEpoch);
class Cat extends PositionComponent {
static const vmin = 0.1;
static const vmax = 150.0;
static const accLength = 20.0;
static const minDistance = 4.0;
final anchor = Anchor.bottomCenter;
final renderFlipX = true;
final axis = Vector2(-1.0, 0.0);
final catNumber = random.nextInt(7) + 1;
void Function() onBored;
bool shouldDestroy = false;
Vector2 target;
Vector2 position;
Vector2 velocity = Vector2.zero();
bool bored = false;
bool get isSitting => velocity.length < vmin;
double get width => isSitting ? 25.0 : 40.0;
double get height => isSitting ? 18.0 : 18.0;
double get x => position.x;
double get y => position.y;
double get angle => -velocity.angleToSigned(axis);
bool get renderFlipY => angle.abs() > 0.5 * pi;
Sprite sitting;
Sprite running;
Cat() {
sitting = Sprite('cat${catNumber}s.png');
running = Sprite('cat${catNumber}r.png');
}
void runTo(Vector2 target) {
bored = false;
this.target = target;
if (position == null) {
position = target;
}
velocity = (target - position).normalized() * vmax;
}
@override
void render(Canvas canvas) {
prepareCanvas(canvas);
if (isSitting) {
sitting.render(canvas, width: width, height: height);
} else {
running.render(canvas, width: width, height: height);
}
}
@override
void update(double t) {
if ((position - target).length < minDistance) {
position = target;
velocity.setZero();
if (!bored) {
bored = true;
if (onBored != null) {
onBored();
}
}
} else {
position += velocity * t;
}
}
@override
bool destroy() => shouldDestroy;
@override
int priority() => 10000;
}

View file

@ -0,0 +1,65 @@
import 'dart:ui';
import 'package:flame/anchor.dart';
import 'package:flame/components/component.dart';
import 'package:flame/components/mixins/resizable.dart';
import 'package:flame/position.dart';
import 'package:flame/text_config.dart';
import 'package:sprintf/sprintf.dart';
import '../localizations.dart';
class Progress extends Component with Resizable {
static const height = 2.0;
static const color = Color(0xff000000);
static const subtileTextConfig = TextConfig(
fontSize: 28.0,
fontFamily: 'Tangerine',
textAlign: TextAlign.center,
);
final ChristmasCatsLocalizations localizations;
final void Function() onComplete;
int rounds = 0;
double progress = 0.0;
double seconds = 0.0;
bool playing = false;
bool completed = false;
double get endSeconds => 20.0 + rounds * 10.0;
int get score => (2 * (rounds * endSeconds + seconds)).floor();
Progress(this.localizations, this.onComplete);
@override
void render(Canvas canvas) {
final paint = Paint()..color = color;
final width = (seconds / endSeconds) * size.width;
canvas.drawRect(Rect.fromLTWH(0, 0, width, height), paint);
subtileTextConfig.render(
canvas,
sprintf(localizations.score, [score]),
Position(size.width / 2, 4),
anchor: Anchor.topCenter,
);
}
@override
void update(double dt) {
if (playing && !completed) {
seconds += dt;
if (seconds > endSeconds) {
completed = true;
if (onComplete != null) {
rounds++;
seconds = 0;
onComplete();
}
}
} else if (seconds < endSeconds) {
completed = false;
}
}
}

112
lib/components/tree.dart Normal file
View file

@ -0,0 +1,112 @@
import 'dart:ui';
import 'dart:math';
import 'package:flame/anchor.dart';
import 'package:flame/components/component.dart';
import 'package:flame/sprite.dart';
import 'package:flame/time.dart';
import 'package:vector_math/vector_math_64.dart';
final random = Random(DateTime.now().millisecondsSinceEpoch);
class Tree extends PositionComponent {
final anchor = Anchor.bottomCenter;
final void Function() onDestroy;
final treeNumber = random.nextInt(4) + 1;
bool shouldDestroy = false;
Timer nextLevelTimer;
Timer killTimer;
int shakeLevel = 0;
bool shakingLeft = true;
double get shakeAngle => shakeLevel * shakeLevel * pi / 1000;
double get width => treeNumber <= 2 ? 80.0 : 70.0;
double get height => treeNumber <= 2 ? 100.0 : 80.0;
Sprite sprite;
Tree(Vector2 position, this.onDestroy) {
x = position.x;
y = position.y;
sprite = Sprite('tree$treeNumber.png');
nextLevelTimer = Timer(
0.1,
repeat: true,
callback: () {
shakeLevel++;
if (shakeLevel > 16 && onDestroy != null) {
onDestroy();
}
},
);
killTimer = Timer(1, callback: () {
shouldDestroy = true;
});
}
void shake() {
if (shakeLevel == 0) {
shakeLevel = 1;
nextLevelTimer.start();
}
}
void stopShaking() {
shakeLevel = 0;
nextLevelTimer.stop();
}
void kill() {
shakeLevel = -1;
nextLevelTimer.stop();
killTimer.start();
}
@override
void render(Canvas c) {
prepareCanvas(c);
sprite.render(c, width: width, height: height);
}
@override
void update(double t) {
nextLevelTimer.update(t);
killTimer.update(t);
if (shakeLevel >= 0) {
if ((angle - shakeAngle).abs() > 0.01) {
if (shakingLeft) {
angle -= t * (shakeLevel + 1) / 3;
if (angle < -shakeAngle) {
shakingLeft = false;
}
} else {
angle += t * (shakeLevel + 1) / 3;
if (angle > shakeAngle) {
shakingLeft = true;
}
}
}
} else {
if (shakingLeft) {
if (angle > -0.5 * pi) {
angle -= t * 10;
}
} else {
if (angle < 0.5 * pi) {
angle += t * 10;
}
}
}
}
@override
bool destroy() => shouldDestroy;
@override
int priority() => 20000 + y.floor();
}