diff --git a/src/entities/Object.js b/src/entities/Object.js new file mode 100644 index 0000000..0a806a6 --- /dev/null +++ b/src/entities/Object.js @@ -0,0 +1,50 @@ +var asdf = require("asdf-games"); +// eslint-disable-next-line no-unused-vars +const { Container, TileSpriteXML, math, Texture, SpriteSheetXML } = asdf; + +const texture = new Texture("../res/images/allSprites_default.png"); +const xml = new SpriteSheetXML("../res/images/allSprites_default.xml"); + +// properties = { +// type: "", +// explode: true | false, +// pushable: true | false +// } + +class Object extends TileSpriteXML { + constructor(level, pos, properties) { + var type; + switch (properties.type) { + case "crate_metal": + type = "crateMetal.png"; + properties.pushable = (properties.pushable == undefined) ? true : properties.pushable; + properties.explode = (properties.explode == undefined) ? false : properties.explode; + break; + case "crate_wood": + type = "crateWood.png"; + properties.pushable = (properties.pushable == undefined) ? true : properties.pushable; + properties.explode = (properties.explode == undefined) ? false : properties.explode; + break; + case "fence_red": + type = "fenceRed.png"; + properties.pushable = (properties.pushable == undefined) ? true : properties.pushable; + properties.explode = (properties.explode == undefined) ? false : properties.explode; + break; + case "fence_yellow": + type = "fenceYellow.png"; + properties.pushable = (properties.pushable == undefined) ? true : properties.pushable; + properties.explode = (properties.explode == undefined) ? false : properties.explode; + break; + } + super(texture, xml, xml.findIndex("name", type)); + this.level = level; + this.pos = pos; + this.rotation = properties.rotation || 0; + } + + update(dt, t) { + super.update(dt, t); + } +} + +module.exports = Object; \ No newline at end of file diff --git a/src/entities/Tank.js b/src/entities/Tank.js index 1ad2584..8de2465 100644 --- a/src/entities/Tank.js +++ b/src/entities/Tank.js @@ -1,12 +1,54 @@ var asdf = require("asdf-games"); // eslint-disable-next-line no-unused-vars -const { Container, TileSpriteXML, math } = asdf; +const { Container, TileSpriteXML, math, Texture, SpriteSheetXML } = asdf; + +const texture = new Texture("../res/images/allSprites_default.png"); +const xml = new SpriteSheetXML("../res/images/allSprites_default.xml"); + +class Bullet extends TileSpriteXML { + constructor(player, type) { + var name, speed; + var colour = (player.remote) ? "Red" : "Blue"; + switch (type) { + case 0: + name = `bullet${colour}1_outline.png`; + speed = 5; + break; + case 1: + name = `bullet${colour}2_outline.png`; + speed = 7.5; + break; + case 2: + name = `bullet${colour}3_outline.png`; + speed = 10; + break; + } + super(texture, xml, xml.findIndex("name", name)); + this.player = player; + this.level = player.level; + this.speed = speed; + } + + update(dt, t) { + super.update(dt, t); + + // Move + this.pos.x += this.speed * Math.cos(this.rotation + 0.5 * Math.PI); + this.pos.y += this.speed * Math.sin(this.rotation + 0.5 * Math.PI); + + // Kill bullet when it leaves the level + if (this.pos.x < 0 || this.pos.y < 0 || this.pos.x > this.level.w || this.pos.y > this.level.h) { + this.dead = true; + } + } +} class Tank extends TileSpriteXML { - constructor(keys, mouse, texture, xml, colour, remote = false) { + constructor(keys, mouse, level, colour, remote = false) { super(texture, xml, xml.findIndex("name", `tankBody_${colour.toLowerCase()}.png`)); this.keys = keys; this.mouse = mouse; + this.level = level; this.remote = remote; this.children = []; @@ -28,6 +70,16 @@ class Tank extends TileSpriteXML { y: -3 }; this.children.push(this.barrel); + + this.firerate = { + current: 0, + min: 0.1, + maxAmount: 5 + }; + + // Define bullets + this.bullets = new Container(); + this.level.children.push(this.bullets); } update(dt, t) { @@ -76,6 +128,22 @@ class Tank extends TileSpriteXML { this.pos.x -= this.speed.move * Math.cos(this.rotation + 0.5 * Math.PI); this.pos.y -= this.speed.move * Math.sin(this.rotation + 0.5 * Math.PI); } + + // Shoot bullet on action key + if (this.keys.action && this.firerate.current >= this.firerate.min && this.bullets.children.length <= this.firerate.maxAmount) { + var bullet = new Bullet(this, 0); + bullet.rotation = this.barrel.rotation; + bullet.pos = { + x: this.pos.x / 1 + this.barrel.pivot.x + this.barrel.pos.x, + y: this.pos.y / 1 + this.barrel.pivot.y + this.barrel.pos.y + }; + this.bullets.add(bullet); + this.firerate.current = 0; + } else { + if (this.firerate.current < this.firerate.min) { + this.firerate.current += dt; + } + } } } } diff --git a/src/helpers/Level.js b/src/helpers/Level.js new file mode 100644 index 0000000..7aa7279 --- /dev/null +++ b/src/helpers/Level.js @@ -0,0 +1,34 @@ +const asdf = require("asdf-games"); +// eslint-disable-next-line no-unused-vars +const { Container, Texture, SpriteSheetXML, TileMapXML } = asdf; + +const texture = new Texture("../res/images/allSprites_default.png"); +const xml = new SpriteSheetXML("../res/images/allSprites_default.xml"); + +const Object = require("../entities/Object.js"); + +class Level extends TileMapXML { + constructor(level, game, players) { + super(level.tileData, Math.ceil(game.w / 64), Math.ceil(game.h / 64), texture, xml); + this.game = game; + this.players = players; + + this.bullets = new Container(); + this.children.push(this.bullets); + + this.objects = new Container(); + level.objects.forEach(element => { + this.objects.add( + new Object(this, element.pos, element.properties) + ); + }); + + this.children.push(this.objects); + } + + update(dt, t) { + super.update(dt, t); + } +} + +module.exports = Level; \ No newline at end of file diff --git a/src/levels/default.json b/src/levels/default.json new file mode 100644 index 0000000..5a70735 --- /dev/null +++ b/src/levels/default.json @@ -0,0 +1,33 @@ +{ + "tileData": [ + 161, 160, 160, 161, 160, 159, 134, 135, 143, 134, 135, 135, + 161, 160, 160, 161, 161, 159, 135, 134, 143, 135, 135, 134, + 161, 161, 160, 161, 160, 159, 134, 135, 144, 142, 142, 142, + 161, 160, 160, 161, 160, 159, 135, 134, 143, 135, 134, 135, + 161, 160, 161, 161, 160, 159, 134, 135, 143, 134, 135, 135, + 160, 160, 160, 161, 160, 159, 135, 134, 143, 135, 135, 134, + 161, 160, 160, 168, 168, 155, 142, 142, 138, 135, 135, 135, + 160, 160, 160, 161, 160, 159, 135, 134, 134, 135, 134, 135 + ], + "objects": [ + { + "pos": { "x": 100, "y": 100 }, + "properties": { + "type": "crate_metal" + } + }, + { + "pos": { "x": 100, "y": 100 }, + "properties": { + "type": "fence_yellow", + "rotation": 3 + } + } + ], + "startPos": [ + { "x": 0, "y": 0 }, + { "x": 100, "y": 100 }, + { "x": 200, "y": 200 }, + { "x": 300, "y": 300 } + ] +} \ No newline at end of file diff --git a/src/screens/game.js b/src/screens/game.js index 12ee08d..0115b40 100644 --- a/src/screens/game.js +++ b/src/screens/game.js @@ -1,12 +1,11 @@ var io = require("socket.io-client"); +var fs = require("fs"); const asdf = require("asdf-games"); // eslint-disable-next-line no-unused-vars const { Container, Camera, Texture, SpriteSheetXML, TileMapXML, KeyControls, MouseControls } = asdf; -const texture = new Texture("../res/images/allSprites_default.png"); -const xml = new SpriteSheetXML("../res/images/allSprites_default.xml"); - +const Level = require("../helpers/Level.js"); const Tank = require("../entities/Tank.js"); class GameScreen extends Container { @@ -19,20 +18,6 @@ class GameScreen extends Container { this.controls.keys.reset(); - // Draw level - const level = [ - 161, 160, 160, 161, 160, 159, 134, 135, 143, 134, 135, 135, - 161, 160, 160, 161, 161, 159, 135, 134, 143, 135, 135, 134, - 161, 161, 160, 161, 160, 159, 134, 135, 144, 142, 142, 142, - 161, 160, 160, 161, 160, 159, 135, 134, 143, 135, 134, 135, - 161, 160, 161, 161, 160, 159, 134, 135, 143, 134, 135, 135, - 160, 160, 160, 161, 160, 159, 135, 134, 143, 135, 135, 134, - 161, 160, 160, 168, 168, 155, 142, 142, 138, 135, 135, 135, - 160, 160, 160, 161, 160, 159, 135, 134, 134, 135, 134, 135 - ]; - - this.add(new TileMapXML(level, Math.ceil(this.game.w / 64), Math.ceil(this.game.h / 64), texture, xml)); - // Connect to TanksJS-Server instance this.socket = io("http://localhost:3000"); this.socket.on("identify", () => { @@ -44,14 +29,20 @@ class GameScreen extends Container { }); // Define tank colours - const colours = ["Blue", "Red", "Green", "Yellow"]; + const colours = ["Blue", "Red", "Green", "Sand"]; + // Keep local and external players this.players = {}; + // Draw level + var json = fs.readFileSync("./src/levels/default.json"); + var level = new Level(JSON.parse(json), this.game, this.players); + this.add(level); + // Define local player - this.player = new Tank(this.controls.keys, this.controls.mouse, texture, xml, colours[Object.keys(this.players).length]); - this.player.uuid = this.socket.id; - this.add(this.player); + this.players[this.socket.id] = new Tank(this.controls.keys, this.controls.mouse, level, colours[Object.keys(this.players).length]); + this.player = this.players[this.socket.id]; + this.add(this.players[this.socket.id]); // Store current state of controls for comparing this.dataBuffer = JSON.stringify({ @@ -67,7 +58,7 @@ class GameScreen extends Container { // Add any player that is not the local player and is not already added for (const id in data) { if (id != this.socket.id && !(this.players[id])) { - this.players[id] = new Tank(new KeyControls(false), new MouseControls(false), texture, xml, colours[Object.keys(this.players).length], true); + this.players[id] = new Tank(new KeyControls(false), new MouseControls(false), level, colours[Object.keys(this.players).length], true); this.add(this.players[id]); } }