Add coins to game

This adds a new asset, a new component and some new game mechanics.
Coins will appear every one to two minutes and can be collected by
tapping them.
This commit is contained in:
Elias Projahn 2020-01-19 14:12:11 +01:00
parent 72aa6d7183
commit 03c94fe48c
5 changed files with 258 additions and 0 deletions

146
art/coin.svg Normal file
View file

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="12.700001mm"
height="12.7mm"
viewBox="0 0 12.700001 12.7"
version="1.1"
id="svg8"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="coin.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.2"
inkscape:cx="46.064289"
inkscape:cy="36.680608"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-94.676527,-139.76874)">
<circle
style="fill:#ffcc00;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4524"
cx="101.02653"
cy="146.11874"
r="6.0854168" />
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.02374466;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle6443"
cx="101.55569"
cy="146.11874"
r="4.2333331" />
<circle
r="4.2333331"
cy="146.11874"
cx="100.49736"
id="circle6441"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.02374466;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
style="fill:#ffe680;fill-opacity:1;stroke:none;stroke-width:0.02374466;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4522"
cx="101.02653"
cy="146.11874"
r="4.2333331" />
<g
id="g7849"
style="fill:#c9a100;fill-opacity:1"
transform="translate(0,0.52916667)">
<ellipse
ry="0.26458335"
rx="0.26458332"
cy="145.61581"
cx="100.54639"
id="path7822"
style="fill:#c9a100;fill-opacity:1;stroke:none;stroke-width:0.5291667;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
r="0.26458332"
cy="145.75754"
cx="101.79843"
id="path7824"
style="fill:#c9a100;fill-opacity:1;stroke:none;stroke-width:0.52916658;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
<g
id="g7845"
style="stroke:#c9a100;stroke-opacity:1"
transform="translate(0,0.52916667)">
<path
inkscape:export-ydpi="96"
inkscape:export-xdpi="96"
inkscape:export-filename="/home/johrpan/Projekte/jolakotturinn/assets/images/cat6s.png"
inkscape:connector-curvature="0"
id="path1178-6"
d="m 99.07953,146.84377 c 0,0 -0.24582,-0.85541 0.28092,-1.32675 0,0 0.0176,-4.45166 1.15876,-1.06491 0,0 1.05343,0.40154 1.40459,0.22696 0,0 2.3,-3.19472 1.26411,0.80303 0,0 0.40382,1.13475 -0.31602,1.90286 -2.47717,2.02429 -3.79236,-0.54119 -3.79236,-0.54119 z"
style="fill:none;stroke:#c9a100;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path7826"
d="m 100.0692,146.54185 -1.842639,-1.12212"
style="fill:none;stroke:#c9a100;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path7828"
d="m 99.951078,146.84896 -1.724517,-0.47247"
style="fill:none;stroke:#c9a100;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path7830"
d="m 100.10463,147.10882 -1.559151,0.16536"
style="fill:none;stroke:#c9a100;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path7832"
d="m 102.05357,146.73084 2.03162,-0.57878"
style="fill:none;stroke:#c9a100;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path7834"
d="m 101.95908,147.08519 1.88988,0.12993"
style="fill:none;stroke:#c9a100;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path7836"
d="m 101.6756,147.36867 1.22842,0.72052"
style="fill:none;stroke:#c9a100;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
assets/images/coin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

75
lib/components/coin.dart Normal file
View file

@ -0,0 +1,75 @@
import 'dart:ui';
import 'package:flame/anchor.dart';
import 'package:flame/components/component.dart';
import 'package:flame/sprite.dart';
import 'package:flame/time.dart';
import 'package:flutter/widgets.dart';
import 'package:vector_math/vector_math_64.dart';
import '../storage.dart';
class Coin extends PositionComponent {
static const flightTime = 0.8;
final sprite = Sprite('coin.png');
final Vector2 position;
final Vector2 target;
Timer killTimer;
bool shouldDestroy = false;
bool flying = false;
double flight = 0.0;
Coin(this.position, this.target, void Function() onDestroy) {
x = position.x;
y = position.y;
width = 24.0;
height = 24.0;
anchor = Anchor.center;
killTimer = Timer(2.5, callback: () {
onDestroy();
shouldDestroy = true;
});
killTimer.start();
}
void tap() {
killTimer.stop();
flying = true;
storage.addCoins(1);
}
@override
void render(Canvas c) {
prepareCanvas(c);
sprite.render(c, width: width, height: height);
}
@override
void update(double t) {
killTimer.update(t);
if (flying) {
flight += t / flightTime;
if (flight > 1.0) {
flight = 1.0;
flying = false;
shouldDestroy = true;
}
x = lerpDouble(position.x, target.x, Curves.easeIn.transform(flight));
y = lerpDouble(position.y, target.y, Curves.easeInBack.transform(flight));
}
}
@override
bool destroy() => shouldDestroy;
@override
int priority() => 25000;
}

View file

@ -9,6 +9,7 @@ import 'package:flutter/widgets.dart';
import 'package:vector_math/vector_math_64.dart';
import 'components/cat.dart';
import 'components/coin.dart';
import 'components/tree.dart';
import 'localizations.dart';
@ -30,6 +31,7 @@ class Cell {
Tree tree;
Cat cat;
Coin coin;
Cell(this.x, this.y);
}
@ -65,6 +67,7 @@ class ChristmasCats extends BaseGame with Tapable {
bool gameOver = false;
Timer nextCatTimer;
Timer coinTimer;
Timer scoreTimer;
List<Cell> cells;
List<int> treeCells;
@ -98,6 +101,12 @@ class ChristmasCats extends BaseGame with Tapable {
}
}
Vector2 getCoinPosition(Cell cell) {
final x = marginLRB + (cell.x + 0.5) * cellWidth;
final y = marginTop + (cell.y + 0.5) * cellHeight;
return Vector2(x, y);
}
void updateCat(int oldCellIndex, Cat cat) {
int newCellIndex;
@ -150,6 +159,26 @@ class ChristmasCats extends BaseGame with Tapable {
nCats++;
}
void createCoin() {
coinTimer = Timer(60.0 + random.nextInt(60), callback: () {
final cellIndex = emptyCells.pick();
final cell = cells[cellIndex];
final coin = Coin(
getCoinPosition(cell),
Vector2(size.width / 2, -cellHeight),
() {
cell.coin = null;
},
);
add(coin);
cell.coin = coin;
createCoin();
});
coinTimer.start();
}
void reset() {
paused = true;
nCats = 0;
@ -208,6 +237,7 @@ class ChristmasCats extends BaseGame with Tapable {
}
createCat();
createCoin();
for (final tree in trees) {
add(tree);
@ -238,6 +268,7 @@ class ChristmasCats extends BaseGame with Tapable {
void update(double t) {
if (!paused) {
nextCatTimer?.update(t);
coinTimer?.update(t);
scoreTimer?.update(t);
final List<Timer> oldTimers = [];
@ -285,6 +316,11 @@ class ChristmasCats extends BaseGame with Tapable {
}
onScoreChanged(score);
} else if (cell?.coin != null) {
cell.coin.tap();
if (cell.cat == null) {
emptyCells.add(cellIndex);
}
}
}
}

View file

@ -35,6 +35,7 @@ flutter:
- assets/images/cat6s.png
- assets/images/cat7r.png
- assets/images/cat7s.png
- assets/images/coin.png
- assets/images/tree1.png
- assets/images/tree2.png
- assets/images/tree3.png