diff --git a/examples/game/assets/game_ui.json b/examples/game/assets/game_ui.json index bd9d13a3c4eda..f8a09f2e0e4ec 100644 --- a/examples/game/assets/game_ui.json +++ b/examples/game/assets/game_ui.json @@ -36,6 +36,15 @@ "sourceSize": {"w":472,"h":484}, "pivot": {"x":0.5,"y":0.5} }, +{ + "filename": "coinboard.png", + "frame": {"x":366,"y":1056,"w":261,"h":100}, + "rotated": true, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":261,"h":100}, + "sourceSize": {"w":261,"h":100}, + "pivot": {"x":0.5,"y":0.5} +}, { "filename": "number_0.png", "frame": {"x":416,"y":954,"w":38,"h":63}, @@ -47,7 +56,7 @@ }, { "filename": "number_1.png", - "frame": {"x":324,"y":1221,"w":16,"h":57}, + "frame": {"x":299,"y":1286,"w":16,"h":57}, "rotated": true, "trimmed": true, "spriteSourceSize": {"x":45,"y":25,"w":16,"h":57}, @@ -56,7 +65,7 @@ }, { "filename": "number_2.png", - "frame": {"x":366,"y":1056,"w":38,"h":63}, + "frame": {"x":324,"y":1156,"w":38,"h":63}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":23,"y":22,"w":38,"h":63}, @@ -65,8 +74,8 @@ }, { "filename": "number_3.png", - "frame": {"x":364,"y":1156,"w":35,"h":63}, - "rotated": false, + "frame": {"x":197,"y":1230,"w":35,"h":63}, + "rotated": true, "trimmed": true, "spriteSourceSize": {"x":26,"y":22,"w":35,"h":63}, "sourceSize": {"w":84,"h":107}, @@ -74,8 +83,8 @@ }, { "filename": "number_4.png", - "frame": {"x":416,"y":1019,"w":38,"h":57}, - "rotated": false, + "frame": {"x":197,"y":1267,"w":38,"h":57}, + "rotated": true, "trimmed": true, "spriteSourceSize": {"x":23,"y":25,"w":38,"h":57}, "sourceSize": {"w":84,"h":107}, @@ -83,7 +92,7 @@ }, { "filename": "number_5.png", - "frame": {"x":324,"y":1156,"w":38,"h":63}, + "frame": {"x":324,"y":1221,"w":38,"h":63}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":23,"y":22,"w":38,"h":63}, @@ -92,7 +101,7 @@ }, { "filename": "number_6.png", - "frame": {"x":406,"y":1078,"w":38,"h":63}, + "frame": {"x":2,"y":1230,"w":38,"h":63}, "rotated": true, "trimmed": true, "spriteSourceSize": {"x":23,"y":22,"w":38,"h":63}, @@ -101,8 +110,8 @@ }, { "filename": "number_7.png", - "frame": {"x":401,"y":1198,"w":35,"h":60}, - "rotated": true, + "frame": {"x":262,"y":1230,"w":35,"h":60}, + "rotated": false, "trimmed": true, "spriteSourceSize": {"x":26,"y":22,"w":35,"h":60}, "sourceSize": {"w":84,"h":107}, @@ -110,7 +119,7 @@ }, { "filename": "number_8.png", - "frame": {"x":406,"y":1118,"w":38,"h":63}, + "frame": {"x":67,"y":1230,"w":38,"h":63}, "rotated": true, "trimmed": true, "spriteSourceSize": {"x":23,"y":22,"w":38,"h":63}, @@ -119,7 +128,7 @@ }, { "filename": "number_9.png", - "frame": {"x":401,"y":1158,"w":38,"h":63}, + "frame": {"x":132,"y":1230,"w":38,"h":63}, "rotated": true, "trimmed": true, "spriteSourceSize": {"x":23,"y":22,"w":38,"h":63}, @@ -140,8 +149,8 @@ "version": "1.0", "image": "game_ui.png", "format": "RGBA8888", - "size": {"w":472,"h":1239}, + "size": {"w":472,"h":1319}, "scale": "1", - "smartupdate": "$TexturePacker:SmartUpdate:02d6676bdde949110cbdc9a2c385b33a:6b0974f94eba9593dd9636cc730412b8:10ac111e32c27e51f4e8444dbb39eff6$" + "smartupdate": "$TexturePacker:SmartUpdate:2fc7dfe766eba152274e2661737d6b51:b44b32d1e0a4146b3591d51b12f2d7ae:10ac111e32c27e51f4e8444dbb39eff6$" } } diff --git a/examples/game/assets/game_ui.png b/examples/game/assets/game_ui.png index 8cc95b60a45fe..73359c83ea44b 100644 Binary files a/examples/game/assets/game_ui.png and b/examples/game/assets/game_ui.png differ diff --git a/examples/game/assets/sprites.json b/examples/game/assets/sprites.json index 656227827e618..fcde813dd291b 100644 --- a/examples/game/assets/sprites.json +++ b/examples/game/assets/sprites.json @@ -11,7 +11,7 @@ }, { "filename": "asteroid_big_0.png", - "frame": {"x":260,"y":193,"w":200,"h":167}, + "frame": {"x":2,"y":450,"w":200,"h":167}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":21,"w":200,"h":167}, @@ -20,7 +20,7 @@ }, { "filename": "asteroid_big_1.nrm.png", - "frame": {"x":451,"y":2,"w":204,"h":166}, + "frame": {"x":2,"y":619,"w":204,"h":166}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":204,"h":166}, @@ -29,7 +29,7 @@ }, { "filename": "asteroid_big_1.png", - "frame": {"x":657,"y":2,"w":204,"h":166}, + "frame": {"x":2,"y":787,"w":204,"h":166}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":204,"h":166}, @@ -38,7 +38,7 @@ }, { "filename": "asteroid_big_2.nrm.png", - "frame": {"x":462,"y":170,"w":194,"h":165}, + "frame": {"x":204,"y":335,"w":194,"h":165}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":194,"h":165}, @@ -47,7 +47,7 @@ }, { "filename": "asteroid_big_2.png", - "frame": {"x":658,"y":170,"w":194,"h":165}, + "frame": {"x":208,"y":502,"w":194,"h":165}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":194,"h":165}, @@ -56,7 +56,7 @@ }, { "filename": "asteroid_small_0.nrm.png", - "frame": {"x":204,"y":362,"w":102,"h":84}, + "frame": {"x":347,"y":843,"w":102,"h":84}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":102,"h":84}, @@ -65,7 +65,7 @@ }, { "filename": "asteroid_small_0.png", - "frame": {"x":308,"y":362,"w":102,"h":84}, + "frame": {"x":347,"y":929,"w":102,"h":84}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":102,"h":84}, @@ -74,7 +74,7 @@ }, { "filename": "asteroid_small_1.nrm.png", - "frame": {"x":854,"y":213,"w":96,"h":102}, + "frame": {"x":404,"y":463,"w":96,"h":102}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":102}, @@ -83,7 +83,7 @@ }, { "filename": "asteroid_small_1.png", - "frame": {"x":854,"y":317,"w":96,"h":102}, + "frame": {"x":404,"y":567,"w":96,"h":102}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":96,"h":102}, @@ -92,7 +92,7 @@ }, { "filename": "asteroid_small_2.nrm.png", - "frame": {"x":740,"y":337,"w":109,"h":84}, + "frame": {"x":347,"y":671,"w":109,"h":84}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":109,"h":84}, @@ -101,16 +101,43 @@ }, { "filename": "asteroid_small_2.png", - "frame": {"x":740,"y":423,"w":109,"h":84}, + "frame": {"x":347,"y":757,"w":109,"h":84}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":109,"h":84}, "sourceSize": {"w":109,"h":84}, "pivot": {"x":0.5,"y":0.5} }, +{ + "filename": "coin.png", + "frame": {"x":429,"y":270,"w":42,"h":47}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":6,"y":4,"w":42,"h":47}, + "sourceSize": {"w":54,"h":56}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "enemy_destroyer_1.png", + "frame": {"x":260,"y":193,"w":167,"h":140}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":10,"y":31,"w":167,"h":140}, + "sourceSize": {"w":188,"h":188}, + "pivot": {"x":0.5,"y":0.5} +}, +{ + "filename": "enemy_scout_0.png", + "frame": {"x":400,"y":335,"w":107,"h":126}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":11,"y":1,"w":107,"h":126}, + "sourceSize": {"w":129,"h":129}, + "pivot": {"x":0.5,"y":0.5} +}, { "filename": "explosion_flare.png", - "frame": {"x":863,"y":2,"w":56,"h":209}, + "frame": {"x":451,"y":2,"w":56,"h":209}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":0,"w":56,"h":209}, @@ -119,7 +146,7 @@ }, { "filename": "explosion_particle.png", - "frame": {"x":2,"y":450,"w":36,"h":60}, + "frame": {"x":204,"y":260,"w":36,"h":60}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":14,"y":1,"w":36,"h":60}, @@ -137,7 +164,7 @@ }, { "filename": "fire_particle.png", - "frame": {"x":40,"y":450,"w":55,"h":55}, + "frame": {"x":429,"y":213,"w":55,"h":55}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":4,"w":55,"h":55}, @@ -146,7 +173,7 @@ }, { "filename": "laser.png", - "frame": {"x":204,"y":260,"w":37,"h":76}, + "frame": {"x":458,"y":671,"w":37,"h":76}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":37,"h":76}, @@ -164,7 +191,7 @@ }, { "filename": "ship.nrm.png", - "frame": {"x":462,"y":337,"w":137,"h":167}, + "frame": {"x":208,"y":669,"w":137,"h":167}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":137,"h":167}, @@ -173,7 +200,7 @@ }, { "filename": "ship.png", - "frame": {"x":601,"y":337,"w":137,"h":167}, + "frame": {"x":208,"y":838,"w":137,"h":167}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":25,"y":10,"w":137,"h":167}, @@ -182,7 +209,7 @@ }, { "filename": "star_0.png", - "frame": {"x":204,"y":448,"w":62,"h":62}, + "frame": {"x":2,"y":955,"w":62,"h":62}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":62,"h":62}, @@ -191,7 +218,7 @@ }, { "filename": "star_1.png", - "frame": {"x":268,"y":448,"w":62,"h":62}, + "frame": {"x":66,"y":955,"w":62,"h":62}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":62,"h":62}, @@ -200,7 +227,7 @@ }, { "filename": "star_2.png", - "frame": {"x":332,"y":448,"w":62,"h":62}, + "frame": {"x":130,"y":955,"w":62,"h":62}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":62,"h":62}, @@ -212,8 +239,8 @@ "version": "1.0", "image": "sprites.png", "format": "RGBA8888", - "size": {"w":952,"h":512}, + "size": {"w":509,"h":1019}, "scale": "1", - "smartupdate": "$TexturePacker:SmartUpdate:342fc72defddab59bb356b48894e2931:ecb4b4fa7772ea6a35788ebf670ca27c:1eabdf11f75e3a4fe3147baf7b5be24b$" + "smartupdate": "$TexturePacker:SmartUpdate:2164a72d7de59aa3603277aa505ff73b:f339feca6ccc1f78132ecc733c94dbc5:1eabdf11f75e3a4fe3147baf7b5be24b$" } } diff --git a/examples/game/assets/sprites.png b/examples/game/assets/sprites.png index dcba9b09c2a9a..37c5cf698987e 100644 Binary files a/examples/game/assets/sprites.png and b/examples/game/assets/sprites.png differ diff --git a/examples/game/lib/custom_actions.dart b/examples/game/lib/custom_actions.dart new file mode 100644 index 0000000000000..19e507f574beb --- /dev/null +++ b/examples/game/lib/custom_actions.dart @@ -0,0 +1,19 @@ +part of game; + +class ActionCircularMove extends ActionInterval { + ActionCircularMove(this.setter, this.center, this.radius, this.startAngle, this.clockWise, double duration) : super (duration); + + final Function setter; + final Point center; + final double radius; + final double startAngle; + final bool clockWise; + + void update(double t) { + if (!clockWise) t = -t; + double rad = radians(startAngle + t * 360.0); + Offset offset = new Offset(math.cos(rad) * radius, math.sin(rad) * radius); + Point pos = center + offset; + setter(pos); + } +} diff --git a/examples/game/lib/explosions.dart b/examples/game/lib/explosions.dart index 8bfb97ada0d61..cfaefe22edf45 100644 --- a/examples/game/lib/explosions.dart +++ b/examples/game/lib/explosions.dart @@ -1,7 +1,13 @@ part of game; class Explosion extends Node { - Explosion(SpriteSheet sheet) { + Explosion() { + zPosition = 10.0; + } +} + +class ExplosionBig extends Explosion { + ExplosionBig(SpriteSheet sheet) { // Add particles ParticleSystem particlesDebris = new ParticleSystem( sheet["explosion_particle.png"], @@ -69,3 +75,7 @@ class Explosion extends Node { } } } + +class ExplosionMini extends Explosion { + +} diff --git a/examples/game/lib/game_demo.dart b/examples/game/lib/game_demo.dart index 699c03a63db7b..ee45d52307d9d 100644 --- a/examples/game/lib/game_demo.dart +++ b/examples/game/lib/game_demo.dart @@ -7,7 +7,9 @@ import 'dart:sky' as sky; import 'package:sky/rendering/object.dart'; import 'package:sky/widgets/framework.dart'; import 'package:skysprites/skysprites.dart'; +import 'package:vector_math/vector_math.dart'; +part 'custom_actions.dart'; part 'explosions.dart'; part 'flash.dart'; part 'game_demo_node.dart'; diff --git a/examples/game/lib/game_demo_node.dart b/examples/game/lib/game_demo_node.dart index b55eeecaa0e31..457c81ea56391 100644 --- a/examples/game/lib/game_demo_node.dart +++ b/examples/game/lib/game_demo_node.dart @@ -45,6 +45,7 @@ class GameDemoNode extends NodeWithSize { _objectFactory = new GameObjectFactory(_spritesGame, _sounds, _level, _playerState); _level.ship = new Ship(_objectFactory); + _level.ship.setupActions(); _level.addChild(_level.ship); // Add the joystick @@ -111,7 +112,7 @@ class GameDemoNode extends NodeWithSize { // Add shots if (_framesToFire == 0 && _joystick.isDown && !_gameOver) { fire(); - _framesToFire = _framesBetweenShots; + _framesToFire = (_playerState.speedLaserActive) ? _framesBetweenShots ~/ 2 : _framesBetweenShots; } if (_framesToFire > 0) _framesToFire--; @@ -158,9 +159,13 @@ class GameDemoNode extends NodeWithSize { for (Node node in nodes) { if (node is GameObject && node.canDamageShip) { if (node.collidingWith(_level.ship)) { - // The ship was hit :( - killShip(); - _level.ship.visible = false; + 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)) { @@ -198,25 +203,35 @@ class GameDemoNode extends NodeWithSize { if (part == 0) { _objectFactory.addAsteroids(10 + level * 4, yPos, 0.0 + (level * 0.2).clamp(0.0, 0.7)); } else if (part == 1) { - _objectFactory.addSwarm(4 + level * 2, yPos); + _objectFactory.addEnemyScoutSwarm(4 + level * 2, yPos); } else if (part == 2) { _objectFactory.addAsteroids(10 + level * 4, yPos, 0.0 + (level * 0.2).clamp(0.0, 0.7)); } else if (part == 3) { - _objectFactory.addAsteroids(10 + level * 4, yPos, 0.0 + (level * 0.2).clamp(0.0, 0.7)); + _objectFactory.addEnemyDestroyerSwarm(2 + level, yPos); } else if (part == 4) { _objectFactory.addAsteroids(10 + level * 4, yPos, 0.0 + (level * 0.2).clamp(0.0, 0.7)); } } void fire() { - Laser shot0 = new Laser(_objectFactory); + Laser shot0 = new Laser(_objectFactory, -90.0); shot0.position = _level.ship.position + new Offset(17.0, -10.0); _level.addChild(shot0); - Laser shot1 = new Laser(_objectFactory); + Laser shot1 = new Laser(_objectFactory, -90.0); shot1.position = _level.ship.position + new Offset(-17.0, -10.0); _level.addChild(shot1); + if (_playerState.sideLaserActive) { + Laser shot2 = new Laser(_objectFactory, 0.0); + shot2.position = _level.ship.position + new Offset(17.0, -10.0); + _level.addChild(shot2); + + Laser shot3 = new Laser(_objectFactory, 180.0); + shot3.position = _level.ship.position + new Offset(-17.0, -10.0); + _level.addChild(shot3); + } + _effectPlayer.play(_sounds["laser"]); } @@ -227,7 +242,7 @@ class GameDemoNode extends NodeWithSize { _effectPlayer.play(_sounds["explosion"]); // Add explosion - Explosion explo = new Explosion(_spritesGame); + ExplosionBig explo = new ExplosionBig(_spritesGame); explo.scale = 1.5; explo.position = _level.ship.position; _level.addChild(explo); diff --git a/examples/game/lib/game_object_factory.dart b/examples/game/lib/game_object_factory.dart index 97a102f00a006..db790a0da88fe 100644 --- a/examples/game/lib/game_object_factory.dart +++ b/examples/game/lib/game_object_factory.dart @@ -3,7 +3,9 @@ part of game; enum GameObjectType { asteroidBig, asteroidSmall, - movingEnemy, + asteroidPowerUp, + enemyScout, + enemyDestroyer, coin, } @@ -18,17 +20,24 @@ class GameObjectFactory { void addAsteroids(int numAsteroids, double yPos, double distribution) { for (int i = 0; i < numAsteroids; i++) { GameObjectType type = (randomDouble() < distribution) ? GameObjectType.asteroidBig : GameObjectType.asteroidSmall; + if (i == 0) type = GameObjectType.asteroidPowerUp; Point pos = new Point(randomSignedDouble() * 160.0, yPos + _chunkSpacing * randomDouble()); addGameObject(type, pos); } } - void addSwarm(int numEnemies, double yPos) { + void addEnemyScoutSwarm(int numEnemies, double yPos) { for (int i = 0; i < numEnemies; i++) { double spacing = math.max(_chunkSpacing / (numEnemies + 1.0), 80.0); double y = yPos + _chunkSpacing / 2.0 - (numEnemies - 1) * spacing / 2.0 + i * spacing; - addGameObject(GameObjectType.movingEnemy, new Point(0.0, y)); + addGameObject(GameObjectType.enemyScout, new Point(0.0, y)); + } + } + + void addEnemyDestroyerSwarm(int numEnemies, double yPos) { + for (int i = 0; i < numEnemies; i++) { + addGameObject(GameObjectType.enemyDestroyer, new Point(randomSignedDouble() * 120.0 , yPos + _chunkSpacing * randomDouble())); } } @@ -38,8 +47,12 @@ class GameObjectFactory { obj = new AsteroidBig(this); else if (type == GameObjectType.asteroidSmall) obj = new AsteroidSmall(this); - else if (type == GameObjectType.movingEnemy) - obj = new MovingEnemy(this); + else if (type == GameObjectType.asteroidPowerUp) + obj = new AsteroidPowerUp(this); + else if (type == GameObjectType.enemyScout) + obj = new EnemyScout(this); + else if (type == GameObjectType.enemyDestroyer) + obj = new EnemyDestroyer(this); else if (type == GameObjectType.coin) obj = new Coin(this); diff --git a/examples/game/lib/game_objects.dart b/examples/game/lib/game_objects.dart index 02904dbf2a540..582d9108badd6 100644 --- a/examples/game/lib/game_objects.dart +++ b/examples/game/lib/game_objects.dart @@ -42,7 +42,7 @@ abstract class GameObject extends Node { parent.addChild(explo); } - PowerUp powerUp = createPowerUp(); + Collectable powerUp = createPowerUp(); if (powerUp != null) { powerUp.position = position; powerUp.setupActions(); @@ -71,7 +71,7 @@ abstract class GameObject extends Node { return null; } - PowerUp createPowerUp() { + Collectable createPowerUp() { return null; } @@ -93,8 +93,13 @@ class Ship extends GameObject { _sprt.scale = 0.3; _sprt.rotation = -90.0; addChild(_sprt); - radius = 20.0; + _sprtShield = new Sprite(f.sheet["shield.png"]); + _sprtShield.scale = 0.35; + _sprtShield.transferMode = sky.TransferMode.plus; + addChild(_sprtShield); + + radius = 20.0; canBeDamaged = false; canDamageShip = false; @@ -103,6 +108,7 @@ class Ship extends GameObject { } Sprite _sprt; + Sprite _sprtShield; void applyThrust(Point joystickValue, double scroll) { Point oldPos = position; @@ -113,31 +119,59 @@ class Ship extends GameObject { GameMath.filter(oldPos.x, target.x, filterFactor), GameMath.filter(oldPos.y, target.y, filterFactor)); } + + void setupActions() { + ActionTween rotate = new ActionTween((a) => _sprtShield.rotation = a, 0.0, 360.0, 1.0); + _sprtShield.actions.run(new ActionRepeatForever(rotate)); + } + + void update(double dt) { + // Update shield + if (f.playerState.shieldActive) { + if (f.playerState.shieldDeactivating) + _sprtShield.visible = !_sprtShield.visible; + else + _sprtShield.visible = true; + } else { + _sprtShield.visible = false; + } + } } class Laser extends GameObject { double impact = 1.0; - Laser(GameObjectFactory f) : super(f) { + Laser(GameObjectFactory f, double r) : super(f) { // Add sprite - _sprt = new Sprite(f.sheet["laser.png"]); - _sprt.scale = 0.3; + _sprt = new Sprite(f.sheet["explosion_particle.png"]); + _sprt.scale = 0.5; + _sprt.colorOverlay = new Color(0xff95f4fb); _sprt.transferMode = sky.TransferMode.plus; + _sprt.rotation = r + 90.0; addChild(_sprt); radius = 10.0; removeLimit = 640.0; + canDamageShip = false; canBeDamaged = false; + + _offset = new Offset(math.cos(radians(r)) * 10.0, math.sin(radians(r)) * 10.0); } Sprite _sprt; + Offset _offset; void move() { - position += new Offset(0.0, -10.0); + position += _offset; } } +Color colorForDamage(double damage, double maxDamage) { + int alpha = ((200.0 * damage) ~/ maxDamage).clamp(0, 200); + return new Color.fromARGB(alpha, 255, 3, 86); +} + abstract class Obstacle extends GameObject { Obstacle(GameObjectFactory f) : super(f); @@ -146,7 +180,7 @@ abstract class Obstacle extends GameObject { Explosion createExplosion() { SoundEffectPlayer.sharedInstance().play(f.sounds["explosion"]); - Explosion explo = new Explosion(f.sheet); + Explosion explo = new ExplosionBig(f.sheet); explo.scale = explosionScale; return explo; } @@ -169,11 +203,10 @@ abstract class Asteroid extends Obstacle { set damage(double d) { super.damage = d; - int alpha = ((200.0 * d) ~/ maxDamage).clamp(0, 200); - _sprt.colorOverlay = new Color.fromARGB(alpha, 255, 3, 86); + _sprt.colorOverlay = colorForDamage(d, maxDamage); } - PowerUp createPowerUp() { + Collectable createPowerUp() { return new Coin(f); } } @@ -198,10 +231,18 @@ class AsteroidSmall extends Asteroid { } } -class MovingEnemy extends Obstacle { - MovingEnemy(GameObjectFactory f) : super(f) { - _sprt = new Sprite(f.sheet["ship.png"]); - _sprt.scale = 0.2; +class AsteroidPowerUp extends AsteroidBig { + AsteroidPowerUp(GameObjectFactory f) : super(f); + + Collectable createPowerUp() { + return new PowerUp(f, nextPowerUpType()); + } +} + +class EnemyScout extends Obstacle { + EnemyScout(GameObjectFactory f) : super(f) { + _sprt = new Sprite(f.sheet["enemy_scout_0.png"]); + _sprt.scale = 0.32; radius = 12.0; maxDamage = 1.0; addChild(_sprt); @@ -251,31 +292,114 @@ class MovingEnemy extends Obstacle { actions.run(new ActionRepeatForever(spline)); } + Collectable createPowerUp() { + return new Coin(f); + } + Sprite _sprt; } -class PowerUp extends GameObject { - PowerUp(GameObjectFactory f) : super(f) { +class EnemyDestroyer extends Obstacle { + EnemyDestroyer(GameObjectFactory f) : super(f) { + _sprt = new Sprite(f.sheet["enemy_destroyer_1.png"]); + _sprt.scale = 0.32; + radius = 24.0; + maxDamage = 4.0; + addChild(_sprt); + + constraints = [new ConstraintRotationToNode(f.level.ship, dampening: 0.05)]; + } + + int _countDown = randomInt(120) + 240; + + void setupActions() { + ActionCircularMove circle = new ActionCircularMove( + (a) => position = a, + position, 40.0, + 360.0 * randomDouble(), + randomBool(), + 3.0); + actions.run(new ActionRepeatForever(circle)); + } + + Collectable createPowerUp() { + return new Coin(f); + } + + void update(double dt) { + _countDown -= 1; + if (_countDown <= 0) { + print("SHOOT!!"); + + // Shoot at player + EnemyLaser laser = new EnemyLaser(f, rotation, 5.0, new Color(0xffffe38e)); + laser.position = position; + f.level.addChild(laser); + + _countDown = 60 + randomInt(120); + } + } + + set damage(double d) { + super.damage = d; + _sprt.colorOverlay = colorForDamage(d, maxDamage); + } + + Sprite _sprt; +} + +class EnemyLaser extends Obstacle { + EnemyLaser(GameObjectFactory f, double rotation, double speed, Color color) : super(f) { + _sprt = new Sprite(f.sheet["explosion_particle.png"]); + _sprt.scale = 0.5; + _sprt.rotation = rotation + 90; + _sprt.colorOverlay = color; + addChild(_sprt); + + canDamageShip = true; + canBeDamaged = false; + + double rad = radians(rotation); + _movement = new Offset(math.cos(rad) * speed, math.sin(rad) * speed); + + print("LASER!!"); + } + + Sprite _sprt; + Offset _movement; + + void move() { + position += _movement; + } +} + +class Collectable extends GameObject { + Collectable(GameObjectFactory f) : super(f) { canDamageShip = false; canBeDamaged = false; canBeCollected = true; + + zPosition = 20.0; } } -class Coin extends PowerUp { +class Coin extends Collectable { Coin(GameObjectFactory f) : super(f) { - _sprt = new Sprite(f.sheet["shield.png"]); - _sprt.transferMode = sky.TransferMode.plus; - _sprt.size = new Size(15.0, 15.0); - _sprt.colorOverlay = new Color(0xffffff00); + _sprt = new Sprite(f.sheet["coin.png"]); + _sprt.scale = 0.7; addChild(_sprt); radius = 7.5; } - setupActions() { + void setupActions() { + // Rotate ActionTween rotate = new ActionTween((a) => _sprt.rotation = a, 0.0, 360.0, 1.0); actions.run(new ActionRepeatForever(rotate)); + + // Fade in + ActionTween fadeIn = new ActionTween((a) => _sprt.opacity = a, 0.0, 1.0, 0.6); + actions.run(fadeIn); } Sprite _sprt; @@ -285,3 +409,51 @@ class Coin extends PowerUp { super.collect(); } } + +enum PowerUpType { + shield, + speedLaser, + sideLaser, +} + +List _powerUpTypes = new List.from(PowerUpType.values); +int _lastPowerUp = _powerUpTypes.length; + +PowerUpType nextPowerUpType() { + if (_lastPowerUp >= _powerUpTypes.length) { + _powerUpTypes.shuffle(); + _lastPowerUp = 0; + } + + PowerUpType type = _powerUpTypes[_lastPowerUp]; + _lastPowerUp++; + + return type; +} + +class PowerUp extends Collectable { + PowerUp(GameObjectFactory f, this.type) : super(f) { + _sprt = new Sprite(f.sheet["coin.png"]); + _sprt.scale = 1.2; + addChild(_sprt); + + radius = 10.0; + } + + Sprite _sprt; + PowerUpType type; + + void setupActions() { + ActionTween rotate = new ActionTween((a) => _sprt.rotation = a, 0.0, 360.0, 1.0); + actions.run(new ActionRepeatForever(rotate)); + + // Fade in + ActionTween fadeIn = new ActionTween((a) => _sprt.opacity = a, 0.0, 1.0, 0.6); + actions.run(fadeIn); + } + + void collect() { + f.playerState.activatePowerUp(type); + super.collect(); + } +} diff --git a/examples/game/lib/player_state.dart b/examples/game/lib/player_state.dart index 90be2a3b01848..607f60deb514a 100644 --- a/examples/game/lib/player_state.dart +++ b/examples/game/lib/player_state.dart @@ -3,38 +3,41 @@ part of game; class PlayerState extends Node { PlayerState(this._sheetUI, this._sheetGame) { // Score display - Sprite sprtBgScore = new Sprite(_sheetUI["scoreboard.png"]); - sprtBgScore.pivot = new Point(1.0, 0.0); - sprtBgScore.scale = 0.35; - sprtBgScore.position = new Point(310.0, 10.0); - addChild(sprtBgScore); + _sprtBgScore = new Sprite(_sheetUI["scoreboard.png"]); + _sprtBgScore.pivot = new Point(1.0, 0.0); + _sprtBgScore.scale = 0.35; + _sprtBgScore.position = new Point(240.0, 10.0); + addChild(_sprtBgScore); _scoreDisplay = new ScoreDisplay(_sheetUI); _scoreDisplay.position = new Point(-13.0, 49.0); - sprtBgScore.addChild(_scoreDisplay); + _sprtBgScore.addChild(_scoreDisplay); // Coin display - Sprite sprtBgCoins = new Sprite(_sheetUI["scoreboard.png"]); - sprtBgCoins.pivot = new Point(1.0, 0.0); - sprtBgCoins.scale = 0.35; - sprtBgCoins.position = new Point(170.0, 10.0); - addChild(sprtBgCoins); + _sprtBgCoins = new Sprite(_sheetUI["coinboard.png"]); + _sprtBgCoins.pivot = new Point(1.0, 0.0); + _sprtBgCoins.scale = 0.35; + _sprtBgCoins.position = new Point(105.0, 10.0); + addChild(_sprtBgCoins); _coinDisplay = new ScoreDisplay(_sheetUI); _coinDisplay.position = new Point(-13.0, 49.0); - sprtBgCoins.addChild(_coinDisplay); + _sprtBgCoins.addChild(_coinDisplay); } final SpriteSheet _sheetUI; final SpriteSheet _sheetGame; + Sprite _sprtBgScore; ScoreDisplay _scoreDisplay; + Sprite _sprtBgCoins; ScoreDisplay _coinDisplay; int get score => _scoreDisplay.score; set score(int score) { _scoreDisplay.score = score; + flashBgSprite(_sprtBgScore); } int get coins => _coinDisplay.score; @@ -42,26 +45,67 @@ class PlayerState extends Node { void addCoin(Coin c) { // Animate coin to the top of the screen Point startPos = convertPointFromNode(Point.origin, c); - Point finalPos = new Point(10.0, 10.0); + Point finalPos = new Point(30.0, 30.0); Point middlePos = new Point((startPos.x + finalPos.x) / 2.0 + 50.0, (startPos.y + finalPos.y) / 2.0); List path = [startPos, middlePos, finalPos]; - Sprite sprt = new Sprite(_sheetGame["shield.png"]); - sprt.size = new Size(15.0, 15.0); - sprt.transferMode = sky.TransferMode.plus; - sprt.colorOverlay = new Color(0xffffff00); + Sprite sprt = new Sprite(_sheetGame["coin.png"]); + sprt.scale = 0.7; + ActionSpline spline = new ActionSpline((a) => sprt.position = a, path, 0.5); spline.tension = 0.25; + ActionTween rotate = new ActionTween((a) => sprt.rotation = a, 0.0, 360.0, 0.5); + ActionTween scale = new ActionTween((a) => sprt.scale = a, 0.7, 1.2, 0.5); + ActionGroup group = new ActionGroup([spline, rotate, scale]); sprt.actions.run(new ActionSequence([ - spline, + group, new ActionRemoveNode(sprt), - new ActionCallFunction(() { _coinDisplay.score += 1; }) + new ActionCallFunction(() { + _coinDisplay.score += 1; + flashBgSprite(_sprtBgCoins); + }) ])); addChild(sprt); } + + void activatePowerUp(PowerUpType type) { + if (type == PowerUpType.shield) { + _shieldFrames += 300; + } else if (type == PowerUpType.sideLaser) { + _sideLaserFrames += 300; + } else if (type == PowerUpType.speedLaser) { + _speedLaserFrames += 300; + } + } + + int _shieldFrames = 0; + bool get shieldActive => _shieldFrames > 0; + bool get shieldDeactivating => _shieldFrames > 0 && _shieldFrames < 60; + + int _sideLaserFrames = 0; + bool get sideLaserActive => _sideLaserFrames > 0; + + int _speedLaserFrames = 0; + bool get speedLaserActive => _speedLaserFrames > 0; + + void flashBgSprite(Sprite sprt) { + sprt.actions.stopAll(); + ActionTween flash = new ActionTween( + (a) => sprt.colorOverlay = a, + new Color(0x66ccfff0), + new Color(0x00ccfff0), + 0.3); + sprt.actions.run(flash); + } + + void update(double dt) { + if (_shieldFrames > 0) _shieldFrames--; + if (_sideLaserFrames > 0) _sideLaserFrames--; + if (_speedLaserFrames > 0) _speedLaserFrames--; + } } class ScoreDisplay extends Node {