[common] bullet with bricks collision
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tankz",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"ansi-colors": "^1.0.1",
|
||||
|
||||
@@ -19,7 +19,7 @@ import haxework.provider.Provider;
|
||||
import haxework.gui.frame.FrameSwitcher;
|
||||
import haxework.gui.Root;
|
||||
import openfl.Assets;
|
||||
import ru.m.core.connect.IConnection;
|
||||
import ru.m.connect.IConnection;
|
||||
import haxework.log.TraceLogger;
|
||||
|
||||
@:template("layout/main.json", "layout/styles.json")
|
||||
@@ -56,9 +56,9 @@ class Client implements IConnectionHandler {
|
||||
|
||||
Provider.set(IPacketBuilder, new PacketBuilder());
|
||||
#if flash
|
||||
Provider.set(IConnection, new ru.m.core.connect.flash.FlashConnection("localhost", 5001));
|
||||
Provider.set(IConnection, new ru.m.connect.flash.FlashConnection("localhost", 5001));
|
||||
#elseif html5
|
||||
Provider.set(IConnection, new ru.m.core.connect.js.JsConnection("localhost", 5001));
|
||||
Provider.set(IConnection, new ru.m.connect.js.JsConnection("localhost", 5001));
|
||||
#end
|
||||
|
||||
Provider.get(IConnection).handler.addListener(this);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ru.m.tankz.core;
|
||||
|
||||
import ru.m.geom.Direction;
|
||||
import flash.events.FocusEvent;
|
||||
import flash.ui.Keyboard;
|
||||
import ru.m.tankz.engine.IEngine;
|
||||
|
||||
@@ -3,7 +3,8 @@ package ru.m.tankz.render;
|
||||
import haxework.gui.IView;
|
||||
import ru.m.tankz.engine.IEngine;
|
||||
|
||||
|
||||
interface IRender extends IView {
|
||||
public function draw(game:IEngine):Void;
|
||||
public function reset():Void;
|
||||
public function draw(game:IEngine):Void;
|
||||
public function reset():Void;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package ru.m.tankz.render;
|
||||
|
||||
import ru.m.tankz.core.IMobileEntity;
|
||||
import ru.m.tankz.core.Entity;
|
||||
import ru.m.tankz.map.Brick;
|
||||
import ru.m.tankz.core.Direction;
|
||||
import ru.m.geom.Direction;
|
||||
import flash.geom.Matrix;
|
||||
import openfl.Assets;
|
||||
import ru.m.tankz.core.Bullet;
|
||||
@@ -38,9 +39,9 @@ class EntityState implements IState<Entity> {
|
||||
public function new() {}
|
||||
|
||||
public function update(object:Entity):Bool {
|
||||
if (x != object.x || y != object.y) {
|
||||
x = object.x;
|
||||
y = object.y;
|
||||
if (x != object.rect.x || y != object.rect.y) {
|
||||
x = object.rect.x;
|
||||
y = object.rect.y;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -90,7 +91,7 @@ class Render extends SpriteView implements IRender {
|
||||
layersForUpdate[upLayer] = true;
|
||||
}
|
||||
}
|
||||
for (entry in game.mobileEntities) {
|
||||
for (entry in game.entities) {
|
||||
if (!states.exists(entry.key)) {
|
||||
states[entry.key] = new EntityState();
|
||||
}
|
||||
@@ -98,6 +99,12 @@ class Render extends SpriteView implements IRender {
|
||||
layersForUpdate[entryLayer] = true;
|
||||
}
|
||||
}
|
||||
for (key in game.removedEntities) {
|
||||
if (states.exists(key)) {
|
||||
states.remove(key);
|
||||
layersForUpdate[entryLayer] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function drawBackground(game:IEngine):Void {
|
||||
@@ -150,20 +157,21 @@ class Render extends SpriteView implements IRender {
|
||||
if (layersForUpdate[entryLayer]) {
|
||||
var g:Graphics = entryLayer.graphics;
|
||||
g.clear();
|
||||
for (e in game.mobileEntities) {
|
||||
for (ent in game.entities) if (Std.is(ent, IMobileEntity)) {
|
||||
var e:IMobileEntity = cast ent;
|
||||
if (Std.is(e, Tank)) {
|
||||
var m = new Matrix();
|
||||
m.rotate(calcRotate(e.direction));
|
||||
m.translate(e.x, e.y);
|
||||
m.translate(e.rect.x, e.rect.y);
|
||||
g.beginBitmapFill(Assets.getBitmapData("resources/images/tank/player/tank_p0_0-0.png"), m);
|
||||
g.drawRect(e.x, e.y, e.width, e.height);
|
||||
g.drawRect(e.rect.x, e.rect.y, e.rect.width, e.rect.height);
|
||||
g.endFill();
|
||||
} else if (Std.is(e, Bullet)) {
|
||||
var m = new Matrix();
|
||||
m.rotate(calcRotate(e.direction));
|
||||
m.translate(e.x, e.y);
|
||||
m.translate(e.rect.x, e.rect.y);
|
||||
g.beginBitmapFill(Assets.getBitmapData("resources/images/bullet/bullet_0.png"), m);
|
||||
g.drawRect(e.x, e.y, e.width, e.height);
|
||||
g.drawRect(e.rect.x, e.rect.y, e.rect.width, e.rect.height);
|
||||
g.endFill();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import ru.m.tankz.engine.Engine;
|
||||
import ru.m.tankz.engine.IEngine;
|
||||
import protohx.Message;
|
||||
import ru.m.tankz.proto.pack.GameUpdateResponse;
|
||||
import ru.m.core.connect.IConnection;
|
||||
import ru.m.connect.IConnection;
|
||||
import haxework.gui.ViewBuilder;
|
||||
import ru.m.tankz.config.Config;
|
||||
import flash.events.Event;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.m.core;
|
||||
package ru.m;
|
||||
|
||||
import haxe.io.Bytes;
|
||||
import haxe.crypto.BaseCode;
|
||||
@@ -1,11 +1,11 @@
|
||||
package ru.m.core.connect;
|
||||
package ru.m.connect;
|
||||
|
||||
import haxework.dispath.Dispatcher;
|
||||
import haxework.dispath.IDispatcher;
|
||||
import haxework.provider.Provider;
|
||||
import haxe.io.Bytes;
|
||||
import protohx.Message;
|
||||
import ru.m.core.connect.IConnection;
|
||||
import ru.m.connect.IConnection;
|
||||
|
||||
class BaseConnection implements IConnection {
|
||||
public var handler(default,default):IDispatcher<IConnectionHandler>;
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.m.core.connect;
|
||||
package ru.m.connect;
|
||||
|
||||
import haxework.dispath.IDispatcher;
|
||||
import haxe.io.Bytes;
|
||||
@@ -1,6 +1,6 @@
|
||||
package ru.m.core.connect;
|
||||
package ru.m.connect;
|
||||
|
||||
import ru.m.core.connect.IConnection.IPacketBuilder;
|
||||
import ru.m.connect.IConnection.IPacketBuilder;
|
||||
import protohx.Message;
|
||||
import haxe.io.BytesInput;
|
||||
import haxe.io.BytesBuffer;
|
||||
@@ -1,8 +1,8 @@
|
||||
package ru.m.core.connect;
|
||||
package ru.m.connect;
|
||||
|
||||
import haxe.io.Bytes;
|
||||
import haxe.io.BytesOutput;
|
||||
import ru.m.core.connect.IConnection;
|
||||
import ru.m.connect.IConnection;
|
||||
import protohx.Message;
|
||||
|
||||
class WebSocketTools {
|
||||
@@ -1,6 +1,6 @@
|
||||
package ru.m.core.connect.flash;
|
||||
package ru.m.connect.flash;
|
||||
|
||||
import ru.m.core.connect.IConnection.IConnectionHandler;
|
||||
import ru.m.connect.IConnection.IConnectionHandler;
|
||||
import flash.utils.Endian;
|
||||
import haxe.io.BytesOutput;
|
||||
import protohx.Message;
|
||||
@@ -1,7 +1,7 @@
|
||||
package ru.m.core.connect.js;
|
||||
package ru.m.connect.js;
|
||||
|
||||
import ru.m.core.Base64;
|
||||
import ru.m.core.connect.IConnection.IConnectionHandler;
|
||||
import ru.m.connect.IConnection.IConnectionHandler;
|
||||
import protohx.Message;
|
||||
import haxe.io.Bytes;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package ru.m.core.connect.neko;
|
||||
package ru.m.connect.neko;
|
||||
|
||||
import haxe.io.BytesOutput;
|
||||
import protohx.Message;
|
||||
import haxe.io.Bytes;
|
||||
import sys.net.Socket;
|
||||
import ru.m.core.connect.IConnection;
|
||||
import ru.m.connect.IConnection;
|
||||
|
||||
class NekoConnection extends BaseConnection {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package ru.m.core.connect.neko;
|
||||
package ru.m.connect.neko;
|
||||
|
||||
import haxe.crypto.BaseCode;
|
||||
import haxe.crypto.Sha1;
|
||||
import protohx.Message;
|
||||
import haxe.io.Bytes;
|
||||
import sys.net.Socket;
|
||||
import ru.m.core.connect.IConnection;
|
||||
import ru.m.connect.IConnection;
|
||||
|
||||
class NekoWebConnection extends NekoConnection {
|
||||
|
||||
29
src/common/haxe/ru/m/geom/Direction.hx
Normal file
29
src/common/haxe/ru/m/geom/Direction.hx
Normal file
@@ -0,0 +1,29 @@
|
||||
package ru.m.geom;
|
||||
|
||||
import haxe.ds.IntMap;
|
||||
|
||||
class Direction {
|
||||
private static var directions:IntMap<Direction> = new IntMap<Direction>();
|
||||
|
||||
public static var LEFT(default, null) = new Direction(-1, 0);
|
||||
public static var TOP(default, null) = new Direction(0, -1);
|
||||
public static var RIGHT(default, null) = new Direction(1, 0);
|
||||
public static var BOTTOM(default, null) = new Direction(0, 1);
|
||||
|
||||
public var x(default, null):Int;
|
||||
public var y(default, null):Int;
|
||||
|
||||
private function new(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
directions.set(x + y * 10, this);
|
||||
}
|
||||
|
||||
public function reverse():Direction {
|
||||
return from(-x, -y);
|
||||
}
|
||||
|
||||
public static function from(x:Int, y:Int):Direction {
|
||||
return directions.get(x + y * 10);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package ru.m.tankz.core;
|
||||
package ru.m.geom;
|
||||
|
||||
class Point {
|
||||
public var x(default, default):Float;
|
||||
31
src/common/haxe/ru/m/geom/Rectangle.hx
Normal file
31
src/common/haxe/ru/m/geom/Rectangle.hx
Normal file
@@ -0,0 +1,31 @@
|
||||
package ru.m.geom;
|
||||
|
||||
class Rectangle {
|
||||
public var x(default, default):Float;
|
||||
public var y(default, default):Float;
|
||||
public var width(default, default):Float;
|
||||
public var height(default, default):Float;
|
||||
public var center(get, set):Point;
|
||||
|
||||
public function new(x:Float, y:Float, width:Float, height:Float) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
private function get_center():Point {
|
||||
return new Point(x + width / 2, y + height / 2);
|
||||
}
|
||||
|
||||
private function set_center(value:Point):Point {
|
||||
this.x = value.x - width / 2;
|
||||
this.y = value.y - height / 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
public function getSide(direction:Direction):Point {
|
||||
return center.add(new Point(direction.x * width / 2, direction.y * height / 2));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@ 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.core.connect.IConnection;
|
||||
import ru.m.connect.IConnection;
|
||||
import protohx.Message;
|
||||
import ru.m.tankz.proto.pack.ErrorResponse;
|
||||
import ru.m.tankz.proto.pack.GameListRequest;
|
||||
|
||||
@@ -3,7 +3,7 @@ package ru.m.tankz.config;
|
||||
import openfl.utils.Assets;
|
||||
import ru.m.tankz.map.Brick.BrickType;
|
||||
import ru.m.tankz.proto.core.GameType;
|
||||
import ru.m.tankz.core.Direction;
|
||||
import ru.m.geom.Direction;
|
||||
|
||||
typedef MapConfig = {
|
||||
var cellWidth:Float;
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
package ru.m.tankz.core;
|
||||
|
||||
import ru.m.geom.Rectangle;
|
||||
import ru.m.geom.Direction;
|
||||
|
||||
|
||||
class Bullet extends MobileEntity {
|
||||
|
||||
public var personId(default, null):Int;
|
||||
public var tankId(default, null):Int;
|
||||
|
||||
public function new(personId:Int, id:Int, x:Float, y:Float, speed:Float, direction:Direction) {
|
||||
super(id, x, y, speed, direction);
|
||||
this.personId = personId;
|
||||
this.width = 12;
|
||||
this.height = 12;
|
||||
}
|
||||
public function new(tankId:Int, x:Float, y:Float, speed:Float, direction:Direction) {
|
||||
super(new Rectangle(x, y, 12, 12), speed, direction);
|
||||
this.tankId = tankId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package ru.m.tankz.core;
|
||||
|
||||
import haxe.ds.IntMap;
|
||||
|
||||
class Direction {
|
||||
private static var directions:IntMap<Direction> = new IntMap<Direction>();
|
||||
|
||||
public static var LEFT(default, null) = new Direction(-1, 0);
|
||||
public static var TOP(default, null) = new Direction(0, -1);
|
||||
public static var RIGHT(default, null) = new Direction(1, 0);
|
||||
public static var BOTTOM(default, null) = new Direction(0, 1);
|
||||
|
||||
public var x(default, null):Int;
|
||||
public var y(default, null):Int;
|
||||
|
||||
private function new(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
directions.set(x + y * 10, this);
|
||||
}
|
||||
|
||||
public function reverse():Direction {
|
||||
return directions.get(-x + (-y) * 10);
|
||||
}
|
||||
|
||||
public static function from(x:Int, y:Int):Direction {
|
||||
return directions.get(x + y * 10);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,21 @@
|
||||
package ru.m.tankz.core;
|
||||
|
||||
import ru.m.geom.Rectangle;
|
||||
|
||||
class Entity extends Point implements IEntity {
|
||||
|
||||
public var width(default, default):Float;
|
||||
public var height(default, default):Float;
|
||||
class Entity implements IEntity {
|
||||
private static var idCounter:Int = 0;
|
||||
|
||||
public var id(default, null):Int;
|
||||
public var key(get, null):String;
|
||||
public var center(get, set):Point;
|
||||
public var rect(default, null):Rectangle;
|
||||
|
||||
public function new(x:Float, y:Float) {
|
||||
super(x, y);
|
||||
}
|
||||
|
||||
private function get_center():Point {
|
||||
return new Point(x + width / 2, y + height / 2);
|
||||
}
|
||||
|
||||
private function set_center(value:Point):Point {
|
||||
this.x = value.x - width / 2;
|
||||
this.y = value.y - height / 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
public function getSide(direction:Direction):Point {
|
||||
return center.add(new Point(direction.x * width / 2, direction.y * height / 2));
|
||||
public function new(rect:Rectangle) {
|
||||
this.id = ++idCounter;
|
||||
this.rect = rect;
|
||||
}
|
||||
|
||||
private function get_key():String {
|
||||
return '${Type.getClassName(Type.getClass(this))}';
|
||||
return '${Type.getClassName(Type.getClass(this))}:$id';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package ru.m.tankz.core;
|
||||
|
||||
interface IEntity extends IKey {
|
||||
public var x(default, default):Float;
|
||||
public var y(default, default):Float;
|
||||
public var center(get, set):Point;
|
||||
public function getSide(direction:Direction):Point;
|
||||
import ru.m.geom.Rectangle;
|
||||
|
||||
public var width(default, default):Float;
|
||||
public var height(default, default):Float;
|
||||
|
||||
interface IEntity extends IKey {
|
||||
public var id(default, null):Int;
|
||||
public var rect(default, null):Rectangle;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package ru.m.tankz.core;
|
||||
|
||||
import ru.m.geom.Direction;
|
||||
|
||||
|
||||
interface IMobileEntity extends IEntity {
|
||||
public var id(default, null):Int;
|
||||
public var mx(default, default):Float;
|
||||
public var my(default, default):Float;
|
||||
|
||||
public var mx(default, default):Float;
|
||||
public var my(default, default):Float;
|
||||
public var speed(default, null):Float;
|
||||
public var direction(default, default):Direction;
|
||||
|
||||
public var speed(default, null):Float;
|
||||
public var direction(default, default):Direction;
|
||||
|
||||
public function move(direction:Direction):Void;
|
||||
public function stop():Void;
|
||||
public function move(direction:Direction):Void;
|
||||
public function stop():Void;
|
||||
}
|
||||
|
||||
@@ -1,35 +1,30 @@
|
||||
package ru.m.tankz.core;
|
||||
|
||||
import ru.m.geom.Direction;
|
||||
import ru.m.geom.Rectangle;
|
||||
|
||||
|
||||
class MobileEntity extends Entity implements IMobileEntity {
|
||||
private static var idCounter:Int = 0;
|
||||
public var mx(default, default):Float = 0;
|
||||
public var my(default, default):Float = 0;
|
||||
|
||||
public var id(default, null):Int;
|
||||
public var speed(default, null):Float = 0;
|
||||
public var direction(default, default):Direction;
|
||||
|
||||
public var mx(default, default):Float = 0;
|
||||
public var my(default, default):Float = 0;
|
||||
public function new(rect:Rectangle, speed:Float, direction:Direction) {
|
||||
super(rect);
|
||||
this.speed = speed;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public var speed(default, null):Float = 0;
|
||||
public var direction(default, default):Direction;
|
||||
public function move(direction:Direction):Void {
|
||||
this.direction = direction;
|
||||
mx = direction.x * speed;
|
||||
my = direction.y * speed;
|
||||
}
|
||||
|
||||
public function new(id:Int = 0, x:Float = 0, y:Float = 0, speed:Float = 0, direction:Direction = null) {
|
||||
super(x, y);
|
||||
this.id = id == 0 ? ++idCounter : id;
|
||||
this.speed = speed;
|
||||
this.direction = direction == null ? Direction.BOTTOM : direction;
|
||||
}
|
||||
|
||||
public function move(direction:Direction):Void {
|
||||
this.direction = direction;
|
||||
mx = direction.x * speed;
|
||||
my = direction.y * speed;
|
||||
}
|
||||
|
||||
public function stop():Void {
|
||||
mx = 0;
|
||||
my = 0;
|
||||
}
|
||||
|
||||
override private function get_key():String {
|
||||
return '${super.get_key()}:${id}';
|
||||
}
|
||||
public function stop():Void {
|
||||
mx = 0;
|
||||
my = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package ru.m.tankz.core;
|
||||
|
||||
import ru.m.geom.Rectangle;
|
||||
import ru.m.geom.Direction;
|
||||
|
||||
|
||||
enum TankAction {
|
||||
MOVE(direction:Direction);
|
||||
STOP;
|
||||
@@ -8,20 +12,15 @@ enum TankAction {
|
||||
|
||||
class Tank extends MobileEntity {
|
||||
|
||||
public var personId(default, null):Int;
|
||||
|
||||
public var bulletsCount:Int = 0;
|
||||
|
||||
public function new(personId:Int, id:Int, x:Float, y:Float, direction:Direction) {
|
||||
super(id, x, y, 4, direction);
|
||||
this.personId = personId;
|
||||
width = 36;
|
||||
height = 36;
|
||||
public function new(x:Float, y:Float, direction:Direction) {
|
||||
super(new Rectangle(x, y, 36, 36), 4, direction);
|
||||
}
|
||||
|
||||
public function shot():Null<Bullet> {
|
||||
if (bulletsCount >= 5) return null;
|
||||
var bullet = new Bullet(personId, 0, x + width / 2 - 5, y + height / 2 - 5, 6, direction);
|
||||
var bullet = new Bullet(id, rect.x + rect.width / 2 - 5, rect.y + rect.height / 2 - 5, 6, direction);
|
||||
bullet.move(direction);
|
||||
bulletsCount++;
|
||||
return bullet;
|
||||
|
||||
@@ -1,49 +1,58 @@
|
||||
package ru.m.tankz.engine;
|
||||
|
||||
import ru.m.tankz.core.Point;
|
||||
import ru.m.tankz.map.Brick.BrickType;
|
||||
import ru.m.tankz.core.IEntity;
|
||||
import ru.m.geom.Point;
|
||||
import ru.m.tankz.map.Brick;
|
||||
import ru.m.tankz.core.Bullet;
|
||||
import ru.m.tankz.proto.game.GameObjectType;
|
||||
import ru.m.tankz.proto.game.GameChangeType;
|
||||
import ru.m.tankz.proto.game.GameChange;
|
||||
import ru.m.tankz.proto.core.Player;
|
||||
import ru.m.tankz.core.Direction;
|
||||
import ru.m.geom.Direction;
|
||||
import ru.m.tankz.core.IMobileEntity;
|
||||
import ru.m.tankz.config.Config;
|
||||
import ru.m.tankz.core.Tank;
|
||||
import ru.m.tankz.map.LevelMap;
|
||||
import ru.m.tankz.map.ILevelMap;
|
||||
|
||||
|
||||
class Engine implements IEngine {
|
||||
|
||||
private static var STOP_BRICKS:Array<BrickType> = [
|
||||
BrickType.BRICK, BrickType.ARMOR, BrickType.WATER
|
||||
BrickType.BORDER, BrickType.BRICK, BrickType.ARMOR, BrickType.WATER
|
||||
];
|
||||
|
||||
private static var BULLET_BRICKS:Array<BrickType> = [
|
||||
BrickType.BORDER, BrickType.BRICK, BrickType.ARMOR
|
||||
];
|
||||
|
||||
public var config(default, default):Config;
|
||||
public var map(default, null):ILevelMap;
|
||||
|
||||
public var tanks(default, null):Map<Int, Tank>;
|
||||
public var mobileEntities(default, null):Map<Int, IMobileEntity>;
|
||||
public var entities(default, null):Map<Int, IEntity>;
|
||||
public var removedEntities(default, null):Array<String>;
|
||||
|
||||
private var x_limit:Float;
|
||||
private var y_limit:Float;
|
||||
|
||||
private var playerTanks(default, null):Map<Int, Tank>;
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function clear():Void {
|
||||
tanks = new Map<Int, Tank>();
|
||||
playerTanks = new Map<Int, Tank>();
|
||||
}
|
||||
|
||||
private function buildTank(personId:Int, id:Int, cellX:Float, cellY:Float, direction:Direction):Tank {
|
||||
return new Tank(personId, id, cellX * map.cellWidth, cellY * map.cellHeight, direction);
|
||||
private function buildTank(cellX:Float, cellY:Float, direction:Direction):Tank {
|
||||
return new Tank(cellX * map.cellWidth, cellY * map.cellHeight, direction);
|
||||
}
|
||||
|
||||
public function init(config:Config):Void {
|
||||
this.config = config;
|
||||
map = new LevelMap(config.map);
|
||||
tanks = new Map<Int, Tank>();
|
||||
mobileEntities = new Map<Int, IMobileEntity>();
|
||||
playerTanks = new Map<Int, Tank>();
|
||||
entities = new Map<Int, IEntity>();
|
||||
removedEntities = new Array<String>();
|
||||
x_limit = map.gridWidth * map.cellWidth;
|
||||
y_limit = map.gridHeight * map.cellHeight;
|
||||
}
|
||||
@@ -53,24 +62,24 @@ class Engine implements IEngine {
|
||||
for (index in 0...players.length) {
|
||||
var player:Player = players[index];
|
||||
var point:SpawnPoint = config.getSpawnPoint(SpawnPointType.PLAYER, index);
|
||||
var tank = buildTank(player.id, 0, point.x, point.y, point.direction);
|
||||
this.tanks.set(tank.personId, tank);
|
||||
this.mobileEntities.set(tank.id, tank);
|
||||
var tank = buildTank(point.x, point.y, point.direction);
|
||||
playerTanks.set(player.id, tank);
|
||||
entities.set(tank.id, tank);
|
||||
changes.push(new GameChange()
|
||||
.setType(GameChangeType.APPEND)
|
||||
.setObjectType(GameObjectType.TANK)
|
||||
.setObjectId(tank.id)
|
||||
.setX(tank.x)
|
||||
.setY(tank.y)
|
||||
.setDirectionX(tank.direction.x)
|
||||
.setDirectionY(tank.direction.y)
|
||||
.setType(GameChangeType.APPEND)
|
||||
.setObjectType(GameObjectType.TANK)
|
||||
.setObjectId(tank.id)
|
||||
.setX(tank.rect.x)
|
||||
.setY(tank.rect.y)
|
||||
.setDirectionX(tank.direction.x)
|
||||
.setDirectionY(tank.direction.y)
|
||||
);
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
public function action(tankId:Int, action:TankAction):Void {
|
||||
var tank:Tank = tanks.get(tankId);
|
||||
public function action(playerId:Int, action:TankAction):Void {
|
||||
var tank:Tank = playerTanks.get(playerId);
|
||||
switch (action) {
|
||||
case TankAction.MOVE(direction):
|
||||
tank.move(direction);
|
||||
@@ -89,7 +98,7 @@ class Engine implements IEngine {
|
||||
case TankAction.SHOT:
|
||||
var bullet = tank.shot();
|
||||
if (bullet != null) {
|
||||
mobileEntities.set(bullet.id, bullet);
|
||||
entities.set(bullet.id, bullet);
|
||||
}
|
||||
/*Provider.get(IConnection).send(
|
||||
Map GameActionRequest()
|
||||
@@ -126,48 +135,49 @@ class Engine implements IEngine {
|
||||
}
|
||||
}*/
|
||||
|
||||
private function getBricks(entity:IMobileEntity):Array<Brick> {
|
||||
var target:Point = entity.rect.getSide(entity.direction);
|
||||
var cellX:Int = Math.floor(target.x / map.cellWidth);
|
||||
var cellY:Int = Math.floor(target.y / map.cellHeight);
|
||||
var brick1 = map.getBrick(cellX, cellY);
|
||||
var brick2 = map.getBrick(cellX - entity.direction.y * entity.direction.y, cellY - entity.direction.x * entity.direction.x);
|
||||
return [brick1, brick2];
|
||||
}
|
||||
|
||||
public function update():Array<GameChange> {
|
||||
var changes = new Array<GameChange>();
|
||||
|
||||
for (entiny in mobileEntities) {
|
||||
for (ent in entities) if (Std.is(ent, IMobileEntity)) {
|
||||
var entity:IMobileEntity = cast ent;
|
||||
|
||||
var objectType = -1;
|
||||
var personId = Reflect.hasField(entiny, "personId") ? Reflect.field(entiny, "personId") : -1;
|
||||
if (Std.is(entiny, Tank)) objectType = GameObjectType.TANK;
|
||||
if (Std.is(entiny, Bullet)) objectType = GameObjectType.BULLET;
|
||||
if (Std.is(entity, Tank)) objectType = GameObjectType.TANK;
|
||||
if (Std.is(entity, Bullet)) objectType = GameObjectType.BULLET;
|
||||
|
||||
if (objectType == GameObjectType.TANK) {
|
||||
if (entiny.direction.x != 0) {
|
||||
entiny.y = Math.round((entiny.y + entiny.height / 2) / config.map.cellHeight) * config.map.cellHeight - entiny.height / 2;
|
||||
if (entity.direction.x != 0) {
|
||||
entity.rect.y = Math.round((entity.rect.y + entity.rect.height / 2) / config.map.cellHeight) * config.map.cellHeight - entity.rect.height / 2;
|
||||
}
|
||||
if (entiny.direction.y != 0) {
|
||||
entiny.x = Math.round((entiny.x + entiny.width / 2) / config.map.cellWidth) * config.map.cellWidth - entiny.width / 2;
|
||||
if (entity.direction.y != 0) {
|
||||
entity.rect.x = Math.round((entity.rect.x + entity.rect.width / 2) / config.map.cellWidth) * config.map.cellWidth - entity.rect.width / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (entiny.mx != 0 || entiny.my != 0) {
|
||||
entiny.x += entiny.mx;
|
||||
entiny.y += entiny.my;
|
||||
if (entity.mx != 0 || entity.my != 0) {
|
||||
entity.rect.x += entity.mx;
|
||||
entity.rect.y += entity.my;
|
||||
var bricks = getBricks(entity);
|
||||
|
||||
if (objectType == GameObjectType.TANK) {
|
||||
if (entiny.x < 0) entiny.x = 0;
|
||||
if (entiny.x + entiny.width > x_limit) entiny.x = x_limit - entiny.width;
|
||||
if (entiny.y < 0) entiny.y = 0;
|
||||
if (entiny.y + entiny.height > y_limit) entiny.y = y_limit - entiny.height;
|
||||
|
||||
var target:Point = entiny.getSide(entiny.direction);
|
||||
|
||||
var cellX:Int = Math.floor(target.x / map.cellWidth);
|
||||
var cellY:Int = Math.floor(target.y / map.cellHeight);
|
||||
|
||||
var brick1 = map.getBrick(cellX, cellY);
|
||||
var brick2 = map.getBrick(cellX - entiny.direction.y * entiny.direction.y, cellY - entiny.direction.x * entiny.direction.x);
|
||||
|
||||
if (brick1 != null && STOP_BRICKS.indexOf(brick1.type) > -1 || brick2 != null && STOP_BRICKS.indexOf(brick2.type) > -1) {
|
||||
if (entiny.direction.x != 0) {
|
||||
entiny.x = brick1.cellX * map.cellWidth + map.cellWidth / 2 - entiny.direction.x * map.cellWidth / 2 - entiny.direction.x * entiny.width / 2 - entiny.width / 2;
|
||||
}
|
||||
if (entiny.direction.y != 0) {
|
||||
entiny.y = brick1.cellY * map.cellHeight + map.cellHeight / 2 - entiny.direction.y * map.cellHeight / 2 - entiny.direction.y * entiny.height / 2 - entiny.height / 2;
|
||||
for (brick in bricks) {
|
||||
if (STOP_BRICKS.indexOf(brick.type) > -1) {
|
||||
if (entity.direction.x != 0) {
|
||||
entity.rect.x = brick.cellX * map.cellWidth + map.cellWidth / 2 - entity.direction.x * map.cellWidth / 2 - entity.direction.x * entity.rect.width / 2 - entity.rect.width / 2;
|
||||
}
|
||||
if (entity.direction.y != 0) {
|
||||
entity.rect.y = brick.cellY * map.cellHeight + map.cellHeight / 2 - entity.direction.y * map.cellHeight / 2 - entity.direction.y * entity.rect.height / 2 - entity.rect.height / 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,21 +185,30 @@ class Engine implements IEngine {
|
||||
changes.push(new GameChange()
|
||||
.setType(GameChangeType.MOVED)
|
||||
.setObjectType(objectType)
|
||||
.setObjectId(entiny.id)
|
||||
.setX(entiny.x)
|
||||
.setY(entiny.y)
|
||||
.setObjectId(entity.id)
|
||||
.setX(entity.rect.x)
|
||||
.setY(entity.rect.y)
|
||||
);
|
||||
|
||||
if (objectType == GameObjectType.BULLET) {
|
||||
if (entiny.x < 0 || entiny.x + entiny.width > x_limit || entiny.y < 0 || entiny.y + entiny.height > y_limit) {
|
||||
mobileEntities.remove(entiny.id);
|
||||
var tank:Tank = tanks.get(personId);
|
||||
tank.onDestroyBullet();
|
||||
changes.push(new GameChange()
|
||||
.setType(GameChangeType.DESTROED)
|
||||
.setObjectType(objectType)
|
||||
.setObjectId(entiny.id)
|
||||
);
|
||||
for (brick in bricks) {
|
||||
if (BULLET_BRICKS.indexOf(brick.type) > -1) {
|
||||
entities.remove(entity.id);
|
||||
var tank:Tank = cast entities.get(cast(entity, Bullet).tankId);
|
||||
tank.onDestroyBullet();
|
||||
changes.push(new GameChange()
|
||||
.setType(GameChangeType.DESTROED)
|
||||
.setObjectType(objectType)
|
||||
.setObjectId(entity.id)
|
||||
);
|
||||
removedEntities.push(entity.key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (brick in bricks) {
|
||||
if (brick.type == BrickType.BRICK || brick.type == BrickType.BUSH) {
|
||||
brick.type = BrickType.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package ru.m.tankz.engine;
|
||||
|
||||
import ru.m.tankz.core.IEntity;
|
||||
import ru.m.tankz.proto.game.GameChange;
|
||||
import ru.m.tankz.core.IMobileEntity;
|
||||
import ru.m.tankz.core.Tank;
|
||||
import ru.m.tankz.proto.core.Player;
|
||||
import ru.m.tankz.config.Config;
|
||||
@@ -10,8 +10,9 @@ import ru.m.tankz.map.ILevelMap;
|
||||
interface IEngine {
|
||||
public var config(default, default):Config;
|
||||
public var map(default, null):ILevelMap;
|
||||
public var tanks(default, null):Map<Int, Tank>;
|
||||
public var mobileEntities(default, null):Map<Int, IMobileEntity>;
|
||||
|
||||
public var entities(default, null):Map<Int, IEntity>;
|
||||
public var removedEntities(default, null):Array<String>;
|
||||
|
||||
public function clear():Void;
|
||||
public function init(config:Config):Void;
|
||||
|
||||
@@ -4,6 +4,7 @@ import ru.m.tankz.core.IKey;
|
||||
|
||||
|
||||
@:enum abstract BrickType(Int) from Int to Int {
|
||||
var BORDER = -1;
|
||||
var NONE = 0;
|
||||
var ACE = 1;
|
||||
var BUSH = 2;
|
||||
@@ -16,7 +17,7 @@ import ru.m.tankz.core.IKey;
|
||||
class Brick implements IKey {
|
||||
public var cellX(default, null):Int;
|
||||
public var cellY(default, null):Int;
|
||||
public var type(default, null):BrickType;
|
||||
public var type(default, default):BrickType;
|
||||
public var key(get, null):String;
|
||||
|
||||
public function new(type:BrickType, cellX:Int, cellY:Int) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package ru.m.tankz.map;
|
||||
|
||||
import ru.m.tankz.map.Brick.BrickType;
|
||||
import ru.m.tankz.config.Config.MapConfig;
|
||||
|
||||
class LevelMap implements ILevelMap {
|
||||
@@ -10,16 +11,29 @@ class LevelMap implements ILevelMap {
|
||||
public var gridHeight(default, null):Int;
|
||||
|
||||
public var bricks(default, null):Array<Brick>;
|
||||
public var borders(default, null):Array<Brick>;
|
||||
|
||||
public function new(config:MapConfig) {
|
||||
cellWidth = config.cellWidth;
|
||||
cellHeight = config.cellHeight;
|
||||
gridWidth = config.gridWidth;
|
||||
gridHeight = config.gridHeight;
|
||||
borders = [];
|
||||
bricks = Lambda.array(Lambda.mapi(config.bricks, function(i, type):Brick return new Brick(type, Std.int(i % gridWidth), Std.int(Math.floor(i / gridHeight)))));
|
||||
}
|
||||
|
||||
private function getBorderBrick(cellX:Int, cellY:Int):Brick {
|
||||
var index:Int = cellX + cellY * gridWidth;
|
||||
if (borders[index] == null) {
|
||||
borders[index] = new Brick(BrickType.BORDER, cellX, cellY);
|
||||
}
|
||||
return borders[index];
|
||||
}
|
||||
|
||||
public function getBrick(cellX:Int, cellY:Int):Brick {
|
||||
if (cellX < 0 || cellX >= gridWidth || cellY < 0 || cellY >= gridHeight) {
|
||||
return getBorderBrick(cellX, cellY);
|
||||
}
|
||||
return bricks[cellY * gridWidth + cellX];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package ru.m.tankz.server;
|
||||
|
||||
import haxework.log.SocketLogger;
|
||||
import ru.m.core.connect.IConnection.IPacketBuilder;
|
||||
import ru.m.connect.IConnection.IPacketBuilder;
|
||||
import haxework.provider.Provider;
|
||||
import haxework.log.TraceLogger;
|
||||
import ru.m.tankz.server.session.Session;
|
||||
|
||||
@@ -9,19 +9,19 @@ import ru.m.tankz.proto.StartGameRequest;
|
||||
import ru.m.tankz.proto.Person;
|
||||
import ru.m.tankz.proto.JoinGameRequest;
|
||||
import ru.m.tankz.proto.CreateGameRequest;
|
||||
import ru.m.core.connect.neko.NekoWebConnection;
|
||||
import ru.m.connect.neko.NekoWebConnection;
|
||||
import haxe.io.Bytes;
|
||||
import ru.m.tankz.proto.PersonSelectResponse;
|
||||
import ru.m.tankz.proto.PersonSelectRequest;
|
||||
import ru.m.tankz.proto.Account;
|
||||
import ru.m.core.connect.neko.NekoConnection;
|
||||
import ru.m.connect.neko.NekoConnection;
|
||||
import ru.m.tankz.proto.ErrorResponse;
|
||||
import ru.m.tankz.server.db.DbProvider;
|
||||
import ru.m.tankz.proto.LoginResponse;
|
||||
import ru.m.tankz.proto.LoginRequest;
|
||||
import ru.m.tankz.proto.GamesResponse;
|
||||
import protohx.Message;
|
||||
import ru.m.core.connect.IConnection;
|
||||
import ru.m.connect.IConnection;
|
||||
import sys.net.Socket;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user