Parallax-Bicycle/Bicycle.js

245 lines
6.4 KiB
JavaScript

"use strict";
class Bicycle
{
constructor(inPos, inSpeed)
{
this.pos = inPos;
this.speed = inSpeed;
this.wheelLeft = new Wheel(new Vector(-47, 20), 30, 200);
this.wheelRight = new Wheel(new Vector(47, 20), 30, 200);
this.mainColour = "#4f32d2";
this.seatColour = "#312b50";
this.pedalReflectorColour = "rgb(214, 104, 14)"
this.seatSize = 10;
this.gearWheelSize = 7;
this.pedalRadius = 13;
this.pedalSize = 4;
this.pedalSpeed = this.speed * 0.02;
this.pedalRotation = 0;
}
update(dt)
{
this.wheelLeft.update(dt);
this.wheelRight.update(dt);
this.pedalRotation += this.pedalSpeed * dt;
}
render(context)
{
context.save();
context.translate(this.pos.x, this.pos.y);
var pedalPosition = this.wheelRight.pos.clone().subtract(new Vector(35, 0)),
seatPosition = pedalPosition.clone().add(new Vector(15, -40));
this.renderPedalsBack(context, pedalPosition)
this.wheelLeft.render(context);
this.wheelRight.render(context);
// Bicycle frame
context.beginPath();
context.moveTo(this.wheelLeft.pos.x, this.wheelLeft.pos.y);
context.lineTo(this.wheelLeft.pos.x + 20, this.wheelLeft.pos.y - 52);
context.moveTo(this.wheelLeft.pos.x + 13, this.wheelLeft.pos.y - 35);
context.lineTo(pedalPosition.x, pedalPosition.y);
context.lineTo(seatPosition.x, seatPosition.y);
context.moveTo(pedalPosition.x, pedalPosition.y);
context.lineTo(this.wheelRight.pos.x, this.wheelRight.pos.y);
context.lineTo(seatPosition.x - 4, seatPosition.y + 10);
context.lineTo(this.wheelLeft.pos.x + 14, this.wheelLeft.pos.y - 40);
context.lineWidth = 5;
context.strokeStyle = this.mainColour;
context.stroke();
context.beginPath();
context.moveTo(this.wheelLeft.pos.x + 20 + 14, this.wheelLeft.pos.y - 52 - 6);
context.lineTo(this.wheelLeft.pos.x + 20 - 18, this.wheelLeft.pos.y - 52 + 11);
context.lineWidth = 3;
context.strokeStyle = this.mainColour;
context.stroke();
this.renderPedalsFront(context, pedalPosition);
this.renderSeat(context, seatPosition);
context.restore();
}
renderSeat(context, pos)
{
context.save();
context.translate(pos.x - this.seatSize * 0.3, pos.y);
context.beginPath();
context.moveTo(this.seatSize, -this.seatSize / 2.4);
context.lineTo(-this.seatSize * 1.5, 0);
context.lineTo(this.seatSize * 1.3, this.seatSize / 2.3);
context.closePath();
context.fillStyle = this.seatColour;
context.fill();
context.restore();
}
renderPedalsFront(context, pos)
{
context.save();
context.translate(pos.x, pos.y);
// Pedal attachment circle
context.beginPath();
context.ellipse(0, 0, this.gearWheelSize * 0.3, this.gearWheelSize * 0.3, 0, 0, Math.PI * 2, false);
context.lineWidth = 2;
context.strokeStyle = this.wheelLeft.spokeColour;
context.stroke();
context.strokeStyle = "rgba(0, 0, 0, 0.8)";
context.stroke();
// Front pedal
var pedalOuterPosition = new Vector(this.pedalRadius * Math.sin(this.pedalRotation), this.pedalRadius * Math.cos(this.pedalRotation));
context.beginPath();
context.moveTo(0, 0);
context.lineTo(pedalOuterPosition.x, pedalOuterPosition.y);
context.strokeStyle = this.wheelLeft.spokeColour;
context.stroke();
context.strokeStyle = "rgba(0, 0, 0, 0.4)";
context.stroke();
this.renderPedal(context, pedalOuterPosition);
context.restore();
}
renderPedalsBack(context, pos)
{
context.save();
context.translate(pos.x, pos.y);
// Outer gear wheel
context.beginPath();
context.ellipse(0, 0, this.gearWheelSize, this.gearWheelSize, 0, 0, Math.PI * 2, false);
context.lineWidth = 3;
context.strokeStyle = this.wheelLeft.spokeColour;
context.stroke();
// Inner gear wheel
context.beginPath();
context.ellipse(0, 0, this.gearWheelSize * 0.8, this.gearWheelSize * 0.8, 0, 0, Math.PI * 2, false);
context.lineWidth = 2;
context.strokeStyle = this.wheelLeft.spokeColour;
context.stroke();
context.strokeStyle = "rgba(0, 0, 0, 0.4)";
context.stroke();
// Back pedal
var pedalOuterPosition = new Vector(this.pedalRadius * Math.sin(this.pedalRotation + Math.PI), this.pedalRadius * Math.cos(this.pedalRotation + Math.PI));
context.beginPath();
context.moveTo(0, 0);
context.lineTo(pedalOuterPosition.x, pedalOuterPosition.y);
context.strokeStyle = this.wheelLeft.spokeColour;
context.stroke();
context.strokeStyle = "rgba(0, 0, 0, 0.4)";
context.stroke();
this.renderPedal(context, pedalOuterPosition);
context.restore();
}
renderPedal(context, pos)
{
context.save();
context.translate(pos.x, pos.y);
context.beginPath();
context.moveTo(-this.pedalSize, 0);
context.lineTo(this.pedalSize, 0);
context.lineWidth = 3;
context.strokeStyle = this.mainColour;
context.stroke();
context.strokeStyle = "rgba(70, 70, 70, 0.4)";
context.stroke();
context.beginPath();
context.moveTo(-this.pedalSize * 0.5, 0);
context.lineTo(this.pedalSize * 0.5, 0);
context.lineWidth = 2;
context.strokeStyle = this.pedalReflectorColour;
context.stroke();
context.restore();
}
}
class Wheel
{
constructor(inPos, inRadius, inSpeed)
{
this.pos = inPos;
this.radius = inRadius;
this.speed = inSpeed / (Math.PI * 18);
this.rotation = 0;
this.rimColour = "#1f1e1e";
this.spokeColour = "rgb(198, 176, 172)";
this.spokeCount = 12;
this.spokeSpacing = (Math.PI*2) / this.spokeCount;
}
update(dt)
{
this.rotation -= this.speed * dt;
}
render(context)
{
context.save();
context.translate(this.pos.x, this.pos.y);
context.rotate(this.rotation);
context.beginPath();
for (let r = 0; r < Math.PI; r += this.spokeSpacing)
{
context.moveTo(this.radius * Math.cos(r), this.radius * Math.sin(r));
context.lineTo(this.radius * Math.cos(r + Math.PI), this.radius * Math.sin(r + Math.PI));
}
context.lineWidth = 1;
context.strokeStyle = this.spokeColour;
context.stroke();
context.beginPath();
context.ellipse(0, 0, this.radius * 0.95, this.radius * 0.95, 0, 0, Math.PI * 2, false);
context.lineWidth = 3;
context.stroke();
context.beginPath();
context.ellipse(0, 0, this.radius, this.radius, 0, 0, Math.PI * 2, false);
context.strokeStyle = this.rimColour;
context.lineWidth = 4;
context.stroke();
context.restore();
}
}