Dont even remember what was done :D
This commit is contained in:
86
client/package-lock.json
generated
86
client/package-lock.json
generated
@@ -9,6 +9,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz",
|
||||
"integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg=="
|
||||
},
|
||||
"@types/anymatch": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
|
||||
"integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/body-parser": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
|
||||
@@ -169,6 +175,76 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/source-list-map": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
|
||||
"integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/tapable": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz",
|
||||
"integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/uglify-js": {
|
||||
"version": "3.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.1.tgz",
|
||||
"integrity": "sha512-7npvPKV+jINLu1SpSYVWG8KvyJBhBa8tmzMMdDoVc2pWUYHN8KIXlPJhjJ4LT97c4dXJA2SHL/q6ADbDriZN+Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/webpack": {
|
||||
"version": "4.41.26",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.26.tgz",
|
||||
"integrity": "sha512-7ZyTfxjCRwexh+EJFwRUM+CDB2XvgHl4vfuqf1ZKrgGvcS5BrNvPQqJh3tsZ0P6h6Aa1qClVHaJZszLPzpqHeA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/anymatch": "*",
|
||||
"@types/node": "*",
|
||||
"@types/tapable": "*",
|
||||
"@types/uglify-js": "*",
|
||||
"@types/webpack-sources": "*",
|
||||
"source-map": "^0.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/webpack-sources": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz",
|
||||
"integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"@types/source-list-map": "*",
|
||||
"source-map": "^0.7.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@webassemblyjs/ast": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz",
|
||||
@@ -772,6 +848,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"clean-webpack-plugin": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz",
|
||||
"integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/webpack": "^4.4.31",
|
||||
"del": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"scripts": {
|
||||
"tsc": "tsc -w",
|
||||
"build": "webpack",
|
||||
"build:prod": "webpack --config webpack.config.prod.js",
|
||||
"start": "webpack serve --watch"
|
||||
},
|
||||
"repository": {
|
||||
@@ -34,5 +35,7 @@
|
||||
"webpack-cli": "^4.4.0",
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
},
|
||||
"devDependencies": {}
|
||||
"devDependencies": {
|
||||
"clean-webpack-plugin": "^3.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
41
client/src/Bullet.ts
Normal file
41
client/src/Bullet.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import p5 from "p5";
|
||||
import OtherPlayer from "./OtherPlayer";
|
||||
import { Position } from "./types";
|
||||
|
||||
export default class Bullet {
|
||||
|
||||
private timeLeftToLive = 2000;
|
||||
|
||||
private _position: Position
|
||||
|
||||
constructor(
|
||||
private _shooter: OtherPlayer,
|
||||
private direction: Position,
|
||||
) {
|
||||
this._position = {..._shooter.position}
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position
|
||||
}
|
||||
|
||||
get shooter() {
|
||||
return this._shooter
|
||||
}
|
||||
|
||||
move() {
|
||||
this._position.x += this.direction.x
|
||||
this._position.y += this.direction.y
|
||||
|
||||
this.timeLeftToLive -= Math.abs(this.direction.x) + Math.abs(this.direction.y)
|
||||
}
|
||||
|
||||
get timeToLive() {
|
||||
return this.timeLeftToLive
|
||||
}
|
||||
|
||||
set timeToLive(time: number) {
|
||||
this.timeLeftToLive = time
|
||||
}
|
||||
|
||||
}
|
||||
78
client/src/Game.ts
Normal file
78
client/src/Game.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { Socket } from "socket.io-client";
|
||||
import Bullet from "./Bullet";
|
||||
import OtherPlayer from "./OtherPlayer";
|
||||
import UserPlayer from "./UserPlayer";
|
||||
import { PlayerDescription } from "./socketDataTypes";
|
||||
import Pickable from "./Pickable";
|
||||
|
||||
export default class Game {
|
||||
|
||||
private player: UserPlayer
|
||||
private otherPlayers: OtherPlayer[] = []
|
||||
private bullets: Bullet[] = []
|
||||
private items: Pickable[] = []
|
||||
|
||||
constructor(_socket: SocketIOClient.Socket) {
|
||||
this.player = new UserPlayer(_socket.id, _socket, '', {x:0, y:0}, 'white', new Map<number, boolean>(), 100)
|
||||
}
|
||||
|
||||
addItem(item: Pickable) {
|
||||
this.items.push(item)
|
||||
}
|
||||
|
||||
getItems() {
|
||||
return this.items
|
||||
}
|
||||
|
||||
removeItem(pickable: Pickable) {
|
||||
this.items = this.items.filter((item) => {
|
||||
return item !== pickable
|
||||
})
|
||||
}
|
||||
|
||||
getPlayer(): UserPlayer {
|
||||
return this.player
|
||||
}
|
||||
|
||||
setPlayer(description: PlayerDescription) {
|
||||
this.player.id = description.id
|
||||
this.player.name = description.name
|
||||
this.player.position = description.position
|
||||
this.player.color = description.color
|
||||
}
|
||||
|
||||
addOtherPlayer(player: OtherPlayer) {
|
||||
if (player.id === this.player.id) return
|
||||
let oPlayer = this.otherPlayers.find((otherPlayer) => {
|
||||
return player.id === otherPlayer.id
|
||||
})
|
||||
if (oPlayer) {
|
||||
oPlayer.color = player.color
|
||||
oPlayer.id = player.id
|
||||
oPlayer.name = player.name
|
||||
oPlayer.position = player.position
|
||||
} else {
|
||||
this.otherPlayers.push(player)
|
||||
}
|
||||
}
|
||||
|
||||
removeOtherPlayer(id: string) {
|
||||
this.otherPlayers = this.otherPlayers.filter((player) => {
|
||||
return player.id !== id
|
||||
})
|
||||
}
|
||||
|
||||
getOtherPlayers() {
|
||||
return this.otherPlayers
|
||||
}
|
||||
|
||||
getOtherPlayer(id: string) {
|
||||
for (let player of this.otherPlayers) {
|
||||
if (player.id === id) {
|
||||
return player
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
20
client/src/Item.ts
Normal file
20
client/src/Item.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import p5 from "p5";
|
||||
|
||||
export default class Item {
|
||||
|
||||
constructor(
|
||||
private _image: p5.Image,
|
||||
private _type: "HEAL" | "DAMAGE" | "DEFENCE"
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
get image() {
|
||||
return this._image
|
||||
}
|
||||
|
||||
get type() {
|
||||
return this._type
|
||||
}
|
||||
|
||||
}
|
||||
18
client/src/MapTile.ts
Normal file
18
client/src/MapTile.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import p5 from "p5";
|
||||
import { Position } from "./types";
|
||||
|
||||
export default class MapTile {
|
||||
|
||||
constructor(private _image: p5.Image, private _position: Position) {
|
||||
|
||||
}
|
||||
|
||||
get image() {
|
||||
return this._image
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position
|
||||
}
|
||||
|
||||
}
|
||||
101
client/src/OtherPlayer.ts
Normal file
101
client/src/OtherPlayer.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import p5 from "p5"
|
||||
import Bullet from "./Bullet"
|
||||
import { Position } from "./types"
|
||||
|
||||
export default class OtherPlayer {
|
||||
|
||||
private bullets: Bullet[] = []
|
||||
private _damage: number
|
||||
|
||||
constructor(
|
||||
private _id: string,
|
||||
private _name: string,
|
||||
private _position: Position,
|
||||
private _color: string,
|
||||
private _health: number
|
||||
) {
|
||||
this._health = 100
|
||||
this._damage = 10
|
||||
}
|
||||
|
||||
hit(bullet: Bullet, socket: SocketIOClient.Socket) {
|
||||
this.health -= bullet.shooter.damage
|
||||
bullet.timeToLive = -1
|
||||
socket.emit('health-update', {player: this.id, health: this.health})
|
||||
}
|
||||
|
||||
addBullet(bullet: Bullet) {
|
||||
this.bullets.push(bullet)
|
||||
}
|
||||
|
||||
getBullets() {
|
||||
return this.bullets
|
||||
}
|
||||
|
||||
removeExpiredBullets() {
|
||||
this.bullets = this.bullets.filter((bullet) => {
|
||||
return bullet.timeToLive > 0
|
||||
})
|
||||
}
|
||||
|
||||
draw(p5: p5, position: Position) {
|
||||
p5.stroke(0, 0, 0)
|
||||
p5.strokeWeight(5)
|
||||
p5.fill(this.color)
|
||||
p5.ellipse(position.x, position.y, 80, 80)
|
||||
p5.textSize(32)
|
||||
p5.fill(255, 255, 255)
|
||||
p5.textAlign(p5.CENTER, p5.CENTER)
|
||||
p5.text(this.name, position.x - 300, position.y - 150, 600, 50)
|
||||
p5.noStroke()
|
||||
p5.fill('#850000')
|
||||
p5.rect(position.x - 50, position.y - 90, 100, 5)
|
||||
p5.fill('#008500')
|
||||
p5.rect(position.x - 50, position.y - 90, this.health, 5)
|
||||
}
|
||||
|
||||
get health() {
|
||||
return this._health
|
||||
}
|
||||
|
||||
set health(hp: number) {
|
||||
this._health = hp
|
||||
}
|
||||
|
||||
get damage() {
|
||||
return this._damage
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this._id
|
||||
}
|
||||
|
||||
set id(id: string) {
|
||||
this._id = id
|
||||
}
|
||||
|
||||
get position(): Position {
|
||||
return this._position
|
||||
}
|
||||
|
||||
set position(position: Position) {
|
||||
this._position = position
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this._name
|
||||
}
|
||||
|
||||
set name(name: string) {
|
||||
this._name = name
|
||||
}
|
||||
|
||||
get color(): string {
|
||||
return this._color
|
||||
}
|
||||
|
||||
set color(color: string) {
|
||||
this._color = color
|
||||
}
|
||||
|
||||
}
|
||||
22
client/src/Pickable.ts
Normal file
22
client/src/Pickable.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import Item from "./Item";
|
||||
import { Position } from "./types";
|
||||
|
||||
export default class Pickable {
|
||||
|
||||
constructor(
|
||||
private _position: Position,
|
||||
private _item: Item,
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this._position
|
||||
}
|
||||
|
||||
get item() {
|
||||
return this._item
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
82
client/src/UserPlayer.ts
Normal file
82
client/src/UserPlayer.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import SocketIOClient from "socket.io-client";
|
||||
import Bullet from "./Bullet";
|
||||
import OtherPlayer from "./OtherPlayer";
|
||||
import { Position } from "./types";
|
||||
|
||||
export default class UserPlayer extends OtherPlayer{
|
||||
|
||||
private PLAYER_SPEED = 10
|
||||
private KEY_W = 87;
|
||||
private KEY_A = 65;
|
||||
private KEY_S = 83;
|
||||
private KEY_D = 68;
|
||||
|
||||
constructor(
|
||||
_id: string,
|
||||
private _socket: SocketIOClient.Socket,
|
||||
_name: string,
|
||||
_position: Position,
|
||||
_color: string,
|
||||
private _keysPressed: Map<number, boolean>,
|
||||
_health: number
|
||||
) {
|
||||
super(_id, _name, _position, _color, _health)
|
||||
}
|
||||
|
||||
get socket(): SocketIOClient.Socket {
|
||||
return this._socket
|
||||
}
|
||||
|
||||
keyPressed(key: number): boolean {
|
||||
return this._keysPressed.get(key) || false;
|
||||
}
|
||||
|
||||
setKeyPressed(key: number, value: boolean) {
|
||||
this._keysPressed.set(key, value)
|
||||
}
|
||||
|
||||
clearKeysPressed() {
|
||||
this._keysPressed.clear()
|
||||
}
|
||||
|
||||
move() {
|
||||
let previousPosition = {
|
||||
x: this.position.x,
|
||||
y: this.position.y,
|
||||
}
|
||||
if (this.keyPressed(this.KEY_A)) {
|
||||
this.position.x -= this.PLAYER_SPEED;
|
||||
}
|
||||
if (this.keyPressed(this.KEY_D)) {
|
||||
this.position.x += this.PLAYER_SPEED;
|
||||
}
|
||||
|
||||
if (this.keyPressed(this.KEY_W)) {
|
||||
this.position.y -= this.PLAYER_SPEED;
|
||||
}
|
||||
if (this.keyPressed(this.KEY_S)) {
|
||||
this.position.y += this.PLAYER_SPEED;
|
||||
}
|
||||
|
||||
if (this.position.x < -1600) {
|
||||
this.position.x = -1600
|
||||
}
|
||||
|
||||
if (this.position.y < -2000) {
|
||||
this.position.y = -2000
|
||||
}
|
||||
|
||||
if (this.position.x > 1500) {
|
||||
this.position.x = 1500
|
||||
}
|
||||
|
||||
if (this.position.y > 1900) {
|
||||
this.position.y = 1900
|
||||
}
|
||||
|
||||
if (this.position.x !== previousPosition.x || this.position.y !== previousPosition.y) {
|
||||
this.socket.emit('i-moved', {x: this.position.x, y: this.position.y})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,112 +1,137 @@
|
||||
import P5 from 'p5'
|
||||
import io from 'socket.io-client'
|
||||
import Game from './Game'
|
||||
import MapTile from './MapTile'
|
||||
import OtherPlayer from './OtherPlayer'
|
||||
import prealoadResources from './preloadResources'
|
||||
import setupSocketEvents from './setupSocketEvents'
|
||||
import Bullet from './Bullet'
|
||||
import { Position } from './types'
|
||||
import Pickable from './Pickable'
|
||||
import Item from './Item'
|
||||
|
||||
const socket = io("https://blobbystrike.ioi.lt", {secure: true});
|
||||
const socket = io("https://blobbystrike.ioi.lt", {secure: true})
|
||||
const game = new Game(socket)
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
let images: Map<string, P5.Image>
|
||||
let fonts: Map<string, P5.Font>
|
||||
|
||||
var tileTypes, mapTiles: any = [];
|
||||
let canvas: HTMLCanvasElement
|
||||
var tileTypes, mapTiles: MapTile[] = []
|
||||
|
||||
const PLAYER_SPEED = 10;
|
||||
let shootingDelay = Date.now()
|
||||
|
||||
let Player = {
|
||||
id: '',
|
||||
name: '',
|
||||
position: {x:0, y:0},
|
||||
color: '#' + (Math.floor(Math.random() * 256)).toString(16) + (Math.floor(Math.random() * 256)).toString(16) + (Math.floor(Math.random() * 256)).toString(16),
|
||||
keysPressed: [false],
|
||||
}
|
||||
const VISIBLE_RANGE = 2000
|
||||
const VISIBLE_RANGE_X = 1200
|
||||
const VISIBLE_RANGE_Y = 700
|
||||
|
||||
var OtherPlayers: any = []
|
||||
const PLAYER_SIZE = 80
|
||||
const BULLET_SIZE = 30
|
||||
|
||||
var KEY_W = 87;
|
||||
var KEY_A = 65;
|
||||
var KEY_S = 83;
|
||||
var KEY_D = 68;
|
||||
|
||||
let grassImage: P5.Image;
|
||||
const BULLET_SHOOTING_DELAY = 100
|
||||
|
||||
function onKeyDown(e: any) {
|
||||
Player.keysPressed[e.keyCode] = true;
|
||||
game.getPlayer().setKeyPressed(e.keyCode, true)
|
||||
}
|
||||
function onKeyUp(e: any) {
|
||||
Player.keysPressed[e.keyCode] = false;
|
||||
game.getPlayer().setKeyPressed(e.keyCode, false)
|
||||
}
|
||||
|
||||
function onContextMenu() {
|
||||
Player.keysPressed = [];
|
||||
game.getPlayer().clearKeysPressed()
|
||||
}
|
||||
|
||||
function getCursorPosition(canvas: HTMLCanvasElement, event: MouseEvent) {
|
||||
const rect = canvas.getBoundingClientRect()
|
||||
const x = event.clientX - rect.left
|
||||
const y = event.clientY - rect.top
|
||||
return {
|
||||
x: x,
|
||||
y: y,
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseUp(e: MouseEvent) {
|
||||
if (shootingDelay > Date.now()) return
|
||||
shootingDelay = Date.now() + BULLET_SHOOTING_DELAY
|
||||
let pos = getCursorPosition(canvas, e)
|
||||
pos.x -= parseInt(canvas.style.width) / 2
|
||||
pos.y -= parseInt(canvas.style.height) / 2
|
||||
let length = Math.sqrt((pos.x * pos.x) + (pos.y * pos.y))
|
||||
let scale = 1 / length
|
||||
scale *= 50
|
||||
pos.x *= scale
|
||||
pos.y *= scale
|
||||
game.getPlayer().addBullet(new Bullet(game.getPlayer(), pos))
|
||||
socket.emit('shoot', {position: game.getPlayer().position, direction: pos})
|
||||
}
|
||||
|
||||
function onCanvasResize() {
|
||||
var w = window.innerWidth;
|
||||
var h = window.innerHeight;
|
||||
var w = window.innerWidth
|
||||
var h = window.innerHeight
|
||||
|
||||
var scale = 16/9;
|
||||
var windowScale = w/h;
|
||||
var windowScale = w/h
|
||||
|
||||
if (scale > windowScale) {
|
||||
// higher
|
||||
canvas.style.width = w + 'px';
|
||||
canvas.style.height = (w/16*9) + 'px';
|
||||
canvas.style.width = w + 'px'
|
||||
canvas.style.height = (w/16*9) + 'px'
|
||||
} else {
|
||||
// wider
|
||||
canvas.style.width = (h/9*16) + 'px';
|
||||
canvas.style.height = h + 'px';
|
||||
canvas.style.width = (h/9*16) + 'px'
|
||||
canvas.style.height = h + 'px'
|
||||
}
|
||||
}
|
||||
|
||||
function drawPlayer(p5: P5, player: any, x: any, y: any) {
|
||||
function drawPlayer(p5: P5, player: OtherPlayer, x: any, y: any) {
|
||||
p5.stroke(0, 0, 0)
|
||||
p5.strokeWeight(5)
|
||||
// translate(-width/2, -height/2)
|
||||
p5.fill(player.color)
|
||||
p5.ellipse(x, y, 80, 80);
|
||||
p5.textSize(32);
|
||||
p5.fill(255, 255, 255);
|
||||
p5.textAlign(p5.CENTER, p5.CENTER);
|
||||
p5.text(player.name, x - 300,y - 100, 600, 50);
|
||||
p5.ellipse(x, y, 80, 80)
|
||||
p5.textSize(32)
|
||||
p5.fill(255, 255, 255)
|
||||
p5.textAlign(p5.CENTER, p5.CENTER)
|
||||
p5.text(player.name, x - 300,y - 150, 600, 50)
|
||||
p5.noStroke()
|
||||
p5.fill('#850000')
|
||||
p5.rect(x - 50, y - 90, 100, 5)
|
||||
p5.fill('#008500')
|
||||
p5.rect(x - 50, y - 90, player.health, 5)
|
||||
}
|
||||
|
||||
function relativePosition(pos1: any, pos2: any) {
|
||||
return {
|
||||
x: pos2.x - pos1.x,
|
||||
y: pos2.y - pos1.y,
|
||||
}
|
||||
function drawBullet(p5: P5, color: string, x: any, y: any) {
|
||||
p5.stroke(0, 0, 0)
|
||||
p5.strokeWeight(3)
|
||||
p5.fill(color)
|
||||
p5.ellipse(x, y, 30, 30)
|
||||
}
|
||||
|
||||
function buildMap() {
|
||||
tileTypes = {
|
||||
grass: {
|
||||
image: grassImage
|
||||
image: images.get('grass')
|
||||
}
|
||||
}
|
||||
|
||||
for (let x = 0; x < 10; x++) {
|
||||
mapTiles[x] = []
|
||||
for (let y = 0; y < 6; y++) {
|
||||
mapTiles[x][y] = {
|
||||
tile: tileTypes.grass.image,
|
||||
x: x * 380,
|
||||
y: y * 380,
|
||||
}
|
||||
for (let x = -20; x < 20; x++) {
|
||||
for (let y = -20; y < 20; y++) {
|
||||
mapTiles.push(
|
||||
new MapTile(
|
||||
images.get('grass')!,
|
||||
{
|
||||
x: x * (images.get('grass')?.width || 256),
|
||||
y: y * (images.get('grass')?.height || 256)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
console.log(mapTiles)
|
||||
}
|
||||
|
||||
function isVisible(middlePoint: any, visibleAreaSize: any, position: any, size: any) {
|
||||
if (
|
||||
position.x - size.width > middlePoint.x - visibleAreaSize.width/2 &&
|
||||
position.x + size.width < middlePoint.x + visibleAreaSize.width/2 &&
|
||||
position.y - size.height > middlePoint.y - visibleAreaSize.height/2 &&
|
||||
position.y + size.height < middlePoint.y + visibleAreaSize.height/2
|
||||
) {
|
||||
// console.log('visible')
|
||||
return true;
|
||||
}
|
||||
// console.log('not visible')
|
||||
return false;
|
||||
function isVisible(p1: Position, p2: Position) {
|
||||
return Math.abs(p1.x - p2.x) < VISIBLE_RANGE_X && Math.abs(p1.y - p2.y) < VISIBLE_RANGE_Y
|
||||
}
|
||||
|
||||
function distance(p1: any, p2: any) {
|
||||
@@ -114,103 +139,134 @@ function distance(p1: any, p2: any) {
|
||||
}
|
||||
|
||||
function drawMap(p5: P5) {
|
||||
|
||||
for (let xTiles of mapTiles) {
|
||||
for (let yTile of xTiles) {
|
||||
if (distance(Player.position, {x: yTile.x, y: yTile.y}) < 2000) {
|
||||
p5.image(yTile.tile, yTile.x + p5.width/2, yTile.y + p5.height/2)
|
||||
}
|
||||
for (let tile of mapTiles) {
|
||||
if (isVisible(game.getPlayer().position, tile.position)) {
|
||||
p5.image(tile.image, tile.position.x - game.getPlayer().position.x - tile.image.width/2, tile.position.y - game.getPlayer().position.y - tile.image.height/2)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
socket.on('your-info', function (playerData: any) {
|
||||
Player.name = playerData.name;
|
||||
Player.position = playerData.position;
|
||||
Player.color = playerData.color;
|
||||
Player.id = playerData.id;
|
||||
})
|
||||
socket.on('players-info', function (playersData: any) {
|
||||
for (let playerData of playersData) {
|
||||
if (Player.id !== playerData.id) {
|
||||
OtherPlayers.push({
|
||||
name: playerData.name,
|
||||
position: playerData.position,
|
||||
color: playerData.color,
|
||||
id: playerData.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
socket.on('new-player-joined', function (playerData: any) {
|
||||
if (Player.id !== playerData.id) {
|
||||
OtherPlayers.push({
|
||||
name: playerData.name,
|
||||
position: playerData.position,
|
||||
color: playerData.color,
|
||||
id: playerData.id,
|
||||
})
|
||||
}
|
||||
})
|
||||
socket.on('player-moved', function (movedPlayerData: any) {
|
||||
for (let playerData of OtherPlayers) {
|
||||
if (Player.id !== movedPlayerData.id && movedPlayerData.id === playerData.id) {
|
||||
playerData.position = movedPlayerData.position;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const sketch = (p5: P5) => {
|
||||
|
||||
p5.setup = () => {
|
||||
buildMap()
|
||||
p5.createCanvas(1920, 1080);
|
||||
p5.createCanvas(1920, 1080, p5.WEBGL);
|
||||
canvas = document.querySelector('canvas')!
|
||||
onCanvasResize()
|
||||
window.addEventListener('resize', onCanvasResize)
|
||||
document.addEventListener('keydown', onKeyDown)
|
||||
document.addEventListener('keyup', onKeyUp)
|
||||
document.addEventListener("contextmenu", onContextMenu);
|
||||
document.addEventListener("contextmenu", onContextMenu)
|
||||
canvas.addEventListener("mousedown", onMouseUp)
|
||||
p5.textFont(fonts.get('Ubuntu')!)
|
||||
|
||||
game.addItem(new Pickable({x: 150, y: 150}, new Item(images.get('healthPack')!, "HEAL")))
|
||||
game.addItem(new Pickable({x: 150, y: 100}, new Item(images.get('powerUp')!, "DAMAGE")))
|
||||
game.addItem(new Pickable({x: 150, y: 100}, new Item(images.get('shield')!, "DEFENCE")))
|
||||
}
|
||||
|
||||
p5.preload = () => {
|
||||
grassImage = p5.loadImage('grass.png');
|
||||
let resources = prealoadResources(p5)
|
||||
|
||||
images = resources.images
|
||||
fonts = resources.fonts
|
||||
|
||||
setupSocketEvents(socket, game)
|
||||
}
|
||||
|
||||
p5.draw = () => {
|
||||
p5.translate(-Player.position.x, Player.position.y)
|
||||
p5.background('#000000')
|
||||
// p5.translate(p5.width/2, p5.height/2)
|
||||
|
||||
|
||||
// drawing map background
|
||||
drawMap(p5)
|
||||
|
||||
for (let otherPlayer of OtherPlayers) {
|
||||
drawPlayer(p5, otherPlayer, otherPlayer.position.x + p5.width/2, -otherPlayer.position.y + p5.height/2)
|
||||
|
||||
|
||||
// drawing items
|
||||
for (let item of game.getItems()) {
|
||||
|
||||
p5.image(item.item.image, item.position.x - game.getPlayer().position.x, item.position.y - game.getPlayer().position.y)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
p5.translate(Player.position.x, -Player.position.y)
|
||||
drawPlayer(p5, Player, p5.width/2, p5.height/2)
|
||||
p5.text(Math.floor(Player.position.x) + ':' + Math.floor(Player.position.y), p5.width/2, 50)
|
||||
for (let otherPlayer of game.getOtherPlayers()) {
|
||||
// going through other player list
|
||||
|
||||
// draw player if in range
|
||||
if (isVisible(game.getPlayer().position, otherPlayer.position)) {
|
||||
otherPlayer.draw(p5, {
|
||||
x: otherPlayer.position.x - game.getPlayer().position.x,
|
||||
y: otherPlayer.position.y - game.getPlayer().position.y
|
||||
})
|
||||
}
|
||||
|
||||
// going through bullets of that player
|
||||
for (let bullet of otherPlayer.getBullets()) {
|
||||
|
||||
// draw bullet if in range
|
||||
if (isVisible(game.getPlayer().position, bullet.position)) {
|
||||
drawBullet(p5, bullet.shooter.color, bullet.position.x - game.getPlayer().position.x, bullet.position.y - game.getPlayer().position.y)
|
||||
}
|
||||
|
||||
// move bullet
|
||||
bullet.move()
|
||||
|
||||
// check if bullet colloides with current player
|
||||
if (distance(game.getPlayer().position, bullet.position) < BULLET_SIZE + PLAYER_SIZE) {
|
||||
bullet.timeToLive = -1
|
||||
}
|
||||
|
||||
// check if bullet collides with other player
|
||||
for (let otherPlayerCheck of game.getOtherPlayers()) {
|
||||
if (distance(otherPlayerCheck.position, bullet.position) < BULLET_SIZE + PLAYER_SIZE) {
|
||||
// check if player bullet collides with is not the player who shot the bullet
|
||||
if (otherPlayerCheck.id !== bullet.shooter.id) {
|
||||
bullet.timeToLive = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// removig bullets that has traveled far enough
|
||||
otherPlayer.removeExpiredBullets()
|
||||
}
|
||||
|
||||
let previousPosition = {
|
||||
x: Player.position.x,
|
||||
y: Player.position.y,
|
||||
}
|
||||
if (Player.keysPressed[KEY_A]) {
|
||||
Player.position.x -= PLAYER_SPEED;
|
||||
}
|
||||
if (Player.keysPressed[KEY_D]) {
|
||||
Player.position.x += PLAYER_SPEED;
|
||||
}
|
||||
|
||||
if (Player.keysPressed[KEY_W]) {
|
||||
Player.position.y += PLAYER_SPEED;
|
||||
}
|
||||
if (Player.keysPressed[KEY_S]) {
|
||||
Player.position.y -= PLAYER_SPEED;
|
||||
}
|
||||
if (Player.position.x !== previousPosition.x || Player.position.y !== previousPosition.y) {
|
||||
socket.emit('i-moved', {x: Player.position.x, y: Player.position.y})
|
||||
// drawing current player
|
||||
game.getPlayer().draw(p5, {x: 0, y: 0})
|
||||
|
||||
|
||||
// going through current player bullets
|
||||
for (let bullet of game.getPlayer().getBullets()) {
|
||||
// drawing bullet if in range
|
||||
if (isVisible(game.getPlayer().position, bullet.position)) {
|
||||
drawBullet(p5, bullet.shooter.color, bullet.position.x - game.getPlayer().position.x, bullet.position.y - game.getPlayer().position.y)
|
||||
}
|
||||
|
||||
// move bullet
|
||||
bullet.move()
|
||||
|
||||
// check if bullet collides with other player
|
||||
for (let otherPlayer of game.getOtherPlayers()) {
|
||||
if (distance(otherPlayer.position, bullet.position) < BULLET_SIZE + PLAYER_SIZE) {
|
||||
// register hit to other player
|
||||
otherPlayer.hit(bullet, game.getPlayer().socket)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// removig bullets that has traveled far enough
|
||||
game.getPlayer().removeExpiredBullets()
|
||||
|
||||
// drawing coordinates of the current player
|
||||
p5.fill('#ffffff')
|
||||
p5.stroke('#000000')
|
||||
p5.textAlign(p5.LEFT, p5.TOP)
|
||||
p5.text(Math.floor(game.getPlayer().position.x) + ':' + Math.floor(game.getPlayer().position.y), -p5.width/2 + 10, -p5.height/2 + 10)
|
||||
|
||||
// moving player depending on keys pressed
|
||||
game.getPlayer().move()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
22
client/src/preloadResources.ts
Normal file
22
client/src/preloadResources.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import P5 from 'p5'
|
||||
|
||||
export default function prealoadResources(p5: P5): {
|
||||
images: Map<string, P5.Image>,
|
||||
fonts: Map<string, P5.Font>
|
||||
} {
|
||||
|
||||
let images = new Map<string, P5.Image>()
|
||||
let fonts = new Map<string, P5.Font>()
|
||||
|
||||
images.set('grass', p5.loadImage('images/grass.png'))
|
||||
images.set('powerUp', p5.loadImage('images/PowerUp.png'))
|
||||
images.set('shield', p5.loadImage('images/Shield.png'))
|
||||
images.set('healthPack', p5.loadImage('images/HealthPack.png'))
|
||||
|
||||
fonts.set('Ubuntu', p5.loadFont('fonts/Ubuntu/Ubuntu-Regular.ttf'))
|
||||
|
||||
return {
|
||||
images,
|
||||
fonts
|
||||
};
|
||||
}
|
||||
59
client/src/setupSocketEvents.ts
Normal file
59
client/src/setupSocketEvents.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import SocketIOClient from 'socket.io-client'
|
||||
import Bullet from './Bullet'
|
||||
import Game from './Game'
|
||||
import OtherPlayer from './OtherPlayer'
|
||||
import { BulletData, PlayerDescription } from './socketDataTypes'
|
||||
import { Position } from './types'
|
||||
|
||||
export default function setupSocketEvents(socket: SocketIOClient.Socket, game: Game) {
|
||||
socket.on('your-info', function (playerData: PlayerDescription) {
|
||||
let player = game.getPlayer()
|
||||
player.color = playerData.color
|
||||
player.id = playerData.id
|
||||
player.name = playerData.name
|
||||
player.position = playerData.position
|
||||
player.health = playerData.health
|
||||
|
||||
socket.emit('get-other-players')
|
||||
})
|
||||
socket.on('players-info', function (playersData: PlayerDescription[]) {
|
||||
for (let playerData of playersData) {
|
||||
game.addOtherPlayer(new OtherPlayer(playerData.id, playerData.name, playerData.position, playerData.color, playerData.health))
|
||||
}
|
||||
})
|
||||
socket.on('new-player-joined', function (playerData: PlayerDescription) {
|
||||
if (game.getPlayer().id !== playerData.id) {
|
||||
game.addOtherPlayer(new OtherPlayer(playerData.id, playerData.name, playerData.position, playerData.color, playerData.health))
|
||||
}
|
||||
})
|
||||
socket.on('player-moved', function (movedPlayerData: {id: string, position: Position}) {
|
||||
for (let playerData of game.getOtherPlayers()) {
|
||||
if (movedPlayerData.id === playerData.id) {
|
||||
playerData.position = movedPlayerData.position;
|
||||
}
|
||||
}
|
||||
})
|
||||
socket.on('player-disconnected', function (disconnectedPlayer: string) {
|
||||
game.removeOtherPlayer(disconnectedPlayer)
|
||||
})
|
||||
|
||||
socket.on('shoot', (data: BulletData) => {
|
||||
let otherPlayer = game.getOtherPlayer(data.id)
|
||||
if (otherPlayer) {
|
||||
otherPlayer.addBullet(new Bullet(otherPlayer, data.direction))
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('health-update', (data: {id: string, health: number}) => {
|
||||
let otherPlayer = game.getOtherPlayer(data.id)
|
||||
if (otherPlayer) {
|
||||
otherPlayer.health = data.health
|
||||
}
|
||||
if (game.getPlayer().socket.id === data.id) {
|
||||
game.getPlayer().health = data.health
|
||||
if (data.health <= 0) {
|
||||
window.location.href = '/ded';
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
18
client/src/socketDataTypes.ts
Normal file
18
client/src/socketDataTypes.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Position } from "./types"
|
||||
|
||||
export type PlayerDescription = {
|
||||
name: string,
|
||||
color: string,
|
||||
position: {
|
||||
x: number,
|
||||
y: number,
|
||||
},
|
||||
id: string,
|
||||
health: number,
|
||||
}
|
||||
|
||||
export type BulletData = {
|
||||
id: string,
|
||||
position: Position,
|
||||
direction: Position
|
||||
}
|
||||
4
client/src/types.ts
Normal file
4
client/src/types.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export type Position = {
|
||||
x: number,
|
||||
y: number,
|
||||
}
|
||||
96
client/static/assets/fonts/Ubuntu/UFL.txt
Normal file
96
client/static/assets/fonts/Ubuntu/UFL.txt
Normal file
@@ -0,0 +1,96 @@
|
||||
-------------------------------
|
||||
UBUNTU FONT LICENCE Version 1.0
|
||||
-------------------------------
|
||||
|
||||
PREAMBLE
|
||||
This licence allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely. The fonts, including any derivative works, can be
|
||||
bundled, embedded, and redistributed provided the terms of this licence
|
||||
are met. The fonts and derivatives, however, cannot be released under
|
||||
any other licence. The requirement for fonts to remain under this
|
||||
licence does not require any document created using the fonts or their
|
||||
derivatives to be published under this licence, as long as the primary
|
||||
purpose of the document is not to be a vehicle for the distribution of
|
||||
the fonts.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this licence and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Original Version" refers to the collection of Font Software components
|
||||
as received under this licence.
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to
|
||||
a new environment.
|
||||
|
||||
"Copyright Holder(s)" refers to all individuals and companies who have a
|
||||
copyright ownership of the Font Software.
|
||||
|
||||
"Substantially Changed" refers to Modified Versions which can be easily
|
||||
identified as dissimilar to the Font Software by users of the Font
|
||||
Software comparing the Original Version with the Modified Version.
|
||||
|
||||
To "Propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification and with or without charging
|
||||
a redistribution fee), making available to the public, and in some
|
||||
countries other activities as well.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
This licence does not grant any rights under trademark law and all such
|
||||
rights are reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of the Font Software, to propagate the Font Software, subject to
|
||||
the below conditions:
|
||||
|
||||
1) Each copy of the Font Software must contain the above copyright
|
||||
notice and this licence. These can be included either as stand-alone
|
||||
text files, human-readable headers or in the appropriate machine-
|
||||
readable metadata fields within text or binary files as long as those
|
||||
fields can be easily viewed by the user.
|
||||
|
||||
2) The font name complies with the following:
|
||||
(a) The Original Version must retain its name, unmodified.
|
||||
(b) Modified Versions which are Substantially Changed must be renamed to
|
||||
avoid use of the name of the Original Version or similar names entirely.
|
||||
(c) Modified Versions which are not Substantially Changed must be
|
||||
renamed to both (i) retain the name of the Original Version and (ii) add
|
||||
additional naming elements to distinguish the Modified Version from the
|
||||
Original Version. The name of such Modified Versions must be the name of
|
||||
the Original Version, with "derivative X" where X represents the name of
|
||||
the new work, appended to that name.
|
||||
|
||||
3) The name(s) of the Copyright Holder(s) and any contributor to the
|
||||
Font Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except (i) as required by this licence, (ii) to
|
||||
acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with
|
||||
their explicit written permission.
|
||||
|
||||
4) The Font Software, modified or unmodified, in part or in whole, must
|
||||
be distributed entirely under this licence, and must not be distributed
|
||||
under any other licence. The requirement for fonts to remain under this
|
||||
licence does not affect any document created using the Font Software,
|
||||
except any version of the Font Software extracted from a document
|
||||
created using the Font Software may only be distributed under this
|
||||
licence.
|
||||
|
||||
TERMINATION
|
||||
This licence becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
|
||||
DEALINGS IN THE FONT SOFTWARE.
|
||||
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-Bold.ttf
Normal file
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-Bold.ttf
Normal file
Binary file not shown.
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-BoldItalic.ttf
Normal file
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-Italic.ttf
Normal file
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-Italic.ttf
Normal file
Binary file not shown.
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-Light.ttf
Normal file
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-Light.ttf
Normal file
Binary file not shown.
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-LightItalic.ttf
Normal file
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-LightItalic.ttf
Normal file
Binary file not shown.
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-Medium.ttf
Normal file
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-Medium.ttf
Normal file
Binary file not shown.
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-MediumItalic.ttf
Normal file
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-MediumItalic.ttf
Normal file
Binary file not shown.
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-Regular.ttf
Normal file
BIN
client/static/assets/fonts/Ubuntu/Ubuntu-Regular.ttf
Normal file
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 8.9 KiB |
BIN
client/static/assets/images/HealthPack.png
Normal file
BIN
client/static/assets/images/HealthPack.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 177 B |
BIN
client/static/assets/images/PowerUp.png
Normal file
BIN
client/static/assets/images/PowerUp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 538 B |
BIN
client/static/assets/images/Shield.png
Normal file
BIN
client/static/assets/images/Shield.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 377 B |
BIN
client/static/assets/images/grass.jpg
Normal file
BIN
client/static/assets/images/grass.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
BIN
client/static/assets/images/grass.png
Normal file
BIN
client/static/assets/images/grass.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 438 B |
7
client/static/assets/socket.io.min.js
vendored
7
client/static/assets/socket.io.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
33
client/static/ded.html
Normal file
33
client/static/ded.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BlobbyStrike - U Ded</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
main {
|
||||
background: #000000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
div {
|
||||
display: block;
|
||||
color: #850000;
|
||||
font-size: 8rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div>U DED...<br /><a href="/">RESPAWN</a></div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,11 +1,11 @@
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
mode: 'development',
|
||||
entry: './src/app.ts',
|
||||
output: {
|
||||
filename: 'bundle.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
publicPath: 'dist',
|
||||
path: path.resolve(__dirname, 'dist')
|
||||
},
|
||||
devtool: 'inline-source-map',
|
||||
module: {
|
||||
|
||||
27
client/webpack.config.prod.js
Normal file
27
client/webpack.config.prod.js
Normal file
@@ -0,0 +1,27 @@
|
||||
const path = require('path')
|
||||
const CleanPlugin = require('clean-webpack-plugin')
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: './src/app.ts',
|
||||
output: {
|
||||
filename: 'bundle.js',
|
||||
path: path.resolve(__dirname, 'dist')
|
||||
},
|
||||
devtool: 'nosources-source-map',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
use: 'ts-loader',
|
||||
exclude: /node_modules/
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
plugins: [
|
||||
new CleanPlugin.CleanWebpackPlugin()
|
||||
]
|
||||
}
|
||||
@@ -33,6 +33,15 @@ class Players {
|
||||
})
|
||||
}
|
||||
|
||||
updatePlayerHealth(id: string, health: number) {
|
||||
for (let player of this.players) {
|
||||
if (player.socketID === id) {
|
||||
player.player.setHealth(health)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getPlayers(): Player[] {
|
||||
let playerList = []
|
||||
for (let player of this.players) {
|
||||
@@ -56,14 +65,16 @@ class Player {
|
||||
private name: string
|
||||
private position: {x: number, y: number}
|
||||
private color: string
|
||||
private health: number
|
||||
|
||||
constructor(private socket: socketIO.Socket) {
|
||||
this.name = 'Player#' + Math.floor(Math.random() * 10000)
|
||||
this.position = {
|
||||
x: Math.random()*10 - 5,
|
||||
y: Math.random()*10 - 5,
|
||||
x: Math.random()*500 - 250,
|
||||
y: Math.random()*500 - 250,
|
||||
}
|
||||
this.color = '#' + (Math.floor(Math.random() * 256)).toString(16) + (Math.floor(Math.random() * 256)).toString(16) + (Math.floor(Math.random() * 256)).toString(16)
|
||||
this.health = 100
|
||||
}
|
||||
|
||||
getPlayerDescription() {
|
||||
@@ -72,9 +83,14 @@ class Player {
|
||||
color: this.color,
|
||||
position: this.position,
|
||||
id: this.socket.id,
|
||||
health: this.health
|
||||
}
|
||||
}
|
||||
|
||||
setHealth(hp: number) {
|
||||
this.health = hp
|
||||
}
|
||||
|
||||
setPosition(x: number, y: number) {
|
||||
this.position.x = x
|
||||
this.position.y = y
|
||||
@@ -92,27 +108,52 @@ app.use(express.static(path.join(__dirname, '/../../client/dist')))
|
||||
app.get('/', function(req, res) {
|
||||
res.sendFile('index.html', { root: __dirname + '/../../client/static/'});
|
||||
});
|
||||
app.get('/ded', function(req, res) {
|
||||
res.sendFile('ded.html', { root: __dirname + '/../../client/static/'});
|
||||
});
|
||||
|
||||
server.listen(8089, function(){
|
||||
server.listen(8089, function() {
|
||||
console.log('running on port 8089');
|
||||
});
|
||||
|
||||
io.on('connection', function(socket: socketIO.Socket) {
|
||||
console.log('Player connected');
|
||||
console.log(socket.id, 'connected');
|
||||
|
||||
let player = new Player(socket)
|
||||
let otherPlayers = []
|
||||
for (let p of players.getPlayers()) {
|
||||
otherPlayers.push(p.getPlayerDescription())
|
||||
}
|
||||
players.addPlayer(socket.id, player)
|
||||
socket.emit('players-info', otherPlayers)
|
||||
io.emit('new-player-joined', player.getPlayerDescription())
|
||||
socket.emit('your-info', player.getPlayerDescription())
|
||||
socket.on('message', function(msg) {
|
||||
console.log(msg)
|
||||
});
|
||||
|
||||
socket.on('get-other-players', () => {
|
||||
let otherPlayers = []
|
||||
for (let p of players.getPlayers()) {
|
||||
if (socket.id !== p.getPlayerDescription().id) {
|
||||
otherPlayers.push(p.getPlayerDescription())
|
||||
}
|
||||
}
|
||||
socket.emit('players-info', otherPlayers)
|
||||
})
|
||||
|
||||
io.emit('new-player-joined', player.getPlayerDescription())
|
||||
|
||||
|
||||
socket.on('i-moved', (position: {x: number, y: number}) => {
|
||||
players.updatePlayerPosition(socket.id, {x: position.x, y: position.y})
|
||||
io.emit('player-moved', {id: socket.id, position: position})
|
||||
})
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
console.log(socket.id, 'disconnected')
|
||||
players.removePlayer(socket.id)
|
||||
io.emit('player-disconnected', socket.id)
|
||||
})
|
||||
|
||||
socket.on('shoot', (data: {position: {x: number, y: number}, direction: {x: number, y: number}}) => {
|
||||
io.emit('shoot', {id: socket.id, position: data.position, direction: data.direction})
|
||||
})
|
||||
|
||||
socket.on('health-update', (data: {player: string, health: number}) => {
|
||||
players.updatePlayerHealth(data.player, data.health)
|
||||
io.emit('health-update', {id: data.player, health: data.health})
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user