35 Commits
0.2.1 ... 0.6.2

Author SHA1 Message Date
79039ae79e [version] up 2018-02-16 00:09:13 +03:00
1ae84cf5a8 [common] bonuses implemented 2018-02-15 17:11:41 +03:00
032fa0c0ad [client] yaml layouts 2018-02-14 17:15:15 +03:00
1f8b43ba5d [editor] tank color view 2018-02-13 22:32:21 +03:00
4fc0ae103e [editor] added frame switcher 2018-02-13 17:57:07 +03:00
bd86412d83 [editor] fixes 2018-02-13 17:12:24 +03:00
592e59e01f [common] added Eagle death flag 2018-02-13 16:59:01 +03:00
05b6fe4a56 [client] added any map item renders 2018-02-13 14:44:04 +03:00
f68e5d160f [common] game state refactored 2018-02-12 22:26:30 +03:00
d279d52b09 [editor] fix 2018-02-11 14:37:02 +03:00
a1ed498bf5 [client] render fixes 2018-02-10 15:25:16 +03:00
41c5610f9a [common] added Bonus entity 2018-02-09 16:57:33 +03:00
5c57454998 [common] added Type bundle 2018-02-09 10:59:25 +03:00
a7effef412 [render] tankz colors 2018-02-08 23:12:10 +03:00
dd1014e230 [client] added draw package 2018-02-08 17:57:40 +03:00
89ac9fd225 [resources] added dota maps 2018-02-07 22:49:23 +03:00
3096fba7c5 [editor] update spwan view 2018-02-07 21:47:13 +03:00
baf696a3e1 [editor] game type select 2018-02-07 10:57:23 +03:00
5daf4fafc7 fix 2018-02-06 23:36:40 +03:00
db59377cb2 Merge remote-tracking branch 'origin/editor' 2018-02-06 23:20:20 +03:00
1f6e4fbc3d [common] update level config, spawns points 2018-02-06 17:41:49 +03:00
db5b805276 [editor] ui update 2018-02-06 10:54:48 +03:00
38538b9147 fix 2018-02-05 22:47:46 +03:00
15d830a0d4 [game] added dota maps 2018-02-05 22:24:00 +03:00
feb5bafe72 [editor] update 2018-02-05 20:46:11 +03:00
b36fd77d74 [editor] added save button 2018-02-05 17:54:16 +03:00
421f925a60 [editor] added editor module 2018-02-04 23:32:00 +03:00
ad4744cfef [common] change game team players from array to map 2018-02-04 22:33:50 +03:00
1c9ccf0fb8 [common] humans in DotaGame 2018-02-04 21:02:08 +03:00
e0ceff68f9 update worklist 2018-02-04 14:11:43 +03:00
59cab68e3e [common] tanks spawn types 2018-02-02 20:53:26 +03:00
f9cb985059 [engine] update collision detect 2018-02-02 17:30:50 +03:00
6f338584eb [render] added animates 2018-02-01 00:05:14 +03:00
f2f860fc9d Merge branch 'develop' 2018-01-31 23:04:38 +03:00
3e65a5ba5d [cap] use master branch in production 2018-01-17 09:16:17 +03:00
114 changed files with 2678 additions and 1251 deletions

77
WORK.md
View File

@@ -1,46 +1,73 @@
* build
* gulp 100%
* linux 100%
* deb-package 100%
* windows 0%
* exe-package 0% (inno setup)
* deploy
* capistrano 100%
* ui
* login frame
* select person frame (autoselect)
* game mode frame (single, start server, find server)
* game frame
* auth frame 0%
* select game frame 100% (classic 1/2 player, dota singe/coop/vs)
* select level frame 10%
* game frame 50%
* engine
* config 90%
* map 80%
* tanks 30%
* bullets 30%
* boxes 0%
* map changes 50%
* bonuses 0%
* eagle 0%
* config 100%
* map 100%
* tanks 100%
* bullets 100%
* boxes 100%
* map changes 100%
* bonuses 100%
* eagle 100%
* game
* classic
* state 0%
* bot 5%
* player: 50%
* state 50%
* bot 50%
* human 100%
* dota
* state 50%
* bot 10%
* human 100%
* bonus
* star 50%
* grenade 0%
* helm 0%
* clock 0%
* shovel 0%
* state
* score 0%
* human tank 0%
* save/load 0%
* export/import 0%
* render
* map 100%
* tanks 100%
* bullet 100%
* calc redraw 20%
* calc redraw 50%
* animations
* tank spawn
* bullet boom
* tank boom
* bonuses
* html5
* tank spawn 0%
* tank move 100%
* map water 100%
* bullet boom 90%
* tank boom 90%
* bonuses 100%
* html5 50%
* proto
...
* webapp
* angular app 0%
* google analytics 0%
* editor
* level
* open 100%
* edit 50%
* save 100%
* tank
* color 10%

35
build/editor.js Normal file
View File

@@ -0,0 +1,35 @@
const gulp = require('gulp');
const yargs = require('yargs');
const Haxe = require('../tasks/haxe');
const FlashPlayer = require('../tasks/flashplayer');
const version = require('./version');
const prepare = require('./prepare');
const debug = require('../tasks/debug');
const build = (platform) => function build() {
const argv = yargs.argv;
return gulp.src('.')
.pipe(new Haxe().openfl({
command: 'build',
platform: platform,
version: version,
values: {
build_editor: true
},
debug: argv.dev,
}))
.pipe(gulp.dest(`target/${platform}`));
};
const testFlash = function() {
const argv = yargs.argv;
return build('flash')()
.pipe(new FlashPlayer().run(argv.dev))
.pipe(debug());
};
exports['editor:flash'] = gulp.series(prepare(Haxe.ID), build('flash'));
exports['editor:flash:test'] = gulp.series(prepare(Haxe.ID, FlashPlayer.ID), testFlash);

View File

@@ -10,4 +10,4 @@ user = fetch(:user)
server host, ssh_options: { port: 22, user: user, forward_agent: true }
set :tmp_dir, "/home/#{user}/tmp"
set :branch, 'develop'
set :branch, 'master'

View File

@@ -29,6 +29,7 @@ const merge = (value) => {
exports.update = prepare.update;
merge('./build/prepare');
merge('./build/client');
merge('./build/editor');
merge('./build/server');

View File

@@ -1,6 +1,6 @@
{
"name": "tankz",
"version": "0.2.1",
"version": "0.6.2",
"private": true,
"devDependencies": {
"ansi-colors": "^1.0.1",
@@ -23,6 +23,7 @@
"plugin-error": "^0.1.2",
"progress": "^2.0.0",
"promise-streams": "^2.1.1",
"rmdir": "^1.2.0",
"tar": "^4.2.0",
"tmp-file": "^2.0.1",
"unzip-stream": "^0.2.1",
@@ -36,6 +37,7 @@
"protohx": "0.4.6",
"yaml": "1.3.0",
"haxework": "git@bitbucket.org:shmyga/haxework.git",
"orm": "2.1.0"
"orm": "2.1.0",
"yield": "1.1.2"
}
}

View File

@@ -12,6 +12,8 @@
<haxelib name="protohx" version="0.4.6"/>
<haxelib name="haxework" version="git"/>
<haxelib name="yaml" version="1.3.0"/>
<haxelib name="yield" version="1.1.2"/>
<window fps="30"/>
<window width="1024" height="768" unless="html5"/>
<haxeflag name="-D" value="swf-gpu"/>
<haxeflag name="-D" value="native-trace"/>
@@ -19,4 +21,9 @@
<haxeflag name="-dce" value="no"/>
<haxeflag name="-D" value="dom"/>
<!--<template path="src/client/webapp/index_template.html" rename="index.html"/>-->
<section if="build_editor">
<app main="ru.m.tankz.editor.Editor" path="target" file="editor"/>
<source path="src/editor/haxe"/>
</section>
</project>

View File

@@ -1,13 +0,0 @@
{
"pWidth": 100, "pHeight": 100,
"views": [
{
"id": "state", "@type": "haxework.gui.LabelView", "@style": "label",
"pWidth": 100, "height": 20
},
{
"id": "render", "@type": "ru.m.tankz.render.Render",
"contentSize": true
}
]
}

View File

@@ -1,21 +0,0 @@
{
"pWidth": 100, "pHeight": 100,
"views": [
{
"id":"levels", "@type":"haxework.gui.list.VListView<Int>",
"factory": "@class:ru.m.tankz.view.frames.list.LevelView",
"pWidth":100,
"pHeight":100,
"paddings":10,
"scroll":{
"@type":"haxework.gui.list.VScrollView",
"width":10, "pHeight":100,
"skin":{"@type":"haxework.gui.list.VScrollSkin"}
},
"skin": {
"@type": "haxework.gui.skin.ColorSkin",
"color": "0x000000", "alpha": 0.0
}
}
]
}

View File

@@ -1,28 +0,0 @@
{
"pWidth": 100, "pHeight": 100,
"views": [
{
"@type": "haxework.gui.ImageView",
"image": "@asset:image:resources/images/logo/logo.png",
"contentSize": true, "bottomMargin": 15
},
{
"id": "start_1p",
"@type": "haxework.gui.ButtonView",
"text": "1 Player",
"@style": "button"
},
{
"id": "start_2p",
"@type": "haxework.gui.ButtonView",
"text": "2 Player",
"@style": "button"
},
{
"id": "dota",
"@type": "haxework.gui.ButtonView",
"text": "DotA",
"@style": "button"
}
]
}

View File

@@ -1,38 +0,0 @@
{
"@type": "haxework.gui.VGroupView",
"pWidth": 100, "pHeight": 100,
"views": [
{
"id": "switcher", "@type": "haxework.gui.frame.FrameSwitcher",
"pWidth": 100, "pHeight": 100,
"skin": {
"@type": "haxework.gui.skin.BitmapSkin",
"image": "@asset:image:resources/images/background.png",
"fillType": "REPEAT"
},
"views": [
{
"id": "start",
"@type": "ru.m.tankz.view.frames.StartFrame"
},
{
"id": "level",
"@type": "ru.m.tankz.view.frames.LevelFrame"
},
{
"id": "game",
"@type": "ru.m.tankz.view.frames.GameFrame"
}
]
},
{
"@type": "haxework.gui.LabelView",
"inLayout": false,
"contentSize": true,
"vAlign": "BOTTOM",
"hAlign": "RIGHT",
"text": "@res:text:version",
"@style": "label"
}
]
}

View File

@@ -1,18 +0,0 @@
{
"level": {
"width": 440, "height": 44,
"margins": 5,
"views": [
{
"id": "label",
"@type": "haxework.gui.LabelView",
"pWidth": 100, "pHeight": 100, "text": "",
"@style": "label"
}
],
"skin": {
"@type": "haxework.gui.skin.ColorSkin",
"color": "0x000000", "alpha": 0.2
}
}
}

View File

@@ -1,33 +0,0 @@
{
"button": {
"width":250, "height":60,
"skin": {
"@type": "haxework.gui.skin.ButtonBitmapSkin",
"upImage": "@asset:image:resources/images/control/button_normal.png",
"downImage": "@asset:image:resources/images/control/button_down.png",
"overImage": "@asset:image:resources/images/control/button_over.png",
"fillType": "NINEPATH"
},
"fontFamily":"@res:text:font", "fontEmbed":true, "fontColor":"0xE7E0BB", "fontSize":20
},
"label": {
"fontColor": "0xffffff",
"fontEmbed": false,
"fontFamily": "@res:text:fontName",
"fontSize": 16,
"shadowColor": "0x000000"
},
"input": {
"fontColor": "0xffffff",
"fontEmbed": false,
"fontFamily": "@res:text:fontName",
"fontSize": 16,
"shadowColor": "0x000000",
"skin": {
"@type": "haxework.gui.skin.ColorSkin",
"color": "0x000000"
}
}
}

View File

@@ -0,0 +1,71 @@
package ru.m.animate;
import flash.display.PixelSnapping;
import haxe.Timer;
import flash.display.Bitmap;
import flash.display.BitmapData;
class Animate extends Bitmap {
private static var timer:Timer;
private static var instances:Array<Animate> = [];
private static function init():Void {
if (timer == null) {
timer = new Timer(30);
timer.run = updateAll;
}
}
private static function updateAll():Void {
for (instance in instances) {
if (instance.playing) {
instance.update();
}
}
}
public var playing(default, set):Bool;
public var frames(default, set):Array<BitmapData>;
private var index:Int;
public function new(?frames:Array<BitmapData>) {
super(null, PixelSnapping.AUTO, true);
this.frames = frames == null ? [] : frames;
init();
instances.push(this);
}
public function set_frames(value:Array<BitmapData>):Array<BitmapData> {
if (value != null) {
frames = value;
bitmapData = frames[0];
index = 0;
}
return frames;
}
public function set_playing(value:Bool):Bool {
if (playing != value) {
playing = value;
}
return playing;
}
private function update():Void {
if (++index >= frames.length) {
index = 0;
}
var nextBitmapData = frames[index];
x -= (nextBitmapData.width - bitmapData.width) / 2;
y -= (nextBitmapData.height - bitmapData.height) / 2;
bitmapData = nextBitmapData;
}
public function dispose():Void {
if (instances.indexOf(this) > -1) {
instances.remove(this);
}
}
}

View File

@@ -0,0 +1,31 @@
package ru.m.animate;
import promhx.Deferred;
import flash.display.BitmapData;
import promhx.Promise;
class OnceAnimate extends Animate {
private var deferred:Deferred<Animate>;
public function new(frames:Array<BitmapData>) {
super(frames);
}
public function play():Promise<Animate> {
deferred = new Deferred();
playing = true;
return deferred.promise();
}
override private function update():Void {
super.update();
if (index == 0) {
playing = false;
if (deferred != null) {
deferred.resolve(this);
}
}
}
}

View File

@@ -0,0 +1,17 @@
package ru.m.draw;
import flash.geom.ColorTransform;
import flash.geom.Rectangle;
import flash.display.BitmapData;
class BitmapUtil {
public static function colorize(data: BitmapData, color: Color):BitmapData {
if (color.zero) return data;
var result = data.clone();
var transform = new ColorTransform(color.red / 255, color.green / 255, color.blue / 255, 1, 0, 0, 0, 0);
result.colorTransform(new Rectangle(0, 0, result.width, result.height), transform);
return result;
}
}

View File

@@ -0,0 +1,47 @@
package ru.m.draw;
abstract Color(Int) {
public var alpha(get, never):Int;
public var red(get, never):Int;
public var green(get, never):Int;
public var blue(get, never):Int;
public var zero(get, never):Bool;
public inline function new(value:Int) {
this = value;
}
private inline function get_alpha():Int {
return (this >> 24) & 255;
}
private inline function get_red():Int {
return (this >> 16) & 255;
}
private inline function get_green():Int {
return (this >> 8) & 255;
}
private inline function get_blue():Int {
return this & 255;
}
private inline function get_zero():Bool {
return this == 0;
}
@:from
static public inline function fromInt(value:Int):Color {
return new Color(value);
}
@:from
static public inline function fromString(value:String):Color {
return new Color(Std.parseInt('0x${value.split('#').pop()}'));
}
public function toString():String {
return 'Color(${red},${green},${blue})';
}
}

View File

@@ -1,34 +1,37 @@
package ru.m.tankz;
import flash.events.KeyboardEvent;
import flash.text.Font;
import flash.ui.Keyboard;
import haxework.gui.ButtonView;
import haxework.gui.frame.IFrameSwitcher;
import haxework.gui.Root;
import haxework.gui.VGroupView;
import haxework.gui.ViewBuilder;
import haxework.log.TraceLogger;
import haxework.provider.Provider;
import haxework.resources.IResources;
import haxework.resources.Resources;
import ru.m.connect.IConnection;
import ru.m.tankz.frame.StartFrame;
import ru.m.tankz.game.ClassicGame;
import ru.m.tankz.game.DotaGame;
import ru.m.tankz.game.Game;
import flash.ui.Keyboard;
import flash.events.KeyboardEvent;
import flash.text.Font;
import ru.m.tankz.view.frames.StartFrame;
import haxework.log.SocketLogger;
import haxework.resources.Resources;
import haxework.resources.IResources;
import haxework.gui.VGroupView;
import haxework.gui.ViewBuilder;
import haxework.gui.ButtonView;
import ru.m.tankz.PacketBuilder;
import haxework.log.JSLogger;
import haxework.gui.frame.IFrameSwitcher;
import haxework.provider.Provider;
import haxework.gui.frame.FrameSwitcher;
import haxework.gui.Root;
import openfl.Assets;
import ru.m.connect.IConnection;
import haxework.log.TraceLogger;
#if flash import haxework.log.JSLogger; #end
#if debug import haxework.log.SocketLogger; #end
@:template("layout/main.json", "layout/styles.json")
class MainView extends VGroupView implements ViewBuilder {}
interface ClientViewLayout {
var switcher(default, null):IFrameSwitcher;
}
@:template('ru/m/tankz/Client.yaml', 'ru/m/tankz/Style.yaml')
class ClientView extends VGroupView implements ClientViewLayout implements ViewBuilder {}
class Client implements IConnectionHandler {
private static inline var TAG = "Tankz";
private static inline var TAG = 'Tankz';
public static function main() {
L.push(new TraceLogger());
@@ -39,31 +42,31 @@ class Client implements IConnectionHandler {
L.push(new SocketLogger());
#end
Const.init();
L.d(TAG, "Debug: " + Const.DEBUG);
L.i(TAG, "Version: " + Const.VERSION);
L.i(TAG, "Build: " + Const.BUILD);
L.d(TAG, 'Debug: ${Const.DEBUG}');
L.i(TAG, 'Version: ${Const.VERSION}');
L.i(TAG, 'Build: ${Const.BUILD}');
new Client();
}
private var view:MainView;
private var view:ClientView;
public function new() {
Provider.setFactory(IResources, Resources);
var font:Font = Font.enumerateFonts()[0];
Provider.get(IResources).text.put("font", "Bookman Old Style");
Provider.get(IResources).text.put("version", 'v${Const.VERSION} b${Const.BUILD}');
Provider.get(IResources).text.put('font', 'Bookman Old Style');
Provider.get(IResources).text.put('version', 'v${Const.VERSION} b${Const.BUILD}');
Provider.set(IPacketBuilder, new PacketBuilder());
#if flash
Provider.set(IConnection, new ru.m.connect.flash.FlashConnection("localhost", 5001));
Provider.set(IConnection, new ru.m.connect.flash.FlashConnection('localhost', 5001));
#elseif html5
Provider.set(IConnection, new ru.m.connect.js.JsConnection("localhost", 5001));
Provider.set(IConnection, new ru.m.connect.js.JsConnection('localhost', 5001));
#end
//Provider.get(IConnection).handler.addListener(this);
view = new MainView();
view = new ClientView();
Provider.set(IFrameSwitcher, view.switcher);
Root.bind(view);
view.content.stage.stageFocusRect = false;
@@ -82,7 +85,7 @@ class Client implements IConnectionHandler {
public function onPress(view:ButtonView):Void {
switch (view.id) {
case "logout":
case 'logout':
Provider.get(IConnection).disconnect();
}
}
@@ -94,7 +97,7 @@ class Client implements IConnectionHandler {
}
public function onError(error:Dynamic):Void {
L.e(TAG, "", error);
L.e(TAG, '', error);
//view.switcher.change(AuthFrame.ID);
}
}

View File

@@ -0,0 +1,27 @@
---
$type: haxework.gui.VGroupView
pWidth: 100
pHeight: 100
views:
- id: switcher
$type: haxework.gui.frame.FrameSwitcher
pWidth: 100
pHeight: 100
skin:
$type: haxework.gui.skin.BitmapSkin
image: "@asset:image:resources/images/background.png"
fillType: REPEAT
views:
- id: start
$type: ru.m.tankz.frame.StartFrame
- id: level
$type: ru.m.tankz.frame.LevelFrame
- id: game
$type: ru.m.tankz.frame.GameFrame
- $type: haxework.gui.LabelView
$style: label
inLayout: false
contentSize: true
vAlign: BOTTOM
hAlign: RIGHT
text: "@res:text:version"

View File

@@ -0,0 +1,21 @@
---
button:
width: 250
height: 60
skin:
$type: haxework.gui.skin.ButtonBitmapSkin
upImage: "@asset:image:resources/images/control/button_normal.png"
downImage: "@asset:image:resources/images/control/button_down.png"
overImage: "@asset:image:resources/images/control/button_over.png"
fillType: NINEPATH
fontFamily: "@res:text:font"
fontEmbed: true
fontColor: "#E7E0BB"
fontSize: 20
label:
fontColor: "#ffffff"
fontEmbed: false
fontFamily: Courirer New
fontSize: 16
shadowColor: 0x000000

View File

@@ -1,27 +1,26 @@
package ru.m.tankz.control;
import ru.m.tankz.control.Control;
import haxe.Timer;
import ru.m.geom.Direction;
import flash.events.FocusEvent;
import flash.ui.Keyboard;
import flash.events.KeyboardEvent;
import flash.Lib;
import flash.ui.Keyboard;
import haxe.Timer;
import ru.m.geom.Direction;
import ru.m.tankz.control.Control;
import ru.m.tankz.Type;
typedef KeyBinding = Map<Int, TankAction>;
class HumanControl extends Control {
public static var TYPE(default, never):ControlType = 'human';
private var keyBinding:KeyBinding;
private var moveQueue:Array<Int>;
private var shotTimer:Timer;
public function new(index:Int) {
super({type:TYPE, index:index});
this.keyBinding = resolve(index);
public function new(playerId:PlayerId, controlIndex:Int) {
super(playerId);
this.keyBinding = resolve(controlIndex);
moveQueue = new Array<Int>();
Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
Lib.current.stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
@@ -44,7 +43,7 @@ class HumanControl extends Control {
case _:
}
if (event.keyCode == Keyboard.U) {
action(TankAction.LEVEL_UP(1));
action(TankAction.UPGRADE);
}
}
@@ -83,8 +82,8 @@ class HumanControl extends Control {
action(TankAction.SHOT);
}
private static function resolve(index:Int):KeyBinding {
switch (index) {
private static function resolve(controlIndex:Int):KeyBinding {
switch (controlIndex) {
case 0:
return [
Keyboard.A => TankAction.MOVE(Direction.LEFT),
@@ -101,8 +100,8 @@ class HumanControl extends Control {
Keyboard.RIGHT => TankAction.MOVE(Direction.RIGHT),
Keyboard.NUMPAD_0 => TankAction.SHOT
];
case _:
throw 'Invalid control index ${index}';
case x:
throw 'Invalid control index ${x}';
}
}
}

View File

@@ -1,8 +1,7 @@
package ru.m.tankz.view.frames;
package ru.m.tankz.frame;
import haxe.ds.Option;
import haxe.ds.Option;
import flash.events.Event;
import haxe.ds.Option;
import haxe.Timer;
import haxework.gui.frame.IFrameSwitcher;
import haxework.gui.LabelView;
@@ -22,8 +21,7 @@ interface GameFrameLayout {
var render(default, null):Render;
}
@:template("layout/frames/game.json", "layout/styles.json")
@:template("ru/m/tankz/frame/GameFrame.yaml", "ru/m/tankz/Style.yaml")
class GameFrame extends VGroupView implements ViewBuilder implements IPacketHandler implements GameFrameLayout {
private static inline var TAG = "GameFrame";
@@ -51,7 +49,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand
render.draw(game.engine);
timer = new Timer(10);
timer.run = updateEngine;
state.text = stateString(s);
state.text = stateString(game);
}
private function stop():Void {
@@ -68,20 +66,18 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand
render.reset();
}
private function stateString(state:GameState):String {
private function stateString(game:Game):String {
var result:Array<String> = [];
result.push('Level: ${state.level}');
for (teamId in state.teams.keys()) {
var ts:TeamState = state.teams[teamId];
if (ts.lose) {
result.push('${teamId}: LOSE');
} else if (ts.life > -1) {
result.push('${teamId}: ${ts.life}');
result.push('Level: ${game.state.level}');
for (team in game.teams) {
if (game.state.loser == team.id) {
result.push('${team.id}: LOSE');
} else if (team.life > -1) {
result.push('${team.id}: ${team.life}');
} else {
for (index in ts.players.keys()) {
var ps:PlayerState = ts.players[index];
if (ps.life > -1) {
result.push('${teamId}${index}: ${ps.life}');
for (player in team.players) {
if (player.life > -1) {
result.push('${player.id.team}${player.id.index}: ${player.life}');
}
}
}
@@ -90,14 +86,14 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand
}
private function onGameStateChange(s:GameState):GameState {
state.text = stateString(s);
state.text = stateString(game);
return s;
}
private function onGameComplete(result:Option<GameState>):Void {
switch (result) {
case Option.Some(s):
state.text = stateString(s);
state.text = stateString(game);
case Option.None:
}
switch (game.next()) {

View File

@@ -0,0 +1,12 @@
---
pWidth: 100
pHeight: 100
views:
- id: state
$type: haxework.gui.LabelView
$style: label
pWidth: 100
height: 20
- id: render
$type: ru.m.tankz.render.Render
contentSize: true

View File

@@ -1,4 +1,4 @@
package ru.m.tankz.view.frames;
package ru.m.tankz.frame;
import ru.m.tankz.config.ConfigBundle;
import haxework.gui.frame.IFrameSwitcher;
@@ -14,8 +14,8 @@ interface LevelFrameLayout {
}
@:template("layout/frames/level.json", "layout/styles.json")
class LevelFrame extends VGroupView implements ViewBuilder implements LevelFrameLayout implements ListViewListener<Int> {
@:template("ru/m/tankz/frame/LevelFrame.yaml", "ru/m/tankz/Style.yaml")
class LevelFrame extends VGroupView implements ViewBuilder implements LevelFrameLayout {
public static inline var ID = "level";
public function init():Void {
@@ -24,7 +24,7 @@ class LevelFrame extends VGroupView implements ViewBuilder implements LevelFrame
public function onShow():Void {
var state = Provider.get(GameState);
var c = ConfigBundle.get(state.type).levels;
var c = ConfigBundle.get(state.type).game.levels;
levels.data = [for (i in 0...c) i];
}

View File

@@ -0,0 +1,20 @@
---
pWidth: 100
pHeight: 100
views:
- id: levels
$type: haxework.gui.list.VListView<Int>
factory: "@class:ru.m.tankz.frame.level.LevelView"
pWidth: 100
pHeight: 100
paddings: 10
scroll:
$type: haxework.gui.list.VScrollView
width: 10
pHeight: 100
skin:
$type: haxework.gui.list.VScrollSkin
skin:
$type: haxework.gui.skin.ColorSkin
color: "#000000"
alpha: 0

View File

@@ -0,0 +1,54 @@
package ru.m.tankz.frame;
import haxework.gui.ButtonView;
import haxework.gui.frame.IFrameSwitcher;
import haxework.gui.VGroupView;
import haxework.gui.ViewBuilder;
import haxework.provider.Provider;
import ru.m.tankz.game.ClassicGame;
import ru.m.tankz.game.DotaGame;
import ru.m.tankz.game.GameState;
import ru.m.tankz.Type;
interface StartFrameLayout {
var classic_1p(default, null):ButtonView;
var classic_2p(default, null):ButtonView;
var dota_1p(default, null):ButtonView;
var dota_2p_coop(default, null):ButtonView;
var dota_2p_vs(default, null):ButtonView;
}
@:template("ru/m/tankz/frame/StartFrame.yaml", "ru/m/tankz/Style.yaml")
class StartFrame extends VGroupView implements ViewBuilder implements StartFrameLayout {
public static inline var ID = "start";
public function init() {
classic_1p.onPress = this;
classic_2p.onPress = this;
dota_1p.onPress = this;
dota_2p_coop.onPress = this;
dota_2p_vs.onPress = this;
}
public function onPress(view:ButtonView):Void {
switch (view.id) {
case 'classic_1p':
startGame(ClassicGame.TYPE, ClassicGame.PLAYER1);
case 'classic_2p':
startGame(ClassicGame.TYPE, ClassicGame.PLAYER2);
case 'dota_1p':
startGame(DotaGame.TYPE, DotaGame.PLAYER1);
case 'dota_2p_coop':
startGame(DotaGame.TYPE, DotaGame.PLAYER2_COOP);
case 'dota_2p_vs':
startGame(DotaGame.TYPE, DotaGame.PLAYER2_VS);
}
}
private function startGame(type:GameType, presetId:PresetId):Void {
Provider.set(GameState, new GameState(type, presetId));
Provider.get(IFrameSwitcher).change(LevelFrame.ID);
}
}

View File

@@ -0,0 +1,40 @@
---
pWidth: 100
pHeight: 100
views:
- $type: haxework.gui.ImageView
image: "@asset:image:resources/images/logo/logo.png"
contentSize: true
bottomMargin: 15
- $type: haxework.gui.LabelView
$style: label
fontSize: 20
topMargin: 15
contentSize: true
text: Classic
- id: classic_1p
$type: haxework.gui.ButtonView
text: 1 Player
$style: button
- id: classic_2p
$type: haxework.gui.ButtonView
text: 2 Player
$style: button
- $type: haxework.gui.LabelView
$style: label
fontSize: 20
topMargin: 15
contentSize: true
text: DotA
- id: dota_1p
$type: haxework.gui.ButtonView
text: 1 Player
$style: button
- id: dota_2p_coop
$type: haxework.gui.ButtonView
text: 2 COOP
$style: button
- id: dota_2p_vs
$type: haxework.gui.ButtonView
text: 2 VS
$style: button

View File

@@ -1,4 +1,4 @@
package ru.m.tankz.view.frames.list;
package ru.m.tankz.frame.level;
import haxework.gui.ViewBuilder;
import haxework.gui.HGroupView;
@@ -10,7 +10,7 @@ interface LevelViewLayout {
var label(default, null):LabelView;
}
@:template("layout/other.json@level", "layout/styles.json")
@:template("ru/m/tankz/frame/level/LevelView.yaml", "ru/m/tankz/Style.yaml")
class LevelView extends HGroupView implements ViewBuilder implements IListItemView<Int> implements LevelViewLayout {
public var item_index(default, default):Int;

View File

@@ -0,0 +1,15 @@
---
width: 440
height: 44
margins: 5
views:
- id: label
$type: haxework.gui.LabelView
$style: label
pWidth: 100
pHeight: 100
text: ""
skin:
$type: haxework.gui.skin.ColorSkin
color: "#000000"
alpha: 0.2

View File

@@ -1,13 +1,12 @@
package ru.m.tankz.render;
import ru.m.geom.Point;
import openfl.Assets;
import ru.m.animate.OnceAnimate;
import flash.display.DisplayObjectContainer;
import ru.m.tankz.core.EntityType;
import flash.display.DisplayObject;
import Type.ValueType;
import ru.m.tankz.render.RenderItem;
import ru.m.tankz.engine.Engine;
import ru.m.tankz.core.Bullet;
import ru.m.tankz.core.Tank;
import flash.display.Sprite;
import flash.display.Graphics;
import haxework.gui.SpriteView;
@@ -19,20 +18,24 @@ class Render extends SpriteView implements EngineListener {
private var groundLayer:Sprite;
private var entryLayer:Sprite;
private var upLayer:Sprite;
private var upperLayer:Sprite;
private var background:Sprite;
private var items:Map<String, RenderItem<Dynamic>>;
private var items:Map<String, RenderItem<Dynamic, Dynamic>>;
public function new() {
super();
items = new Map();
backgroundLayer = new Sprite();
groundLayer = new Sprite();
entryLayer = new Sprite();
upLayer = new Sprite();
upperLayer = new Sprite();
contentAsSprite.addChild(backgroundLayer);
contentAsSprite.addChild(groundLayer);
contentAsSprite.addChild(entryLayer);
contentAsSprite.addChild(upLayer);
contentAsSprite.addChild(upperLayer);
reset();
}
@@ -51,13 +54,21 @@ class Render extends SpriteView implements EngineListener {
}
public function draw(game:Engine):Void {
for (brick in game.map.bricks) if (brick.config.type > 0) {
for (brick in game.map.bricks) if (brick.config.index > 0) {
if (!items.exists(brick.key)) {
items[brick.key] = new BrickItem(brick);
var item:RenderItem<Dynamic, Dynamic> = switch(brick.config.type) {
case 'ace' | 'bush': new BrickItem(brick);
case 'water': new BrickAnimateItem(brick);
case 'armor' | 'brick': new BrickBreakingItem(brick);
case x: null;
};
if (item != null) {
items[brick.key] = item;
if (brick.config.layer > 2) {
upLayer.addChild(items[brick.key].view);
upLayer.addChild(item.view);
} else {
groundLayer.addChild(items[brick.key].view);
groundLayer.addChild(item.view);
}
}
}
}
@@ -74,7 +85,10 @@ class Render extends SpriteView implements EngineListener {
}
public function reset():Void {
items = new Map<String, RenderItem<Dynamic>>();
for (item in items.iterator()) {
item.dispose();
}
items = new Map();
if (background != null) {
backgroundLayer.removeChild(background);
background = null;
@@ -91,6 +105,7 @@ class Render extends SpriteView implements EngineListener {
items.set(tank.key, item);
entryLayer.addChild(item.view);
item.update();
playTankSpawn(tank.rect.center);
case EntityType.BULLET(bullet):
var item = new BulletItem(bullet);
items.set(bullet.key, item);
@@ -101,32 +116,88 @@ class Render extends SpriteView implements EngineListener {
items.set(eagle.key, item);
entryLayer.addChild(item.view);
item.update();
case EntityType.BONUS(bonus):
var item = new BonusItem(bonus);
items.set(bonus.key, item);
entryLayer.addChild(item.view);
item.update();
case _:
}
}
public function onCollision(entity:EntityType, with:EntityType):Void {
switch [entity, with] {
case [EntityType.BULLET(_), EntityType.EAGLE(eagle)]:
playTankBoom(eagle.rect.center);
case _:
}
}
public function onDestroy(entity:EntityType):Void {
switch(entity) {
switch entity {
case EntityType.TANK(tank):
if (items.exists(tank.key)) {
entryLayer.removeChild(items.get(tank.key).view);
items.remove(tank.key);
playTankBoom(tank.rect.center);
}
case EntityType.BULLET(bullet):
if (items.exists(bullet.key)) {
entryLayer.removeChild(items.get(bullet.key).view);
items.remove(bullet.key);
playBulletBoom(bullet.rect.center.add(new Point(bullet.rect.width * bullet.rect.direction.x, bullet.rect.height * bullet.rect.direction.y)));
}
case EntityType.EAGLE(eagle):
if (items.exists(eagle.key)) {
cast(items.get(eagle.key), EagleItem).destoyed = true;
items.get(eagle.key).redraw();
case EntityType.BONUS(bonus):
if (items.exists(bonus.key)) {
entryLayer.removeChild(items.get(bonus.key).view);
items.remove(bonus.key);
}
case _:
}
}
private function playTankSpawn(point:Point):Void {
var arr = [
0, 1, 2, 3, 3, 4, 5, 5, 6
];
var frames = [for (i in arr) Assets.getBitmapData('resources/images/tank/appear/appear-${i}.png')];
var animate = new OnceAnimate(frames);
animate.x = point.x - animate.width / 2;
animate.y = point.y - animate.height / 2;
upperLayer.addChild(animate);
animate.play().then(function(animate) {
upperLayer.removeChild(animate);
animate.dispose();
});
}
private function playBulletBoom(point:Point):Void {
var arr = [
0, 1, 1, 0, 0, 1
];
var frames = [for (i in arr) Assets.getBitmapData('resources/images/bullet/boom/boom-${i}.png')];
var animate = new OnceAnimate(frames);
animate.x = point.x - animate.width / 2;
animate.y = point.y - animate.height / 2;
upperLayer.addChild(animate);
animate.play().then(function(animate) {
upperLayer.removeChild(animate);
animate.dispose();
});
}
private function playTankBoom(point:Point):Void {
var arr = [
0, 1, 2, 3, 4, 4, 4, 1, 4, 4, 7, 7, 8, 9, 9
];
var frames = [for (i in arr) Assets.getBitmapData('resources/images/tank/kaboom/kaboom-${i}.png')];
var animate = new OnceAnimate(frames);
animate.x = point.x - animate.width / 2;
animate.y = point.y - animate.height / 2;
upperLayer.addChild(animate);
animate.play().then(function(animate) {
upperLayer.removeChild(animate);
animate.dispose();
});
}
}

View File

@@ -1,39 +1,39 @@
package ru.m.tankz.render;
import ru.m.tankz.core.Eagle;
import ru.m.tankz.Type.BrickType;
import openfl.display.BitmapData;
import ru.m.draw.Color;
import ru.m.tankz.core.Bonus;
import flash.display.Bitmap;
import flash.display.DisplayObject;
import flash.display.Shape;
import flash.display.Sprite;
import openfl.Assets;
import ru.m.animate.Animate;
import ru.m.draw.BitmapUtil;
import ru.m.geom.Direction;
import ru.m.geom.Rectangle;
import ru.m.tankz.core.Bullet;
import ru.m.tankz.map.Brick;
import openfl.Assets;
import ru.m.tankz.core.Eagle;
import ru.m.tankz.core.Tank;
import flash.display.Bitmap;
import ru.m.tankz.map.Brick;
typedef TRectangle = {
var rect(default, null):Rectangle;
}
class RenderItem<T:TRectangle> {
class RenderItem<T:TRectangle, D:DisplayObject> {
public var value(default, null):T;
public var view(default, null):DisplayObject;
private var bitmap:Bitmap;
public var view(default, null):D;
public function new(value:T) {
this.value = value;
this.bitmap = new Bitmap();
this.view = bitmap;
redraw();
this.view = null;
}
public function redraw():Void {
bitmap.bitmapData = Assets.getBitmapData(getImage());
}
public function redraw():Void {}
public function update():Void {
var rect = value.rect;
@@ -42,10 +42,6 @@ class RenderItem<T:TRectangle> {
view.y = rect.y - rect.height * (rect.direction.x + 1) / 2 - rect.height * (rect.direction.y + 1) / 2 + 1.5 * rect.height;
}
private function getImage():String {
return 'ERROR';
}
private static function calcRotate(direction:Direction):Float {
return (if (direction == Direction.RIGHT) {
0;
@@ -59,25 +55,87 @@ class RenderItem<T:TRectangle> {
0;
});
}
public function dispose():Void {}
}
class BrickItem extends RenderItem<Brick> {
class BitmapItem<T:TRectangle> extends RenderItem<T, Bitmap> {
private var shape:Shape;
private var broken:Int;
public function new(value:T) {
super(value);
this.view = new Bitmap();
redraw();
}
override public function redraw():Void {
view.bitmapData = Assets.getBitmapData(getImage());
}
private function getImage():String {
return 'ERROR';
}
}
class BrickItem extends BitmapItem<Brick> {
private var type:BrickType;
public function new(value:Brick) {
this.shape = new Shape();
super(value);
this.view = shape;
redraw();
}
override public function update():Void {
super.update();
var t = value.config.type;
if (t != type) {
type = t;
view.visible = t != 'none';
redraw();
}
}
override private function getImage():String {
return 'resources/image/map/${value.config.type}.png';
}
}
class BrickAnimateItem extends AnimateItem<Brick> {
public function new(value:Brick) {
super(value);
redraw();
}
override public function redraw():Void {
var frame0 = Assets.getBitmapData('resources/image/map/${value.config.type}-0.png');
var frame1 = Assets.getBitmapData('resources/image/map/${value.config.type}-1.png');
view.frames = [for (i in 0...15) frame0].concat([for (i in 0...15) frame1]);
view.playing = true;
}
}
class BrickBreakingItem extends RenderItem<Brick, Shape> {
private var broken:Int;
private var type:BrickType;
public function new(value:Brick) {
super(value);
this.view = new Shape();
redraw();
}
override public function redraw():Void {
var image = Assets.getBitmapData(getImage());
var g = shape.graphics;
var g = view.graphics;
g.clear();
if (value.destroyed) return;
if (value.config.index > 0) {
g.beginBitmapFill(image);
g.drawRect(0, 0, value.rect.width, value.rect.height);
for (c in value.cells) {
@@ -88,55 +146,112 @@ class BrickItem extends RenderItem<Brick> {
}
g.endFill();
}
}
override public function update():Void {
super.update();
var b = value.broken;
if (b != this.broken) {
this.broken = b;
var t = value.config.type;
if (b != broken || t != type) {
broken = b;
type = t;
redraw();
}
}
override private function getImage():String {
return 'resources/images/map/map_${value.config.type}.png';
private function getImage():String {
return 'resources/image/map/${value.config.type}.png';
}
}
class AnimateItem<T:TRectangle> extends RenderItem<T, Animate> {
class TankItem extends RenderItem<Tank> {
public function new(value:T) {
super(value);
view = new Animate();
}
override public function dispose():Void {
view.dispose();
}
}
class TankItem extends RenderItem<Tank, Sprite> {
private var type:String;
private var hits:Int;
private var protected:Bool;
private var frozen:Bool;
override private function getImage():String {
var group = value.config.group;
var index = value.playerId.index;
if (group == 'human') group = 'player';
if (group == 'radiant') {
group = 'player';
index = 0;
private var tankView:Animate;
private var protectView:Animate;
public function new(value:Tank) {
super(value);
view = new Sprite();
tankView = new Animate();
view.addChild(tankView);
protectView = new Animate(
[for (i in 0...5) Assets.getBitmapData('resources/images/tank/protect/protect-0.png')].concat(
[for (i in 0...5) Assets.getBitmapData('resources/images/tank/protect/protect-1.png')])
);
protectView.visible = false;
view.addChild(protectView);
redraw();
}
if (group == 'dire') {
group = 'player';
index = 1;
override public function redraw():Void {
var colors:Array<Color> = [value.color, value.bonus ? 0xff00aa : value.color];
var frames = [for (frame in getFrames()) BitmapUtil.colorize(Assets.getBitmapData(frame), colors.shift())];
tankView.frames = [
frames[0], frames[0], frames[0],
frames[1], frames[1], frames[1],
];
if (value.protect.active) {
protectView.x = (tankView.frames[0].width - protectView.frames[0].width) / 2;
protectView.y = (tankView.frames[0].height - protectView.frames[0].height) / 2;
protectView.playing = true;
protectView.visible = true;
} else {
protectView.playing = false;
protectView.visible = false;
}
if (group == 'bot') index = 0;
return 'resources/images/tank/${group}/tank_${group.charAt(0)}${value.config.type}_${index}-0.png';
}
private function getFrames():Array<String> {
var frame0 = 'resources/image/tank/${value.config.skin}-0.png';
var frame1 = 'resources/image/tank/${value.config.skin}-1.png';
return [frame1, frame0];
}
override public function update():Void {
super.update();
var t = value.config.type;
if (t != this.type) {
var h = value.hits;
var p = value.protect.active;
var f = value.freezing.active;
if (t != type || h != hits || p != protected || f != frozen) {
this.type = t;
this.hits = h;
this.protected = p;
this.frozen = f;
redraw();
}
tankView.playing = !value.freezing.active && (value.mx !=0 || value.my != 0);
}
override public function dispose():Void {
if (tankView != null) {
tankView.dispose();
tankView = null;
}
}
}
class BulletItem extends RenderItem<Bullet> {
class BulletItem extends BitmapItem<Bullet> {
override private function getImage():String {
return 'resources/images/bullet/bullet_${value.config.piercing > 1 ? 1 : 0}.png';
@@ -144,11 +259,36 @@ class BulletItem extends RenderItem<Bullet> {
}
class EagleItem extends RenderItem<Eagle> {
class EagleItem extends BitmapItem<Eagle> {
public var destoyed(default, default):Bool;
private var death:Bool;
override public function update():Void {
super.update();
var d = value.death;
if (d != death) {
death = d;
redraw();
}
}
override private function getImage():String {
return 'resources/images/eagle/eagle-${destoyed ? 1 : 0}.png';
return 'resources/image/eagle/eagle${value.death ? '-death' : ''}.png';
}
}
class BonusItem extends AnimateItem<Bonus> {
public function new(value:Bonus) {
super(value);
redraw();
}
override public function redraw():Void {
var image = Assets.getBitmapData('resources/image/bonus/${value.bonusType}.png');
var empty = new BitmapData(image.width, image.height, true, 0x00000000);
view.frames = [for (i in 0...15) image].concat([for (i in 0...15) empty]);
view.playing = true;
}
}

View File

@@ -1,53 +0,0 @@
package ru.m.tankz.view.frames;
import ru.m.tankz.game.Game;
import ru.m.tankz.game.GameState;
import ru.m.tankz.game.ClassicGame;
import ru.m.tankz.game.DotaGame;
import haxework.gui.frame.IFrameSwitcher;
import haxework.provider.Provider;
import haxework.gui.ButtonView;
import haxework.gui.ViewBuilder;
import haxework.gui.VGroupView;
interface StartFrameLayout {
var start_1p(default, null):ButtonView;
var start_2p(default, null):ButtonView;
var dota(default, null):ButtonView;
}
@:template("layout/frames/start.json", "layout/styles.json")
class StartFrame extends VGroupView implements ViewBuilder implements StartFrameLayout {
public static inline var ID = "start";
public function init() {
start_1p.onPress = this;
start_2p.onPress = this;
dota.onPress = this;
}
public function onPress(view:ButtonView):Void {
switch (view.id) {
case 'start_1p':
startGame(ClassicGame.TYPE, 1);
case 'start_2p':
startGame(ClassicGame.TYPE, 2);
case 'dota':
startGame(DotaGame.TYPE, 2);
}
}
private function startGame(type:GameType, humans:Int):Void {
switch (type) {
case ClassicGame.TYPE:
Provider.set(GameState, ClassicGame.buildState(0, humans));
Provider.get(IFrameSwitcher).change(LevelFrame.ID);
case DotaGame.TYPE:
Provider.set(GameState, DotaGame.buildState(0, humans));
Provider.get(IFrameSwitcher).change(GameFrame.ID);
}
}
}

View File

@@ -1,4 +1,6 @@
levels: 36
game:
levels: 36
friendlyFire: false
map:
cellWidth: 22
@@ -7,72 +9,70 @@ map:
gridHeight: 26
bricks:
# border
- type: -1
layer: 2
armor: -1
# none
- type: 0
layer: 0
armor: 0
# ace
- type: 1
layer: 0
armor: 0
# bush
- type: 2
layer: 3
armor: 0
# water
- type: 3
layer: 1
armor: 0
# armor
- type: 4
layer: 2
armor: 2
# brick
- type: 5
layer: 2
armor: 1
- {type: border, index: -1, layer: 2, armor: -1}
- {type: none, index: 0, layer: 0, armor: 0}
- {type: ace, index: 1, layer: 0, armor: 0}
- {type: bush, index: 2, layer: 3, armor: 0}
- {type: water, index: 3, layer: 1, armor: 0}
- {type: armor, index: 4, layer: 2, armor: 2}
- {type: brick, index: 5, layer: 2, armor: 1}
teams:
player:
human: &human
control: human
life: 3
tanks:
- {type: human0, rate: 1, protect: 5}
bot: &bot
control: bot
life: -1
tanks:
- {type: bot0, rate: 0.25, bonus: 0.25}
- {type: bot1, rate: 0.25, bonus: 0.25}
- {type: bot2, rate: 0.25, bonus: 0.25}
- {type: bot3, rate: 0.25, bonus: 0.25}
presets:
- id: player1
teams:
- id: human
spawnInterval: 0
points:
- type: eagle
index: -1
x: 12
y: 24
direction: right
- type: tank
index: 0
x: 8
y: 24
direction: top
- type: tank
index: 1
x: 16
y: 24
direction: top
life: -1
players:
- {<<: *human, index: 0, color: 0xF5C040, life: 3}
- id: bot
spawnInterval: 3000
points:
- type: tank
index: -1
x: 0
y: 0
direction: bottom
- type: tank
index: -1
x: 12
y: 0
direction: bottom
- type: tank
index: -1
x: 24
y: 0
direction: bottom
life: 20
players:
- {<<: *bot, index: 0}
- {<<: *bot, index: 1}
- {<<: *bot, index: 2}
- {<<: *bot, index: 3}
- id: player2
teams:
- id: human
life: -1
players:
- {<<: *human, index: 0, color: 0xF5C040, life: 3}
- {<<: *human, index: 1, color: 0x15C040, life: 3}
- id: bot
spawnInterval: 3000
life: 20
players:
- {<<: *bot, index: 0}
- {<<: *bot, index: 1}
- {<<: *bot, index: 2}
- {<<: *bot, index: 3}
- {<<: *bot, index: 4}
- {<<: *bot, index: 5}
points:
- {team: human, type: eagle, index: -1, direction: right, x: 12, y: 24}
- {team: human, type: tank, index: 0, direction: top, x: 8, y: 24}
- {team: human, type: tank, index: 1, direction: top, x: 16, y: 24}
- {team: bot, type: tank, index: -1, direction: bottom, x: 0, y: 0}
- {team: bot, type: tank, index: -2, direction: bottom, x: 12, y: 0}
- {team: bot, type: tank, index: -3, direction: bottom, x: 24, y: 0}
bullet: &bullet
width: 12
@@ -81,8 +81,8 @@ bullet: &bullet
piercing: 1
tanks:
human:
- type: 0
- type: human0
upgrade: human1
width: 36
height: 36
speed: 2.5
@@ -90,8 +90,10 @@ tanks:
<<: *bullet
speed: 8.0
bullets: 1
skin: pa
- type: 1
- type: human1
upgrade: human2
width: 40
height: 36
speed: 3.0
@@ -99,17 +101,21 @@ tanks:
<<: *bullet
speed: 8.5
bullets: 1
skin: pb
- type: 2
- type: human2
upgrade: human3
width: 40
height: 36
speed: 3.0
bullet:
<<: *bullet
speed: 9.0
bullets: 3
bullets: 2
skin: pc
- type: 3
- type: human3
upgrade: human3
width: 42
height: 38
speed: 2.9
@@ -118,9 +124,10 @@ tanks:
speed: 9.0
piercing: 3
bullets: 2
hits: 1
skin: pd
bot:
- type: 0
- type: bot0
width: 38
height: 36
speed: 2.0
@@ -129,8 +136,9 @@ tanks:
speed: 7.0
bullets: 1
score: 100
skin: ba
- type: 1
- type: bot1
width: 40
height: 36
speed: 4.0
@@ -139,8 +147,9 @@ tanks:
speed: 7.0
bullets: 1
score: 200
skin: bb
- type: 2
- type: bot2
width: 38
height: 36
speed: 2.0
@@ -149,8 +158,9 @@ tanks:
speed: 9.0
bullets: 1
score: 300
skin: bc
- type: 3
- type: bot3
width: 40
height: 36
speed: 1.8
@@ -159,4 +169,13 @@ tanks:
speed: 8.0
bullets: 1
score: 400
hits: 4
hits: 3
skin: bd
bonuses:
- {type: clock}
- {type: grenade}
- {type: helmet}
- {type: life}
- {type: shovel}
- {type: star}

View File

@@ -1,95 +0,0 @@
[keyboard]
reset = 27 ;Escape
pause = 80 ;P
[player0]
key_left = 37 ;Left
key_up = 38 ;Up
key_right = 39 ;Rigth
key_down = 40 ;Down
key_shot = 96 ;Num0
[player1]
key_left = 65 ;A
key_up = 87 ;W
key_right = 68 ;D
key_down = 83 ;S
key_shot = 32 ;Space
[bonus]
score = 500
freeztime = 10
eagletime = 20
protecttime = 15
[bots]
count = 20 ;количество ботов на уровне
respawntime = 2.5 ;задержка между появлением ботов в секундах
shotdelay = 1.0 ;задержка между выстрелами
turndelay = 0.3 ;задержка перед поворотом при столкновении
rndturndelay = 2.0 ;задержка перед случайным поворотом
turntoeagle = 0.75 ;вероятность поворота к Орлу
bonus = 0.25 ;вероятность появления бонусного танка
[tank_p0]
movespeed = 2.5 ;скорость передвижения
bulletspeed = 8.0 ;скорость полёта снаряда
bullettype = 0 ;тип снаряда (0 - обычный, 1 - бронебойный)
bulletcount = 1 ;количество снарядов
hits = 1 ;количество хитпойнтов
[tank_p1]
movespeed = 3.0
bulletspeed = 8.5
bullettype = 0
bulletcount = 1
hits = 1
[tank_p2]
movespeed = 3.0
bulletspeed = 9.0
bullettype = 0
bulletcount = 2
hits = 1
[tank_p3]
movespeed = 2.9
bulletspeed = 9.0
bullettype = 1
bulletcount = 2
hits = 2
[tank_b0]
movespeed = 2.0
bulletspeed = 7.0
bullettype = 0
bulletcount = 1
hits = 1
score = 100
[tank_b1]
movespeed = 4.0
bulletspeed = 7.0
bullettype = 0
bulletcount = 1
hits = 1
score = 200
[tank_b2]
movespeed = 2.0
bulletspeed = 9.0
bullettype = 0
bulletcount = 1
hits = 1
score = 300
[tank_b3]
movespeed = 1.8
bulletspeed = 8.0
bullettype = 0
bulletcount = 1
hits = 4
score = 400

View File

@@ -1,4 +1,6 @@
levels: 36
game:
levels: 8
friendlyFire: true
map:
cellWidth: 22
@@ -7,103 +9,104 @@ map:
gridHeight: 30
bricks:
# border
- type: -1
layer: 2
armor: -1
# none
- type: 0
layer: 0
armor: 0
# ace
- type: 1
layer: 0
armor: 0
# bush
- type: 2
layer: 3
armor: 0
# water
- type: 3
layer: 1
armor: 0
# armor
- type: 4
layer: 2
armor: 2
# brick
- type: 5
layer: 2
armor: 1
- {type: border, index: -1, layer: 2, armor: -1}
- {type: none, index: 0, layer: 0, armor: 0}
- {type: ace, index: 1, layer: 0, armor: 0}
- {type: bush, index: 2, layer: 3, armor: 0}
- {type: water, index: 3, layer: 1, armor: 0}
- {type: armor, index: 4, layer: 2, armor: 2}
- {type: brick, index: 5, layer: 2, armor: 1}
teams:
- id: radiant
spawnInterval: 0
points:
- type: eagle
index: -1
x: 0
y: 28
direction: right
- type: tank
index: 0
x: 0
y: 0
direction: top
- type: tank
index: 1
x: 6
y: 10
direction: top
- type: tank
index: 2
x: 6
y: 16
direction: top
- type: tank
index: 3
x: 6
y: 22
direction: top
- type: tank
index: 4
x: 10
y: 28
direction: top
- id: dire
spawnInterval: 0
points:
- type: eagle
index: -1
x: 38
y: 0
direction: right
- type: tank
index: 0
x: 38
y: 28
direction: bottom
- type: tank
index: 1
x: 32
y: 18
direction: bottom
- type: tank
index: 2
x: 32
y: 12
direction: bottom
- type: tank
index: 3
x: 32
y: 6
direction: bottom
- type: tank
index: 4
x: 28
y: 0
direction: bottom
team:
radiant: &radiant
id: radiant
color: 0xff4422
life: 20
dire: &dire
id: dire
color: 0x2244ff
life: 20
player: &player
life: -1
control: bot
tanks:
- {type: slow, rate: 0.5, protect: 3, bonus: 0}
- {type: fast, rate: 0.5, protect: 3, bonus: 0}
human1: &human1
<<: *player
control: human
color: 0xf055a0
human2: &human2
<<: *player
control: human
color: 0xa055f0
presets:
- id: player1
teams:
- <<: *radiant
players:
- {<<: *human1, index: 0}
- {<<: *player, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
- <<: *dire
players:
- {<<: *player, index: 0}
- {<<: *player, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
- id: player2_coop
teams:
- <<: *radiant
players:
- {<<: *human1, index: 0}
- {<<: *human1, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
- <<: *dire
players:
- {<<: *player, index: 0}
- {<<: *player, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
- id: player2_vs
teams:
- <<: *radiant
players:
- {<<: *human1, index: 0}
- {<<: *player, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
- <<: *dire
players:
- {<<: *human2, index: 0}
- {<<: *player, index: 1}
- {<<: *player, index: 2}
- {<<: *player, index: 3}
- {<<: *player, index: 4}
points:
- {team: radiant, type: eagle, index: -1, direction: right, x: 0, y: 28}
- {team: radiant, type: tank, index: 0, direction: right, x: 0, y: 0}
- {team: radiant, type: tank, index: 1, direction: right, x: 6, y: 10}
- {team: radiant, type: tank, index: 2, direction: right, x: 6, y: 16}
- {team: radiant, type: tank, index: 3, direction: right, x: 6, y: 22}
- {team: radiant, type: tank, index: 4, direction: right, x: 10, y: 28}
- {team: dire, type: eagle, index: -1, direction: right, x: 38, y: 0}
- {team: dire, type: tank, index: 0, direction: left, x: 38, y: 28}
- {team: dire, type: tank, index: 1, direction: left, x: 32, y: 18}
- {team: dire, type: tank, index: 2, direction: left, x: 32, y: 12}
- {team: dire, type: tank, index: 3, direction: left, x: 32, y: 6}
- {team: dire, type: tank, index: 4, direction: left, x: 28, y: 0}
bullet: &bullet
width: 12
@@ -112,23 +115,30 @@ bullet: &bullet
piercing: 1
tanks:
radiant: &tanks
- type: 0
width: 36
- type: slow
width: 38
height: 36
speed: 2.5
speed: 2.3
bullet:
<<: *bullet
speed: 12.0
bullets: 1
skin: bc
- type: fast
width: 40
height: 36
speed: 4.0
bullet:
<<: *bullet
speed: 8.0
bullets: 1
skin: bb
- type: 1
width: 40
height: 36
speed: 3.0
bullet:
<<: *bullet
speed: 8.5
bullets: 1
dire:
- <<: *tanks
bonuses:
- {type: clock}
- {type: grenade}
- {type: helmet}
- {type: life}
- {type: shovel}
- {type: star}

View File

@@ -1,30 +1,2 @@
0000000000000000000000000000000000005500
0000000000000000000000000000000000005500
0000000000000000000000000000000000005555
0000000000000000000000000000000000005555
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
5555000000000000000000000000000000000000
5555000000000000000000000000000000000000
0055000000000000000000000000000000000000
0055000000000000000000000000000000000000
points: [{index: -1, team: radiant, x: 0, direction: right, type: eagle, y: 28}, {index: 0, team: radiant, x: 0, direction: right, type: tank, y: 0}, {index: 1, team: radiant, x: 6, direction: right, type: tank, y: 10}, {index: 2, team: radiant, x: 6, direction: right, type: tank, y: 16}, {index: 3, team: radiant, x: 6, direction: right, type: tank, y: 22}, {index: 4, team: radiant, x: 10, direction: right, type: tank, y: 28}, {index: -1, team: dire, x: 38, direction: right, type: eagle, y: 0}, {index: 0, team: dire, x: 38, direction: left, type: tank, y: 28}, {index: 1, team: dire, x: 32, direction: left, type: tank, y: 18}, {index: 2, team: dire, x: 32, direction: left, type: tank, y: 12}, {index: 3, team: dire, x: 32, direction: left, type: tank, y: 6}, {index: 4, team: dire, x: 28, direction: left, type: tank, y: 0}]
data: "000044000000000000000000005500004400550000004400000000000000000000550000440055000000440000004400003333000055000044005555000044000000440000333300005500004400555500004422442244000000000000550000440000000000442244224400000000000055000044000000000000000000444444555544444400442200330000000000000044444455554444440044220033005555333333554422220000222244000022003300555533333355442222000022224400002200330000000000000044220000000022440000440033000000000000004422000000002244000044003300000000000000550000555500005500002200000000000000000055000055550000550000220000004444444400005500445555440055000044444444444444440000550044555544005500004444444400000022000055000055550000550000000000000000002200005500005555000055000000000000003300440000442200000000224400000000000000330044000044220000000022440000000000000033002200004422220000222244553333335555003300220000442222000022224455333333555500330022440044444455554444440000000000000033002244004444445555444444000000000000000000440000550000000000004422442244000000000044000055000000000000442244224400005555004400005500003333000044000000440000555500440000550000333300004400000044000000550044000055000000000000000000004400000055004400005500000000000000000000440000"

View File

@@ -0,0 +1,2 @@
points: [{index: -1, direction: right, team: radiant, type: eagle, y: 28, x: 0}, {index: 0, direction: right, team: radiant, type: tank, y: 2, x: 2}, {index: 1, direction: right, team: radiant, type: tank, y: 6, x: 2}, {index: 2, direction: right, team: radiant, type: tank, y: 10, x: 2}, {index: 3, direction: right, team: radiant, type: tank, y: 14, x: 2}, {index: 4, direction: right, team: radiant, type: tank, y: 18, x: 2}, {index: -1, direction: right, team: dire, type: eagle, y: 28, x: 38}, {index: 0, direction: left, team: dire, type: tank, y: 2, x: 36}, {index: 1, direction: left, team: dire, type: tank, y: 6, x: 36}, {index: 2, direction: left, team: dire, type: tank, y: 10, x: 36}, {index: 3, direction: left, team: dire, type: tank, y: 14, x: 36}, {index: 4, direction: left, team: dire, type: tank, y: 18, x: 36}]
data: "005500330033003300333300330033003300550000550033003300330033330033003300330055000000000000330033000000003300330000000000000000000033003300000000330033000000000000550033000000330000000033000000330055000055003300000033000000003300000033005500000000330000003300333300330000003300000000000033000000330033330033000000330000000055000000330033003333003300330000005500005500000033003300333300330033000000550000000033003300330033330033003300330000000000003300330033003333003300330033000000005500330000003300333300330000003300550000550033000000330033330033000000330055000000000000330033003333003300330000000000000000000033003300333300330033000000000000550033003300330033330033003300330055000055003300330033003333003300330033005500000000330033003300333300330033003300000000000033003300330033330033003300330000005555553300330033003333003300330033555555555555330033003300333300330033003355555555555533003300330033330033003300335555555555553300330033003333003300330033555555440000330033000000333300000033000000004444000033003300000033330000003300000000440000443300330000003333000000330033440000000044330033000000333300000033003344000000440033003300330033330033003300330044000044003300330033003333003300330033004400"

View File

@@ -0,0 +1,2 @@
data: "000000000000000000000000000000440000000000000000000000000000000000000044000000000044003300005500440000440055000000000000004400330000550044000044005500000000000000000000440000000000000000000055004400000000000044000000000000000000005500440000003300000000330044003300440000000000000000330000000033004400330044000000000000000000440055000000000000000000005500003300000044005500000000000000000000550000330000000000000055000044005500440000004400000000000000005500004400550044000000440000555500003300000000000000000000000000555555550000330000000000000000000000000055550055440000004400330000000000003300445500005544000000440033000000000000330044550055550000440000000044004400550000000055555555000044000000004400440055000000005555000000000000000000000000000044000044000000000000000000000000000000004400004400000044000044000044005500004400000000000000004400004400004400550000440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003300000000550000330055003300005500440000330000000055000033005500330000550044000000440033000000440000000000440000000000000044003300000044000000000044000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
points: [{direction: right, team: radiant, x: 0, type: eagle, y: 14, index: -1}, {direction: right, team: radiant, x: 0, type: tank, y: 0, index: 0}, {direction: right, team: radiant, x: 6, type: tank, y: 10, index: 1}, {direction: right, team: radiant, x: 6, type: tank, y: 16, index: 2}, {direction: right, team: radiant, x: 6, type: tank, y: 22, index: 3}, {direction: right, team: radiant, x: 10, type: tank, y: 28, index: 4}, {direction: right, team: dire, x: 38, type: eagle, y: 14, index: -1}, {direction: left, team: dire, x: 38, type: tank, y: 28, index: 0}, {direction: left, team: dire, x: 32, type: tank, y: 18, index: 1}, {direction: left, team: dire, x: 32, type: tank, y: 12, index: 2}, {direction: left, team: dire, x: 32, type: tank, y: 6, index: 3}, {direction: left, team: dire, x: 28, type: tank, y: 0, index: 4}]

View File

@@ -0,0 +1,2 @@
points: [{index: -1, direction: right, team: radiant, x: 24, type: eagle, y: 26}, {index: 0, direction: right, team: radiant, x: 14, type: tank, y: 26}, {index: 1, direction: right, team: radiant, x: 20, type: tank, y: 20}, {index: 2, direction: right, team: radiant, x: 26, type: tank, y: 20}, {index: 3, direction: right, team: radiant, x: 34, type: tank, y: 24}, {index: 4, direction: right, team: radiant, x: 38, type: tank, y: 22}, {index: -1, direction: right, team: dire, x: 22, type: eagle, y: 2}, {index: 0, direction: left, team: dire, x: 8, type: tank, y: 2}, {index: 1, direction: left, team: dire, x: 12, type: tank, y: 6}, {index: 2, direction: left, team: dire, x: 20, type: tank, y: 6}, {index: 3, direction: left, team: dire, x: 21, type: tank, y: 10}, {index: 4, direction: left, team: dire, x: 28, type: tank, y: 4}]
data: "444444444400000000440000004444000000000044444444440000000044000000444400000000004444440000004444004400000044440033444400444444000000444400440000004444003344440000000000440000440044000000000000000000000000000044000044004400000000000000000000003344004400000000000044004444440000444400334400440000000000004400444444000044440000000000004400444444440033440000005544000000000000440044444444003344000000554444004433440044444400000000004400440000004400443344004444440000000000440044000000440000000000004444004444440044004444440044000000000000444400444444004400444444000000440055440044440044440000000055444400000044005544004444004444000000005544440000444400444400000000000000443300000000000044440044440000000000000044330000000000000044004444003300444444004444004433004400004400444400330044444400444400443300444400000000000033000000000000000044000000440000000000003300000000000000004400000044440044004444444400444444440000440044004444004400444444440044444444000044004400000000000000440000000000000000000000440000000000000044000000000000000000000044004455003344000000440044000000440033444400445500334400000044004400000044003344440044440000000044000000440000004400000000004444000000004400000044000000440000000000"

View File

@@ -0,0 +1,2 @@
points: [{index: -1, direction: right, team: radiant, x: 12, type: eagle, y: 2}, {index: 0, direction: right, team: radiant, x: 6, type: tank, y: 6}, {index: 1, direction: right, team: radiant, x: 10, type: tank, y: 10}, {index: 2, direction: right, team: radiant, x: 14, type: tank, y: 10}, {index: 3, direction: right, team: radiant, x: 18, type: tank, y: 6}, {index: 4, direction: right, team: radiant, x: 20, type: tank, y: 2}, {index: -1, direction: right, team: dire, x: 22, type: eagle, y: 26}, {index: 0, direction: left, team: dire, x: 12, type: tank, y: 26}, {index: 1, direction: left, team: dire, x: 18, type: tank, y: 22}, {index: 2, direction: left, team: dire, x: 24, type: tank, y: 22}, {index: 3, direction: left, team: dire, x: 28, type: tank, y: 18}, {index: 4, direction: left, team: dire, x: 30, type: tank, y: 10}]
data: "000000000033333300000000000000000000000000000000003333330000000000000000000000000000004400330033004400000000003300000044000000440033003300440000000000330000004400000000003333330000000044440000000000000000000000333333000000004444000000000000000000000000000000003300000000004444000000000000000000000000330000000000444400000044000000004400000000004400000044000000004400000000440000000000440000004400000000000033000000000000004444000000000000000000003300000000000000444400000000000000000000000000330000440000000033000000000000000000000033000044000000003300000000000000000000000000444400004400000000000000000000000000000044440000440000000000000000000000334444004444000000000044000000000000000033444400444400000000004400000000004400000044000000000000330000440000000000440000004400000000000033000044000000000000440000000000330000440000000000000033000044000000000033000044000000000000003300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000003333330000000033000000000000004400000000333333000000003300000000000000000000440033003300440000000000000000000000000044003300330044000000000000000000000000000000333333000000000000000000000000000000000033333300000000000000"

View File

@@ -0,0 +1,2 @@
points: [{index: -1, direction: right, team: radiant, x: 19, type: eagle, y: 28}, {index: 0, direction: right, team: radiant, x: 0, type: tank, y: 28}, {index: 1, direction: right, team: radiant, x: 10, type: tank, y: 22}, {index: 2, direction: right, team: radiant, x: 19, type: tank, y: 18}, {index: 3, direction: right, team: radiant, x: 28, type: tank, y: 22}, {index: 4, direction: right, team: radiant, x: 38, type: tank, y: 28}, {index: -1, direction: right, team: dire, x: 19, type: eagle, y: 0}, {index: 0, direction: left, team: dire, x: 0, type: tank, y: 0}, {index: 1, direction: left, team: dire, x: 10, type: tank, y: 6}, {index: 2, direction: left, team: dire, x: 19, type: tank, y: 10}, {index: 3, direction: left, team: dire, x: 28, type: tank, y: 6}, {index: 4, direction: left, team: dire, x: 38, type: tank, y: 0}]
data: "000000000000440000000000004400000000000000000000000044000000000000440000000000004400000000000000000440000000000000000044440000000000000000044000000000000000004400000000005555555555555555555500000000000000000000555555555555555555550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000000000000000000440000000000000000440000000000000000000044000000005555555544333333333553333333334455555555555555554433333333355333333333445555555500000000440000000000000000000044000000000000000044000000000000000000004400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000055000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055555555555555555555000000000000000000005555555555555555555500000000004400000000000000000440000000000000000044440000000000000000044000000000000000004400000000000044000000000000440000000000000000000000004400000000000044000000000000"

View File

@@ -0,0 +1,2 @@
points: [{index: -1, direction: right, team: radiant, x: 19, type: eagle, y: 28}, {index: 0, direction: right, team: radiant, x: 2, type: tank, y: 22}, {index: 1, direction: right, team: radiant, x: 9, type: tank, y: 20}, {index: 2, direction: right, team: radiant, x: 19, type: tank, y: 24}, {index: 3, direction: right, team: radiant, x: 29, type: tank, y: 20}, {index: 4, direction: right, team: radiant, x: 36, type: tank, y: 22}, {index: -1, direction: right, team: dire, x: 19, type: eagle, y: 0}, {index: 0, direction: left, team: dire, x: 2, type: tank, y: 6}, {index: 1, direction: left, team: dire, x: 9, type: tank, y: 8}, {index: 2, direction: left, team: dire, x: 19, type: tank, y: 4}, {index: 3, direction: left, team: dire, x: 29, type: tank, y: 8}, {index: 4, direction: left, team: dire, x: 36, type: tank, y: 6}]
data: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005555555544444455555555000000000000000000555555554444445555555500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005500000000000000550000000000000000000000550000000000000055000000000000000000000055000000000000005500000000000000000000005500000000000000550000000000000000000000000044000000440000000000000000000000000000004400000044000000000000000333333333333333445500004433333333333333333333333333333344550000443333333333333333333333333333334400440044333333333333333333333333333333440044004433333333333333333333333333333344000055443333333333333333333333333333334400005544333333333333333000000000000000440000004400000000000000000000000000000044000000440000000000000000000000000055000000000000005500000000000000000000005500000000000000550000000000000000000000550000000000000055000000000000000000000055000000000000005500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005555555544444455555555000000000000000000555555554444445555555500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

View File

@@ -0,0 +1,2 @@
data: "444455555555555555555555555555555555444444445555555555555555555555555555555544440044004444444400444444440044444444004400004400444444440044444444004444444400440000220000000000000000000000000000000022000022000000000000000000000000000000002200004400444444442244444444224444444400440000440044444444224444444422444444440044000011000033550000000000000000553300001100001100003355000000000000000055330000110000110000444444004444444400444444440011000011000044444400444444440044444444001100004400000000000055333355000000000000440000440000000000005533335500000000000044000000442244444400443333440044444422440000000044224444440044333344004444442244000000440000000000005533335500000000000044000044000000000000553333550000000000004400001100444444440044444444004444444400110000110044444444004444444400444444440011000011000033550000000000000000553300001100001100003355000000000000000055330000110000440044444444224444444422444444440044000044004444444422444444442244444444004400002200000000000000000000000000000000220000220000000000000000000000000000000022000044004444444400444444440044444440004400004400444444440044444444004444444000440044445555555555555555555555555555555544444444555555555555555555555555555555554444"
points: [{team: radiant, direction: right, x: 2, type: eagle, y: 14, index: -1}, {team: radiant, direction: right, x: 14, type: tank, y: 2, index: 0}, {team: radiant, direction: right, x: 6, type: tank, y: 8, index: 1}, {team: radiant, direction: right, x: 14, type: tank, y: 14, index: 2}, {team: radiant, direction: right, x: 6, type: tank, y: 20, index: 3}, {team: radiant, direction: right, x: 14, type: tank, y: 26, index: 4}, {team: dire, direction: right, x: 36, type: eagle, y: 14, index: -1}, {team: dire, direction: left, x: 24, type: tank, y: 2, index: 0}, {team: dire, direction: left, x: 32, type: tank, y: 8, index: 1}, {team: dire, direction: left, x: 24, type: tank, y: 14, index: 2}, {team: dire, direction: left, x: 32, type: tank, y: 20, index: 3}, {team: dire, direction: left, x: 24, type: tank, y: 26, index: 4}]

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

View File

Before

Width:  |  Height:  |  Size: 374 B

After

Width:  |  Height:  |  Size: 374 B

View File

Before

Width:  |  Height:  |  Size: 737 B

After

Width:  |  Height:  |  Size: 737 B

View File

Before

Width:  |  Height:  |  Size: 307 B

After

Width:  |  Height:  |  Size: 307 B

View File

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 304 B

View File

Before

Width:  |  Height:  |  Size: 279 B

After

Width:  |  Height:  |  Size: 279 B

View File

Before

Width:  |  Height:  |  Size: 969 B

After

Width:  |  Height:  |  Size: 969 B

View File

Before

Width:  |  Height:  |  Size: 93 B

After

Width:  |  Height:  |  Size: 93 B

View File

Before

Width:  |  Height:  |  Size: 598 B

After

Width:  |  Height:  |  Size: 598 B

View File

Before

Width:  |  Height:  |  Size: 531 B

After

Width:  |  Height:  |  Size: 531 B

View File

Before

Width:  |  Height:  |  Size: 598 B

After

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

View File

@@ -18,6 +18,10 @@ class Line {
);
}
public function move(point:Point):Line {
return new Line(point1.add(point), point2.add(point));
}
public function setLength(value:Float):Line {
var center = this.center;
var width = point2.x - point1.x;

View File

@@ -18,6 +18,6 @@ class Point {
}
public function toString():String {
return 'Point{x=$x,y=$y}';
return 'Point{x=${Math.round(x * 100) / 100},y=${Math.round(y * 100) / 100}}';
}
}

View File

@@ -1,20 +1,22 @@
package ru.m.tankz;
import ru.m.tankz.proto.pack.LeaveGameRequest;
import ru.m.tankz.proto.pack.LeaveGameResponse;
import ru.m.tankz.proto.pack.GameUpdateResponse;
import ru.m.tankz.proto.pack.GameActionRequest;
import ru.m.connect.IConnection;
import protohx.Message;
import ru.m.tankz.proto.pack.ErrorResponse;
import ru.m.tankz.proto.pack.GameListRequest;
import ru.m.tankz.proto.pack.GameListResponse;
import ru.m.connect.IConnection;
import ru.m.tankz.proto.pack.CreateGameRequest;
import ru.m.tankz.proto.pack.CreateGameResponse;
import ru.m.tankz.proto.pack.ErrorResponse;
import ru.m.tankz.proto.pack.GameActionRequest;
import ru.m.tankz.proto.pack.GameListRequest;
import ru.m.tankz.proto.pack.GameListResponse;
import ru.m.tankz.proto.pack.GameUpdateResponse;
import ru.m.tankz.proto.pack.JoinGameRequest;
import ru.m.tankz.proto.pack.JoinGameResponse;
import ru.m.tankz.proto.pack.LeaveGameRequest;
import ru.m.tankz.proto.pack.LeaveGameResponse;
import ru.m.tankz.proto.pack.StartGameRequest;
import ru.m.tankz.proto.pack.StartGameResponse;
import Type;
class PacketBuilder implements IPacketBuilder {

View File

@@ -0,0 +1,23 @@
package ru.m.tankz;
typedef Type = Dynamic;
typedef GameType = String;
typedef TeamId = String;
typedef ControlType = String;
typedef BrickType = String;
typedef TankType = String;
typedef BonusType = String;
typedef PlayerId = {
var team:TeamId;
var index:Int;
}
typedef PresetId = String;

View File

@@ -1,63 +1,41 @@
package ru.m.tankz.bot;
import ru.m.tankz.core.EntityType;
import ru.m.tankz.control.Control;
import ru.m.geom.Direction;
import haxe.Timer;
import ru.m.geom.Direction;
import ru.m.tankz.control.Control;
import ru.m.tankz.core.Eagle;
import ru.m.tankz.core.Entity;
import ru.m.tankz.core.EntityType;
import ru.m.tankz.core.Tank;
import ru.m.tankz.Type;
class BotControl extends Control {
public static var TYPE(default, never):ControlType = 'bot';
class BotHelper {
private var shotTimer:Timer;
private var turnTimer:Timer;
public function new(index:Int) {
super({type:TYPE, index:index});
public static function findEagle(team:TeamId, handler:ControlHandler):Null<Eagle> {
for (entity in handler.entities) {
switch (EntityTypeResolver.of(entity)) {
case EntityType.EAGLE(eagle):
if (eagle.team != team) {
return eagle;
}
case x:
}
}
return null;
}
override public function onCollision(with:EntityType):Void {
switch (with) {
case EntityType.TANK(_): turn();
case EntityType.CELL(_): turn();
case _:
}
public static function getDirectionTo(entity:Entity, target:Entity):Direction {
var x:Float = target.rect.x - entity.rect.x;
var y:Float = target.rect.y - entity.rect.y;
var xD:Direction = Direction.from(Std.int(x / Math.abs(x)), 0);
var yD:Direction = Direction.from(0, Std.int(y / Math.abs(y)));
if (entity.rect.direction == xD) return yD;
if (entity.rect.direction == yD) return xD;
return Math.abs(x) > Math.abs(y) ? xD : yD;
}
override public function start():Void {
//var tank = handler.entities.get(tankId);
//action(TankAction.MOVE(tank.rect.direction));
action(TankAction.MOVE(Direction.BOTTOM)); // ToDo: hardcode bot start direction
if (shotTimer == null) {
shotTimer = new Timer(1000);
shotTimer.run = shot;
}
if (turnTimer == null) {
turnTimer = new Timer(3000);
turnTimer.run = turn;
}
}
override public function stop():Void {
if (shotTimer != null) {
shotTimer.stop();
shotTimer = null;
}
if (turnTimer != null) {
turnTimer.stop();
turnTimer = null;
}
}
public function shot():Void {
action(TankAction.SHOT);
}
public function turn():Void {
action(TankAction.MOVE(randomDirection()));
}
private function randomDirection():Direction {
public static function randomDirection():Direction {
return [
Direction.TOP,
Direction.BOTTOM,
@@ -66,3 +44,76 @@ class BotControl extends Control {
][Math.floor(Math.random() * 4)];
}
}
class BotControl extends Control {
private var shotTimer:Timer;
private var turnRandomTimer:Timer;
private var turnTimer:Timer;
private var tank(get, null):Tank;
public function new(playerId:PlayerId) {
super(playerId);
}
override public function onCollision(with:EntityType):Void {
switch (with) {
case EntityType.TANK(_): turnAfter(300);
case EntityType.CELL(_): turnAfter(300);
case _:
}
}
override public function start():Void {
if (handler == null) return;
action(TankAction.MOVE(tank.rect.direction));
if (shotTimer == null) {
shotTimer = new Timer(1000);
shotTimer.run = shot;
}
if (turnRandomTimer == null) {
turnRandomTimer = new Timer(2000);
turnRandomTimer.run = turn;
}
}
override public function stop():Void {
if (shotTimer != null) {
shotTimer.stop();
shotTimer = null;
}
if (turnRandomTimer != null) {
turnRandomTimer.stop();
turnRandomTimer = null;
}
}
public function shot():Void {
action(TankAction.SHOT);
}
public function turnAfter(delay:Int):Void {
if (turnTimer == null) {
turnTimer = Timer.delay(turn, delay);
}
}
public function turn():Void {
if (turnTimer != null) {
turnTimer.stop();
turnTimer = null;
}
// ToDo:
if (handler == null || tank == null) return;
var eagle:Eagle = BotHelper.findEagle(playerId.team, handler);
if (eagle != null && Math.random() > 0.25) {
action(TankAction.MOVE(BotHelper.getDirectionTo(tank, eagle)));
} else {
action(TankAction.MOVE(BotHelper.randomDirection()));
}
}
private function get_tank():Tank {
return cast handler.entities[tankId];
}
}

View File

@@ -1,7 +1,16 @@
package ru.m.tankz.config;
import ru.m.draw.Color;
import ru.m.tankz.Type;
typedef GameConfig = {
var levels: Int;
var friendlyFire:Bool;
}
typedef SpawnPoint = {
var team:TeamId;
var type:String;
var index:Int;
var x:Int;
@@ -17,7 +26,8 @@ typedef MapConfig = {
}
typedef BrickConfig = {
var type:Int;
var type:BrickType;
var index:Int;
var layer:Int;
var armor:Int;
}
@@ -29,76 +39,131 @@ typedef BulletConfig = {
var piercing:Int;
}
typedef TankType = {
var group:String;
var type:String;
}
typedef TankConfig = { > TankType,
typedef TankConfig = {
var type:TankType;
var width:Float;
var height:Float;
var speed:Float;
var bullet:BulletConfig;
var bullets:Int;
var hits:Int;
var skin:String;
@:optinal var upgrade:TankType;
}
typedef BonusConfig = {
var type:BonusType;
}
typedef TankSpawn = {
var type:TankType;
var rate:Float;
@:optional var bonus:Float;
@:optional var protect:Float;
}
typedef PlayerConfig = {
var index:Int;
var control:ControlType;
var tanks:Array<TankSpawn>;
@:optional var life:Int;
@:optional var color:Color;
}
typedef TeamConfig = {
var id:String;
var size:Int;
var spawnInterval:Int;
var points:Array<SpawnPoint>;
var id:TeamId;
var players:Array<PlayerConfig>;
@:optional var life:Int;
@:optional var spawnInterval:Int;
@:optional var color:Color;
}
typedef GamePreset = {
var id:PresetId;
var teams:Array<TeamConfig>;
}
typedef LevelConfig = {
var data:Array<BrickConfig>;
@:optional var points:Array<SpawnPoint>;
}
class Config {
public var type(default, null):String;
public var levels(default, null):Int;
public var game(default, null):GameConfig;
public var map(default, null):MapConfig;
public var bricks(default, null):Array<BrickConfig>;
public var tanks(default, null):Array<TankConfig>;
public var teams(default, null):Array<TeamConfig>;
public var presets(default, null):Array<GamePreset>;
public var points(default, null):Array<SpawnPoint>;
public var bonuses(default, null):Array<BonusConfig>;
private var brickMap:Map<Int, BrickConfig>;
private var tankMap:Map<String, Map<String, TankConfig>>;
private var teamMap:Map<String, TeamConfig>;
private var brickMap:Map<BrickType, BrickConfig>;
private var brickMapByIndex:Map<Int, BrickConfig>;
private var tankMap:Map<TankType, TankConfig>;
private var presetsMap:Map<PresetId, GamePreset>;
private var bonusMap:Map<BonusType, BonusConfig>;
public function new(type:String, levels:Int, map:MapConfig, bricks:Array<BrickConfig>, teams:Array<TeamConfig>, tanks:Array<TankConfig>) {
public function new(
type:String,
game:GameConfig,
map:MapConfig,
bricks:Array<BrickConfig>,
presets:Array<GamePreset>,
points:Array<SpawnPoint>,
tanks:Array<TankConfig>,
bonuses:Array<BonusConfig>
) {
this.type = type;
this.levels = levels;
this.game = game;
this.map = map;
this.bricks = bricks;
this.teams = teams;
this.presets = presets;
this.points = points;
this.tanks = tanks;
this.bonuses = bonuses;
init();
}
private function init() {
brickMap = new Map();
brickMapByIndex = new Map();
for (item in bricks) {
brickMap.set(item.type, item);
brickMapByIndex.set(item.index, item);
}
teamMap = new Map();
for (team in teams) {
teamMap.set(team.id, team);
presetsMap = new Map();
for (preset in presets) {
presetsMap.set(preset.id, preset);
}
tankMap = new Map();
for (item in tanks) {
if (!tankMap.exists(item.group)) tankMap.set(item.group, new Map<String, TankConfig>());
tankMap.get(item.group).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:BrickType):BrickConfig {
return brickMap.get(type);
}
public function getTeam(id:String):TeamConfig {
return teamMap.get(id);
public function getBrickByIndex(index:Int):BrickConfig {
return brickMapByIndex.get(index);
}
public function getTank(group:String, type:String):TankConfig {
return tankMap.get(group).get(type);
public function getPreset(id:PresetId):GamePreset {
return presetsMap.get(id);
}
public function getTank(type:TankType):TankConfig {
return tankMap.get(type);
}
public function getBonus(type:BonusType):BonusConfig {
return bonusMap.get(type);
}
}

View File

@@ -1,6 +1,5 @@
package ru.m.tankz.config;
import ru.m.tankz.game.ClassicGame;
import yaml.Parser;
import openfl.Assets;
import yaml.Yaml;
@@ -8,11 +7,13 @@ import ru.m.tankz.config.Config;
typedef ConfigSource = {
var levels:Int;
var game:GameConfig;
var map: MapConfig;
var bricks: Array<BrickConfig>;
var teams: Array<TeamConfig>;
var tanks: Dynamic<Array<TankConfig>>;
var presets: Array<GamePreset>;
var points: Array<SpawnPoint>;
var tanks: Array<TankConfig>;
var bonuses: Array<BonusConfig>;
}
class ConfigBundle {
@@ -22,15 +23,7 @@ class ConfigBundle {
}
public static function get(type:String):Config {
var source:ConfigSource = convert(Yaml.parse(Assets.getText('resources/${type}/config.yaml'), Parser.options().useObjects()));
var tanks:Array<TankConfig> = [];
for (group in Reflect.fields(source.tanks)) {
var data:Array<TankConfig> = Reflect.field(source.tanks, group);
for (item in data) {
item.group = group;
tanks.push(item);
}
}
return new Config(type, source.levels, source.map, source.bricks, source.teams, tanks);
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.presets, source.points, source.tanks, source.bonuses);
}
}

View File

@@ -1,10 +1,18 @@
package ru.m.tankz.config;
import openfl.Assets;
import ru.m.tankz.game.Game;
import ru.m.tankz.config.Config;
import ru.m.tankz.Type;
import yaml.Parser;
import yaml.Renderer;
import yaml.Yaml;
typedef LevelSource = {
var data:String;
@:optional var points:Array<SpawnPoint>;
}
class LevelBundle {
private static function formatLevel(level:Int):String {
@@ -13,16 +21,48 @@ class LevelBundle {
return result;
}
public static function get(type:GameType, config:Config, level:Int):Array<BrickConfig> {
var bricksData:String = Assets.getText('resources/${type}/levels/level${formatLevel(level)}.txt');
public static function loadsOld(config:Config, data:String):LevelConfig {
var bricks:Array<BrickConfig> = [];
for (line in ~/\s+/g.split(bricksData)) {
for (line in ~/\s+/g.split(data)) {
for (c in line.split('')) {
if (c.length > 0) {
bricks.push(config.bricks[Std.parseInt(c) + 1]);
bricks.push(config.getBrickByIndex(Std.parseInt(c)));
}
}
}
return bricks;
return {
data: bricks
}
}
public static function loads(config:Config, data:String):LevelConfig {
if (config.type == 'classic') {
return loadsOld(config, data);
} else {
var obj:LevelSource = Yaml.parse(data, Parser.options().useObjects());
return {
data: obj.data.split('').map(function(c) return config.getBrickByIndex(Std.parseInt(c))),
points: obj.points,
}
}
}
public static function dumps(config:Config, level:LevelConfig):String {
var bricksStr = level.data.map(function(brick:BrickConfig) return Std.string(brick.index)).join('');
return Yaml.render({
data: bricksStr,
points: level.points,
}, Renderer.options().setFlowLevel(1));
}
public static function empty(config:Config):LevelConfig {
return {
data: [for (i in 0...config.map.gridWidth * config.map.gridHeight) config.bricks[1]]
}
}
public static function get(type:GameType, config:Config, level:Int):LevelConfig {
var data:String = Assets.getText('resources/${type}/levels/level${formatLevel(level)}.txt');
return loads(config, data);
}
}

View File

@@ -1,34 +1,30 @@
package ru.m.tankz.control;
import ru.m.geom.Direction;
import ru.m.tankz.core.Entity;
import ru.m.tankz.core.EntityType;
import ru.m.geom.Direction;
import ru.m.tankz.Type;
enum TankAction {
MOVE(direction:Direction);
LEVEL_UP(level:Int);
UPGRADE;
STOP;
SHOT;
}
typedef ControlType = String;
typedef ControlId = {
var type:ControlType;
var index:Int;
}
class Control {
public var id:ControlId;
public static var NONE(default, never):ControlType = 'none';
public static var HUMAN(default, never):ControlType = 'human';
public static var BOT(default, never):ControlType = 'bot';
public var playerId(default, null):PlayerId;
public var tankId(default, default):Int;
private var handler:ControlHandler;
public function new(id:ControlId) {
this.id = id;
public function new(playerId:PlayerId) {
this.playerId = playerId;
}
public function bind(handler:ControlHandler):Void {

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,9 +1,9 @@
package ru.m.tankz.core;
import ru.m.tankz.game.Game;
import ru.m.tankz.config.Config;
import ru.m.geom.Rectangle;
import ru.m.geom.Direction;
import ru.m.geom.Rectangle;
import ru.m.tankz.config.Config;
import ru.m.tankz.Type;
class Bullet extends MobileEntity {

View File

@@ -1,15 +1,17 @@
package ru.m.tankz.core;
import ru.m.tankz.game.Game;
import ru.m.geom.Rectangle;
import ru.m.tankz.Type;
class Eagle extends Entity {
public var team(default, null):TeamId;
public var death(default, default):Bool;
public function new(team:TeamId) {
super(new Rectangle(0, 0, 44, 44));
this.team = team;
this.death = false;
}
}

View File

@@ -1,6 +1,7 @@
package ru.m.tankz.core;
import ru.m.geom.Rectangle;
import Type;
class Entity implements IKey {

View File

@@ -1,7 +1,7 @@
package ru.m.tankz.core;
import Type.ValueType;
import ru.m.tankz.map.Grid.GridCell;
import Type;
import ru.m.tankz.map.Grid;
enum EntityType {
@@ -9,6 +9,7 @@ enum EntityType {
TANK(tank:Tank);
BULLET(bullet:Bullet);
CELL(cell:GridCell);
BONUS(bonus:Bonus);
}
@@ -20,7 +21,23 @@ class EntityTypeResolver {
case ValueType.TClass(Tank): EntityType.TANK(cast entity);
case ValueType.TClass(Bullet): EntityType.BULLET(cast entity);
case ValueType.TClass(GridCell): EntityType.CELL(cast entity);
case ValueType.TClass(Bonus): EntityType.BONUS(cast entity);
case x: null;
}
}
public static function as<T>(entity:Entity, type:Class<T>):Null<T> {
if (Std.is(entity, type)) {
return cast entity;
}
return null;
}
public static function asCall<T, R>(entity:Entity, type:Class<T>, fun:T->R, ?defaultResult:R):R {
var e:T = as(entity, type);
if (e != null) {
return fun(e);
}
return defaultResult;
}
}

View File

@@ -0,0 +1,27 @@
package ru.m.tankz.core;
import haxe.Timer;
class Modificator {
public var active(default, default):Bool;
private var timer:Timer;
public function new() {
active = false;
}
public function on(seconds:Float):Void {
off();
active = true;
timer = Timer.delay(off, Std.int(seconds * 1000));
}
public function off():Void {
if (timer != null) {
timer.stop();
timer = null;
}
active = false;
}
}

View File

@@ -1,23 +1,32 @@
package ru.m.tankz.core;
import ru.m.tankz.game.Game;
import ru.m.draw.Color;
import ru.m.geom.Direction;
import ru.m.geom.Point;
import ru.m.geom.Rectangle;
import ru.m.tankz.config.Config;
import ru.m.tankz.core.Bullet;
import ru.m.geom.Rectangle;
import ru.m.geom.Direction;
import ru.m.tankz.Type;
class Tank extends MobileEntity {
public var playerId(default, null):PlayerId;
public var config(default, set):TankConfig;
public var color(default, default):Color;
public var hits(default, default):Int;
public var bonus(default, default):Bool;
public var protect(default, null):Modificator;
public var freezing(default, null):Modificator;
private var bulletsCounter:Int = 0;
public function new(playerId:PlayerId, config:TankConfig) {
super(new Rectangle(0, 0, config.width, config.height), config.speed, Direction.RIGHT);
this.protect = new Modificator();
this.freezing = new Modificator();
this.playerId = playerId;
this.config = config;
this.hits = config.hits;
this.layer = 1;
}
@@ -30,7 +39,14 @@ class Tank extends MobileEntity {
return value;
}
override public function move(direction:Direction):Void {
if (!freezing.active) {
super.move(direction);
}
}
public function shot():Null<Bullet> {
if (freezing.active) return null;
if (bulletsCounter >= config.bullets) return null;
var bullet = new Bullet(this);
bullet.rect.center = rect.center.add(new Point(rect.width / 4 * rect.direction.x, rect.height / 4 * rect.direction.y));

View File

@@ -1,5 +1,6 @@
package ru.m.tankz.engine;
import ru.m.geom.Point;
import ru.m.geom.Line;
import ru.m.tankz.config.Config;
import ru.m.tankz.control.Control;
@@ -11,14 +12,12 @@ import ru.m.tankz.core.Tank;
import ru.m.tankz.map.LevelMap;
interface EngineListener {
public function onSpawn(entity:EntityType):Void;
public function onCollision(entity:EntityType, with:EntityType):Void;
public function onDestroy(entity:EntityType):Void;
}
class CollisionProcessor implements EngineListener {
private var engine:Engine;
@@ -29,42 +28,36 @@ class CollisionProcessor implements EngineListener {
public function onSpawn(entity:EntityType):Void {}
private function checkTankBullet(tank:Tank, bullet:Bullet):Bool {
return tank.playerId.team != bullet.playerId.team;
}
public function onCollision(entity:EntityType, with:EntityType):Void {
switch (entity) {
case EntityType.TANK(tank1):
switch (with) {
case EntityType.TANK(tank2):
tank1.rect.lean(tank2.rect);
case EntityType.BULLET(bullet2):
if (checkTankBullet(tank1, bullet2)) {
engine.destroy(tank1);
engine.destroy(bullet2);
switch [entity, with] {
case [EntityType.TANK(tank), EntityType.TANK(other_tank)]:
tank.rect.lean(other_tank.rect);
case [EntityType.TANK(tank), EntityType.EAGLE(eagle)]:
tank.rect.lean(eagle.rect);
case [EntityType.TANK(tank), EntityType.BONUS(bonus)]:
engine.destroy(bonus);
case [EntityType.TANK(tank), EntityType.BULLET(bullet)] |
[EntityType.BULLET(bullet), EntityType.TANK(tank)]:
if (bullet.tankId == tank.id || (!engine.config.game.friendlyFire && tank.playerId.team == bullet.playerId.team)) {
// Nothing
} else {
if (!tank.protect.active) {
if (tank.hits > 0) {
tank.hits--;
} else {
engine.destroy(tank);
}
case EntityType.EAGLE(eagle):
tank1.rect.lean(eagle.rect);
case EntityType.CELL(cell):
tank1.rect.lean(cell.rect);
}
case EntityType.BULLET(bullet1):
switch (with) {
case EntityType.TANK(tank2):
if (checkTankBullet(tank2, bullet1)) {
engine.destroy(bullet1);
engine.destroy(tank2);
}
case EntityType.BULLET(bullet2):
engine.destroy(bullet1);
engine.destroy(bullet2);
case EntityType.EAGLE(eagle):
engine.destroy(bullet1);
engine.destroy(eagle);
case EntityType.CELL(cell):
engine.destroy(bullet1);
engine.destroy(bullet);
}
case [EntityType.BULLET(bullet), EntityType.BULLET(other_bullet)]:
engine.destroy(bullet);
engine.destroy(other_bullet);
case [EntityType.BULLET(bullet), EntityType.CELL(cell)]:
engine.destroy(bullet);
case [EntityType.BULLET(bullet), EntityType.EAGLE(eagle)]:
engine.destroy(bullet);
eagle.death = true;
case _:
}
}
@@ -72,7 +65,8 @@ class CollisionProcessor implements EngineListener {
public function onDestroy(entity:EntityType):Void { }
}
@:build(yield.parser.Parser.run())
//@:yield //ToDo: not working
class Engine implements ControlHandler {
public var config(default, default):Config;
@@ -121,9 +115,10 @@ class Engine implements ControlHandler {
switch (action) {
case TankAction.MOVE(direction):
tank.move(direction);
case TankAction.LEVEL_UP(level):
// ToDo:
tank.config = config.getTank('human', Std.string(Std.int(Math.min(Std.parseInt(tank.config.type) + level, 3))));
case TankAction.UPGRADE:
if (tank.config.upgrade != null) {
tank.config = config.getTank(tank.config.upgrade);
}
case TankAction.STOP:
tank.stop();
case TankAction.SHOT:
@@ -153,10 +148,24 @@ class Engine implements ControlHandler {
}*/
if (entity.mx != 0 || entity.my != 0) {
entity.rect.x += entity.mx * (d / 30);
entity.rect.y += entity.my * (d / 30);
var asTank:Tank = EntityTypeResolver.as(entity, Tank);
var asBullet:Bullet = EntityTypeResolver.as(entity, Bullet);
if (asTank != null) {
if (asTank.freezing.active) {
continue;
}
}
var side:Line = entity.rect.getSide(entity.rect.direction.reverse());
var step:Point = new Point(entity.rect.direction.x * map.cellWidth / 4, entity.rect.direction.y * map.cellHeight / 4);
var end:Point = side.center.add(new Point(entity.mx * (d / 30), entity.my * (d / 30)));
var c:Int = Math.floor(Math.abs(((end.x - side.center.x) / (map.cellWidth / 4) + (end.y - side.center.y) / (map.cellHeight / 4))));
var isStop:Bool = false;
while (c-- >= 0) {
side = side.move(step);
var cells = map.grid.getCells(side);
var collision:Bool = false;
@@ -166,6 +175,7 @@ class Engine implements ControlHandler {
collision = true;
var with = EntityTypeResolver.of(cell);
for (l in listeners) l.onCollision(entityType, with);
isStop = true;
break;
}
}
@@ -175,19 +185,19 @@ class Engine implements ControlHandler {
if (other.rect.intersection2(side)) {
var with = EntityTypeResolver.of(other);
for (l in listeners) l.onCollision(entityType, with);
isStop = true;
}
}
}
if (Std.is(entity, Bullet)) {
var bullet:Bullet = cast ent;
if (asBullet != null) {
if (collision) {
cells = map.grid.getCells(side.setLength(map.grid.cellWidth * 3));
for (cell in cells) {
if (cell.armor > 0) {
if (cell.armor == bullet.config.piercing) {
if (cell.armor == asBullet.config.piercing) {
cell.destroyed = true;
} else if (cell.armor < bullet.config.piercing) {
} else if (cell.armor < asBullet.config.piercing) {
var brick = map.getBrick(cell);
brick.destroyed = true;
}
@@ -195,6 +205,14 @@ class Engine implements ControlHandler {
}
}
}
if (isStop) break;
}
if (!isStop || Std.is(entity, Bullet)) {
entity.rect.x += entity.mx * (d / 30);
entity.rect.y += entity.my * (d / 30);
}
}
}
}
@@ -203,4 +221,13 @@ class Engine implements ControlHandler {
listeners = [];
entities = new Map();
}
public function iterTanks(filter:Tank->Bool):Iterator<Tank> {
for (entity in entities) {
var tank:Tank = EntityTypeResolver.as(entity, Tank);
if (tank != null && filter(tank)) {
@yield return tank;
}
}
}
}

View File

@@ -1,8 +1,9 @@
package ru.m.tankz.game;
import haxe.ds.Option;
import ru.m.tankz.game.GameState.PlayerState;
import ru.m.tankz.game.Game;
import ru.m.tankz.game.GameState;
import ru.m.tankz.Type;
class ClassicGame extends Game {
@@ -12,61 +13,17 @@ class ClassicGame extends Game {
public static var HUMAN(default, never):TeamId = 'human';
public static var BOT(default, never):TeamId = 'bot';
private static var HUMAN_LIFE(default, never):Int = 3;
private static var BOT_LIFE(default, never):Int = 20;
public static var PLAYER1(default, never):PresetId = 'player1';
public static var PLAYER2(default, never):PresetId = 'player2';
public function new() {
super(TYPE);
}
public static function buildState(level:Int, humans:Int):GameState {
var state = new GameState();
state.type = TYPE;
state.level = level;
state.teams[HUMAN] = {life: -1, players: new Map(), lose: false};
state.teams[BOT] = {life: BOT_LIFE, players: new Map(), lose: false};
for (i in 0...humans) {
state.teams[HUMAN].players[i] = {
index:i,
tank:{
group: HUMAN,
type: '1'
},
control:{
type: 'human',
index: i
},
life:HUMAN_LIFE,
};
}
for (i in 0...humans*2+2) {
state.teams[BOT].players[i] = {
index:i,
tank:{
group: BOT,
type: '1'
},
control:{
type: 'bot',
index: i
},
life:-1,
};
}
return state;
}
override public function next():Option<GameState> {
if (!state.teams[HUMAN].lose) {
state.level++;
if (state.level >= config.levels) state.level = 0;
state.teams[BOT].lose = false;
state.teams[BOT].life = BOT_LIFE;
for (ps in state.teams[HUMAN].players) {
if (ps.life > 0) ps.life++;
}
return Option.Some(state);
}
if (state.loser == HUMAN) {
return Option.None;
}
return super.next();
}
}

View File

@@ -1,7 +1,7 @@
package ru.m.tankz.game;
import ru.m.tankz.game.Game;
import ru.m.tankz.game.GameState;
import ru.m.tankz.Type;
class DotaGame extends Game {
@@ -11,46 +11,11 @@ class DotaGame extends Game {
public static var RADIANT(default, never):TeamId = 'radiant';
public static var DIRE(default, never):TeamId = 'dire';
private static var TEAM_SIZE(default, never):Int = 5;
public static var PLAYER1(default, never):PresetId = 'player1';
public static var PLAYER2_COOP(default, never):PresetId = 'player2_coop';
public static var PLAYER2_VS(default, never):PresetId = 'player2_vs';
public function new() {
super(TYPE);
}
public static function buildState(level:Int, humans:Int):GameState {
var state = new GameState();
state.type = TYPE;
state.level = level;
state.teams[RADIANT] = {life: 20, players: new Map(), lose: false};
state.teams[DIRE] = {life: 20, players: new Map(), lose: false};
for (i in 0...TEAM_SIZE) {
state.teams[RADIANT].players[i] = {
index:i,
tank:{
group: RADIANT,
type: '1'
},
control:{
type: 'bot',
index: i
},
life:-1,
};
}
for (i in 0...TEAM_SIZE) {
state.teams[DIRE].players[i] = {
index:i,
tank:{
group: DIRE,
type: '1'
},
control:{
type: 'bot',
index: i
},
life:-1,
};
}
return state;
}
}

View File

@@ -12,6 +12,7 @@ import ru.m.tankz.config.ConfigBundle;
import ru.m.tankz.config.LevelBundle;
import ru.m.tankz.control.Control;
import ru.m.tankz.control.HumanControl;
import ru.m.tankz.core.Bonus;
import ru.m.tankz.core.Eagle;
import ru.m.tankz.core.Entity;
import ru.m.tankz.core.EntityType;
@@ -19,27 +20,21 @@ import ru.m.tankz.core.Tank;
import ru.m.tankz.engine.Engine;
import ru.m.tankz.game.GameState;
import ru.m.tankz.game.Spawner;
typedef GameType = String;
typedef TeamId = String;
typedef PlayerId = {
var team:TeamId;
var index:Int;
}
import ru.m.tankz.Type;
class Game implements EngineListener {
private static var TAG(default, never):String = 'Game';
public var type(default, null):GameType;
public var state(default, null):GameState;
public var preset(default, null):GamePreset;
public var teams(default, null):Map<TeamId, Team>;
public var config(default, null):Config;
public var engine(default, null):Engine;
private var spawners:Map<TeamId, Spawner>;
private var points:Array<SpawnPoint>;
private var deferred:Deferred<GameState>;
private var stream:Stream<GameState>;
@@ -50,13 +45,26 @@ class Game implements EngineListener {
engine.listeners.push(this);
}
public function getPlayer(playerId:PlayerId):Player {
return teams.get(playerId.team).players[playerId.index];
public function getTeam(teamId:TeamId):Team {
return teams[teamId];
}
private function buildTank(playerId:PlayerId, config:TankConfig, point:SpawnPoint):Tank {
var tank = new Tank(playerId, config);
public function getPlayer(playerId:PlayerId):Player {
return teams[playerId.team].players[playerId.index];
}
private function buildTank(playerId:PlayerId, point:SpawnPoint):Tank {
var player = getPlayer(playerId);
var spawns:Array<TankSpawn> = player.config.tanks;
var spawn:TankSpawn = spawns[Math.floor(Math.random() * spawns.length)];
var tankConfig:TankConfig = config.getTank(spawn.type);
var tank = new Tank(playerId, tankConfig);
tank.color = player.config.color.zero ? teams[playerId.team].config.color : player.config.color;
tank.bonus = Math.random() < spawn.bonus;
applyPoint(tank, point);
if (spawn.protect > 0) {
tank.protect.on(spawn.protect);
}
return tank;
}
@@ -66,41 +74,43 @@ class Game implements EngineListener {
}
public function start(state:GameState):Stream<GameState> {
this.deferred = new Deferred();
this.state = state;
var bricks = LevelBundle.get(type, config, state.level);
engine.map.setData(bricks);
this.preset = config.getPreset(state.presetId);
this.deferred = new Deferred();
var level = LevelBundle.get(type, config, state.level);
points = level.points != null ? level.points : config.points;
engine.map.setData(level.data);
teams = new Map<TeamId, Team>();
spawners = new Map<TeamId, Spawner>();
for (teamConfig in config.teams) {
var team = new Team(teamConfig);
for (playerState in state.teams.get(team.id).players) {
var player = new Player({team:team.id, index:playerState.index});
team.players.push(player);
teams.set(team.id, team);
if (playerState.control != null) {
var control = switch (playerState.control.type) {
case HumanControl.TYPE: new HumanControl(playerState.control.index);
case BotControl.TYPE: new BotControl(playerState.control.index);
case 'none': null;
case _: throw 'Unsupported control type: "${playerState.control.type}"';
var humanControlIndex = 0;
for (teamConfig in preset.teams) {
var teamPoints = points.filter(function(p:SpawnPoint) return p.team == teamConfig.id);
var team:Team = new Team(teamConfig, teamPoints);
teams[team.id] = team;
for (player in team.players.iterator()) {
if (player.config.control != null) {
var control = switch (player.config.control) {
case Control.HUMAN: new HumanControl(player.id, humanControlIndex++);
case Control.BOT: new BotControl(player.id);
case Control.NONE: null;
case _: throw 'Unsupported control type: "${player.config.control}"';
}
L.d(TAG, 'control(${player.id} - ${control})');
if (control != null) {
player.control = control;
player.control.bind(engine);
}
}
}
spawners.set(team.id, new Spawner(team.config, spawn));
team.spawner.runner = spawn;
}
for (team in teams) {
for (player in team.players) {
if (trySpawn(player.id)) {
spawners.get(team.id).push(player.id);
for (team in teams.iterator()) {
for (player in team.players.iterator()) {
if (team.trySpawn(player.id)) {
team.spawner.push(player.id);
}
}
var eaglePoint = spawners.get(team.id).getPoint('eagle');
var eaglePoint = team.spawner.getPoint('eagle');
if (eaglePoint != null) {
var eagle = new Eagle(team.id);
applyPoint(eagle, eaglePoint);
@@ -112,15 +122,16 @@ class Game implements EngineListener {
}
private function spawn(task:SpawnTask):Void {
getPlayer(task.playerId).tankId = 0;
if (trySpawn(task.playerId, true)) {
var tank = buildTank(task.playerId, config.getTank(task.playerId.team, '0'), task.point);
var player:Player = getPlayer(task.playerId);
engine.spawn(tank);
L.d(TAG, 'spawn(${task}');
var team = getTeam(task.playerId.team);
var player = getPlayer(task.playerId);
player.tankId = 0;
if (getTeam(task.playerId.team).trySpawn(task.playerId, true)) {
var tank = buildTank(task.playerId, task.point);
player.tankId = tank.id;
} else if (!isTeamAlive(task.playerId.team)) {
state.teams[task.playerId.team].lose = true;
complete();
engine.spawn(tank);
} else if (!team.isAlive) {
lose(team.id);
}
deferred.resolve(state);
}
@@ -132,111 +143,114 @@ class Game implements EngineListener {
player.control.dispose();
}
}
var timer = new Timer(5000);
timer.run = function() {
timer.stop();
Timer.delay(function() {
deferred.resolve(state);
stream.end();
}, 5000);
}
}
public function setControl(playerId:PlayerId, control:Control):Void {
for (team in teams.iterator()) {
if (team.id == playerId.team) {
var player = team.players[playerId.index];
if (player.control != null) {
player.control.dispose();
}
player.control = control;
player.control.bind(engine);
break;
}
}
}
public function onSpawn(entity:EntityType):Void {
switch (entity) {
case EntityType.TANK(tank):
getPlayer(tank.playerId).control.start();
case _:
}
}
public function onCollision(entity:EntityType, with:EntityType):Void {
switch (entity) {
switch entity {
case EntityType.TANK(tank):
var control = getPlayer(tank.playerId).control;
if (control != null) control.onCollision(with);
case x:
case _:
}
switch [entity, with] {
case [EntityType.TANK(tank), EntityType.BONUS(bonus)]:
applyBonus(tank, bonus);
case [EntityType.BULLET(_), EntityType.EAGLE(eagle)]:
lose(eagle.team);
deferred.resolve(state);
case _:
}
private function isTeamAlive(team:TeamId):Bool {
var ts:TeamState = state.teams[team];
var life:Int = Lambda.fold(ts.players, function(ps, t) return t + ps.life, ts.life);
if (life > 0) {
return true;
} else {
for (player in teams[team].players) {
if (player.tankId > 0) {
return true;
}
}
if (spawners[team].active) {
return true;
}
}
return false;
}
private function trySpawn(player:PlayerId, spawn:Bool = false):Bool {
var ts:TeamState = state.teams[player.team];
var ps:PlayerState = ts.players[player.index];
var result = false;
if (ps.life > -1) {
if (ps.life > 0) {
if (spawn) ps.life--;
result = true;
}
} else if (ts.life > -1) {
if (ts.life > 0) {
if (spawn) ts.life--;
result = true;
}
}
return result;
}
public function onDestroy(entity:EntityType):Void {
switch (entity) {
case EntityType.TANK(tank):
getPlayer(tank.playerId).tankId = 0;
var respawn:Bool = trySpawn(tank.playerId);
var team = getTeam(tank.playerId.team);
var player = getPlayer(tank.playerId);
player.control.stop();
player.tankId = 0; //ToDo: ?
var respawn:Bool = team.trySpawn(player.id);
if (respawn) {
spawners.get(tank.playerId.team).push(tank.playerId);
team.spawner.push(player.id);
}
if (!isTeamAlive(tank.playerId.team)) {
state.teams[tank.playerId.team].lose = true;
complete();
if (!team.isAlive) {
lose(team.id);
}
if (tank.bonus) spawnBonus();
deferred.resolve(state);
case EntityType.EAGLE(eagle):
state.teams[eagle.team].lose = true;
complete();
deferred.resolve(state);
case x:
case _:
}
}
private function lose(teamId:TeamId):Void {
state.loser = teamId;
complete();
}
public function onAction(tankId:Int, action:TankAction):Void {
engine.action(tankId, action);
}
public function next():Option<GameState> {
return Option.None;
var level = state.level + 1;
state.level++;
if (level >= config.game.levels) level = 0;
return Option.Some(new GameState(state.type, preset.id, level));
}
public function dispose():Void {
engine.dispose();
}
private function spawnBonus(?type:BonusType):Void {
var bonusConfig:BonusConfig = type != null ? config.getBonus(type) : config.bonuses[Math.floor(Math.random() * config.bonuses.length)];
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);
}
inline private function alienTank(team:TeamId):Tank->Bool {
return function(tank:Tank):Bool return team != tank.playerId.team;
}
private function applyBonus(tank:Tank, bonus:Bonus):Void {
L.e('XXX', 'applyBonus: ${bonus.bonusType}');
switch (bonus.bonusType) {
case 'life':
getPlayer(tank.playerId).life++;
case 'star':
if (tank.config.upgrade != null) {
tank.config = config.getTank(tank.config.upgrade);
} else {
tank.hits++;
}
case 'grenade':
for (t in engine.iterTanks(alienTank(tank.playerId.team))) {
engine.destroy(t);
}
case 'helmet':
tank.protect.on(20);
case 'clock':
for (t in engine.iterTanks(alienTank(tank.playerId.team))) {
t.freezing.on(10);
}
case 'shovel':
// ToDo: protect eagle/area
case _:
engine.destroy(tank); // :-D
}
}
}

View File

@@ -1,41 +1,18 @@
package ru.m.tankz.game;
import ru.m.tankz.game.Game;
import ru.m.tankz.config.Config;
typedef ControlType = String;
typedef ControId = {
var type:ControlType;
var index:Int;
}
typedef PlayerState = {
var index:Int;
var tank:TankType;
var life:Int;
var control:ControId;
}
typedef TeamState = {
var players:Map<Int, PlayerState>;
var life:Int;
var lose:Bool;
}
import ru.m.tankz.Type;
class GameState {
public var type:GameType;
public var level:Int;
public var teams:Map<TeamId, TeamState>;
public var presetId:PresetId;
public var loser:TeamId;
public function new() {
type = null;
level = -1;
teams = new Map();
public function new(type:GameType, presetId:PresetId, level:Int = 0) {
this.type = type;
this.presetId = presetId;
this.level = level;
this.loser = null;
}
}

View File

@@ -1,42 +1,44 @@
package ru.m.tankz.game;
import ru.m.tankz.config.Config;
import ru.m.tankz.control.Control;
import ru.m.tankz.game.Game;
import ru.m.tankz.Type;
class Player {
public var config(default, null):PlayerConfig;
public var id(default, null):PlayerId;
public var tankId(default, set):Int;
public var control(default, set):Control;
public var life(default, default):Int;
public var isAlive(get, null):Bool;
public function new(id:PlayerId, control:Control=null) {
this.id = id;
this.control = control;
public function new(teamId:TeamId, config:PlayerConfig) {
this.config = config;
this.id = {team:teamId, index:config.index};
this.control = null;
this.life = config.life;
}
public function set_tankId(value:Int):Int {
private function set_tankId(value:Int):Int {
tankId = value;
if (control != null) {
control.tankId = tankId;
if (tankId != 0) {
control.start();
} else {
control.stop();
}
}
return tankId;
}
public function set_control(value:Control):Control {
private function set_control(value:Control):Control {
if (control != null) control.dispose();
control = value;
if (control != null) {
control.tankId = tankId;
if (tankId != 0) {
control.start();
}
}
return control;
}
private function get_isAlive():Bool {
return tankId > 0 || life > 0;
}
}

View File

@@ -1,9 +1,8 @@
package ru.m.tankz.game;
import haxe.Timer;
import ru.m.tankz.game.Game;
import ru.m.tankz.config.Config;
import ru.m.tankz.Type;
typedef SpawnTask = {
@@ -11,13 +10,13 @@ typedef SpawnTask = {
var playerId:PlayerId;
}
class Spawner {
public var active(get, never):Bool;
public var runner(default, default):SpawnTask -> Void;
private var config:TeamConfig;
private var runner:SpawnTask -> Void;
private var points:Array<SpawnPoint>;
private var queue:Array<SpawnTask>;
private var timer:Timer;
@@ -25,13 +24,14 @@ class Spawner {
private var anyPoints:Array<SpawnPoint>;
private var index:Int;
public function new(config:TeamConfig, runner:SpawnTask -> Void) {
public function new(config:TeamConfig, points:Array<SpawnPoint>) {
this.config = config;
this.runner = runner;
this.points = points;
this.runner = null;
queue = [];
indexedPoints = new Map();
anyPoints = [];
for (point in config.points) {
for (point in points) {
if (point.type == 'tank') {
if (point.index > -1) {
indexedPoints.set(point.index, point);
@@ -43,7 +43,7 @@ class Spawner {
}
public function getPoint(type:String, index:Int=-1):Null<SpawnPoint> {
for (point in config.points) {
for (point in points) {
if (point.type == type && point.index == index) {
return point;
}

View File

@@ -1,21 +1,59 @@
package ru.m.tankz.game;
import ru.m.tankz.config.Config.TeamConfig;
import ru.m.tankz.game.Player;
import ru.m.tankz.game.Game;
import ru.m.tankz.Type;
import ru.m.tankz.config.Config;
class Team {
public var id(default, null):TeamId;
public var config(default, null):TeamConfig;
public var players(default, null):Array<Player>;
public var spawner(default, null):Spawner;
public var players(default, null):Map<Int, Player>;
public var life(default, default):Int;
public var isAlive(get, null):Bool;
private static var i:Int = 0;
public function new(config:TeamConfig) {
public function new(config:TeamConfig, points:Array<SpawnPoint>) {
this.id = config.id;
this.config = config;
this.players = [];
this.players = new Map();
for (playerConfig in config.players) {
this.players[playerConfig.index] = new Player(id, playerConfig);
}
this.life = config.life;
this.spawner = new Spawner(config, points);
}
public function trySpawn(playerId:PlayerId, spawn:Bool = false):Bool {
var player:Player = players[playerId.index];
var result = false;
if (player.life > -1) {
if (player.life > 0) {
if (spawn) player.life--;
result = true;
}
} else if (life > -1) {
if (life > 0) {
if (spawn) life--;
result = true;
}
}
return result;
}
// ToDo: eagle state?
private function get_isAlive():Bool {
if (life > 0) {
return true;
}
if (spawner.active) {
return true;
}
for (player in players) {
if (player.isAlive) {
return true;
}
}
return false;
}
}

View File

@@ -9,12 +9,6 @@ import ru.m.tankz.core.IKey;
class Brick implements IKey {
public static var BORDER:BrickConfig = {
type: -1,
layer: 2,
armor: -1,
}
public var cellX(default, null):Int;
public var cellY(default, null):Int;
public var key(get, null):String;

Some files were not shown because too many files have changed in this diff Show More