flutter/examples/game/lib/game_demo_node.dart
2015-10-09 20:55:54 -07:00

278 lines
7.5 KiB
Dart

part of game;
final double _gameSizeWidth = 320.0;
double _gameSizeHeight = 320.0;
final double _chunkSpacing = 640.0;
final int _chunksPerLevel = 9;
final bool _drawDebug = false;
class GameDemoNode extends NodeWithSize {
GameDemoNode(
this._images,
this._spritesGame,
this._spritesUI,
this._sounds,
this._gameOverCallback
): super(new Size(320.0, 320.0)) {
// Add background
_background = new RepeatedImage(_images["assets/starfield.png"]);
addChild(_background);
// Create starfield
_starField = new StarField(_spritesGame, 200);
addChild(_starField);
// Add nebula
_nebula = new RepeatedImage(_images["assets/nebula.png"], ui.TransferMode.plus);
addChild(_nebula);
// Setup game screen, it will always be anchored to the bottom of the screen
_gameScreen = new Node();
addChild(_gameScreen);
// Setup the level and add it to the screen, the level is the node where
// all our game objects live. It is moved to scroll the game
_level = new Level();
_gameScreen.addChild(_level);
// Add heads up display
_playerState = new PlayerState(_spritesUI, _spritesGame);
addChild(_playerState);
_objectFactory = new GameObjectFactory(_spritesGame, _sounds, _level, _playerState);
_level.ship = new Ship(_objectFactory);
_level.ship.setupActions();
_level.addChild(_level.ship);
// Add the joystick
_joystick = new VirtualJoystick();
_gameScreen.addChild(_joystick);
// Add initial game objects
addObjects();
}
// Resources
ImageMap _images;
Map<String, SoundEffect> _sounds;
SpriteSheet _spritesGame;
SpriteSheet _spritesUI;
// Sounds
SoundEffectPlayer _effectPlayer = SoundEffectPlayer.sharedInstance();
// Callback
Function _gameOverCallback;
// Game screen nodes
Node _gameScreen;
VirtualJoystick _joystick;
GameObjectFactory _objectFactory;
Level _level;
StarField _starField;
RepeatedImage _background;
RepeatedImage _nebula;
PlayerState _playerState;
// Game properties
double _scroll = 0.0;
int _framesToFire = 0;
int _framesBetweenShots = 20;
bool _gameOver = false;
void spriteBoxPerformedLayout() {
_gameSizeHeight = spriteBox.visibleArea.height;
_gameScreen.position = new Point(0.0, _gameSizeHeight);
}
void update(double dt) {
// Scroll the level
_scroll = _level.scroll(_playerState.scrollSpeed);
_starField.move(0.0, _playerState.scrollSpeed);
_background.move(_playerState.scrollSpeed * 0.1);
_nebula.move(_playerState.scrollSpeed);
// Add objects
addObjects();
// Move the ship
if (!_gameOver) {
_level.ship.applyThrust(_joystick.value, _scroll);
}
// Add shots
if (_framesToFire == 0 && _joystick.isDown && !_gameOver) {
fire();
_framesToFire = (_playerState.speedLaserActive) ? _framesBetweenShots ~/ 2 : _framesBetweenShots;
}
if (_framesToFire > 0) _framesToFire--;
// Move game objects
for (Node node in _level.children) {
if (node is GameObject) {
node.move();
}
}
// Remove offscreen game objects
for (int i = _level.children.length - 1; i >= 0; i--) {
Node node = _level.children[i];
if (node is GameObject) {
node.removeIfOffscreen(_scroll);
}
}
if (_gameOver) return;
// Check for collisions between lasers and objects that can take damage
List<Laser> lasers = [];
for (Node node in _level.children) {
if (node is Laser) lasers.add(node);
}
List<GameObject> damageables = [];
for (Node node in _level.children) {
if (node is GameObject && node.canBeDamaged) damageables.add(node);
}
for (Laser laser in lasers) {
for (GameObject damageable in damageables) {
if (laser.collidingWith(damageable)) {
// Hit something that can take damage
damageable.addDamage(laser.impact);
laser.destroy();
}
}
}
// Check for collsions between ship and objects that can damage the ship
List<Node> nodes = new List.from(_level.children);
for (Node node in nodes) {
if (node is GameObject && node.canDamageShip) {
if (node.collidingWith(_level.ship)) {
if (_playerState.shieldActive) {
// Hit, but saved by the shield!
node.destroy();
} else {
// The ship was hit :(
killShip();
}
}
} else if (node is GameObject && node.canBeCollected) {
if (node.collidingWith(_level.ship)) {
// The ship ran over something collectable
node.collect();
}
}
}
}
int _chunk = 0;
void addObjects() {
while (_scroll + _chunkSpacing >= _chunk * _chunkSpacing) {
addLevelChunk(
_chunk,
-_chunk * _chunkSpacing - _chunkSpacing);
_chunk += 1;
}
}
void addLevelChunk(int chunk, double yPos) {
int level = chunk ~/ _chunksPerLevel;
int part = chunk % _chunksPerLevel;
if (part == 0) {
LevelLabel lbl = new LevelLabel(_objectFactory, level + 1);
lbl.position = new Point(0.0, yPos + _chunkSpacing / 2.0 - 150.0);
_level.addChild(lbl);
} else if (part == 1) {
_objectFactory.addAsteroids(10 + level * 2, yPos, 0.0 + (level * 0.2).clamp(0.0, 0.7));
} else if (part == 2) {
_objectFactory.addEnemyScoutSwarm(4 + level * 2, yPos);
} else if (part == 3) {
_objectFactory.addAsteroids(10 + level * 2, yPos, 0.0 + (level * 0.2).clamp(0.0, 0.7));
} else if (part == 4) {
_objectFactory.addEnemyDestroyerSwarm(2 + level, yPos);
} else if (part == 5) {
_objectFactory.addAsteroids(10 + level * 2, yPos, 0.0 + (level * 0.2).clamp(0.0, 0.7));
} else if (part == 6) {
_objectFactory.addEnemyScoutSwarm(4 + level * 2, yPos);
} else if (part == 7) {
_objectFactory.addAsteroids(10 + level * 2, yPos, 0.0 + (level * 0.2).clamp(0.0, 0.7));
} else if (part == 8) {
_objectFactory.addBossFight(level, yPos);
}
}
void fire() {
int laserLevel = _objectFactory.playerState.laserLevel;
Laser shot0 = new Laser(_objectFactory, laserLevel, -90.0);
shot0.position = _level.ship.position + new Offset(17.0, -10.0);
_level.addChild(shot0);
Laser shot1 = new Laser(_objectFactory, laserLevel, -90.0);
shot1.position = _level.ship.position + new Offset(-17.0, -10.0);
_level.addChild(shot1);
if (_playerState.sideLaserActive) {
Laser shot2 = new Laser(_objectFactory, laserLevel, -45.0);
shot2.position = _level.ship.position + new Offset(17.0, -10.0);
_level.addChild(shot2);
Laser shot3 = new Laser(_objectFactory, laserLevel, -135.0);
shot3.position = _level.ship.position + new Offset(-17.0, -10.0);
_level.addChild(shot3);
}
_effectPlayer.play(_sounds["laser"]);
}
void killShip() {
// Hide ship
_level.ship.visible = false;
_effectPlayer.play(_sounds["explosion"]);
// Add explosion
ExplosionBig explo = new ExplosionBig(_spritesGame);
explo.scale = 1.5;
explo.position = _level.ship.position;
_level.addChild(explo);
// Add flash
Flash flash = new Flash(size, 1.0);
addChild(flash);
// Set the state to game over
_gameOver = true;
// Return to main scene and report the score back in 2 seconds
new Timer(new Duration(seconds: 2), () { _gameOverCallback(_playerState.score); });
}
}
class Level extends Node {
Level() {
position = new Point(160.0, 0.0);
}
Ship ship;
double scroll(double scrollSpeed) {
position += new Offset(0.0, scrollSpeed);
return position.y;
}
}