-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
aacef5a
commit 2c639f3
Showing
15 changed files
with
601 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
export 'camera_target.dart'; | ||
export 'game_state_controller.dart'; | ||
export 'keyboard_handler.dart'; | ||
export 'platform_spawner.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import 'package:crystal_ball/game/game.dart'; | ||
import 'package:flame/components.dart'; | ||
import 'package:flame_bloc/flame_bloc.dart'; | ||
import 'package:flutter/animation.dart'; | ||
|
||
class GameStateController extends Component | ||
with | ||
HasGameRef<CrystalBallGame>, | ||
FlameBlocListenable<GameCubit, GameState> { | ||
Timer? timer; | ||
|
||
@override | ||
void onNewState(GameState state) { | ||
super.onNewState(state); | ||
timer?.stop(); | ||
timer = null; | ||
switch (state) { | ||
case GameState.initial: | ||
break; | ||
case GameState.starting: | ||
game.world.cameraTarget.go( | ||
to: Vector2(0, -kCameraSize.height / 4), | ||
curve: Curves.easeInOutCubic, | ||
duration: kOpeningDuration, | ||
); | ||
timer = Timer( | ||
kOpeningDuration, | ||
onTick: bloc.gameStarted, | ||
); | ||
case GameState.playing: | ||
break; | ||
case GameState.gameOver: | ||
game.world.cameraTarget.go( | ||
to: Vector2(0, 0), | ||
curve: Curves.easeInOutCubic, | ||
duration: 0.3, | ||
); | ||
game.world.theBall.position = Vector2.zero(); | ||
for (final platform in game.world.flameMultiBlocProvider | ||
.descendants() | ||
.whereType<Platform>()) { | ||
platform.removeFromParent(); | ||
} | ||
timer = Timer( | ||
1, | ||
onTick: bloc.setInitial, | ||
); | ||
} | ||
} | ||
|
||
@override | ||
void update(double dt) { | ||
super.update(dt); | ||
timer?.update(dt); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import 'package:crystal_ball/game/game.dart'; | ||
import 'package:flame/components.dart'; | ||
import 'package:flame_bloc/flame_bloc.dart'; | ||
import 'package:flutter/services.dart'; | ||
|
||
class KeyboardHandlerSync extends Component | ||
with FlameBlocReader<GameCubit, GameState> { | ||
KeyboardHandlerSync(); | ||
|
||
@override | ||
Future<void> onLoad() async { | ||
await add(KeyboardListenerComponent( | ||
keyDown: { | ||
LogicalKeyboardKey.space: onSpace, | ||
}, | ||
)); | ||
|
||
return super.onLoad(); | ||
} | ||
|
||
bool onSpace(Set<LogicalKeyboardKey> logicalKeys) { | ||
if (bloc.state == GameState.initial) { | ||
bloc.startGame(); | ||
return false; | ||
} | ||
return true; | ||
} | ||
} | ||
|
||
class DirectionalController extends Component | ||
with FlameBlocReader<GameCubit, GameState> { | ||
DirectionalController(); | ||
|
||
double _directionalCoefficient = 0; | ||
|
||
double get directionalCoefficient => _directionalCoefficient; | ||
|
||
@override | ||
Future<void> onLoad() async { | ||
await add(KeyboardListenerComponent( | ||
keyDown: { | ||
LogicalKeyboardKey.arrowLeft: onLeftStart, | ||
LogicalKeyboardKey.arrowRight: onRightStart, | ||
}, | ||
keyUp: { | ||
LogicalKeyboardKey.arrowLeft: onLeftEnd, | ||
LogicalKeyboardKey.arrowRight: onRightEnd, | ||
}, | ||
)); | ||
|
||
return super.onLoad(); | ||
} | ||
|
||
bool onLeftStart(Set<LogicalKeyboardKey> logicalKeys) { | ||
if (!bloc.isPlaying) return true; | ||
_directionalCoefficient = -1; | ||
return false; | ||
} | ||
|
||
bool onRightStart(Set<LogicalKeyboardKey> logicalKeys) { | ||
if (!bloc.isPlaying) return true; | ||
_directionalCoefficient = 1; | ||
return false; | ||
} | ||
|
||
bool onLeftEnd(Set<LogicalKeyboardKey> logicalKeys) { | ||
if (!bloc.isPlaying) return true; | ||
if (_directionalCoefficient < 0) { | ||
_directionalCoefficient = 0; | ||
} | ||
return false; | ||
} | ||
|
||
bool onRightEnd(Set<LogicalKeyboardKey> logicalKeys) { | ||
if (!bloc.isPlaying) return true; | ||
if (_directionalCoefficient > 0) { | ||
_directionalCoefficient = 0; | ||
} | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,53 @@ | ||
import 'dart:math'; | ||
|
||
import 'package:flame/components.dart'; | ||
|
||
const (double, double) kCameraSize = (900, 1600); | ||
const double kPlayerRadius = 50; | ||
const double kPlayerRadius = 20; | ||
const (double, double) kPlayerSize = (kPlayerRadius * 2, kPlayerRadius * 2); | ||
|
||
const double kOpeningDuration = 4; | ||
|
||
const double kPlatformSpawnDuration = 0.4; | ||
const double kPlatformVerticalInterval = 1; | ||
const double kStartPlatformHeight = 400; | ||
const double kMeanPlatformInterval = 370; | ||
const double kPlatformIntervalVariation = 100; | ||
const double kPlatformMinWidth = 120; | ||
const double kPlatformWidthVariation = 100; | ||
const double kPlatformHeight = 40; | ||
const double kPlatformPreloadArea = 1600; | ||
|
||
const double kGravity = 100; | ||
const double kJumpVelocity = 3000; | ||
|
||
const double kReaperTolerance = 800; | ||
|
||
extension TransformRec on (double, double) { | ||
Vector2 get asVector2 => Vector2($1, $2); | ||
|
||
double get width => $1; | ||
|
||
double get height => $2; | ||
} | ||
|
||
extension RandomX on Random { | ||
double nextDoubleAntiSmooth() { | ||
final normal = nextDouble(); | ||
return _invSmoothstep(normal); | ||
} | ||
|
||
double nextVariation() { | ||
return nextDoubleAntiSmooth() * 2 - 1; | ||
} | ||
|
||
double nextDoubleInBetween(double min, double max) { | ||
return nextDoubleAntiSmooth() * (max - min) + min; | ||
} | ||
} | ||
|
||
double _invSmoothstep(double normal) { | ||
if (normal <= 0) return 0; | ||
if (normal >= 1) return 1; | ||
return 0.5 - sin(asin(1 - 2 * normal) / 3); | ||
} |
Oops, something went wrong.