[common] added Bonus entity

This commit is contained in:
2018-02-09 16:57:33 +03:00
parent 5c57454998
commit 41c5610f9a
22 changed files with 182 additions and 40 deletions

View File

@@ -43,7 +43,7 @@ class HumanControl extends Control {
case _: case _:
} }
if (event.keyCode == Keyboard.U) { if (event.keyCode == Keyboard.U) {
action(TankAction.LEVEL_UP(1)); action(TankAction.UPGRADE);
} }
} }

View File

@@ -108,6 +108,11 @@ class Render extends SpriteView implements EngineListener {
items.set(eagle.key, item); items.set(eagle.key, item);
entryLayer.addChild(item.view); entryLayer.addChild(item.view);
item.update(); item.update();
case EntityType.BONUS(bonus):
var item = new BonusItem(bonus);
items.set(bonus.key, item);
entryLayer.addChild(item.view);
item.update();
case _: case _:
} }
} }
@@ -136,6 +141,11 @@ class Render extends SpriteView implements EngineListener {
items.get(eagle.key).redraw(); items.get(eagle.key).redraw();
playTankBoom(eagle.rect.center); playTankBoom(eagle.rect.center);
} }
case EntityType.BONUS(bonus):
if (items.exists(bonus.key)) {
entryLayer.removeChild(items.get(bonus.key).view);
items.remove(bonus.key);
}
case _: case _:
} }
} }

View File

@@ -1,5 +1,8 @@
package ru.m.tankz.render; package ru.m.tankz.render;
import openfl.display.BitmapData;
import ru.m.draw.Color;
import ru.m.tankz.core.Bonus;
import flash.display.Bitmap; import flash.display.Bitmap;
import flash.display.DisplayObject; import flash.display.DisplayObject;
import flash.display.Shape; import flash.display.Shape;
@@ -9,7 +12,6 @@ import ru.m.animate.Animate;
import ru.m.draw.BitmapUtil; import ru.m.draw.BitmapUtil;
import ru.m.geom.Direction; import ru.m.geom.Direction;
import ru.m.geom.Rectangle; import ru.m.geom.Rectangle;
import ru.m.tankz.control.Control;
import ru.m.tankz.core.Bullet; import ru.m.tankz.core.Bullet;
import ru.m.tankz.core.Eagle; import ru.m.tankz.core.Eagle;
import ru.m.tankz.core.Tank; import ru.m.tankz.core.Tank;
@@ -121,6 +123,19 @@ class BrickItem extends RenderItem<Brick, Shape> {
} }
class AnimateItem<T:TRectangle> extends RenderItem<T, Animate> {
public function new(value:T) {
super(value);
view = new Animate();
}
override public function dispose():Void {
view.dispose();
}
}
class TankItem extends RenderItem<Tank, Sprite> { class TankItem extends RenderItem<Tank, Sprite> {
private var type:String; private var type:String;
@@ -131,28 +146,14 @@ class TankItem extends RenderItem<Tank, Sprite> {
public function new(value:Tank) { public function new(value:Tank) {
super(value); super(value);
view = new Sprite(); view = new Sprite();
if (value.playerId.type == Control.HUMAN) {
view.addChild(buildHumanMarkView(value));
}
tankView = new Animate(); tankView = new Animate();
view.addChild(tankView); view.addChild(tankView);
redraw(); redraw();
} }
private static function buildHumanMarkView(tank:Tank):DisplayObject {
var view = new Shape();
view.graphics.beginFill(0x00aa00);
view.graphics.lineStyle(2, 0x00ff00);
view.graphics.drawCircle(0, 0, 23);
view.graphics.endFill();
view.x = tank.rect.width / 2;
view.y = tank.rect.height / 2;
view.alpha = 0.2;
return view;
}
override public function redraw():Void { override public function redraw():Void {
tankView.frames = getFrames().map(function(src) return BitmapUtil.colorize(Assets.getBitmapData(src), value.color)); var colors:Array<Color> = [value.color, value.bonus ? 0xff00aa : value.color];
tankView.frames = getFrames().map(function(src) return BitmapUtil.colorize(Assets.getBitmapData(src), colors.shift()));
} }
private function getFrames():Array<String> { private function getFrames():Array<String> {
@@ -199,3 +200,21 @@ class EagleItem extends BitmapItem<Eagle> {
return 'resources/images/eagle/eagle-${destoyed ? 1 : 0}.png'; return 'resources/images/eagle/eagle-${destoyed ? 1 : 0}.png';
} }
} }
class BonusItem extends AnimateItem<Bonus> {
public function new(value:Bonus) {
super(value);
redraw();
}
override public function redraw():Void {
// ToDo: 15/15 frames
view.frames = [
Assets.getBitmapData('resources/image/bonus/${value.bonusType}.png'),
new BitmapData(1, 1),
];
view.playing = true;
}
}

View File

@@ -24,10 +24,10 @@ teams:
- id: bot - id: bot
spawnInterval: 3000 spawnInterval: 3000
tanks: tanks:
- {type: bot0, rate: 0.5} - {type: bot0, rate: 0.25, bonus: 1}
- {type: bot1, rate: 0.5} - {type: bot1, rate: 0.25, bonus: 1}
- {type: bot2, rate: 0.5} - {type: bot2, rate: 0.25, bonus: 1}
- {type: bot3, rate: 0.5} - {type: bot3, rate: 0.25, bonus: 1}
points: points:
- {team: human, type: eagle, index: -1, direction: right, x: 12, y: 24} - {team: human, type: eagle, index: -1, direction: right, x: 12, y: 24}
@@ -45,6 +45,7 @@ bullet: &bullet
tanks: tanks:
- type: human0 - type: human0
upgrade: human1
width: 36 width: 36
height: 36 height: 36
speed: 2.5 speed: 2.5
@@ -55,6 +56,7 @@ tanks:
skin: pa skin: pa
- type: human1 - type: human1
upgrade: human2
width: 40 width: 40
height: 36 height: 36
speed: 3.0 speed: 3.0
@@ -65,6 +67,7 @@ tanks:
skin: pb skin: pb
- type: human2 - type: human2
upgrade: human3
width: 40 width: 40
height: 36 height: 36
speed: 3.0 speed: 3.0
@@ -75,6 +78,7 @@ tanks:
skin: pc skin: pc
- type: human3 - type: human3
upgrade: human3
width: 42 width: 42
height: 38 height: 38
speed: 2.9 speed: 2.9
@@ -130,3 +134,11 @@ tanks:
score: 400 score: 400
hits: 3 hits: 3
skin: bd skin: bd
bonuses:
- {type: clock}
- {type: grenade}
- {type: helmet}
- {type: life}
- {type: shovel}
- {type: star}

View File

@@ -70,3 +70,11 @@ tanks:
speed: 7.0 speed: 7.0
bullets: 1 bullets: 1
skin: bb skin: bb
bonuses:
- {type: clock}
- {type: grenade}
- {type: helmet}
- {type: life}
- {type: shovel}
- {type: star}

View File

Before

Width:  |  Height:  |  Size: 450 B

After

Width:  |  Height:  |  Size: 450 B

View File

Before

Width:  |  Height:  |  Size: 566 B

After

Width:  |  Height:  |  Size: 566 B

View File

Before

Width:  |  Height:  |  Size: 354 B

After

Width:  |  Height:  |  Size: 354 B

View File

Before

Width:  |  Height:  |  Size: 541 B

After

Width:  |  Height:  |  Size: 541 B

View File

Before

Width:  |  Height:  |  Size: 455 B

After

Width:  |  Height:  |  Size: 455 B

View File

Before

Width:  |  Height:  |  Size: 532 B

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

View File

@@ -10,8 +10,12 @@ typedef TeamId = String;
typedef ControlType = String; typedef ControlType = String;
typedef BrickType = Int;
typedef TankType = String; typedef TankType = String;
typedef BonusType = String;
typedef PlayerId = { typedef PlayerId = {
var team:TeamId; var team:TeamId;
var type:ControlType; var type:ControlType;

View File

@@ -26,7 +26,7 @@ typedef MapConfig = {
} }
typedef BrickConfig = { typedef BrickConfig = {
var type:Int; var type:BrickType;
var layer:Int; var layer:Int;
var armor:Int; var armor:Int;
} }
@@ -47,11 +47,17 @@ typedef TankConfig = {
var bullets:Int; var bullets:Int;
var hits:Int; var hits:Int;
var skin:String; var skin:String;
@:optinal var upgrade:TankType;
}
typedef BonusConfig = {
var type:BonusType;
} }
typedef TankSpawn = { typedef TankSpawn = {
var type:TankType; var type:TankType;
var rate: Float; var rate:Float;
@:optional var bonus:Float;
} }
@@ -78,10 +84,12 @@ class Config {
public var tanks(default, null):Array<TankConfig>; public var tanks(default, null):Array<TankConfig>;
public var teams(default, null):Array<TeamConfig>; public var teams(default, null):Array<TeamConfig>;
public var points(default, null):Array<SpawnPoint>; public var points(default, null):Array<SpawnPoint>;
public var bonuses(default, null):Array<BonusConfig>;
private var brickMap:Map<Int, BrickConfig>; private var brickMap:Map<Int, BrickConfig>;
private var tankMap:Map<TankType, TankConfig>; private var tankMap:Map<TankType, TankConfig>;
private var teamMap:Map<String, TeamConfig>; private var teamMap:Map<TeamId, TeamConfig>;
private var bonusMap:Map<BonusType, BonusConfig>;
public function new( public function new(
type:String, type:String,
@@ -90,7 +98,8 @@ class Config {
bricks:Array<BrickConfig>, bricks:Array<BrickConfig>,
teams:Array<TeamConfig>, teams:Array<TeamConfig>,
points:Array<SpawnPoint>, points:Array<SpawnPoint>,
tanks:Array<TankConfig> tanks:Array<TankConfig>,
bonuses:Array<BonusConfig>
) { ) {
this.type = type; this.type = type;
this.game = game; this.game = game;
@@ -99,6 +108,7 @@ class Config {
this.teams = teams; this.teams = teams;
this.points = points; this.points = points;
this.tanks = tanks; this.tanks = tanks;
this.bonuses = bonuses;
init(); init();
} }
@@ -115,6 +125,10 @@ class Config {
for (item in tanks) { for (item in tanks) {
tankMap.set(item.type, item); tankMap.set(item.type, item);
} }
bonusMap = new Map();
for (item in bonuses) {
bonusMap.set(item.type, item);
}
} }
public function getBrick(type:Int):BrickConfig { public function getBrick(type:Int):BrickConfig {
@@ -128,4 +142,8 @@ class Config {
public function getTank(type:TankType):TankConfig { public function getTank(type:TankType):TankConfig {
return tankMap.get(type); return tankMap.get(type);
} }
public function getBonus(type:BonusType):BonusConfig {
return bonusMap.get(type);
}
} }

View File

@@ -13,6 +13,7 @@ typedef ConfigSource = {
var teams: Array<TeamConfig>; var teams: Array<TeamConfig>;
var points: Array<SpawnPoint>; var points: Array<SpawnPoint>;
var tanks: Array<TankConfig>; var tanks: Array<TankConfig>;
var bonuses: Array<BonusConfig>;
} }
class ConfigBundle { class ConfigBundle {
@@ -23,6 +24,6 @@ class ConfigBundle {
public static function get(type:String):Config { public static function get(type:String):Config {
var source = convert(Yaml.parse(Assets.getText('resources/${type}/config.yaml'), Parser.options().useObjects())); var source = convert(Yaml.parse(Assets.getText('resources/${type}/config.yaml'), Parser.options().useObjects()));
return new Config(type, source.game, source.map, source.bricks, source.teams, source.points, source.tanks); return new Config(type, source.game, source.map, source.bricks, source.teams, source.points, source.tanks, source.bonuses);
} }
} }

View File

@@ -8,7 +8,7 @@ import ru.m.tankz.Type;
enum TankAction { enum TankAction {
MOVE(direction:Direction); MOVE(direction:Direction);
LEVEL_UP(level:Int); UPGRADE;
STOP; STOP;
SHOT; SHOT;
} }

View File

@@ -0,0 +1,15 @@
package ru.m.tankz.core;
import ru.m.geom.Rectangle;
import ru.m.tankz.Type;
class Bonus extends Entity {
public var bonusType(default, null):BonusType;
public function new(bonusType:BonusType) {
super(new Rectangle(0, 0, 44, 44));
this.bonusType = bonusType;
}
}

View File

@@ -1,7 +1,7 @@
package ru.m.tankz.core; package ru.m.tankz.core;
import Type; import Type;
import ru.m.tankz.map.Grid.GridCell; import ru.m.tankz.map.Grid;
enum EntityType { enum EntityType {
@@ -9,6 +9,7 @@ enum EntityType {
TANK(tank:Tank); TANK(tank:Tank);
BULLET(bullet:Bullet); BULLET(bullet:Bullet);
CELL(cell:GridCell); CELL(cell:GridCell);
BONUS(bonus:Bonus);
} }
@@ -20,6 +21,7 @@ class EntityTypeResolver {
case ValueType.TClass(Tank): EntityType.TANK(cast entity); case ValueType.TClass(Tank): EntityType.TANK(cast entity);
case ValueType.TClass(Bullet): EntityType.BULLET(cast entity); case ValueType.TClass(Bullet): EntityType.BULLET(cast entity);
case ValueType.TClass(GridCell): EntityType.CELL(cast entity); case ValueType.TClass(GridCell): EntityType.CELL(cast entity);
case ValueType.TClass(Bonus): EntityType.BONUS(cast entity);
case x: null; case x: null;
} }
} }

View File

@@ -14,6 +14,7 @@ class Tank extends MobileEntity {
public var config(default, set):TankConfig; public var config(default, set):TankConfig;
public var color(default, default):Color; public var color(default, default):Color;
public var hits(default, default):Int; public var hits(default, default):Int;
public var bonus(default, default):Bool;
private var bulletsCounter:Int = 0; private var bulletsCounter:Int = 0;

View File

@@ -58,6 +58,8 @@ class CollisionProcessor implements EngineListener {
tank1.rect.lean(eagle.rect); tank1.rect.lean(eagle.rect);
case EntityType.CELL(cell): case EntityType.CELL(cell):
tank1.rect.lean(cell.rect); tank1.rect.lean(cell.rect);
case EntityType.BONUS(bonus):
engine.destroy(bonus);
} }
case EntityType.BULLET(bullet1): case EntityType.BULLET(bullet1):
switch (with) { switch (with) {
@@ -74,6 +76,7 @@ class CollisionProcessor implements EngineListener {
engine.destroy(eagle); engine.destroy(eagle);
case EntityType.CELL(cell): case EntityType.CELL(cell):
engine.destroy(bullet1); engine.destroy(bullet1);
case EntityType.BONUS(bonus):
} }
case _: case _:
} }
@@ -131,15 +134,10 @@ class Engine implements ControlHandler {
switch (action) { switch (action) {
case TankAction.MOVE(direction): case TankAction.MOVE(direction):
tank.move(direction); tank.move(direction);
case TankAction.LEVEL_UP(level): case TankAction.UPGRADE:
// ToDo: if (tank.config.upgrade != null) {
var newType = switch(tank.config.type) { tank.config = config.getTank(tank.config.upgrade);
case 'human0': 'human1';
case 'human1': 'human2';
case 'human2': 'human3';
case x: 'human3';
} }
tank.config = config.getTank(newType);
case TankAction.STOP: case TankAction.STOP:
tank.stop(); tank.stop();
case TankAction.SHOT: case TankAction.SHOT:

View File

@@ -1,5 +1,6 @@
package ru.m.tankz.game; package ru.m.tankz.game;
import ru.m.tankz.core.Bonus;
import haxe.ds.Option; import haxe.ds.Option;
import haxe.Timer; import haxe.Timer;
import promhx.Deferred; import promhx.Deferred;
@@ -54,6 +55,7 @@ class Game implements EngineListener {
var tankConfig:TankConfig = config.getTank(spawn.type); var tankConfig:TankConfig = config.getTank(spawn.type);
var tank = new Tank(playerId, tankConfig); var tank = new Tank(playerId, tankConfig);
tank.color = playerId.color.zero ? teams[playerId.team].config.color : playerId.color; tank.color = playerId.color.zero ? teams[playerId.team].config.color : playerId.color;
tank.bonus = Math.random() < spawn.bonus;
applyPoint(tank, point); applyPoint(tank, point);
return tank; return tank;
} }
@@ -154,6 +156,11 @@ class Game implements EngineListener {
case EntityType.TANK(tank): case EntityType.TANK(tank):
var control = getPlayer(tank.playerId).control; var control = getPlayer(tank.playerId).control;
if (control != null) control.onCollision(with); if (control != null) control.onCollision(with);
switch (with) {
case EntityType.BONUS(bonus):
applyBonus(tank, bonus);
case x:
}
case x: case x:
} }
} }
@@ -207,6 +214,7 @@ class Game implements EngineListener {
state.teams[tank.playerId.team].lose = true; state.teams[tank.playerId.team].lose = true;
complete(); complete();
} }
if (tank.bonus) spawnBonus();
deferred.resolve(state); deferred.resolve(state);
case EntityType.EAGLE(eagle): case EntityType.EAGLE(eagle):
state.teams[eagle.team].lose = true; state.teams[eagle.team].lose = true;
@@ -216,18 +224,53 @@ class Game implements EngineListener {
} }
} }
public function onAction(tankId:Int, action:TankAction):Void { public function onAction(tankId:Int, action:TankAction):Void {
engine.action(tankId, action); engine.action(tankId, action);
} }
public function next():Option<GameState> { public function next():Option<GameState> {
return Option.None; return Option.None;
} }
public function dispose():Void { public function dispose():Void {
engine.dispose(); engine.dispose();
} }
private function spawnBonus():Void {
var bonusConfig = config.bonuses[Math.floor(Math.random() * config.bonuses.length)];
L.d(TAG, 'Spawn Bonus(${bonusConfig}');
var bonus = new Bonus(bonusConfig.type);
bonus.rect.x = Math.random() * engine.map.width;
bonus.rect.y = Math.random() * engine.map.height;
engine.spawn(bonus);
}
private function applyBonus(tank:Tank, bonus:Bonus):Void {
switch (bonus.bonusType) {
case 'life':
state.teams[tank.playerId.team].players[tank.playerId.index].life++;
case 'star':
if (tank.config.upgrade != null) {
tank.config = config.getTank(tank.config.upgrade);
} else {
tank.hits++;
}
case 'grenade':
for (entity in engine.entities.iterator()) {
switch (EntityTypeResolver.of(entity)) {
case EntityType.TANK(t):
if (t.playerId.team != tank.playerId.team) {
engine.destroy(t);
}
case x:
}
}
case 'helmet':
case 'clock':
case 'shovel':
case x:
engine.destroy(tank); // :-D
}
}
} }

View File

@@ -15,6 +15,9 @@ class LevelMap {
public var gridWidth(default, null):Int; public var gridWidth(default, null):Int;
public var gridHeight(default, null):Int; public var gridHeight(default, null):Int;
public var width(get, null):Float;
public var height(get, null):Float;
public var bricks(default, null):Array<Brick>; public var bricks(default, null):Array<Brick>;
public var grid(default, null):Grid; public var grid(default, null):Grid;
@@ -68,4 +71,12 @@ class LevelMap {
var cellY:Int = Math.floor(point.y / config.cellHeight); var cellY:Int = Math.floor(point.y / config.cellHeight);
return bricks[cellX + cellY * config.gridWidth]; return bricks[cellX + cellY * config.gridWidth];
} }
private inline function get_width():Float {
return config.cellWidth * config.gridWidth;
}
private inline function get_height():Float {
return config.cellHeight * config.gridHeight;
}
} }