/**
* @class Represents a blimp vehicle.
*/
class MyVehicle extends CGFobject {
/**
* Initializes a new vehicle instance.
* @param {CGFscene} scene - the scene
* @param {number} positionY - the height/y position of the vehicle
*/
constructor(scene, positionY = 10) {
super(scene);
this.initTextures();
this.initObjects();
this.initMovement();
this.positionY = positionY;
this.camera = new CGFcamera(0.7, 0.1, 500, vec3.fromValues(this.positionX, this.positionY, this.positionZ), vec3.fromValues(0, 5, 0));
this.scene.cameras.push(this.camera);
}
/**
* Initializes the required objects.
*/
initObjects() {
this.balloon = new MySphere(this.scene, 20, 10);
this.mainCockpit = new MyCylinder(this.scene, 20);
this.cockpitSide = new MySphere(this.scene, 10, 10);
this.wings = new MyWingsManager(this.scene, this.material);
this.turbineHolder = new MySphere(this.scene, 10, 10);
this.turbine = new MyTurbine(this.scene, 10, 10);
this.flag = new MyFlag(this.scene, 20);
this.flagHolder = new MyCylinder(this.scene, 8);
this.scale = 1;
}
/**
* Initializes the required textures.
*/
initTextures() {
var path = this.scene.skins[this.scene.selectedSkin];
this.blimp = new CGFtexture(this.scene, path.concat("blimp/blimp.png"));
this.cockpitFront = new CGFtexture(this.scene, path.concat("blimp/cockpit_front_texture.png"));
this.cockpit = new CGFtexture(this.scene, path.concat("blimp/cockpit.png"));
this.rope = new CGFtexture(this.scene, "../resources/textures/rope.png");
this.material = new CGFappearance(this.scene);
this.material.setDiffuse(1, 1, 1, 1);
this.material.setSpecular(1, 1, 1, 1);
this.material.setAmbient(0.8, 0.8, 0.8, 1);
}
/**
* Initializes the movement of the wings, defining constants and relevant variables.
*/
initMovement() {
this.customMovement = false;
this.speed = 0; // units/second
this.acceleration = 0; // units/second²; not counting friction
this.yyangle = 0; // radians; the angle the vehicle makes with z axis
this.accelerationMultiplier = 1; // speed factor slider, units/second
this.turningValue = 0; // the turning multiplier
this.positionX = 0; // the x position
this.positionZ = 0; // the z position
this.lastTime = 0;
this.autoPilot = false;
}
/**
* Increases or decreases the speed of the vehicle.
* @param {number} value - the increase/decrease value
*/
accelerate(value) {
value *= this.accelerationMultiplier * 5
this.acceleration = value;
this.speed += this.acceleration;
// speed limits
let maxSpeed = this.accelerationMultiplier * 5;
if (this.speed > maxSpeed)
this.speed = maxSpeed;
if (this.speed < -maxSpeed)
this.speed = -maxSpeed;
}
/**
* Turns the vehicle.
* @param {number} value - the turn multiplier
*/
turn(value) {
this.turningValue = value;
}
/**
* Breaks the vehicle.
* @param {number} amount - the break multiplier
*/
brake(amount) {
this.speed += this.speed * -amount;
}
/**
* Turns on the vehicle auto-pilot.
* @param {number} radius - the radius of the rotation
* @param {integer} time - the time the rotation takes
* @param {integer} timeElapsed - the elapsed time
*/
applyAutoPilot(radius, time, timeElapsed) {
this.speed = radius * 2 * Math.PI / time; // perimeter / time <=> 2 * PI * radius / time
this.apangle = 2 * Math.PI * timeElapsed / time;
this.turningValue = this.apangle / (Math.PI / 2);
}
/**
* Resets the position of the vehicle.
*/
reset() {
this.speed = 0;
this.acceleration = 0;
this.yyangle = 0;
this.positionX = 0;
this.positionZ = 0;
this.turbine.reset();
this.wings.reset();
}
/**
* Updates the movement of the vehicle.
* @param {integer} t - the current time in milliseconds
*/
update(t) {
var elapsed = t - this.lastTime;
this.lastTime = t;
elapsed /= 1000; // seconds
if (this.autoPilot)
this.applyAutoPilot(5, 5, elapsed);
this.wings.update(elapsed, this.turningValue);
this.turbine.update(elapsed, this.speed);
this.flag.update(elapsed, this.turningValue, this.speed, this.wings.angle * this.speed / 50, this.accelerationMultiplier);
if (this.autoPilot) // completely ignore wing input
this.yyangle += this.apangle;
else
this.yyangle -= this.wings.angle * this.speed / 50; // 50 smooths
// this.yyangle += this.turningValue * this.speed * 15 / elapsed; // deprecated
if (this.customMovement) {
this.friction = this.speed * -0.009;
this.speed += this.friction;
}
this.positionX += this.speed * Math.sin(this.yyangle) * elapsed;
this.positionZ += this.speed * Math.cos(this.yyangle) * elapsed;
this.turningValue = 0;
this.camera.setPosition(vec3.fromValues(this.positionX - Math.sin(this.yyangle) * 20, this.positionY + 8, this.positionZ - Math.cos(this.yyangle) * 20));
this.camera.setTarget(vec3.fromValues(this.positionX + Math.sin(this.yyangle) * 15, this.positionY - 8, this.positionZ + Math.cos(this.yyangle) * 15))
}
/**
* Displays the static part of the vehicle.
*/
display() {
/* movement */
this.scene.pushMatrix();
this.scene.translate(this.positionX, this.positionY, this.positionZ);
this.scene.rotate(this.yyangle, 0, 1, 0);
this.displayObject();
this.scene.popMatrix();
}
/**
* Displays the part of the vehicle that requires shaders.
*/
displayWithShaders() {
// flag
this.scene.pushMatrix();
this.scene.translate(this.positionX, this.positionY, this.positionZ);
this.scene.rotate(this.yyangle, 0, 1, 0);
this.scene.scale(this.scale, this.scale, this.scale);
this.scene.pushMatrix();
this.scene.translate(0, 0, -2.5);
this.scene.rotate(Math.PI / 2, 0, 1, 0);
this.flag.displayWithShaders();
this.scene.popMatrix();
this.scene.popMatrix();
}
/**
* Displays the objects of the vehicle.
*/
displayObject() {
this.scene.pushMatrix();
this.scene.scale(this.scale, this.scale, this.scale);
/* central balloon */
this.material.setTexture(this.blimp);
this.material.apply();
this.scene.pushMatrix();
this.scene.scale(0.5, 0.5, 1);
this.balloon.display();
this.scene.popMatrix();
/* cockpit */
this.material.setTexture(this.cockpit);
this.material.apply();
this.scene.pushMatrix();
this.scene.translate(0, -0.5, 0);
this.scene.rotate(Math.PI / 2, 1, 0, 0);
this.scene.scale(0.1, 0.45, 0.1);
this.scene.translate(0, -0.5, 0);
this.mainCockpit.display();
this.scene.popMatrix();
this.material.setTexture(this.cockpitFront);
this.material.apply();
this.scene.pushMatrix();
this.scene.translate(0, -0.5, 0.225);
this.scene.scale(0.1, 0.1, 0.1);
this.cockpitSide.display();
this.scene.popMatrix();
this.material.setTexture(this.cockpitFront);
this.material.apply();
this.scene.pushMatrix();
this.scene.translate(0, -0.5, -0.225);
this.scene.scale(0.1, 0.1, 0.1);
this.cockpitSide.display();
this.scene.popMatrix();
/* wings */
this.wings.display();
/* turbine holders */
// left
this.material.setTexture(this.blimp);
this.material.apply();
this.scene.pushMatrix();
this.scene.translate(0.11, -0.54, -0.25);
this.scene.scale(0.04, 0.02, 0.07);
this.turbineHolder.display();
this.scene.popMatrix();
// right
this.material.setTexture(this.blimp);
this.material.apply();
this.scene.pushMatrix();
this.scene.translate(-0.11, -0.54, -0.25);
this.scene.scale(0.04, 0.02, 0.07);
this.turbineHolder.display();
this.scene.popMatrix();
/* turbines */
this.material.setTexture(this.cockpit);
this.material.apply();
// left
this.scene.pushMatrix();
this.scene.translate(0.11, -0.54, -0.30);
this.scene.rotate(-Math.PI / 2, 1, 0, 0);
this.scene.scale(0.02, 0.02, 0.01);
this.turbine.display();
this.scene.popMatrix();
// right
this.scene.pushMatrix();
this.scene.translate(-0.11, -0.54, -0.3);
this.scene.rotate(-Math.PI / 2, 1, 0, 0);
this.scene.scale(0.02, 0.02, 0.01);
this.turbine.display();
this.scene.popMatrix();
// flag holders
this.scene.pushMatrix();
this.scene.translate(0, 0, -1.75);
this.scene.scale(0.02, 0.8, 0.02);
this.scene.translate(0, -0.5, 0);
this.flagHolder.display();
this.scene.popMatrix();
this.material.setTexture(this.rope);
this.material.apply();
this.scene.pushMatrix();
this.scene.translate(0, 0.2, -1.35);
this.scene.rotate(Math.PI / 2 + 0.38995733, 1, 0, 0);
this.scene.scale(0.0075, 0.85, 0.0075);
this.scene.translate(0, -0.5, 0);
this.flagHolder.display();
this.scene.popMatrix();
this.scene.pushMatrix();
this.scene.translate(0, -0.2, -1.35);
this.scene.rotate(Math.PI / 2 - 0.38995733, 1, 0, 0);
this.scene.scale(0.0075, 0.85, 0.0075);
this.scene.translate(0, -0.5, 0);
this.flagHolder.display();
this.scene.popMatrix();
this.scene.popMatrix();
}
}