xxxxxxxxxx
136
// Ship
class Ship {
constructor(x, y, angle) {
this.angle = angle;
this.thrust_radius = 400;
this.vectorV = createVector(0, 0);
this.friction = 0.015;
this.maxV = 10;
this.pos = createVector(x, y);
this.cannon = new Cannon(this);
}
// create Vector of mousepostion and subtract position of ship
mouseVector(mag = 1) {
const v = createVector(mouseX, mouseY).sub(ship.pos);
v.setMag(v.mag() * mag);
v.limit(this.thrust_radius / 2);
return v;
}
thrust() {
if (!THRUST_MODE || !inscreen) return;
this.vectorV.add(this.mouseVector(0.025));
}
move() {
if (!THRUST_MODE && inscreen && mouseIsPressed)
this.vectorV.add(this.mouseVector(0.001));
//rotate ship to mousepointer
// to get mouseposition relative to the ship
// then get its angle via heading
if (inscreen) this.angle = this.mouseVector().heading();
if (this.angle < 0) this.angle += TWO_PI;
// limit Velocity to max Velocity
this.vectorV.limit(this.maxV);
// reduce velocity by friction // add/subtract for negative/positive velocity
if (FRICTION)
this.vectorV.sub(this.vectorV.copy().normalize().mult(this.friction));
// if velocity is nearly zero then set it to zero
if (abs(this.vectorV.x) < 0.05) this.vectorV.x = 0;
if (abs(this.vectorV.y) < 0.05) this.vectorV.y = 0;
// Add velocity vector to current position vector ==> move by velocity
this.pos.add(this.vectorV);
// Handle position to wrap edges of canvas
this.pos.rem(createVector(CANVAS_WIDTH, CANVAS_HEIGHT));
if (this.pos.x < 0) this.pos.x = CANVAS_WIDTH;
if (this.pos.y < 0) this.pos.y = CANVAS_HEIGHT;
this.cannon.moveBullets();
}
// draw spaceship
draw() {
push();
noFill();
strokeWeight(2);
stroke(255);
translate(this.pos);
rotate(this.angle + radians(90));
rectMode(CENTER);
triangle(0, -20, 20, 20, -20, 20);
rect(-10, 23, 10, 5);
rect(10, 23, 10, 5);
rect(0, -20, 2, 10);
strokeWeight(0.25);
circle(0, 0, this.thrust_radius);
pop();
}
}
// The cannon
class Cannon {
constructor(ship) {
this.ship = ship;
this.speed = 12;
this.bullets = [];
this.cooldown = 15; // frames
this.current_cooldown = 0;
}
// Generate bullet with position vector and velocity vector (direction)
shoot(pos, direction) {
if (this.current_cooldown > 0) return;
this.current_cooldown = this.cooldown;
this.bullets.push({
pos: this.ship.pos.copy(),
direction: p5.Vector.fromAngle(this.ship.angle, this.speed),
alive: 1,
});
}
moveBullets() {
// move bullet by velocity vector
this.bullets.forEach((bullet) => {
bullet.pos.add(bullet.direction);
// if bullet leaves screen, mark it as dead
if (vectorOOB(bullet.pos, 0)) bullet.alive = 0;
});
}
drawBullets() {
if (this.current_cooldown > 0) this.current_cooldown--;
for (let i = 0; i < this.bullets.length; i++) {
const bullet = this.bullets[i];
// skip invalid entries and dead bullets
if (!bullet || bullet == 0 || !bullet.alive) continue;
push();
rectMode(CENTER);
translate(bullet.pos);
rotate(bullet.direction.heading() - radians(90));
rect(0, 0, 5, 20);
pop();
}
// remove dead bullets from array, every 60th frame
if (frameCount % 60 == 0)
this.bullets = this.bullets.filter((bullet) => bullet.alive);
}
}