//---------------------------------------------------------------------------------------------
// UncycloEngine 1 by Epic Ungames, 2019-2020
//---------------------------------------------------------------------------------------------
//----------------------------------mapinfo and object definition------------------------------
// Objects must also be defined in server-side javascript
function GameRule(RedClock, BlueClock, initialstate) {
this.state = initialstate; // 0: game ceased, 1: game setup, 2: game on!, 3: round end
this.RedClock = RedClock;
this.BlueClock = BlueClock;
this.currentdominating = 0; // 0: neutral, 1: red, 2:blue
this.reddominatingprogress = 0;
this.bluedominatingprogress = 0;
}
let redteamnum = 0;
let blueteamnum = 0;
function GameObject (pos, size, direction, team, collidetype, flag, health = 100) {
// pos: array[x, y], size: array(cube)[x, y]/integer(cylinder), direction: integer(degree)
this.pos = pos;
this.size = size;
this.rotation = [0, 0 ,0];
this.direction = direction; // define camera angle
this.height = 0;
this.scale = [1, 1, 1];
this.collidetype = collidetype; // 0: statical cubic(no direction), 1: cylinder
this.flag = flag; // free flag
this.team = team; // team : integer(0: not defined, 1: Red Yangachi, 2: Blue Yingeo, 3: Neutral)
this.state = 0; // state depends on type of Game Object(0 is usually initial state)
this.healthpoint = health;
this.maxhealthpoint = health;
this.canbedamaged = false;
this.cameraMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
this.cameraAngleRadians = 0;
this.updateCameraAngle = (event, value) => {
this.cameraAngleRadians = degToRad(value);
};
this.updatePosition = (index, value)=> {
switch (index) {
case 0:
this.pos[0] = value;
break;
case 2:
this.pos[1] = value;
break;
case 1:
this.height = value;
break;
default:
break;
}
};
this.vertexlist = [
// wall 1
2*pos[0], 32, 2*pos[1],
2*pos[0], -32, 2*pos[1],
2*pos[0], -32, 2*pos[1] + 2*size[1],
2*pos[0], 32, 2*pos[1],
2*pos[0], -32, 2*pos[1] + 2*size[1],
2*pos[0], 32, 2*pos[1] + 2*size[1],
// wall 2
2*pos[0]+ 2*size[0], 32, 2*pos[1],
2*pos[0]+ 2*size[0], -32, 2*pos[1] + 2*size[1],
2*pos[0]+ 2*size[0], -32, 2*pos[1],
2*pos[0]+ 2*size[0], 32, 2*pos[1],
2*pos[0]+ 2*size[0], 32, 2*pos[1] + 2*size[1],
2*pos[0]+ 2*size[0], -32, 2*pos[1] + 2*size[1],
// wall 3
2*pos[0], 32, 2*pos[1],
2*pos[0]+ 2*size[0], -32, 2*pos[1],
2*pos[0], -32, 2*pos[1],
2*pos[0], 32, 2*pos[1],
2*pos[0]+ 2*size[0], 32, 2*pos[1],
2*pos[0]+ 2*size[0], -32, 2*pos[1],
// wall 4
2*pos[0], 32, 2*pos[1] + 2*size[1],
2*pos[0], -32, 2*pos[1] + 2*size[1],
2*pos[0]+ 2*size[0], -32, 2*pos[1] + 2*size[1],
2*pos[0], 32, 2*pos[1] + 2*size[1],
2*pos[0]+ 2*size[0], -32, 2*pos[1] + 2*size[1],
2*pos[0]+ 2*size[0], 32, 2*pos[1] + 2*size[1]
];
this.updateRotation = (index, value) => {
var angleInDegrees = value;
var angleInRadians = (angleInDegree % 360) * Math.PI / 180;
this.rotation[index] = angleInRadians;
};
this.updatescale = (index, value) =>{
this.scale[index] = value;
};
this.GetCenterPosition = () => {
if (this.collidetype === 0) {
return [this.pos[0] + this.size[0] /2, this.pos[1] + this.size[1] / 2];
} else {
return [this.pos[0] + this.size, this.pos[1] + this.size];
}
};
this.SetCenterPosition = (position) => {
if (this.collidetype === 0) {
this.pos = [position[0] -this.size[0] /2, position[1] -this.size[1] / 2];
} else {
this.pos = [position[0] -this.size, position[1] - this.size];
}
};
this.IsColliding = (target) => {
if (this.collidetype === 0 && target.collidetype === 0) { // cube vs cube
if (this.GetCenterPosition()[0] + this.size[0]/2 >= target.GetCenterPosition()[0] - target.size[0]/2 && this.GetCenterPosition()[0] - this.size[0]/2 <= target.GetCenterPosition()[0] + target.size[0]/2 && this.GetCenterPosition()[1] + this.size[1]/2 >= target.GetCenterPosition()[1] - target.size[1]/2 && this.GetCenterPosition()[1] - this.size[1]/2 <= target.GetCenterPosition()[1] + target.size[1]/2) return true;
else return false;
} else if (this.collidetype === 0 && target.collidetype === 1) {
if (target.GetCenterPosition()[0] + target.size >= this.GetCenterPosition()[0] - this.size[0] / 2 && target.GetCenterPosition()[0] - target.size <= this.GetCenterPosition()[0] + this.size[0] / 2) { // horizontal collision
if (target.GetCenterPosition()[1] >= this.GetCenterPosition()[1] - this.size[1]/2 - target.size && target.GetCenterPosition()[1] <= this.GetCenterPosition()[1] + this.size[1]/2 + target.size ) return true;
}
if (target.GetCenterPosition()[1] + target.size >= this.GetCenterPosition()[1] - this.size[1] /2 && target.GetCenterPosition()[1] - target.size <= this.GetCenterPosition()[1] + this.size[1] /2) {
// vertical collision
if (target.GetCenterPosition()[0]+ target.size >= this.GetCenterPosition()[0] - this.size[0]/2 && target.GetCenterPosition()[0] - target.size <= this.GetCenterPosition()[0] + this.size[0] /2) {
return true;
}
}
// corner collision
let equation1 = (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0] - this.size[0] / 2)) * (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0]- this.size[0] / 2))+ (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]- this.size[1] / 2)) * (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]- this.size[1] / 2));
let equation2 = (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0] - this.size[0] / 2)) * (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0]- this.size[0] / 2))+ (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]+this.size[1]/2)) * (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]+this.size[1]/2));
let equation3 = (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0]+this.size[0]/2)) * (target.GetCenterPosition()[0]-(this.GetCenterPosition()[0]+this.size[0]/2))+ (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]- this.size[1] / 2)) * (target.GetCenterPosition()[1]-(this.GetCenterPosition()[1]- this.size[1] / 2));
let equation4 = (target.GetCenterPosition()[0]-this.GetCenterPosition()[0]-this.size[0]/2) * (target.GetCenterPosition()[0]-this.GetCenterPosition()[0]-this.size[0]/2)+ (target.GetCenterPosition()[1]-this.GetCenterPosition()[1]-this.size[1]/2) * (target.GetCenterPosition()[1]-this.GetCenterPosition()[1]-this.size[1]/2);
if (equation1 <= target.size* target.size || equation2 <= target.size* target.size || equation3 <= target.size* target.size || equation4 <= target.size* target.size) {
return true;
} else {
return false;
}
} else if (this.collidetype === 1 && target.collidetype === 0) {
if (this.GetCenterPosition()[0] + this.size >= target.GetCenterPosition()[0] - target.size[0] / 2 && this.GetCenterPosition()[0] - this.size <= target.GetCenterPosition()[0] + target.size[0]/2) { // horizontal collision
if (this.GetCenterPosition()[1] + this.size>= target.GetCenterPosition()[1] - target.size[1] / 2 && this.GetCenterPosition()[1] - this.size <= target.GetCenterPosition()[1] + target.size[1]/2 ) return true;
}
if (this.GetCenterPosition()[1] + this.size >= target.GetCenterPosition()[1] - target.size[1] / 2 && this.GetCenterPosition()[1] - this.size <= target.GetCenterPosition()[1] + target.size[1]/2 ) {
// vertical collision
if (this.GetCenterPosition()[0] + this.size>= target.GetCenterPosition()[0] - target.size[0] / 2 && this.GetCenterPosition()[0]- this.size <= target.GetCenterPosition()[0] + target.size[0] /2) {
return true;
}
}
// corner collision
let equation1 = (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0]+target.size[0]/2)) * (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0]+target.size[0]/2))+ (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]+target.size[1]/2)) * (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]+target.size[1]/2));
let equation2 = (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0] - target.size[0] / 2)) * (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0]- target.size[0] / 2))+ (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]+target.size[1]/2)) * (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]+target.size[1]/2));
let equation3 = (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0]+target.size[0]/2)) * (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0]+target.size[0]/2))+ (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1] - target.size[1] / 2)) * (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1] - target.size[1] / 2));
let equation4 = (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0] - target.size[0] / 2)) * (this.GetCenterPosition()[0]-(target.GetCenterPosition()[0] - target.size[0] / 2))+ (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]- target.size[1] / 2)) * (this.GetCenterPosition()[1]-(target.GetCenterPosition()[1]- target.size[1] / 2));
if (equation1 <= this.size* this.size || equation2 <= this.size* this.size || equation3 <= this.size* this.size || equation4 <= this.size* this.size) {
return true;
} else {
return false;
}
} else { // cylinder vs cylinder
if ((this.GetCenterPosition()[0] - target.GetCenterPosition()[0])*(this.GetCenterPosition()[0] - target.GetCenterPosition()[0]) + (this.GetCenterPosition()[1] - target.GetCenterPosition()[1])*(this.GetCenterPosition()[1] - target.GetCenterPosition()[1]) <= (this.size + target.size) * (this.size + target.size)) return true;
else return false;
}
return false; // this could not be happened
};
}
function Projectile(pos, size, direction, team, shooter, imgsrc, type = 0) {
GameObject.call(this, pos, size, direction, team, 1, 0, 1);
this.movespeed = 4;
this.shooter = shooter;
this.imgsrc = imgsrc;
this.visible = false;
this.type = type;
this.cameraMatrix = m4.lookAt([this.GetCenterPosition()[0],0,this.GetCenterPosition()[1]],[this.GetCenterPosition()[0]+Math.cos(this.direction), 0, this.GetCenterPosition()[1]+Math.sin(this.direction)], up );
this.vertexlist = [
];
}
Projectile.prototype = Object.create(GameObject.prototype);
Projectile.prototype.constructor = Projectile;
const MAX_PROJECTILE_PER_PLAYER = 100;
const MAX_PROJECTILE_NUMBER = 100 * MAX_PROJECTILE_PER_PLAYER;
let projectilelist = [];
function Explosion(pos, size, type = 0) {
GameObject.call(this, pos, size, 0, 0, 1, 0, 1);
this.type = type;
this.counter = 0;
this.active = true;
this.cameraMatrix = m4.lookAt([this.GetCenterPosition()[0],0,this.GetCenterPosition()[1]],[this.GetCenterPosition()[0]+Math.cos(this.direction), 0, this.GetCenterPosition()[1]+Math.sin(this.direction)], up );
this.vertexlist = GeneratePlaneVertex(this.GetCenterPosition(), size * 2, this.cameraMatrix);
}
Explosion.prototype = Object.create(GameObject.prototype);
Explosion.prototype.constructor = Explosion;
const MAX_EXPLOSION_NUMBER = 100 * MAX_PROJECTILE_PER_PLAYER;
let explosionlist = [];
function Player(pos, size, direction, team, health, id = 0, isdead = false, playername = "unknown player", classnum = 0) {
GameObject.call(this, pos, size, direction, team, 1, 0, health);
this.playername = playername;
this.playerID = id;
this.movespeed = 1;
this.classnumber = classnum;
this.canbedamaged = true;
this.isdead = isdead;
this.deadtimer;
this.secondweapon = undefined; // weapon 0
this.firstweapon = undefined; // weapon 1
this.currentweapon = 0;
this.ReloadWeapon = () => {
console.log("Reloaded");
};
this.FireWeapon = () =>{
console.log("Fired");
};
this.DoSpecialSkill = () => {
console.log("Did SpecialSkill");
};
this.ReleaseFire = () => {
return;
}
this.reloadDelaying = false;
this.raylist = []; // remember, this only has MAX_RAY_PER_PLAYER number of elements
this.moveSomething = () => {
let camMatrix = m4.lookAt([this.GetCenterPosition()[0],this.height,this.GetCenterPosition()[1]],[this.GetCenterPosition()[0]+Math.cos(this.direction), 0, this.GetCenterPosition()[1]+Math.sin(this.direction)], up );
let forwardvector = m4.getForward(camMatrix);
let rightvector = m4.getRight(camMatrix);
if (keystate[0] && keystate[2] || keystate[0] && keystate[3] || keystate[1] && keystate[2] || keystate[1] && keystate[3]) {
rightvector[0] *= 0.7071;
rightvector[2] *= 0.7071;
forwardvector[0] *= 0.7071;
forwardvector[2] *= 0.7071;
}
// remember, the map has reversed axis
if (keystate[0]){ // a
let freeToMove = true;
for (let mapobject of mapinfo.mapobjectlist) {
let tempmapobject = new GameObject([mapobject.pos[0] - this.movespeed*rightvector[0], mapobject.pos[1] ], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
if (tempmapobject.team != this.team && this.IsColliding(tempmapobject)) freeToMove = false;
}
if (freeToMove){
this.updatePosition(0, this.pos[0] + this.movespeed*rightvector[0]);
}
freeToMove = true;
for (let mapobject of mapinfo.mapobjectlist) {
let tempmapobject = new GameObject([mapobject.pos[0], mapobject.pos[1] - this.movespeed*rightvector[2]], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
}
if (freeToMove){
this.updatePosition(2, this.pos[1] + this.movespeed*rightvector[2]);
}
ws.send(JSON.stringify({
type:5,
id: this.playerID,
pos: this.pos,
direction: this.direction
}));
}
if (keystate[1]){ //d
let freeToMove = true;
for (let mapobject of mapinfo.mapobjectlist) {
let tempmapobject = new GameObject([mapobject.pos[0] + this.movespeed*rightvector[0], mapobject.pos[1] ], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
}
if (freeToMove){
this.updatePosition(0, this.pos[0] - this.movespeed*rightvector[0]);
}
freeToMove = true;
for (let mapobject of mapinfo.mapobjectlist) {
let tempmapobject = new GameObject([mapobject.pos[0], mapobject.pos[1] + this.movespeed*rightvector[2]], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
}
if (freeToMove){
this.updatePosition(2, this.pos[1] - this.movespeed*rightvector[2]);
}
ws.send(JSON.stringify({
type:5,
id: this.playerID,
pos: this.pos,
direction: this.direction
}));
}
if (keystate[2]) { //s
let freeToMove = true;
for (let mapobject of mapinfo.mapobjectlist) {
let tempmapobject = new GameObject([mapobject.pos[0] - this.movespeed*forwardvector[0], mapobject.pos[1] ], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
}
if (freeToMove){
this.updatePosition(0, this.pos[0] + this.movespeed*forwardvector[0]);
}
freeToMove = true;
for (let mapobject of mapinfo.mapobjectlist) {
let tempmapobject = new GameObject([mapobject.pos[0], mapobject.pos[1] - this.movespeed*forwardvector[2]], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
}
if (freeToMove){
this.updatePosition(2, this.pos[1] + this.movespeed*forwardvector[2]);
}
ws.send(JSON.stringify({
type:5,
id: this.playerID,
pos: this.pos,
direction: this.direction
}));
}
if (keystate[3]) { // w
let freeToMove = true;
for (let mapobject of mapinfo.mapobjectlist) {
let tempmapobject = new GameObject([mapobject.pos[0] + this.movespeed*forwardvector[0], mapobject.pos[1] ], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
}
if (freeToMove){
this.updatePosition(0, this.pos[0] -this.movespeed*forwardvector[0]);
}
freeToMove = true;
for (let mapobject of mapinfo.mapobjectlist) {
let tempmapobject = new GameObject([mapobject.pos[0], mapobject.pos[1] + this.movespeed*forwardvector[2]], mapobject.size, mapobject.direction, mapobject.team, mapobject.collidetype, mapobject.flag, mapobject.healthpoint);
if (tempmapobject.team != this.team &&this.IsColliding(tempmapobject)) freeToMove = false;
}
if (freeToMove){
this.updatePosition(2, this.pos[1] - this.movespeed*forwardvector[2]);
}
ws.send(JSON.stringify({
type:5,
id: this.playerID,
pos: this.pos,
direction: this.direction
}));
}
if (keystate[0] || keystate[1] || keystate[2] || keystate[3]) {
if ( heightcount >= 0 && heightcount <20) this.updatePosition(1, 0.1* heightcount);
else this.updatePosition(1, 2-0.1*heightcount);
if (heightcount >= 39) heightcount = 0;
else heightcount = heightcount +1;
}
if (keystate[4] && this.reloadDelaying === false) { // q
if (this.currentweapon === 0) {
this.secondweapon.isFiring = false;
this.currentweapon = 1;
} else {
this.firstweapon.isFiring = false;
this.currentweapon = 0;
}
ws.send(JSON.stringify({
type:16,
id: this.playerID,
currentweapon: this.currentweapon
}));
this.reloadDelaying = true;
setTimeout(this.keydelayEnd,400);
}
if (keystate[5]) { // e
}
if (keystate[6]) { // r
this.ReloadWeapon();
}
if (keystate[7]) { // f
}
}
this.keydelayEnd = () => {
this.reloadDelaying = false;
}
this.vertexlist = GeneratePlaneVertex(this.GetCenterPosition(), 32, this.cameraMatrix);
}
Player.prototype = Object.create(GameObject.prototype);
Player.prototype.constructor = Player;
let playerlist = [];
function Building(pos, size, direction, team, health, id = 0) {
Player.call(this, pos, size, direction, team, health, id)
}
Building.prototype = Object.create(Player.prototype);
Building.prototype.constructor = Building;
const mapobjectsizeconstant = 32;
function MapInfo (text) { // map infomation
this.rawmapdata = text;
let mapdataarray = this.rawmapdata.split('\n');
let mapsize = mapdataarray[0].split(' ');
this.mapheight = parseInt(mapsize[0]);
this.mapwidth = parseInt(mapsize[1]);
this.mapversion = parseInt(mapsize[2]);
this.mapdata = mapdataarray;
this.mapwallcounter = 0;
this.mapobjectlist = [];
this.maphealthkitlist = [];
let mapX = 64* this.mapwidth;
let mapY = 64* this.mapheight;
this.polygons = [
// ground
0, -32, 0,
mapX, -32, mapY,
mapX, -32, 0,
mapX, -32, mapY,
0, -32, 0,
0, -32, mapY,
// ceiling
0, 32, 0,
mapX, 32, 0,
mapX, 32, mapY,
mapX, 32, mapY,
0, 32, mapY,
0, 32, 0
// walls
];
this.mapColors = [
// ground and ceiling
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 0
// other wall
];
for (let i = 1; i <= this.mapheight; i++) {
for (let j = 0; j < this.mapwidth; j++){
switch (this.mapdata[i][j]) {
case 'R':
this.RedSpawn = [ mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)];
break;
case 'B':
this.BlueSpawn = [ mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)];
break;
case 'W':
this.mapobjectlist.push(new GameObject([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],0, 0, 0, 0));
break;
case 'Q':
this.mapobjectlist.push(new GameObject([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],0, 0, 0, 2));
break;
case 'A':
this.mapobjectlist.push(new GameObject([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],0, 0, 0, 1));
break;
case 'H':
this.maphealthkitlist.push(new Healthkit([mapobjectsizeconstant*j + 8, mapobjectsizeconstant*(i-1) +8], 8, this.maphealthkitlist.length));
break;
case 'Z':
this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],270, 2));
break;
case 'X':
this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],90, 2));
break;
case 'C':
this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],180, 2));
break;
case 'V':
this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],0, 2));
break;
case 'U':
this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],270, 1));
break;
case 'I':
this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],90, 1));
break;
case 'O':
this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],180, 1));
break;
case 'P':
this.mapobjectlist.push(new Door([mapobjectsizeconstant*j, mapobjectsizeconstant*(i-1)], [mapobjectsizeconstant, mapobjectsizeconstant],0, 1));
break;
default:
break; // do nothing
}
}
}
for (let object of this.mapobjectlist) {
if (object.constructor === GameObject) {
this.mapwallcounter += 4;
} else if (object.constructor === Door) {
this.mapwallcounter += 2;
}
this.polygons = this.polygons.concat(object.vertexlist);
}
}
function Healthkit(pos, size, id) {
GameObject.call(this, pos, size, 0, 0, 1, 1, 0);
this.id = id;
this.respawntime = 8000;
this.isSpawned = true;
this.respawntimer = undefined;
this.vertexlist = GenerateProjectile(this.GetCenterPosition(), size, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
this.respawn = () => {
this.isSpawned = true;
return;
}
}
Healthkit.prototype = Object.create(GameObject.prototype);
Healthkit.prototype.constructor = Healthkit;
function Door(pos, size, direction, team) {
GameObject.call(this, pos, size, direction, team, 0, 0, 100000);
switch (direction) {
case 0:
this.vertexlist = [
// wall (right)
2*pos[0] + 2* size[0], 32, 2*pos[1],
2*pos[0] + 2* size[0], -32, 2*pos[1]+2*size[1],
2*pos[0] + 2* size[0], -32, 2*pos[1],
2*pos[0] + 2* size[0], 32, 2*pos[1],
2*pos[0] + 2* size[0], 32, 2*pos[1]+2*size[1],
2*pos[0] + 2* size[0], -32, 2*pos[1]+2*size[1],
// wall (left)
2*pos[0] + 2* size[0] - 4, 32, 2*pos[1],
2*pos[0] + 2* size[0] - 4, -32, 2*pos[1],
2*pos[0] + 2* size[0] - 4, -32, 2*pos[1]+2*size[1],
2*pos[0] + 2* size[0] - 4, 32, 2*pos[1],
2*pos[0] + 2* size[0] - 4, -32, 2*pos[1]+2*size[1],
2*pos[0] + 2* size[0] - 4, 32, 2*pos[1]+2*size[1]
];
break;
case 90:
this.vertexlist = [
// wall (down)
2*pos[0], 32, 2*pos[1]+2*size[1],
2*pos[0], -32, 2*pos[1]+2*size[1],
2*pos[0] + 2* size[0], -32, 2*pos[1]+2*size[1],
2*pos[0], 32, 2*pos[1]+2*size[1],
2*pos[0] + 2* size[0], -32, 2*pos[1]+2*size[1],
2*pos[0] + 2* size[0], 32, 2*pos[1]+2*size[1],
// wall (Up)
2*pos[0], 32, 2*pos[1]+2*size[1]-4,
2*pos[0] + 2* size[0], -32, 2*pos[1]+2*size[1]-4,
2*pos[0], -32, 2*pos[1]+2*size[1]-4,
2*pos[0], 32, 2*pos[1]+2*size[1]-4,
2*pos[0] + 2* size[0], 32, 2*pos[1]+2*size[1]-4,
2*pos[0] + 2* size[0], -32, 2*pos[1]+2*size[1]-4
];
break;
case 180:
this.vertexlist = [
// wall (left)
2*pos[0], 32, 2*pos[1],
2*pos[0], -32, 2*pos[1],
2*pos[0], -32, 2*pos[1]+2*size[1],
2*pos[0], 32, 2*pos[1],
2*pos[0], -32, 2*pos[1]+2*size[1],
2*pos[0], 32, 2*pos[1]+2*size[1],
// wall (right)
2*pos[0] + 4, 32, 2*pos[1],
2*pos[0] + 4, -32, 2*pos[1]+2*size[1],
2*pos[0] + 4, -32, 2*pos[1],
2*pos[0] + 4, 32, 2*pos[1],
2*pos[0] + 4, 32, 2*pos[1]+2*size[1],
2*pos[0] + 4, -32, 2*pos[1]+2*size[1],
];
break;
case 270:
this.vertexlist = [
// wall (Up)
2*pos[0], 32, 2*pos[1],
2*pos[0] + 2* size[0], -32, 2*pos[1],
2*pos[0], -32, 2*pos[1],
2*pos[0], 32, 2*pos[1],
2*pos[0] + 2* size[0], 32, 2*pos[1],
2*pos[0] + 2* size[0], -32, 2*pos[1],
// wall (down)
2*pos[0], 32, 2*pos[1]+4,
2*pos[0], -32, 2*pos[1]+4,
2*pos[0] + 2* size[0], -32, 2*pos[1]+4,
2*pos[0], 32, 2*pos[1]+4,
2*pos[0] + 2* size[0], -32, 2*pos[1]+4,
2*pos[0] + 2* size[0], 32, 2*pos[1]+4
];
break;
default:
break;
}
}
Door.prototype = Object.create(GameObject.prototype);
Door.prototype.constructor = Door;
function AreaEquation(centerpos, firstcornerpos, secondcornerpos) { // 3 dimensional position
this.point = centerpos;
this.normalvector = m4.cross([centerpos[0]-firstcornerpos[0],centerpos[1]-firstcornerpos[1],centerpos[2]-firstcornerpos[2]], [centerpos[0]-secondcornerpos[0],centerpos[1]-secondcornerpos[1],centerpos[2]-secondcornerpos[2]]);
}
function LineEquation(startpos, endpos) { // 3 dimensional position
this.point = startpos;
this.linevector = [endpos[0] - startpos[0],endpos[1] - startpos[1],endpos[2] - startpos[2]];
}
function CylinderEquation(center, radius) {
this.centerpos = center;
this.radius = radius;
}
const MAX_RAY_PER_PLAYER = 10;
const MAX_RAY_NUM = 32 * MAX_RAY_PER_PLAYER;
function Ray (startpos, endpos) {
this.visible = false;
this.startpos = startpos; // array
this.endpos = endpos; // array
this.collidedobjectsinfo = []; // will contain list of GameObject objects and their penetrated positions
this.AddPenetratingObjects = (objectlist) => {
for (let object of objectlist){
let lineeq = new LineEquation(this.startpos, this.endpos);
if (object.collidetype === 0) { // cubic -> doing collision check 4 times
let areaeq1 = new AreaEquation([object.GetCenterPosition()[0]-object.size[0]/2, object.GetCenterPosition()[1],0], [object.GetCenterPosition()[0]-object.size[0]/2, object.GetCenterPosition()[1]-object.size[1]/2,mapobjectsizeconstant/2],[object.GetCenterPosition()[0]-object.size[0]/2, object.GetCenterPosition()[1]-object.size[1]/2,-mapobjectsizeconstant/2]);
let resultArray = LineTrace_Sub1(lineeq, areaeq1);
if (resultArray.length > 0 && resultArray[1] >= object.GetCenterPosition()[1]-object.size[1]/2 && resultArray[1] <= object.GetCenterPosition()[1]+object.size[1]/2) this.collidedobjectsinfo.push([object, resultArray]);
let areaeq2 = new AreaEquation([object.GetCenterPosition()[0], object.GetCenterPosition()[1]-object.size[1]/2,0], [object.GetCenterPosition()[0]-object.size[0]/2, object.GetCenterPosition()[1]-object.size[1]/2,mapobjectsizeconstant/2],[object.GetCenterPosition()[0]-object.size[0]/2, object.GetCenterPosition()[1]-object.size[1]/2,-mapobjectsizeconstant/2]);
resultArray = LineTrace_Sub1(lineeq, areaeq2);
if (resultArray.length > 0 && resultArray[0] >= object.GetCenterPosition()[0]-object.size[0]/2 && resultArray[0] <= object.GetCenterPosition()[0]+object.size[0]/2) this.collidedobjectsinfo.push([object, resultArray]);
let areaeq3 = new AreaEquation([object.GetCenterPosition()[0]+object.size[0]/2, object.GetCenterPosition()[1],0], [object.GetCenterPosition()[0]+object.size[0]/2, object.GetCenterPosition()[1]+object.size[1]/2,mapobjectsizeconstant/2],[object.GetCenterPosition()[0]+object.size[0]/2, object.GetCenterPosition()[1]+object.size[1]/2,-mapobjectsizeconstant/2]);
resultArray = LineTrace_Sub1(lineeq, areaeq3);
if (resultArray.length > 0 && resultArray[1] >= object.GetCenterPosition()[1]-object.size[1]/2 && resultArray[1] <= object.GetCenterPosition()[1]+object.size[1]/2) this.collidedobjectsinfo.push([object, resultArray]);
let areaeq4 = new AreaEquation([object.GetCenterPosition()[0], object.GetCenterPosition()[1]+object.size[1]/2,0], [object.GetCenterPosition()[0]+object.size[0]/2, object.GetCenterPosition()[1]+object.size[1]/2,mapobjectsizeconstant/2],[object.GetCenterPosition()[0]+object.size[0], object.GetCenterPosition()[1]+object.size[1],-mapobjectsizeconstant/2]);
resultArray = LineTrace_Sub1(lineeq, areaeq4);
if (resultArray.length > 0 && resultArray[0] >= object.GetCenterPosition()[0]-object.size[0]/2 && resultArray[0] <= object.GetCenterPosition()[0]+object.size[0]/2) this.collidedobjectsinfo.push([object, resultArray]);
} else if (object.collidetype === 1){ // cylinder -> only find success/fail
let cylindereq = new CylinderEquation(object.GetCenterPosition(), object.size);
let hitpoint = LineTrace_Sub2(lineeq, cylindereq);
if ((hitpoint[0] - this.startpos[0]) * (hitpoint[0] - this.startpos[0]) + (hitpoint[1] - this.startpos[1]) + (hitpoint[2] - this.startpos[2]) * (hitpoint[2] - this.startpos[2]) < (this.endpos[0] - this.startpos[0]) * (this.endpos[0] - this.startpos[0]) + (this.endpos[1] - this.startpos[1]) * (this.endpos[1] - this.startpos[1]) + (this.endpos[2] - this.startpos[2]) * (this.endpos[2] - this.startpos[2]) ) this.collidedobjectsinfo.push([object, hitpoint]);
}
}
}
this.GetClosestCollidedPosition = () => { // only find cube collided position;
let collidedposition = this.endpos;
for (let objectinfo of this.collidedobjectsinfo) {
if (objectinfo.length > 1) {
let line1 = new LineEquation(this.startpos, objectinfo[1]);
let criterionline = new LineEquation(this.startpos, this.endpos);
if (m4.normalize(criterionline.linevector)[0] * m4.normalize(line1.linevector)[0] >0 && GetLineLength(this.startpos, objectinfo[1]) <= GetLineLength(this.startpos, collidedposition)) collidedposition = objectinfo[1];
}
}
return collidedposition;
}
this.GetClosestCollidedObject = (rayownerid = -1) => { // only find cube collided position;
let collidedposition = this.endpos;
let collidedobject = undefined;
for (let objectinfo of this.collidedobjectsinfo) {
if (objectinfo[0].constructor === Player && objectinfo[0].playerID === rayownerid) continue;
if (objectinfo.length > 1) {
let line1 = new LineEquation(this.startpos, objectinfo[1]);
let criterionline = new LineEquation(this.startpos, this.endpos);
if (m4.normalize(criterionline.linevector)[0] * m4.normalize(line1.linevector)[0] >0 && GetLineLength(this.startpos, objectinfo[1]) <= GetLineLength(this.startpos, collidedposition)) {
collidedposition = objectinfo[1];
collidedobject = objectinfo[0];
}
}
}
return collidedobject;
}
this.DrawRay = () => {
this.visible = true;
setTimeout(this.DrawRay_timeout, 50);
return;
}
this.DrawRay_timeout = () => {
this.visible = false;
return;
}
};
// -----------------------------------------------global data-------------------------------------------
const up = [0, 1, 0];
// player state
let fieldOfViewRadians = degToRad(90);
let heightcount = 0;
// --------------------------------------------global function -----------------------------------------------
String.format = function() {
// The string containing the format items (e.g. "{0}")
// will and always has to be the first argument.
var theString = arguments[0];
// start with the second argument (i = 1)
for (var i = 1; i < arguments.length; i++) {
// "gm" = RegEx options for Global search (more than one instance)
// and for Multiline search
var regEx = new RegExp("\\{" + (i - 1) + "\\}", "gm");
theString = theString.replace(regEx, arguments[i]);
}
return theString;
}
function radToDeg(r) {
return r * 180 / Math.PI;
}
function degToRad(d) {
return d * Math.PI / 180;
}
function LineTrace_Sub1(lineeq, areaeq) {
if (lineeq.linevector[0] * areaeq.normalvector[0] + lineeq.linevector[1] * areaeq.normalvector[1] === 0) return [];
let t = -(areaeq.normalvector[0]*(lineeq.point[0]-areaeq.point[0]) + areaeq.normalvector[1]*(lineeq.point[1]-areaeq.point[1]) + areaeq.normalvector[2]*(lineeq.point[2]-areaeq.point[2])) / (areaeq.normalvector[0]*lineeq.linevector[0] + areaeq.normalvector[1]*lineeq.linevector[1] +areaeq.normalvector[2]*lineeq.linevector[2]);
return [lineeq.linevector[0]*t + lineeq.point[0], lineeq.linevector[1]*t + lineeq.point[1],lineeq.linevector[2]*t + lineeq.point[2]];
}
function LineTrace_Sub2(lineeq, cylindereq) {
let a = lineeq.linevector[0];
let b = lineeq.linevector[1];
let c = cylindereq.centerpos[0] - lineeq.point[0];
let d = cylindereq.centerpos[1] - lineeq.point[1];
let t1 = (a*c + b* d + Math.sqrt( (a*c + b*d) * (a*c + b*d) - (a*a + b*b) * (c*c + d* d - cylindereq.radius * cylindereq.radius) )) / (a*a + b*b);
let t2 = (a*c + b* d - Math.sqrt( (a*c + b*d) * (a*c + b*d) - (a*a + b*b) * (c*c + d* d - cylindereq.radius * cylindereq.radius) )) / (a*a + b*b);
let dx1 = a * t1;
let dy1 = b * t1;
let dx2 = a * t2;
let dy2 = b * t2;
return dx1*dx1+ dy1*dy1 < dx2*dx2 + dy2*dy2 ? [dx1 + lineeq.point[0], dy1 + lineeq.point[1], lineeq.linevector[2]* t1 + lineeq.point[2]] : [dx2 + lineeq.point[0], dy2 + lineeq.point[1], lineeq.linevector[2]* t2 + lineeq.point[2]];
}
function GetLineLength(startpos, endpos) {
return Math.sqrt((endpos[0] - startpos[0])* (endpos[0] - startpos[0]) + (endpos[1] - startpos[1]) * (endpos[1] - startpos[1]) + (endpos[2] - startpos[2]) * (endpos[2] - startpos[2]));
}
function createShader(gl, type, source) {
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (success) {
return shader;
}
console.log(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
}
function createProgram(gl, vertexShader, fragmentShader) {
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
var success = gl.getProgramParameter(program, gl.LINK_STATUS);
if (success) {
return program;
}
console.log(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
}
function updateFieldOfView(event, value) {
fieldOfViewRadians = degToRad(value);
}
function GenerateProjectile(pos, size, cameraMatrix) { // pos: [x, y](center), size: integer, cameraMatrix: 4x4 matrix
return [
//plane 1
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
//plane 2
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
// plane 3
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
// plane 4
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2]
];
}
function GeneratePlaneVertex(pos, size, cameraMatrix) { // pos: [x, y](center), size: integer, height: interger, cameraMatrix: 4x4 matrix
return [
//plane
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
//plane 2
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
// plane 3
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]-size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]-size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]-size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
// plane 4
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] -size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
-size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] -size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] - size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] - size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] - size *m4.getUp(cameraMatrix)[2],
2*pos[0] +size* m4.getForward(cameraMatrix)[0]+size* m4.getRight(cameraMatrix)[0] + size *m4.getUp(cameraMatrix)[0],
size* m4.getForward(cameraMatrix)[1]+size* m4.getRight(cameraMatrix)[1] + size *m4.getUp(cameraMatrix)[1],
2*pos[1] +size* m4.getForward(cameraMatrix)[2]+size* m4.getRight(cameraMatrix)[2] + size *m4.getUp(cameraMatrix)[2]
];
}
// ------------------------------------------------ input control ------------------------------------------------
let keystate = [];
function Input(screen) {
this.screen = screen;
this.target;
this.keyboardinputtimer;
this.havePointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
this.InitInput = () => {
if (this.havePointerLock){
this.screen.onclick = () => { // requestPointerLock must be in callback
this.screen.requestPointerLock = this.screen.requestPointerLock || this.screen.mozRequestPointerLock || this.screen.webkitRequestPointerLock;
// Ask the browser to lock the pointer
this.screen.requestPointerLock();
}
// Hook pointer lock state change events
document.addEventListener('pointerlockchange', this.changeCallback, false);
document.addEventListener('mozpointerlockchange', this.changeCallback, false);
document.addEventListener('webkitpointerlockchange', this.changeCallback, false);
document.addEventListener('pointerlockerror', this.errorCallback, false);
document.addEventListener('mozpointerlockerror', this.errorCallback, false);
document.addEventListener('webkitpointerlockerror', this.errorCallback, false);
}
return;
}
// ----------------------mouse management----------------------------------
this.GrabInput = (target) => {
this.target = target;
this.keyboardinputtimer = setInterval(this.target.moveSomething, 10);
return;
};
this.manageKeyboardInputDown = () => {
if (event.keyCode === 65 || event.keyCode === 97) //a
keystate[0] = true;
if (event.keyCode === 68 || event.keyCode === 100) //d
keystate[1] = true;
if (event.keyCode === 83 || event.keyCode === 115) //s
keystate[2] = true;
if (event.keyCode === 87 || event.keyCode === 119) // w
keystate[3] = true;
if (event.keyCode === 81 || event.keyCode === 113) // q
keystate[4] = true;
if (event.keyCode === 69 || event.keyCode === 101) //e
keystate[5] = true;
if (event.keyCode === 82 || event.keyCode === 114) //r
keystate[6] = true;
if (event.keyCode === 70 || event.keyCode === 102) // f
keystate[7] = true;
};
this.manageKeyboardInputUp = () => {
if (event.keyCode === 65 || event.keyCode === 97) // a
keystate[0] = false;
if (event.keyCode === 68 || event.keyCode === 100) //d
keystate[1] = false;
if (event.keyCode === 83 || event.keyCode === 115) //s
keystate[2] = false;
if (event.keyCode === 87 || event.keyCode === 119) //w
keystate[3] = false;
if (event.keyCode === 81 || event.keyCode === 113) //q
keystate[4] = false;
if (event.keyCode === 69 || event.keyCode === 101) //e
keystate[5] = false;
if (event.keyCode === 82 || event.keyCode === 114) //r
keystate[6] = false;
if (event.keyCode === 70 || event.keyCode === 102) // f
keystate[7] = false;
};
this.errorCallback = (e) => {
alert( "Fail to initialize point lock process" );
}
this.moveCallback = (e) => {
let movementX = 0;
let movementY = 0;
movementX = e.movementX ||
e.mozMovementX ||
e.webkitMovementX ||
0,
movementY = e.movementY ||
e.mozMovementY ||
e.webkitMovementY ||
0;
if (this.target != undefined) {
this.target.direction = this.target.direction + degToRad(movementX);
ws.send(JSON.stringify({
type:5,
id: this.target.playerID,
pos: this.target.pos,
direction: this.target.direction
}));
}
}
this.ReleasePlayer = () => {
clearInterval(this.keyboardinputtimer);
return;
}
this.changeCallback = (e) => {
if (document.pointerLockElement === this.screen ||
document.mozPointerLockElement === this.screen ||
document.webkitPointerLockElement === this.screen) {
// Pointer was just locked
// Enable the mousemove listener
document.addEventListener("mousemove", this.moveCallback);
document.addEventListener("keydown", this.manageKeyboardInputDown);
document.addEventListener("keyup", this.manageKeyboardInputUp);
document.onmousedown = () => {
switch(event.button) {
case 0:
this.target.FireWeapon();
break;
case 2:
this.target.DoSpecialSkill();
break;
default:
break;
}
}
document.onmouseup = () => {
if (event.button === 0) this.target.ReleaseFire();
return;
}
} else {
// Disable the mousemove listener
document.removeEventListener("mousemove", this.moveCallback);
document.removeEventListener("keydown", this.manageKeyboardInputDown);
document.removeEventListener("keyup", this.manageKeyboardInputUp);
document.onmousedown = () => {
return;
}
document.onmouseup = () => {
return;
}
}
}
}
// ------------------------------------------ Engine Main ----------------------------------------------
let mapdataurl = "http://libertyga.me/index.php?title=%EC%82%AC%EC%9A%A9%EC%9E%90:Senouis/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8/%ED%85%8C%EC%8A%A4%ED%8A%B8%EB%A7%B5&action=raw";
let mapinfo; // map information object
let player;
let gamerule;
function EngineMain() {
// init player
player = new Player([0, 0], 8, degToRad(0), 1);
gamerule = new GameRule(0, 0, 0);
// ----------------------------Procedure Start--------------------------------
// Get A WebGL context
let canvas = document.getElementById("MainCanvas");
let gl = canvas.getContext("webgl");
if (!gl) {
return;
}
// setup GLSL program
let vertexshader = createShader(gl, gl.VERTEX_SHADER, document.getElementById("3d-vertex-shader").text);
let fragmentshader = createShader(gl, gl.FRAGMENT_SHADER, document.getElementById("3d-fragment-shader").text);
let program = createProgram(gl, vertexshader, fragmentshader);
let planevertexshader = createShader(gl, gl.VERTEX_SHADER, document.getElementById("2d-vertex-shader").text);
let planefragmentshader = createShader(gl, gl.FRAGMENT_SHADER, document.getElementById("2d-fragment-shader").text);
let textureprogram = createProgram(gl, planevertexshader, planefragmentshader);
// load map data
mapinfo = new MapInfo ("25 45 1\n\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\
AFFFFFPFFFFFFFFFFFFAFFFFFFFFFAFFFFFFFFFFFFFFW\n\
AFFFFFPFFFFFFFFFFFFWFFFFFFFFFWFFFFFFFFFFFFFFW\n\
AFFRFFAAAFFFFFFFFFFFFFFFFFFFFFFFFFFFAAAAAFFFW\n\
AFFFFHAFFFFFFFFFFFFWFFFFHFFFFWFFFFFFFFFFWFFFW\n\
AFFFHHAFFFFFFFFWAAAAAAAAAAAAAWFFFFFFFFFFWFFFW\n\
AIIAAAAFFFFFFFFFFFFFFFFFFFFFFWFFFFFFFFFFWFFFW\n\
AFFAFFFFFFFFFFFWFFFAAAAAAAFFFWWWWWWFFFFFWFFFW\n\
AFFAFFFFFFFAAAAWFFFFFFFFFFFFFFFFFFFFFFFFFFFFW\n\
AFFFFFFFFFFFFFFWFFFFFFFFFFFFFFFFFFFFFFFFFFFFW\n\
AFFFFFFFFFFFFFFWWWWWFFFFFWWWFFFFFFAWWWWHFFFFW\n\
WWWWFFFFFFAFFFFFFWFFFFFFFFFWFFFFFFAFFFFFFFFFW\n\
WFFFFFFFFFAFFFFFFFFFFFTFFFFFFFFFFFQFFFFFFFFFW\n\
WFFFFFFFFFQFFFFFFWFFFFFFFFFWFFFFFFQFFFFFFWWWW\n\
WFFFFHWWWWQFFFFFFWWWFFFFFWWWWWFFFFFFFFFFFFFFQ\n\
WFFFFFFFFFFFFFFFFFFFFFFFFFFFFWFFFFFFFFFFFFFFQ\n\
WFFFFFFFFFFFFFFFFFFFFFFFFFFFFWQQQQFFFFFFFQFFQ\n\
WFFFWFFFFFWWWWWWFFFQQQQQQQFFFWFFFFFFFFFFFQFFQ\n\
WFFFWFFFFFFFFFFWFFFFFFFFFFFFFFFFFFFFFFQQQQZZQ\n\
WFFFWFFFFFFFFFFWQQQQQQQQQQQQQWFFFFFFFFQHHFFFQ\n\
WFFFWFFFFFFFFFFWFFFFHFFFFWFFFFFFFFFFFFQHFFFFQ\n\
WFFFQQQQQFFFFFFFFFFFFFFFFFFFFFFFFFFFQQQFFBFFQ\n\
WFFFFFFFFFFFFFFWFFFFFFFFFWFFFFFFFFFFFFCFFFFFQ\n\
WFFFFFFFFFFFFFFQFFFFFFFFFQFFFFFFFFFFFFCFFFFFQ\n\
QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ");
ProcedureAfterMapDataload();
DoSomethingAfterMapLoad();
// ----------------------Procedure End--------------------------------------
//---------------------------------- function used inside the procedure -----------------------------------------
function ProcedureAfterMapDataload () {
// -------------------------- initialize web socket ----------------------------------------
ws = new WebSocket("ws://" + ip );
ws.addEventListener("error" , function() {
alert("Failed to connect to server...");
})
ws.addEventListener("open", function() {
});
ws.addEventListener("message", messageHandler);
ws.addEventListener("close", closeHandler);
//------------------------ get attribute from 3D Shader program ----------------------------
// look up where the vertex, color data needs to go.
var positionLocation = gl.getAttribLocation(program, "a_position");
let colorLocation = gl.getAttribLocation(program, "a_color");
// lookup uniforms
var matrixLocation = gl.getUniformLocation(program, "u_matrix");
//------------------------ get attribute from 2D Shader program ----------------------------
// look up where the vertex, color data needs to go.
let texpositionLocation = gl.getAttribLocation(textureprogram, "a_position");
let texcoordLocation = gl.getAttribLocation(textureprogram, "a_texcoord");
// lookup uniforms
let texmatrixLocation = gl.getUniformLocation(textureprogram, "u_matrix");
let textureLocation = gl.getUniformLocation(textureprogram, "u_texture");
// ----------------------- Create Buffer ------------------------------
let positionBuffer = gl.createBuffer();
// Put geometry data into buffer
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
setMapGeometry(gl, mapinfo);
// Put color data into buffer
let colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
setMapColors(gl, mapinfo);
// Put coordinate for texture
let texcoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
let texcoords = new Array(2* 6 * 32* MAX_PROJECTILE_PER_PLAYER);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoords), gl.STATIC_DRAW);
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
let img = new Image();
img.src = "https://static.miraheze.org/libertygamewiki/7/7e/UF_Rocket_Red.png";
img.crossOrigin = "anonymous";
img.addEventListener('load', function() {
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
});
let redplayertex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, redplayertex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255]));
let redplayerimg = new Image();
redplayerimg.src = "https://static.miraheze.org/libertygamewiki/c/c7/UF_Player_Red.png";
redplayerimg.crossOrigin = "anonymous";
redplayerimg.addEventListener('load', function() {
gl.bindTexture(gl.TEXTURE_2D, redplayertex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, redplayerimg);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
});
let blueplayertex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, blueplayertex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 255, 255]));
let blueplayerimg = new Image();
blueplayerimg.src = "https://static.miraheze.org/libertygamewiki/d/d7/UF_Player_Blue.png";
blueplayerimg.crossOrigin = "anonymous";
blueplayerimg.addEventListener('load', function() {
gl.bindTexture(gl.TEXTURE_2D, blueplayertex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, blueplayerimg);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
});
// dead image
let redplayerdeadtex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, redplayerdeadtex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255]));
let redplayerdeadimg = new Image();
redplayerdeadimg.src = "https://static.miraheze.org/libertygamewiki/f/f4/UF_Player_Dead_Red.png";
redplayerdeadimg.crossOrigin = "anonymous";
redplayerdeadimg.addEventListener('load', function() {
gl.bindTexture(gl.TEXTURE_2D, redplayerdeadtex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, redplayerdeadimg);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
});
let blueplayerdeadtex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, blueplayerdeadtex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 255, 255]));
let blueplayerdeadimg = new Image();
blueplayerdeadimg.crossOrigin = "anonymous";
blueplayerdeadimg.src = "https://static.miraheze.org/libertygamewiki/6/6a/UF_Player_Dead_Blue.png";
blueplayerdeadimg.addEventListener('load', function() {
gl.bindTexture(gl.TEXTURE_2D, blueplayerdeadtex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, blueplayerdeadimg);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
});
let explosiontex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, explosiontex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 255, 255]));
let explosionimg = new Image();
explosionimg.src = "https://static.miraheze.org/libertygamewiki/f/f0/UF_Explosion.png";
explosionimg.crossOrigin = "anonymous";
explosionimg.addEventListener('load', function() {
gl.bindTexture(gl.TEXTURE_2D, explosiontex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, explosionimg);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
});
var healthkittex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, healthkittex);
let healthkitimg = new Image();
healthkitimg.src = "https://static.miraheze.org/libertygamewiki/4/46/UF_Healthkit.png";
healthkitimg.crossOrigin = "anonymous";
healthkitimg.addEventListener('load', function() {
gl.bindTexture(gl.TEXTURE_2D, healthkittex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, healthkitimg);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
});
// Draw screen
requestAnimationFrame(drawScene);
// Draw the scene.
function drawScene() {
// Tell WebGL how to convert from clip space to pixels
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.enable(gl.CULL_FACE);
gl.enable(gl.BLEND);
gl.enable(gl.DEPTH_TEST);
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
// Clear the canvas.
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// Tell it to use our program (pair of shaders)
gl.useProgram(program);
// Turn on the attribute
gl.enableVertexAttribArray(positionLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
var size = 3; // 3 components per iteration
var type = gl.FLOAT; // the data is 32bit floats
var normalize = false; // don't normalize the data
var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position
var offset = 0; // start at the beginning of the buffer
gl.vertexAttribPointer( positionLocation, size, type, normalize, stride, offset);
// Turn on the color attribute
gl.enableVertexAttribArray(colorLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
// Tell the attribute how to get data out of colorBuffer (ARRAY_BUFFER)
var size = 3; // 3 components per iteration
var type = gl.UNSIGNED_BYTE; // the data is 8bit unsigned values
var normalize = true; // normalize the data (convert from 0-255 to 0-1)
var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position
var offset = 0; // start at the beginning of the buffer
gl.vertexAttribPointer(colorLocation, size, type, normalize, stride, offset);
// Compute the matrix
var aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
var zNear = 1;
var zFar = 10000;
var projectionMatrix = m4.perspective(fieldOfViewRadians, aspect, zNear, zFar);
projectionMatrix = m4.xRotate(projectionMatrix, player.rotation[0]);
projectionMatrix = m4.yRotate(projectionMatrix, player.rotation[1]);
projectionMatrix = m4.zRotate(projectionMatrix, player.rotation[2]);
projectionMatrix = m4.scale(projectionMatrix, player.scale[0], player.scale[1], player.scale[2]);
// Compute a matrix for the camera
player.cameraMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
player.cameraMatrix = m4.yRotation(player.direction);
player.cameraMatrix = m4.translate(player.cameraMatrix, -player.GetCenterPosition()[0], player.height, -player.GetCenterPosition()[1]);
// Compute a view projection matrix
var viewProjectionMatrix = m4.multiply(projectionMatrix, player.cameraMatrix);
var matrix = m4.translate(viewProjectionMatrix, -player.GetCenterPosition()[0], player.height, -player.GetCenterPosition()[1]);
// Set the matrix.
gl.uniformMatrix4fv(matrixLocation, false, matrix);
// --------------------------------------------------------draw!!!!-------------------------------------------------
// Draw map objects
// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
offset = 0;
var count = (2+mapinfo.mapwallcounter) * 6;
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
let tempArray = mapinfo.polygons;
let polygonArray = new Float32Array(tempArray);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
// Bind the color buffer.
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
tempArray = mapinfo.mapColors;
let mapColorArray = new Uint8Array( tempArray );
gl.bufferSubData(gl.ARRAY_BUFFER, 0, mapColorArray);
gl.drawArrays(gl.TRIANGLES, offset, count);
// Draw rays
for (let playeritem of playerlist) {
for (let ray of playeritem.raylist) {
if (playeritem.raylist.indexOf(ray) > 10) continue;
else if (ray.visible) {
tempArray = [];
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
tempArray = tempArray.concat([2*ray.startpos[0], ray.startpos[2], 2*ray.startpos[1]]);
tempArray = tempArray.concat([2*ray.endpos[0], 0, 2*ray.endpos[1]]);
polygonArray = new Float32Array(tempArray);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
tempArray =[255, 255, 0, 255, 255, 0];
mapColorArray = new Uint8Array( tempArray );
gl.bufferSubData(gl.ARRAY_BUFFER, 0, mapColorArray);
// we have already set the matrix, so directly draw
gl.drawArrays(gl.LINES, 0, 2);
}
}
}
// Draw projectiles
// Tell WebGL to use our shader program pair
gl.useProgram(textureprogram);
gl.enableVertexAttribArray(texpositionLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
var size = 3; // 3 components per iteration
var type = gl.FLOAT; // the data is 32bit floats
var normalize = false; // don't normalize the data
var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position
var offset = 0; // start at the current position
gl.vertexAttribPointer( texpositionLocation, size, type, normalize, stride, offset);
// Setup the attributes to pull data from our buffers
gl.enableVertexAttribArray(texcoordLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
gl.vertexAttribPointer(texcoordLocation, 2, gl.FLOAT, false, 0, 0);
// fill the polygon buffer
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
tempArray = [];
count = 0;
for (let proj of projectilelist) {
tempArray = tempArray.concat(proj.vertexlist);
count += 4*6;
}
polygonArray = new Float32Array(tempArray);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
// Tell the shader to get the texture from texture unit 0
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
tempArray = [];
for (let proj of projectilelist) {
tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
tempArray = tempArray.concat([0.5, 0.5, 0.5, 1.0, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
tempArray = tempArray.concat([0, 0, 0.5, 0, 0, 0.5, 0, 0.5, 0.5, 0, 0.5, 0.5]);
tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
}
let texcoordinates = new Float32Array( tempArray );
gl.bufferSubData(gl.ARRAY_BUFFER, 0, texcoordinates);
// Set the matrix.
gl.uniformMatrix4fv(texmatrixLocation, false, matrix);
gl.uniform1i(textureLocation, 0);
gl.drawArrays(gl.TRIANGLES, 0, count);
// Draw Player
for (let playeritem of playerlist) {
if (playeritem.playerID === player.playerID) continue;
tempArray = [];
count = 4*6;
// vertex
if (playeritem.team === 1) {
if (playeritem.isdead) gl.bindTexture(gl.TEXTURE_2D, redplayerdeadtex);
else gl.bindTexture(gl.TEXTURE_2D, redplayertex);
} else {
if (playeritem.isdead) gl.bindTexture(gl.TEXTURE_2D, blueplayerdeadtex);
else gl.bindTexture(gl.TEXTURE_2D, blueplayertex);
}
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
playeritem.vertexlist = GeneratePlaneVertex(playeritem.GetCenterPosition(), 32, m4.lookAt([playeritem.GetCenterPosition()[0], playeritem.height, playeritem.GetCenterPosition()[1]], [player.GetCenterPosition()[0], player.height, player.GetCenterPosition()[1]], up));
tempArray = tempArray.concat(playeritem.vertexlist);
polygonArray = new Float32Array(tempArray);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
// texture coordinate
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
tempArray = [];
if (radToDeg(playeritem.direction - player.direction) % 360 >= 315 || ( radToDeg(playeritem.direction - player.direction) % 360 >= -45 && radToDeg(playeritem.direction - player.direction) % 360 < 45 ) || radToDeg(playeritem.direction - player.direction) % 360 < -315 ) {
tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
} else if ((radToDeg(playeritem.direction - player.direction) % 360 >= 45 && radToDeg(playeritem.direction - player.direction) % 360 < 135) ||(radToDeg(playeritem.direction - player.direction) % 360 < -225 && radToDeg(playeritem.direction - player.direction) % 360 >= -315)) {
tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
} else if ((radToDeg(playeritem.direction - player.direction) % 360 >= 135 && radToDeg(playeritem.direction - player.direction) % 360 < 225) || (radToDeg(playeritem.direction - player.direction) % 360 < -135 && radToDeg(playeritem.direction - player.direction) % 360 >= -225)) {
tempArray = tempArray.concat([0, 0, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0.5, 0.5, 0]);
tempArray = tempArray.concat([0, 0, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0.5, 0.5, 0]);
tempArray = tempArray.concat([0, 0, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0.5, 0.5, 0]);
tempArray = tempArray.concat([0, 0, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0.5, 0.5, 0]);
} else {
tempArray = tempArray.concat([0.5, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
tempArray = tempArray.concat([0.5, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
tempArray = tempArray.concat([0.5, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
tempArray = tempArray.concat([0.5, 0.5, 0.5, 1, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
}
texcoordinates = new Float32Array( tempArray );
gl.bufferSubData(gl.ARRAY_BUFFER, 0, texcoordinates);
// Set the matrix and draw.
gl.drawArrays(gl.TRIANGLES, 0, count);
}
// Draw Healthkit
gl.bindTexture(gl.TEXTURE_2D, healthkittex);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
tempArray = [];
count = 0;
for (let kit of mapinfo.maphealthkitlist) {
if (kit.isSpawned) {
tempArray = tempArray.concat(kit.vertexlist);
count += 4*6;
}
}
polygonArray = new Float32Array(tempArray);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
// Tell the shader to get the texture from texture unit 0
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
tempArray = [];
for (let kit of mapinfo.maphealthkitlist) {
if (kit.isSpawned) {
tempArray = tempArray.concat([0.5, 0, 0.5, 0.5, 1, 0.5, 0.5, 0, 1, 0.5, 1, 0]);
tempArray = tempArray.concat([0.5, 0.5, 0.5, 1.0, 1, 1, 0.5, 0.5, 1, 1, 1, 0.5]);
tempArray = tempArray.concat([0, 0, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 0.5, 0.5, 0]);
tempArray = tempArray.concat([0, 0.5, 0, 1, 0.5, 1, 0, 0.5, 0.5, 1, 0.5, 0.5]);
}
}
texcoordinates = new Float32Array( tempArray );
gl.bufferSubData(gl.ARRAY_BUFFER, 0, texcoordinates);
// Set the matrix.
gl.uniformMatrix4fv(texmatrixLocation, false, matrix);
gl.uniform1i(textureLocation, 0);
gl.drawArrays(gl.TRIANGLES, 0, count);
// Draw Explosion
for (let explosion of explosionlist) {
if (explosion.active === false) {
continue;
}
tempArray = [];
count = 4*6;
gl.bindTexture(gl.TEXTURE_2D, explosiontex);
// vertex
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
explosion.vertexlist = GeneratePlaneVertex(explosion.GetCenterPosition(), 32, m4.lookAt([explosion.GetCenterPosition()[0], explosion.height, explosion.GetCenterPosition()[1]], [player.GetCenterPosition()[0], player.height, player.GetCenterPosition()[1]], up));
tempArray = tempArray.concat(explosion.vertexlist);
polygonArray = new Float32Array(tempArray);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, polygonArray);
// texture coordinate
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
tempArray = [];
if ( explosion.counter === 0 ) {
tempArray = tempArray.concat([0, 0, 0, 1, 0.25, 1, 0, 0, 0.25, 1, 0.25, 0]);
tempArray = tempArray.concat([0, 0, 0, 1, 0.25, 1, 0, 0, 0.25, 1, 0.25, 0]);
tempArray = tempArray.concat([0, 0, 0, 1, 0.25, 1, 0, 0, 0.25, 1, 0.25, 0]);
tempArray = tempArray.concat([0, 0, 0, 1, 0.25, 1, 0, 0, 0.25, 1, 0.25, 0]);
} else if (explosion.counter === 1) {
tempArray = tempArray.concat([0.25, 0, 0.25, 1, 0.5, 1, 0.25, 0, 0.5, 1, 0.5, 0]);
tempArray = tempArray.concat([0.25, 0, 0.25, 1, 0.5, 1, 0.25, 0, 0.5, 1, 0.5, 0]);
tempArray = tempArray.concat([0.25, 0, 0.25, 1, 0.5, 1, 0.25, 0, 0.5, 1, 0.5, 0]);
tempArray = tempArray.concat([0.25, 0, 0.25, 1, 0.5, 1, 0.25, 0, 0.5, 1, 0.5, 0]);
} else if (explosion.counter === 2) {
tempArray = tempArray.concat([0.5, 0, 0.5, 1, 0.75, 1, 0.5, 0, 0.75, 1, 0.75, 0]);
tempArray = tempArray.concat([0.5, 0, 0.5, 1, 0.75, 1, 0.5, 0, 0.75, 1, 0.75, 0]);
tempArray = tempArray.concat([0.5, 0, 0.5, 1, 0.75, 1, 0.5, 0, 0.75, 1, 0.75, 0]);
tempArray = tempArray.concat([0.5, 0, 0.5, 1, 0.75, 1, 0.5, 0, 0.75, 1, 0.75, 0]);
} else {
tempArray = tempArray.concat([0.75, 0, 0.75, 1, 1, 1, 0.75, 0, 1, 1, 1, 0]);
tempArray = tempArray.concat([0.75, 0, 0.75, 1, 1, 1, 0.75, 0, 1, 1, 1, 0]);
tempArray = tempArray.concat([0.75, 0, 0.75, 1, 1, 1, 0.75, 0, 1, 1, 1, 0]);
tempArray = tempArray.concat([0.75, 0, 0.75, 1, 1, 1, 0.75, 0, 1, 1, 1, 0]);
explosion.active = false;
}
explosion.counter += 1;
texcoordinates = new Float32Array( tempArray );
gl.bufferSubData(gl.ARRAY_BUFFER, 0, texcoordinates);
// Set the matrix and draw.
gl.drawArrays(gl.TRIANGLES, 0, count);
}
for (let explosion of explosionlist) {
if (explosion.active === false) explosionlist.splice(explosionlist.indexOf(explosion), 1);
}
// draw ui
DrawUI();
requestAnimationFrame(drawScene);
}
}
// ---------End----------
}
// ---------------------------------Matrix control -------------------------------
var m4 = {
orthographic: function(left, right, bottom, top, near, far) {
return [
2 / (right - left), 0, 0, 0,
0, 2 / (top - bottom), 0, 0,
0, 0, 2 / (near - far), 0,
(left + right) / (left - right),
(bottom + top) / (bottom - top),
(near + far) / (near - far),
1,
];
},
perspective: function(fieldOfViewInRadians, aspect, near, far) {
var f = Math.tan(Math.PI * 0.5 - 0.5 * fieldOfViewInRadians);
var rangeInv = 1.0 / (near - far);
return [
f / aspect, 0, 0, 0,
0, f, 0, 0,
0, 0, (near + far) * rangeInv, -1,
0, 0, near * far * rangeInv * 2, 0
];
},
projection: function(width, height, depth) {
// Note: This matrix flips the Y axis so 0 is at the top.
return [
2 / width, 0, 0, 0,
0, -2 / height, 0, 0,
0, 0, 2 / depth, 0,
-1, 1, 0, 1,
];
},
multiply: function(a, b) {
var a00 = a[0 * 4 + 0];
var a01 = a[0 * 4 + 1];
var a02 = a[0 * 4 + 2];
var a03 = a[0 * 4 + 3];
var a10 = a[1 * 4 + 0];
var a11 = a[1 * 4 + 1];
var a12 = a[1 * 4 + 2];
var a13 = a[1 * 4 + 3];
var a20 = a[2 * 4 + 0];
var a21 = a[2 * 4 + 1];
var a22 = a[2 * 4 + 2];
var a23 = a[2 * 4 + 3];
var a30 = a[3 * 4 + 0];
var a31 = a[3 * 4 + 1];
var a32 = a[3 * 4 + 2];
var a33 = a[3 * 4 + 3];
var b00 = b[0 * 4 + 0];
var b01 = b[0 * 4 + 1];
var b02 = b[0 * 4 + 2];
var b03 = b[0 * 4 + 3];
var b10 = b[1 * 4 + 0];
var b11 = b[1 * 4 + 1];
var b12 = b[1 * 4 + 2];
var b13 = b[1 * 4 + 3];
var b20 = b[2 * 4 + 0];
var b21 = b[2 * 4 + 1];
var b22 = b[2 * 4 + 2];
var b23 = b[2 * 4 + 3];
var b30 = b[3 * 4 + 0];
var b31 = b[3 * 4 + 1];
var b32 = b[3 * 4 + 2];
var b33 = b[3 * 4 + 3];
return [
b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30,
b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31,
b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32,
b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33,
b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30,
b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31,
b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32,
b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33,
b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30,
b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31,
b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32,
b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33,
b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30,
b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31,
b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32,
b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33,
];
},
translation: function(tx, ty, tz) {
return [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
tx, ty, tz, 1,
];
},
xRotation: function(angleInRadians) {
var c = Math.cos(angleInRadians);
var s = Math.sin(angleInRadians);
return [
1, 0, 0, 0,
0, c, s, 0,
0, -s, c, 0,
0, 0, 0, 1,
];
},
yRotation: function(angleInRadians) {
var c = Math.cos(angleInRadians);
var s = Math.sin(angleInRadians);
return [
c, 0, -s, 0,
0, 1, 0, 0,
s, 0, c, 0,
0, 0, 0, 1,
];
},
zRotation: function(angleInRadians) {
var c = Math.cos(angleInRadians);
var s = Math.sin(angleInRadians);
return [
c, s, 0, 0,
-s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
];
},
scaling: function(sx, sy, sz) {
return [
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, sz, 0,
0, 0, 0, 1,
];
},
translate: function(m, tx, ty, tz) {
return m4.multiply(m, m4.translation(tx, ty, tz));
},
xRotate: function(m, angleInRadians) {
return m4.multiply(m, m4.xRotation(angleInRadians));
},
yRotate: function(m, angleInRadians) {
return m4.multiply(m, m4.yRotation(angleInRadians));
},
zRotate: function(m, angleInRadians) {
return m4.multiply(m, m4.zRotation(angleInRadians));
},
scale: function(m, sx, sy, sz) {
return m4.multiply(m, m4.scaling(sx, sy, sz));
},
inverse: function(m) {
var m00 = m[0 * 4 + 0];
var m01 = m[0 * 4 + 1];
var m02 = m[0 * 4 + 2];
var m03 = m[0 * 4 + 3];
var m10 = m[1 * 4 + 0];
var m11 = m[1 * 4 + 1];
var m12 = m[1 * 4 + 2];
var m13 = m[1 * 4 + 3];
var m20 = m[2 * 4 + 0];
var m21 = m[2 * 4 + 1];
var m22 = m[2 * 4 + 2];
var m23 = m[2 * 4 + 3];
var m30 = m[3 * 4 + 0];
var m31 = m[3 * 4 + 1];
var m32 = m[3 * 4 + 2];
var m33 = m[3 * 4 + 3];
var tmp_0 = m22 * m33;
var tmp_1 = m32 * m23;
var tmp_2 = m12 * m33;
var tmp_3 = m32 * m13;
var tmp_4 = m12 * m23;
var tmp_5 = m22 * m13;
var tmp_6 = m02 * m33;
var tmp_7 = m32 * m03;
var tmp_8 = m02 * m23;
var tmp_9 = m22 * m03;
var tmp_10 = m02 * m13;
var tmp_11 = m12 * m03;
var tmp_12 = m20 * m31;
var tmp_13 = m30 * m21;
var tmp_14 = m10 * m31;
var tmp_15 = m30 * m11;
var tmp_16 = m10 * m21;
var tmp_17 = m20 * m11;
var tmp_18 = m00 * m31;
var tmp_19 = m30 * m01;
var tmp_20 = m00 * m21;
var tmp_21 = m20 * m01;
var tmp_22 = m00 * m11;
var tmp_23 = m10 * m01;
var t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) -
(tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31);
var t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) -
(tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31);
var t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) -
(tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31);
var t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) -
(tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21);
var d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3);
return [
d * t0,
d * t1,
d * t2,
d * t3,
d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) -
(tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30)),
d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) -
(tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30)),
d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) -
(tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30)),
d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) -
(tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20)),
d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) -
(tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33)),
d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) -
(tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33)),
d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) -
(tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33)),
d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) -
(tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23)),
d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) -
(tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22)),
d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) -
(tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02)),
d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) -
(tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12)),
d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) -
(tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02))
];
},
vectorMultiply: function(v, m) {
var dst = [];
for (var i = 0; i < 4; ++i) {
dst[i] = 0.0;
for (var j = 0; j < 4; ++j) {
dst[i] += v[j] * m[j * 4 + i];
}
}
return dst;
},
getRight: function (m) {
return [m[8], m[9], m[10], 0];
},
getForward: function(m) {
return [m[0], m[1], m[2], 0];
},
getUp: function (m) {
return [m[4], m[5], m[6], 0];
},
lookAt: function(cameraPosition, target, up) { // all of the parameters is vector
var zAxis = this.normalize( this.subtractVectors(cameraPosition, target));
var xAxis = this.normalize(this.cross(up, zAxis));
var yAxis = this.normalize(this.cross(zAxis, xAxis));
return [
xAxis[0], xAxis[1], xAxis[2], 0,
yAxis[0], yAxis[1], yAxis[2], 0,
zAxis[0], zAxis[1], zAxis[2], 0,
cameraPosition[0],
cameraPosition[1],
cameraPosition[2],
1,
];
},
cross: function (a, b) {
return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
},
subtractVectors: function (a, b) {
return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
},
normalize: function (v) {
var length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
// make sure we don't divide by 0.
if (length > 0.00001) {
return [v[0] / length, v[1] / length, v[2] / length];
} else {
return [0, 0, 0];
}
},
};
// Fill the buffer with the values of "W" and "F".
function setMapGeometry(gl, mapInfo) {
let temparray = mapInfo.polygons.concat( new Array(6* MAX_RAY_NUM)); // for ray
temparray = temparray.concat (new Array(3* 6 * 4 * MAX_PROJECTILE_NUMBER )); // for projectile
temparray = temparray.concat (new Array(3*6*32)); // for player
temparray = temparray.concat(new Array(3* 6 * MAX_PROJECTILE_NUMBER )); // for explosion
let polygonArray = new Float32Array(temparray);
gl.bufferData(
gl.ARRAY_BUFFER,
polygonArray,
gl.STATIC_DRAW);
return;
}
function setMapColors(gl, mapInfo) {
for (let object of mapInfo.mapobjectlist){
if (object.constructor === Door) {
if (object.team === 1) {
mapInfo.mapColors = mapInfo.mapColors.concat([
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
//wall 2
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14
]);
} else if (object.team === 2) {
mapInfo.mapColors = mapInfo.mapColors.concat([
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
//wall 2
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146
]);
} else {
mapInfo.mapColors = mapInfo.mapColors.concat([
146, 125, 14,
146, 125, 14,
146, 125, 14,
146, 125, 14,
146, 125, 14,
146, 125, 14,
//wall 2
146, 125, 14,
146, 125, 14,
146, 125, 14,
146, 125, 14,
146, 125, 14,
146, 125, 14
]);
}
} else if (object.constructor === GameObject) {
if (object.flag === 0) {
mapInfo.mapColors = mapInfo.mapColors.concat([
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14,
//wall 2
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14,
//wall 3
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14,
//wall 4
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14,
50, 146, 14
]);
} else if (object.flag === 2) {
mapInfo.mapColors = mapInfo.mapColors.concat([
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
//wall 2
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
//wall 3
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
//wall 4
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146,
50, 14, 146
]);
} else if (object.flag === 1) {
mapInfo.mapColors = mapInfo.mapColors.concat([
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
//wall 2
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
//wall 3
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
//wall 4
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14,
146, 25, 14
]);
}
}
}
let temparray = mapInfo.mapColors.concat(new Array(2*3* MAX_RAY_NUM));
temparray = temparray.concat (new Array(3* 6 * 4 * MAX_PROJECTILE_NUMBER )); // for projectile
temparray = temparray.concat (new Array(3*6*32)); // for player
temparray = temparray.concat(new Array(3* 6 * MAX_PROJECTILE_NUMBER )); // for explosion
let mapColorArray = new Uint8Array(temparray);
gl.bufferData(gl.ARRAY_BUFFER, mapColorArray, gl.STATIC_DRAW);
return;
}
// ---------------------------------------HTML document managing function-------------------------------------
let ip = "";
let playername = "";
let ws;
let killloglist = [];
function killlog_Timeout() {
if (killloglist.length > 0) {
killloglist.splice(0, 1);
}
return;
}
function DoInitialJob () {
createCanvasAndShader ();
EngineMain();
}
function closeHandler() {
alert(serverclosereason);
}
///////////////////////////////////////////////////////////////////////////////////////////////
// ---------------------------------Client-side message----------------------------------------
// --------------------------------------------------------------------------------------------
// -------------------------------type of receiving message------------------------------------
// 0: list of players (has heavy net load, do not use this frequently)
// 1: connection notice
// 2: disconnection notice
// 3: connection rejected(due to server player number limit or else)
// 4: reserved for chat
// 5: player's current status renewal
// 6: received fired ray
// 7: received fired projectilelist
// 8: initial player information
// 9: reserved for game objective(GameRule related)
// 10: kill log event
// 11: damaging event
// 12: explosion event
// 13: reserved for list of building
// 14: map version request
// 15: player name change event
// 16: reply to teammate number request
// 17: Healthkit touch event
// 18: sound play request
// 19: sound stop request
// 20: respawn event
// 21: scriptversion request
// 22: weapon change notice
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
// -------------------------------type of sending message--------------------------------------
// 0: request for all player's status
// 1: map version
// 2: player name set request
// 3: class change request
// 4: reserved for chat
// 5: player current position, looking direction info
// 6: fired ray info
// 7: fired projectile info
// 8: reserved for all building's current status
// 9: reserved for building repair
// 10: reserved for building destruction
// 11: heal event request
// 12: teammate number request
// 13: reload request
// 14: script version
// 15: Special skill request(include building construction, zoom in, etc.)
// 16: Weapon change request
// --------------------------------------------------------------------------------------------
let serverclosereason = "서버로부터 연결이 끊겼습니다";
function messageHandler(message) {
let messageinfo = JSON.parse(message.data);
switch (messageinfo.type) {
case 0:
playerlist = [];
for (let playeritem of messageinfo.playerlist){
playerlist.push(new Player(playeritem.pos, 12, playeritem.direction, playeritem.team, playeritem.health, playeritem.id, playeritem.isdead, playeritem.playername, playeritem.classnumber));
}
break;
case 1:
if (player.playerID != messageinfo.id) { // other player is connected
playerlist.push(new Player(messageinfo.pos, 12, messageinfo.direction, messageinfo.team, messageinfo.health, messageinfo.id));
} else { // ok, this is same with my player information, I have to set a reference of player variable to specific element of playerlist
playerlist[messageinfo.id] = player;
}
if (messageinfo.team === 1) {
redteamnum += 1;
}
else if (messageinfo.team === 2) {
blueteamnum += 1;
}
break;
case 2:
var index = messageinfo.id;
let teamnumber = playerlist[index].team;
playerlist.splice(index, 1);
if (teamnumber === 1) {
redteamnum -= 1;
}
else if (teamnumber === 2) {
blueteamnum -= 1;
}
//arrange the new playerlist
for (let i in playerlist) {
playerlist[i].PlayerID = i;
}
break;
case 3:
serverclosereason = messageinfo.message;
ws.close();
break;
case 5:
if (messageinfo.id === player.playerID){
player.pos = messageinfo.pos;
player.direction = messageinfo.direction;
player.team = messageinfo.team;
player.healthpoint = messageinfo.health;
player.canbedamaged = messageinfo.canbedamaged;
player.classnumber = messageinfo.classnum;
player.isdead = messageinfo.isdead;
}
playerlist[messageinfo.id].pos = messageinfo.pos;
playerlist[messageinfo.id].direction = messageinfo.direction;
playerlist[messageinfo.id].team = messageinfo.team;
playerlist[messageinfo.id].healthpoint = messageinfo.health;
playerlist[messageinfo.id].canbedamaged = messageinfo.canbedamaged;
playerlist[messageinfo.id].classnumber = messageinfo.classnum;
playerlist[messageinfo.id].isdead = messageinfo.isdead;
break;
case 6:
playerlist[messageinfo.id].raylist = [];
for (let rayinfo of messageinfo.raylist) {
playerlist[messageinfo.id].raylist.push(new Ray(rayinfo.startpos, rayinfo.endpos));
}
for (let ray of playerlist[messageinfo.id].raylist){
ray.DrawRay();
}
break;
case 7:
projectilelist = [];
for (let projectile of messageinfo.projectilelist) {
switch (projectile.type) {
case 0:
projectilelist.push(new Projectile_Rocket (projectile.pos, 8, projectile.direction, projectile.team, playerlist[projectile.shooterid], "http://libertyga.me/images/4/46/UF_Healthkit.png", projectile.type));
break;
default:
break;
}
}
break;
case 8:
player = new Player(messageinfo.pos, 12, messageinfo.direction, messageinfo.team, messageinfo.health, messageinfo.id, true, playername, 0);
player.canbedamaged = messageinfo.canbedamaged;
player.classnumber = messageinfo.classnum;
player.isdead = messageinfo.isdead;
ws.send(JSON.stringify({
type: 2,
id: messageinfo.id,
newname: playername
}));
break;
case 9:
// reserved for gamerule control
break;
case 10:
let killtext = playerlist[messageinfo.attackerID].playername + " killed " + playerlist[messageinfo.victimID].playername + " with ";
switch (messageinfo.killtype) {
case -1: // suicide
killtext = playerlist[messageinfo.attackerID].playername + " suicided";
break;
case 0: // killed by pistol
killtext = killtext + "pistol";
break;
case 1: // reserved for nail gun
break;
case 2: // reserved for short shotgun
break;
case 3: // reserved
break;
case 4: // killed by power shotgun
killtext = killtext + "power shotgun";
break;
case 5: // killed by minigun
killtext = killtext + "minigun";
break;
case 6: // killed by rocket launcher explosion
killtext = killtext + "rocket launcher";
break;
default:
killtext = playerlist[messageinfo.attackerID].playername + " killed " + playerlist[messageinfo.victimID].playername;
console.log("unknown type kill event" + messageinfo.killtype);
break;
}
if (killloglist.length >= 10) {
killloglist.splice(0, 1);
}
killloglist.push(killtext);
setTimeout(killlog_Timeout, 4000);
break;
case 11: // damaging event
if (player.playerID === messageinfo.victimID){
player.healthpoint -= messageinfo.damage;
player.isdead = messageinfo.isdead;
if (messageinfo.isdead) { // if player is dead
player.healthpoint = 0;
inputhandler.ReleasePlayer();
player.ReloadWeapon = () => {
return;
};
player.FireWeapon = () =>{
return;
};
player.DoSpecialSkill = () => {
return;
};
player.ReleaseFire = () => {
return;
};
clearTimeout(player.deadtimer);
player.deadtimer = setTimeout(deadStateHandler, 4000);
}
} else {
playerlist[messageinfo.victimID].healthpoint -= messageinfo.damage;
playerlist[messageinfo.victimID].isdead = messageinfo.isdead;
if (messageinfo.isdead) {
playerlist[messageinfo.victimID].healthpoint = 0;
}
}
break;
case 12: // reserved for explosion draw
// explosiontype 0: damaging explosion, 1:healing explosion
explosionlist.push(new Explosion(messageinfo.pos, messageinfo.radius, messageinfo.explosiontype));
break;
case 13: // reserved for the list of buildings
break;
case 14:
ws.send(JSON.stringify({type:1, id:player.playerID, mapversion:mapinfo.mapversion}));
break;
case 15:
playerlist[messageinfo.id].playername = messageinfo.newname;
console.log("client "+ messageinfo.id +" changed name to "+ messageinfo.newname);
break;
case 16:
redteamnum = messageinfo.redteamnum;
blueteamnum = messageinfo.blueteamnum;
break;
case 17:
if (messageinfo.id === player.playerID) {
player.healthpoint = player.maxhealthpoint;
}
mapinfo.maphealthkitlist[messageinfo.healthkitid].isSpawned = messageinfo.isSpawned;
break;
case 18: // soundplay start
break;
case 19: // soundplay stop
break;
case 20: // respawn
if (player.playerID === messageinfo.id) {
player.pos = messageinfo.respawnpos;
player.isdead = false;
} else {
playerlist[messageinfo.id].pos = messageinfo.respawnpos;
playerlist[messageinfo.id].isdead = false;
}
break;
case 21:
ws.send(JSON.stringify({ type: 14, id: player.playerID, version: scriptversion}));
break;
case 22:
if (player.playerID != messageinfo.id) {
playerlist[messageinfo.id].currentweapon = messageinfo.currentweapon;
}
break;
default:
console.log("received message type "+ messageinfo.type);
break;
}
}
function deadStateHandler() {
player.isdead = false;
player.healthpoint = player.maxhealthpoint;
inputhandler.GrabInput(player);
player.ReloadWeapon = () => {
if (player.currentweapon === 0) {
player.secondweapon.ReloadWeapon();
} else {
player.firstweapon.ReloadWeapon();
}
};
player.FireWeapon = () =>{
if (player.currentweapon === 0) {
player.secondweapon.FireWeapon();
} else {
player.firstweapon.FireWeapon();
}
};
player.DoSpecialSkill = () => {
if (player.currentweapon === 0) {
player.secondweapon.DoSpecialSkill();
} else {
player.firstweapon.DoSpecialSkill();
}
};
player.ReleaseFire = () => {
if (player.currentweapon === 0) {
player.secondweapon.ReleaseFire();
} else {
player.firstweapon.ReleaseFire();
}
};
if (player.team === 1) {
player.pos = [mapinfo.RedSpawn[0] + 4 , mapinfo.RedSpawn[1] + 4 ];
} else {
player.pos = [mapinfo.BlueSpawn[0] + 4 , mapinfo.BlueSpawn[1] + 4 ];
}
}
function createIPInputBox () {
let gamedisplay = document.getElementById("mw-content-text");
gamedisplay.style.height = "1080px";
let paragraph = document.createElement("p");
paragraph.setAttribute("id", "infoparagraph");
paragraph.innerHTML = "IP주소와 포트를 쓰고 그 오른쪽 칸에 닉네임를 입력해주세요."
gamedisplay.appendChild(paragraph);
let mainInputBox = document.createElement("input");
mainInputBox.setAttribute("id", "input");
mainInputBox.setAttribute("placeholder", "(ex: 127.0.0.1:8080)");
mainInputBox.addEventListener("keydown", CheckInputBox);
gamedisplay.appendChild(mainInputBox);
let nameInputBox = document.createElement("input");
nameInputBox.setAttribute("id", "playername");
nameInputBox.setAttribute("placeholder", "Game Nickname");
nameInputBox.addEventListener("keydown", CheckInputBox);
gamedisplay.appendChild(nameInputBox);
function CheckInputBox(e) {
if (e.keyCode === 13) { // Pressing Enter key
if (document.getElementById("input").value === "" || document.getElementById("playername").value === "" ) {
alert("데이터가 없습니다! 빈칸을 내버려두지 마세요!")
return;
}
ip = document.getElementById("input").value;
playername = document.getElementById("playername").value;
document.getElementById("input").value = "";
document.getElementById("playername").value = "";
document.getElementById("mw-content-text").removeChild(document.getElementById("input"));
document.getElementById("mw-content-text").removeChild(document.getElementById("playername"));
document.getElementById("mw-content-text").removeChild(document.getElementById("infoparagraph"));
DoInitialJob();
}
}
}
function createCanvasAndShader () {
let gamedisplay = document.getElementById("mw-content-text");
gamedisplay.height = "1080px";
let baseDiv = document.createElement("div");
baseDiv.setAttribute("id", "baseDiv");
baseDiv.style = "z-index:0;display:block;";
baseDiv.style.position = "absolute";
baseDiv.width = "1440px";
baseDiv.height = "1080px";
baseDiv.style.top = "0px";
baseDiv.style.left = "0px";
gamedisplay.appendChild(baseDiv);
let baseDiv2 = document.createElement("div");
baseDiv2.setAttribute("id", "baseDiv2");
baseDiv2.style = "z-index:10;display:block;";
baseDiv2.style.position = "absolute";
baseDiv2.width = "1440px";
baseDiv2.height = "1080px";
baseDiv2.style.top = "0px";
baseDiv2.style.left = "0px";
gamedisplay.appendChild(baseDiv2);
//create canvases
let mainCanvas = document.createElement("canvas");
mainCanvas.setAttribute("id", "MainCanvas");
mainCanvas.style.border = "none";
mainCanvas.style.align = "center";
mainCanvas.setAttribute("width", "800");
mainCanvas.setAttribute("height", "600");
baseDiv.appendChild(mainCanvas);
let uiCanvas = document.createElement("canvas");
uiCanvas.setAttribute("id", "UICanvas");
uiCanvas.style.border = "none";
uiCanvas.style.align = "center";
uiCanvas.setAttribute("width", "800");
uiCanvas.setAttribute("height", "600");
baseDiv2.appendChild(uiCanvas);
// create shader script(GLSL)
let vertexshader = document.createElement("script");
vertexshader.setAttribute("id", "3d-vertex-shader");
vertexshader.setAttribute("type", "notjs");
vertexshader.innerText = "\
attribute vec4 a_position; \
attribute vec4 a_color; \
uniform mat4 u_matrix; \
varying vec4 v_color; \
void main() { \
gl_Position = u_matrix * a_position; \
v_color = a_color; \
}";
gamedisplay.appendChild(vertexshader);
let fragmentshader = document.createElement("script");
fragmentshader.setAttribute("id", "3d-fragment-shader");
fragmentshader.setAttribute("type", "notjs");
fragmentshader.innerText = "\
precision mediump float; \
varying vec4 v_color; \
\
void main() { \
gl_FragColor = v_color;\
}";
gamedisplay.appendChild(fragmentshader);
let planevertexshader = document.createElement("script");
planevertexshader.setAttribute("id", "2d-vertex-shader");
planevertexshader.setAttribute("type", "notjs");
planevertexshader.innerText = "\
attribute vec4 a_position; \
attribute vec2 a_texcoord; \
uniform mat4 u_matrix; \
varying vec2 v_texcoord; \
void main() { \
gl_Position = u_matrix * a_position; \
v_texcoord = a_texcoord; \
}";
gamedisplay.appendChild(planevertexshader);
let planefragmentshader = document.createElement("script");
planefragmentshader.setAttribute("id", "2d-fragment-shader");
planefragmentshader.setAttribute("type", "notjs");
planefragmentshader.innerText = "\
precision mediump float; \
varying vec2 v_texcoord; \
uniform sampler2D u_texture; \
void main() { \
gl_FragColor = texture2D(u_texture, v_texcoord);\
gl_FragColor.rgb *= gl_FragColor.a;\
}";
gamedisplay.appendChild(planefragmentshader);
return;
}
createIPInputBox ();
// ------------------------------------------------------------------------------------------------------------
// ----------------------------------------- put your own code here -------------------------------------------
// ------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------
// --------------------------- UncycloFortress client-side Script -------------------------------------
// ----------------------------------------------------------------------------------------------------
let scriptversion = 0.1;
let inputhandler;
function Projectile_Rocket(pos, size, direction, team, shooter, imgsrc) {
Projectile.call(this, pos, size, direction, team, shooter, imgsrc);
this.vertexlist = GenerateProjectile(this.GetCenterPosition(), this.size, this.cameraMatrix);
}
Projectile_Rocket.prototype = Object.create(Projectile.prototype);
Projectile_Rocket.prototype.constructor = Projectile_Rocket;
function Weapon (type, owner) {
this.type = type;
this.owner = owner;
this.timerhandler;
this.loadedbullet = 1;
this.firedelay = 1000;
this.reloaddelay = 1000;
this.isReloading = false;
this.isFiring = false;
this.MaxAmmo = this.loadedbullet;
this.weaponname = "?";
this.ReloadWeapon = () => {
this.isFiring = false;
if (!this.isReloading && this.loadedbullet != this.MaxAmmo){
clearTimeout(this.timerhandler);
this.timerhandler = setTimeout(this.ReloadWeapon_sub, this.reloaddelay);
this.isReloading = true;
}
};
this.ReloadWeapon_sub = () => {
// use fetch to fire event and get result
// apply the result
// if result failed(due to timing or else)
// if result is success
this.loadedbullet = this.MaxAmmo;
this.isReloading = false;
ws.send(JSON.stringify({
type: 13,
id: player.playerID,
currentweapon: player.currentweapon
}));
return;
}
this.FireWeapon = () =>{
if (this.type != 9 && this.loadedbullet === 0 && !this.isReloading) {
this.ReloadWeapon();
} else if (!this.isReloading && !this.isFiring) {
// use fetch to fire event and get result
// apply the result
// if result failed(due to timing or else)
// if result is success
clearTimeout(this.timerhandler);
this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
this.isFiring = true;
}
};
this.FireWeapon_sub = () => {
this.isFiring = false;
};
this.ReleaseFire = () => {
return;
};
this.DoSpecialSkill = () => {
// use fetch to fire event and get result
// apply the result
// if result failed(due to timing or else)
// if result is success
};
}
function Weapon_Pistol (type, owner) {
Weapon.call(this, type, owner);
this.loadedbullet = 6;
this.firedelay = 300;
this.reloaddelay = 1000;
this.MaxAmmo = this.loadedbullet;
this.weaponname = "Pistol";
this.FireWeapon = () =>{
if (this.type != 9 && this.loadedbullet === 0 && !this.isReloading) {
this.ReloadWeapon();
} else if (!this.isReloading && !this.isFiring) {
// use fetch to fire event and get result
// apply the result
// if result failed(due to timing or else)
// if result is success
if (this.type != 9 && this.loadedbullet > 0)this.loadedbullet -= 1;
this.owner.raylist = new Array(1);
let randomNum = Math.random();
this.owner.raylist[0] = new Ray ([this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/360+randomNum* Math.PI/180), this.owner.GetCenterPosition()[1] - 10000* Math.sin(this.owner.direction +Math.PI/2 - Math.PI/360+randomNum* Math.PI/180), 0]);
ws.send(JSON.stringify({
type:6,
id:player.playerID,
raylist: [{startpos:[this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], endpos: [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/360+randomNum* Math.PI/180), this.owner.GetCenterPosition()[1] - 10000* Math.sin(this.owner.direction +Math.PI/2 - Math.PI/360+randomNum* Math.PI/180), 0]}]
}));
this.owner.raylist[0].AddPenetratingObjects(mapinfo.mapobjectlist);
this.owner.raylist[0].endpos = this.owner.raylist[0].GetClosestCollidedPosition();
this.owner.raylist[0].DrawRay();
clearTimeout(this.timerhandler);
this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
this.isFiring = true;
}
};
this.FireWeapon_sub = () => {
this.isFiring = false;
};
this.ReleaseFire = () => {
return;
}
}
Weapon_Pistol.prototype = Object.create(Weapon.prototype);
Weapon_Pistol.prototype.constructor = Weapon_Pistol;
function Weapon_PowerShotgun (type, owner) {
Weapon.call(this, type, owner);
this.loadedbullet = 4;
this.firedelay = 800;
this.reloaddelay = 1000;
this.MaxAmmo = this.loadedbullet;
this.weaponname = "Power Shotgun";
this.FireWeapon = () =>{
if (this.type != 9 && this.loadedbullet === 0 && !this.isReloading) {
this.ReloadWeapon();
} else if (!this.isReloading && !this.isFiring) {
// use fetch to fire event and get result
// apply the result
// if result failed(due to timing or else)
// if result is success
if (this.type != 9 && this.loadedbullet > 0)this.loadedbullet -= 1;
this.owner.raylist = new Array(9);
let raylist = [];
for (let i = 0 ; i < 9; i++) { // 9 < MAX_RAY_PER_PERSON
this.owner.raylist[i] = new Ray ([this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/12+i* Math.PI/48), this.owner.GetCenterPosition()[1] - 10000* Math.sin(this.owner.direction +Math.PI/2- Math.PI/12+i* Math.PI/48), 0]);
raylist.push({startpos:[this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], endpos: [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/12+i* Math.PI/48), this.owner.GetCenterPosition()[1] - 10000* Math.sin(this.owner.direction +Math.PI/2- Math.PI/12+i* Math.PI/48), 0]});
}
ws.send(JSON.stringify({
type:6,
id:player.playerID,
raylist: raylist
}));
for (let i = 0 ; i < 9 ; i++) {
this.owner.raylist[i].AddPenetratingObjects(mapinfo.mapobjectlist);
this.owner.raylist[i].endpos = this.owner.raylist[i].GetClosestCollidedPosition();
this.owner.raylist[i].DrawRay();
}
clearTimeout(this.timerhandler);
this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
this.isFiring = true;
}
};
this.FireWeapon_sub = () => {
this.isFiring = false;
};
this.ReleaseFire = () => {
return;
}
}
Weapon_PowerShotgun.prototype = Object.create(Weapon.prototype);
Weapon_PowerShotgun.prototype.constructor = Weapon_PowerShotgun;
function Weapon_Minigun (type, owner) {
Weapon.call(this, type, owner);
this.loadedbullet = 200;
this.firedelay = 100;
this.reloaddelay = 5000;
this.MaxAmmo = this.loadedbullet;
this.weaponname = "Minigun";
this.FireWeapon = () =>{
if (this.type != 9 && this.loadedbullet === 0 && !this.isReloading) {
this.ReloadWeapon();
} else if (!this.isReloading && !this.isFiring) {
// use fetch to fire event and get result
// apply the result
// if result failed(due to timing or else)
// if result is success
if (this.type != 9 && this.loadedbullet > 0)this.loadedbullet -= 1;
this.owner.raylist = new Array(2);
let raylist = [];
for (let i = 0 ; i < 2; i++) { // 2 < MAX_RAY_PER_PERSON
let randomNum = Math.random();
this.owner.raylist[i] = new Ray ([this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/24+randomNum* Math.PI/12), this.owner.GetCenterPosition()[1] - 10000* Math.sin(this.owner.direction +Math.PI/2 - Math.PI/24+randomNum* Math.PI/12), 0]);
raylist.push({startpos:[this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], endpos: [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/24+randomNum* Math.PI/12), this.owner.GetCenterPosition()[1] - 10000* Math.sin(this.owner.direction +Math.PI/2 - Math.PI/24+randomNum* Math.PI/12), 0]});
}
ws.send(JSON.stringify({
type:6,
id:player.playerID,
raylist: raylist
}));
for (let i = 0 ; i < 2; i++) { // 2 < MAX_RAY_PER_PERSON
this.owner.raylist[i].AddPenetratingObjects(mapinfo.mapobjectlist);
this.owner.raylist[i].endpos = this.owner.raylist[i].GetClosestCollidedPosition();
this.owner.raylist[i].DrawRay();
}
clearTimeout(this.timerhandler);
this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
this.isFiring = true;
}
};
this.FireWeapon_sub = () => {
if (this.loadedbullet > 0 ){
// use fetch to fire event and get result
// apply the result
// if result failed(due to timing or else)
// if result is success
this.loadedbullet -= 1;
this.owner.raylist = new Array(2);
let raylist = [];
for (let i = 0 ; i < 2; i++) { // 2 < MAX_RAY_PER_PERSON
let randomNum = Math.random();
this.owner.raylist[i] = new Ray ([this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/24+randomNum* Math.PI/12), this.owner.GetCenterPosition()[1] - 10000* Math.sin(this.owner.direction +Math.PI/2 - Math.PI/24+randomNum* Math.PI/12), 0]);
raylist.push({startpos:[this.owner.GetCenterPosition()[0], this.owner.GetCenterPosition()[1], -18], endpos: [this.owner.GetCenterPosition()[0]- 10000* Math.cos(this.owner.direction+Math.PI/2- Math.PI/24+randomNum* Math.PI/12), this.owner.GetCenterPosition()[1] - 10000* Math.sin(this.owner.direction +Math.PI/2 - Math.PI/24+randomNum* Math.PI/12), 0]});
}
ws.send(JSON.stringify({
type:6,
id:player.playerID,
raylist: raylist
}));
for (let i = 0 ; i < 2; i++) { // 2 < MAX_RAY_PER_PERSON
this.owner.raylist[i].AddPenetratingObjects(mapinfo.mapobjectlist);
this.owner.raylist[i].endpos = this.owner.raylist[i].GetClosestCollidedPosition();
this.owner.raylist[i].DrawRay();
}
this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
}
};
this.ReleaseFire = () => {
if (this.isFiring) {
clearTimeout(this.timerhandler);
this.isFiring = false;
}
return;
}
}
Weapon_Minigun.prototype = Object.create(Weapon.prototype);
Weapon_Minigun.prototype.constructor = Weapon_Minigun;
function Weapon_RocketLauncher (type, owner) {
Weapon.call(this, type, owner);
this.loadedbullet = 6;
this.firedelay = 800;
this.reloaddelay = 1000;
this.MaxAmmo = this.loadedbullet;
this.weaponname = "Rocket Launcher";
this.FireWeapon = () =>{
if (this.type != 9 && this.loadedbullet === 0 && !this.isReloading) {
this.ReloadWeapon();
} else if (!this.isReloading && !this.isFiring) {
// use fetch to fire event and get result
// apply the result
// if result failed(due to timing or else)
// if result is success
if (this.type != 9 && this.loadedbullet > 0)this.loadedbullet -= 1;
let tempprojectile = new Projectile_Rocket([this.owner.GetCenterPosition()[0] - 8, this.owner.GetCenterPosition()[1] - 8], 1, this.owner.direction, 1, this.owner, "UF_Rocket_Red.png");
tempprojectile.visible = true;
if (projectilelist.length < MAX_PROJECTILE_NUMBER)projectilelist.push(tempprojectile);
ws.send(JSON.stringify({
type:7,
id:player.playerID,
pos: [this.owner.GetCenterPosition()[0] - 8, this.owner.GetCenterPosition()[1] - 8],
direction:this.owner.direction,
shooterid: this.owner.playerID,
projectiletype: 0
}));
clearTimeout(this.timerhandler);
this.timerhandler = setTimeout(this.FireWeapon_sub, this.firedelay);
this.isFiring = true;
}
};
this.FireWeapon_sub = () => {
this.isFiring = false;
};
this.ReleaseFire = () => {
return;
}
}
Weapon_RocketLauncher.prototype = Object.create(Weapon.prototype);
Weapon_RocketLauncher.prototype.constructor = Weapon_RocketLauncher;
function DoSomethingAfterMapLoad () {
// add class selection button
let gamedisplay = document.getElementById("mw-content-text");
let classbutton1 = document.createElement("button");
classbutton1.setAttribute("name", "classbutton1");
classbutton1.setAttribute("type", "button");
classbutton1.setAttribute("value", "1");
classbutton1.innerText = "Speedster";
classbutton1.onclick = ChangeMyCharacter;
gamedisplay.appendChild(classbutton1);
let classbutton2 = document.createElement("button");
classbutton2.setAttribute("name", "classbutton2");
classbutton2.setAttribute("type", "button");
classbutton2.setAttribute("value", "2");
classbutton2.innerText = "Tank";
classbutton2.onclick = ChangeMyCharacter;
gamedisplay.appendChild(classbutton2);
let classbutton3 = document.createElement("button");
classbutton3.setAttribute("name", "classbutton3");
classbutton3.setAttribute("type", "button");
classbutton3.setAttribute("value", "3");
classbutton3.innerText = "Tankbuster";
classbutton3.onclick = ChangeMyCharacter;
gamedisplay.appendChild(classbutton3);
// spawn initial player
player = new Player([mapinfo.RedSpawn[0], mapinfo.RedSpawn[1]], 8, [degToRad(0), degToRad(0), degToRad(0)], degToRad(0), 1, 0);
player.secondweapon = new Weapon(0,player); // weapon 0
player.firstweapon = new Weapon(4,player); // weapon 1
player.currentweapon = 0;
player.ReloadWeapon = () => {
};
player.FireWeapon = () =>{
};
player.DoSpecialSkill = () => {
};
player.ReleaseFire = () => {
};
gamerule = new GameRule(180, 180, 0);
inputhandler = new Input(document.getElementById("UICanvas"));
inputhandler.InitInput();
return;
}
function DrawUI () {
if (player != undefined && player.secondweapon != undefined && player.firstweapon != undefined){
let ctx = document.getElementById("UICanvas").getContext("2d");
ctx.canvas.width = 800; // reset the ui canvas
ctx.beginPath();
ctx.rect(0, 500, 800, 100);
ctx.fillStyle = "rgba(125, 125, 5, 1)";
ctx.fill();
ctx.font = "18px Arial, sans-serif";
ctx.fillStyle = "rgba(255, 255, 0, 1)";
if (player.currentweapon === 0)ctx.fillText("Current Weapon: "+ player.secondweapon.weaponname,20,20);
else ctx.fillText("Current Weapon: "+ player.firstweapon.weaponname,20,20);
ctx.fillStyle = "rgba(255, 0, 0, 1)";
ctx.fillText(String.format("{0}:{1}", Math.floor(gamerule.RedClock /60), gamerule.RedClock % 60),400-90,20 );
ctx.fillStyle = "rgba(25, 125, 255, 1)";
ctx.fillText(String.format("{0}:{1}", Math.floor(gamerule.BlueClock /60), gamerule.BlueClock % 60),400,20 );
// reserved for kill log
ctx.fillStyle = "rgba(255, 255, 0, 1)";
ctx.fillText("Health: "+player.healthpoint, 20, 580);
if (player.currentweapon === 0) {
if (player.secondweapon.isReloading) {
ctx.fillStyle = "rgba(255, 25, 0, 1)";
ctx.fillText("Reloading", 700, 560);
}
ctx.fillText("Ammo: "+player.secondweapon.loadedbullet, 700, 580);
} else {
if (player.firstweapon.isReloading) {
ctx.fillStyle = "rgba(255, 25, 0, 1)";
ctx.fillText("Reloading", 700, 560);
}
ctx.fillText("Ammo: "+player.firstweapon.loadedbullet, 700, 580);
}
ctx.closePath();
ctx.beginPath();
ctx.arc(400, 300, 10, 0, 2*Math.PI, true);
ctx.closePath();
ctx.lineWidth = 2;
ctx.strokeStyle = "#FFFF00";
ctx.stroke();
ctx.beginPath();
ctx.font = "12px Arial, sans-serif";
for (let killlog of killloglist){
ctx.fillStyle = "rgba(0, 255, 0, 1)";
ctx.fillText(killlog, 760 - 5*killlog.length, 40+8*killloglist.indexOf(killlog));
}
ctx.closePath();
if (keystate[7]){
//draw player list board
ctx.beginPath();
ctx.rect(100, 100, 600, 600);
ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
ctx.fill();
ctx.font = "18px Arial, sans-serif";
ctx.fillStyle = "rgba(0, 255, 0, 1)";
ctx.fillText("Players", 400 - "Players".length / 2, 110);
let blueteamplayer = 0;
let redteamplayer = 0;
for (let playeritem of playerlist) {
if (playeritem.team === 1 ) {
ctx.fillStyle = "rgba(255, 0, 0, 1)";
ctx.fillText(playeritem.playername, 660 - 8*playeritem.playername.length, 140+9*redteamplayer);
redteamplayer += 1;
} else if (playeritem.team === 2) {
ctx.fillStyle = "rgba(0, 0, 255, 1)";
ctx.fillText(playeritem.playername, 140, 140+9*blueteamplayer);
blueteamplayer += 1;
}
}
ctx.closePath();
}
}
return;
}
function GetMyNewWeapon(type) {
let newweapon = new Weapon(type,player);
switch (type) {
case 0: // pistol
newweapon = new Weapon_Pistol(type, player);
break;
case 1: // nail gun
newweapon.loadedbullet = 30;
newweapon.firedelay = 200;
newweapon.reloaddelay = 1000;
break;
case 2: // short shotgun
newweapon.loadedbullet = 8;
newweapon.firedelay = 400;
newweapon.reloaddelay = 2000;
break;
case 4: // power shotgun
newweapon = new Weapon_PowerShotgun(type, player);
break;
case 5: // minigun
newweapon = new Weapon_Minigun (type, player);
break;
case 6: // rocket shooter
newweapon = new Weapon_RocketLauncher (type, player);
break;
case 7: // medibeam shooter
newweapon.loadedbullet = -1;
newweapon.firedelay = 200;
newweapon.reloaddelay = 0;
break;
case 8: // watershooter
newweapon.loadedbullet = -1;
newweapon.firedelay = 200;
newweapon.reloaddelay = 0;
break;
case 9: // wrench
newweapon.loadedbullet = 200;
newweapon.firedelay = 800;
newweapon.reloaddelay = 1000;
break;
case 10: // pipe shooter
newweapon.loadedbullet = 8;
newweapon.firedelay = 400;
newweapon.reloaddelay = 2000;
break;
case 11: // sniper rifle
newweapon.loadedbullet = 1;
newweapon.firedelay = 400;
newweapon.reloaddelay = 2000;
break;
case 12: // knife
newweapon.loadedbullet = -1;
newweapon.firedelay = 800;
newweapon.reloaddelay = 1000;
break;
default:
newweapon.loadedbullet = 1;
newweapon.firedelay = 400;
newweapon.reloaddelay = 1000;
break;
}
newweapon.MaxAmmo = newweapon.loadedbullet;
return newweapon;
}
function ChangeMyCharacter(event) {
inputhandler.ReleasePlayer();
switch(event.target.value) {
case "1":
if (player.team === 1) {
player = new Player(player.pos, 12, degToRad(0), player.team, 100, player.playerID, true, player.playername, 1);
} else {
player = new Player(player.pos, 12, degToRad(180), player.team, 100, player.playerID, true, player.playername, 1);
}
player.secondweapon = GetMyNewWeapon(0); // weapon 0
player.firstweapon = GetMyNewWeapon(4); // weapon 1
player.movespeed = 2;
break;
case "2":
if (player.team === 1) {
player = new Player(player.pos, 12, degToRad(0), player.team, 300, player.playerID, true, player.playername, 2);
} else {
player = new Player(player.pos, 12, degToRad(180), player.team, 300, player.playerID, true, player.playername, 2);
}
player.secondweapon = GetMyNewWeapon(0); // weapon 0
player.firstweapon = GetMyNewWeapon(5); // weapon 1
player.movespeed = 0.5;
break;
case "3":
if (player.team === 1) {
player = new Player(player.pos, 12, degToRad(0), player.team, 200, player.playerID, true, player.playername, 3);
} else {
player = new Player(player.pos, 12, degToRad(180), player.team, 200, player.playerID, true, player.playername, 3);
}
player.secondweapon = GetMyNewWeapon(0); // weapon 0
player.firstweapon = GetMyNewWeapon(6); // weapon 1
player.movespeed = 1;
break;
default:
//only possible in initial entrance
break;
}
if (player.team === 1) {
player.SetCenterPosition([mapinfo.RedSpawn[0] + mapobjectsizeconstant/2, mapinfo.RedSpawn[1] + mapobjectsizeconstant/2]);
} else {
player.SetCenterPosition([mapinfo.BlueSpawn[0] + mapobjectsizeconstant/2, mapinfo.BlueSpawn[1] + mapobjectsizeconstant/2]);
}
player.currentweapon = 0;
ws.send(JSON.stringify({
type:3,
id:player.playerID,
classnum:player.classnumber,
team: player.team
}));
clearTimeout(player.deadtimer);
player.deadtimer = setTimeout(deadStateHandler, 4000);
return;
}