Browse Source

improvements and things

master
mort 8 years ago
parent
commit
6f74b8795a
4 changed files with 239 additions and 35 deletions
  1. 170
    34
      es/game.js
  2. 1
    1
      es/script.js
  3. 68
    0
      es/vec2.js
  4. BIN
      imgs/explosion.png

+ 170
- 34
es/game.js View File

@@ -1,3 +1,5 @@
let Vec2 = require("./vec2");

function randint(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
@@ -6,7 +8,11 @@ function random(min, max) {
return Math.random() * (max - min + 1) + min;
}

function background(ctx, camera) {
function diff(n1, n2) {
return Math.abs(n1 - n2);
}

function background(ctx, camera, offset) {
if (!background.cache) {
let cache = [];
let n = 1000;
@@ -29,8 +35,8 @@ function background(ctx, camera) {
ctx.fillStyle = "#FFFFFF";
for (let i = 0, len = cache.length; i < len; ++i) {
let p = cache[i];
let x = ((p.x - cx) / p.p) % window.innerWidth;
let y = ((p.y - cy) / p.p) % window.innerHeight;
let x = (((p.x - cx) / p.p) + offset.x) % window.innerWidth;
let y = (((p.y - cy) / p.p) + offset.y) % window.innerHeight;
if (x < 0)
x += window.innerWidth;
if (y < 0)
@@ -46,12 +52,50 @@ function background(ctx, camera) {

window.addEventListener("resize", () => background.cache = null);

class Animation {
constructor({img, x, y, width, height, nsteps, loop = false, fps = 10}) {
this.img = img;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.nsteps = nsteps;
this.step = 0;
this.onend = function(){};

let interval = setInterval(() => {
this.step += 1;
if (this.step > this.nsteps) {
this.step = 0;

if (!loop)
this.onend();
}
}, 1000/fps);
}

animate(ctx) {
ctx.drawImage(
this.img,
this.step * this.width,
0,
this.width,
this.height,
this.x,
this.y,
this.width,
this.height
);
}
}

class Entity {
constructor(x, y, width, height, id) {
this.pos = {x: x, y: y};
this.vel = {x: 0, y: 0};
constructor(x, y, width, height, id, game) {
this.pos = new Vec2(x, y);
this.vel = new Vec2(0, 0);
this.width = width;
this.height = height;
this.game = game;

this.id = id;
}
@@ -59,21 +103,31 @@ class Entity {
draw(ctx) {}

set(obj) {
this.pos = obj.pos;
this.vel = obj.vel;
this.pos.set(obj.pos.x, obj.pos.y);
this.vel.set(obj.vel.x, obj.vel.y);
}

update(dt) {
this.pos.x += this.vel.x * dt;
this.pos.y += this.vel.y * dt;
}

despawn() {}
}

let BulletImgs = {
despawn: createImage("imgs/bullet_despawn.png")
}

class Bullet extends Entity {
constructor(x, y, vel, id, ownerId) {
super(x, y, 5, 5, id);
this.vel = vel;
constructor(x: 0, y: 0, vel, id, ownerId, game) {
super(x, y, 5, 5, id, game);
this.imgs = BulletImgs;
this.vel.set(vel.x, vel.y);
this.ownerId = ownerId;

if (ownerId == game.id)
game.screenShake(10, 0);
}

draw(ctx, selfId) {
@@ -92,19 +146,28 @@ class Bullet extends Entity {
set(obj) {
super.set(obj);
}

despawn() {
this.game.animate(new Animation({
img: this.imgs.despawn,
x: this.pos.x,
y: this.pos.y
}));
}
}

let PlayerImgs = {
thrust_back: createImage("imgs/thrust_back.png")
thrust_back: createImage("imgs/player_thrust_back.png"),
explosion: createImage("imgs/player_explosion.png")
}

class Player extends Entity {
constructor(x, y, id, rot) {
super(x, y, 25, 60, id);
constructor(x, y, id, rot, game) {
super(x, y, 25, 60, id, game);
this.imgs = PlayerImgs;
this.rot = rot;
this.rotVel = 0;
this.keys = {};
this.imgs = PlayerImgs;
this.health = 0;
}

@@ -112,9 +175,9 @@ class Player extends Entity {
let h = 255-((100-this.health) * 2)

if (selfId == this.id) {
ctx.fillStyle = "rgba("+h+", "+h+", "+h+", 1)";
ctx.fillStyle = "rgb("+h+", "+h+", "+h+")";
} else {
ctx.fillStyle = "rgba("+h+", 0, 0, 1)";
ctx.fillStyle = "rgb("+h+", 0, 0)";
}

ctx.rotate(this.rot);
@@ -135,14 +198,50 @@ class Player extends Entity {
ctx.lineTo(this.width, this.height/2);
ctx.closePath();
ctx.fill();

ctx.rotate(-this.rot);

//Draw pointers to far away players
if (selfId == this.id) {
this.game.entities.forEach((e) => {

//Only draw players
if (!(e instanceof Player))
return;

//Only draw far away players
if (
diff(e.pos.x, this.pos.x) < window.innerWidth / 2 &&
diff(e.pos.y, this.pos.y) < window.innerHeight / 2
) {
return;
}

let pos = e.pos.clone().sub(this.pos).normalize().scale(100);

console.log(pos);

ctx.fillStyle = "rgb(255, 0, 0)";
ctx.beginPath();
ctx.arc(pos.x, pos.y, 10, 0, 2*Math.PI);
ctx.closePath();
ctx.fill();
});
}
}

set(obj) {
super.set(obj);
let lastHealth = this.health;

this.rot = obj.rot;
this.rotVel = obj.rotVel;
this.keys = obj.keys;
this.health = obj.health;

if (this.id == this.game.id && lastHealth > obj.health) {
this.game.screenShake(200);
}
}

update(dt) {
@@ -151,13 +250,14 @@ class Player extends Entity {
}
}

function createEntity(obj) {
function createEntity(obj, game) {
if (obj.type == "player") {
return new Player(obj.pos.x, obj.pos.y, obj.id, obj.rot);
return new Player(obj.pos.x, obj.pos.y, obj.id, obj.rot, game);
} else if (obj.type == "bullet") {
return new Bullet(obj.pos.x, obj.pos.y, obj.vel, obj.id, obj.ownerId);
return new Bullet(obj.pos.x, obj.pos.y, obj.vel, obj.id, obj.ownerId, game);
} else {
throw new Error("Unknown entity type: "+obj.type);
console.log("Unknown entity type: "+obj.type);
return false;
}
}

@@ -173,11 +273,14 @@ export default class Game {
this.canvas = canvas;
this.ctx = canvas.getContext("2d");
this.id = null;
this.camera = {x: 0, y: 0};
this.camera = new Vec2(0, 0);
this.raf = null;
this.prevTime = new Date().getTime();
this.player = null;

this.shake = 0;
this.shakedec = 0.5;

this.keymap = [];
this.keymap[87] = "up";
this.keymap[83] = "down";
@@ -186,6 +289,7 @@ export default class Game {
this.keymap[32] = "shoot";

this.entities = [];
this.animations = [];

sock.on("ready", () => {
sock.send("get_id", {}, (err, res) => {
@@ -194,16 +298,21 @@ export default class Game {
});

sock.on("set", (msg) => {
if (!this.entities[msg.id])
this.entities[msg.id] = createEntity(msg);
else
if (!this.entities[msg.id]) {
let ent = createEntity(msg, this);
if (ent)
this.entities[msg.id] = ent;
} else {
this.entities[msg.id].set(msg);
}
});

sock.on("despawn", (msg) => {
delete this.entities[msg.id];
if (msg.id == this.id)
if (msg.id == this.id) {
alert("You died.");
this.stop();
}
});

window.addEventListener("keydown", (evt) => {
@@ -233,17 +342,30 @@ export default class Game {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;

background(this.ctx, this.camera);

let player = this.entities[this.id];
if (player) {
this.camera = {
x: player.pos.x - (window.innerWidth / 2),
y: player.pos.y - (window.innerHeight / 2)
};
this.camera.set(
player.pos.x - (window.innerWidth / 2),
player.pos.y - (window.innerHeight / 2)
);
}

let shakeOffset = new Vec2(0, 0);
if (this.shake > 0) {
shakeOffset.set(
(Math.random() - 0.5) * this.shake,
(Math.random() - 0.5) * this.shake
);
this.shake -= dt * this.shakedec;
} else {
shakeOffset.set(0, 0);
}

this.ctx.translate(-this.camera.x, -this.camera.y);
let cam = this.camera.clone().add(shakeOffset);

background(this.ctx, this.camera, shakeOffset);

this.ctx.translate(-cam.x, -cam.y);
this.entities.forEach((ent) => {
this.ctx.save();
this.ctx.translate(ent.pos.x, ent.pos.y);
@@ -252,7 +374,8 @@ export default class Game {

ent.update(dt);
});
this.ctx.translate(this.camera.x, this.camera.y);
this.animations.forEach((a) => a.animate());
this.ctx.translate(cam.x, cam.y);

this.raf = window.requestAnimationFrame(this.update.bind(this));
}
@@ -260,4 +383,17 @@ export default class Game {
stop() {
window.cancelAnimationFrame(this.raf);
}

screenShake(n) {
if (this.shake < n)
this.shake = n;
}

animate(animation) {
let i = this.animations.length;
this.animations.add(animation);
animation.onend = () => {
delete this.animations[i];
}
}
}

+ 1
- 1
es/script.js View File

@@ -1,4 +1,4 @@
let Game = require("./game.js");
let Game = require("./game");

document.querySelector("#startGameBtn").addEventListener("click", () => {
view("game");

+ 68
- 0
es/vec2.js View File

@@ -0,0 +1,68 @@
export default class Vec2 {
constructor(x, y) {
this.x = x;
this.y = y;
}

length() {
return Math.sqrt((this.x * this.x) + (this.y * this.y));
}

clone() {
return new Vec2(this.x, this.y);
}

set(x, y) {
if (x instanceof Vec2)
return this.set(x.x, x.y);

this.x = x;
this.y = y;
return this;
}

add(x, y) {
if (x instanceof Vec2)
return this.add(x.x, x.y);

this.x += x;
this.y += y;
return this;
}

sub(x, y) {
if (x instanceof Vec2)
return this.sub(x.x, x.y);

this.x -= x;
this.y -= y;
return this;
}

scale(num) {
this.x *= num;
this.y *= num;
return this;
}

normalize() {
var len = this.length();

if (len === 0) {
this.x = 1;
this.y = 0;
} else {
this.scale(1 / len);
}

return this;
}

rotate(rad) {
let x = this.x;
let y = this.y;
this.x = x * Math.cos(rad) - y * Math.sin(rad);
this.y = y * Math.cos(rad) + x * Math.sin(rad);
return this;
}
}

BIN
imgs/explosion.png View File


Loading…
Cancel
Save