mirror of
https://github.com/johrpan/christmas_cats.git
synced 2025-10-26 02:07:25 +01:00
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:
parent
72aa6d7183
commit
03c94fe48c
5 changed files with 258 additions and 0 deletions
146
art/coin.svg
Normal file
146
art/coin.svg
Normal 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
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
75
lib/components/coin.dart
Normal 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue