Skip to content

Commit

Permalink
Merge pull request #71 from AttAditya/speed-indicator
Browse files Browse the repository at this point in the history
Speedometer
  • Loading branch information
Glowstick0017 authored Oct 28, 2024
2 parents 6b61f69 + 83a135b commit b99c971
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 2 deletions.
18 changes: 18 additions & 0 deletions css/Style.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,24 @@ body {
background-color: transparent;
}

#instrumentCanvases {
width: 100%;
height: 100%;
position: absolute;
z-index: 2;
background-color: transparent;
display: flex;
justify-content: center;
align-items: end;
}
#speedometerCanvas {
width: 100%;
height: 100%;
position: absolute;
z-index: 3;
background-color: transparent;
}

#result {
position: absolute;
left: 25px;
Expand Down
4 changes: 3 additions & 1 deletion engine/Commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const speedCommand = new Command("SPEED", "SPEED <value>", 1, (args) => {
return "Invalid input. Range 0-20";
} else {
speed = speedVal;
$speed.innerHTML = "Speed: " + speed;
speedometerUpdate();
return "New speed set to " + speedVal;
}
});
Expand Down Expand Up @@ -47,6 +47,7 @@ const maxSpeedCommand = new Command("MAXSPEED", "MAXSPEED <value>", 1, (args) =>
return "Invalid input. Max speed cannot be less than min speed";
} else {
maxSpeed = maxSpeedVal;
speedometerUpdate();
return "New max speed set to " + maxSpeedVal;
}
});
Expand All @@ -62,6 +63,7 @@ const minSpeedCommand = new Command("MINSPEED", "MINSPEED <value>", 1, (args) =>
return "Invalid input. Min speed cannot be greater than max speed";
} else {
minSpeed = minSpeedVal;
speedometerUpdate();
return "New min speed set to " + minSpeedVal;
}
});
Expand Down
19 changes: 18 additions & 1 deletion engine/Controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ function clamp(value, min, max) {
return value;
}

function speedometerUpdate() {
$speed.innerHTML = `Speed: ${speed}`;

let speedometerNeedleAnglePercent = (speed - minSpeed);
speedometerNeedleAnglePercent /= (maxSpeed - minSpeed);
speedometerNeedleAnglePercent *= 100;

updateSpeedometerNeedle(speedometerNeedleAnglePercent);
}

function throttleChange(updateFn) {
let shouldClamp = true;

Expand All @@ -102,7 +112,7 @@ function throttleChange(updateFn) {
speed = clamp(speed, minSpeed, maxSpeed);
}

$speed.innerHTML = `Speed: ${speed}`;
speedometerUpdate();
}

// Movement Rotation
Expand Down Expand Up @@ -141,6 +151,12 @@ const verticalMapping = {
[KEYS.ARROW_DOWN]: () => { throttleChange((s, tp) => s - tp) },
};

// Function to initialize the game
function gameInit() {
// update instruments
speedometerUpdate();
}

// Game loop to handle movement and rendering
function gameLoop() {
if (pause) {
Expand Down Expand Up @@ -194,4 +210,5 @@ function gameLoop() {
requestAnimationFrame(gameLoop); // Queue the next iteration
}

gameInit(); // Initialize the game
gameLoop(); // Initiate the game loop
89 changes: 89 additions & 0 deletions engine/Instruments/BaseInstrument.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
class BaseInstrument {
constructor(canvasId) {
// Setting up canvas and its dimensions
/** @type {HTMLCanvasElement} */
this.canvas = document.getElementById(canvasId);
this.rect = this.canvas.getBoundingClientRect();
this.width = this.canvas.width = this.rect.width;
this.height = this.canvas.height = this.rect.height;
this.ctx = this.canvas.getContext("2d");

// Defining parts with their colors and coordinates for rendering
this.parts = {};

// Offsets for the instruments
this.shiftX = 0;
this.shiftY = 0;
}

// Helper function to draw a rectangle with scaling
drawRect(x, y, width, height, color) {
this.ctx.translate(this.width / 2 + this.shiftX, this.height + this.shiftY);
this.ctx.scale(0.5, 0.5);
this.ctx.fillStyle = color;
this.ctx.fillRect(x, y, width, height);
this.ctx.scale(2, 2);
this.ctx.translate(-(this.width / 2 + this.shiftX), -(this.height + this.shiftY));
}

drawInstrument() {
// Adjust the canvas so that element comes in center and bottom
this.shiftY = 0;

for (const partName in this.parts) {
const part = this.parts[partName];
for (const coord of part.coords) {
let [y1, y2] = [coord[1], coord[3]];
this.shiftY = -Math.max(-this.shiftY, y1, y2);
}
}

// Iterating over each plane part to draw it
for (const partName in this.parts) {
const part = this.parts[partName];
for (const coord of part.coords) {
let [x1, y1, x2, y2] = coord;

let x = Math.min(x1, x2);
let y = Math.min(y1, y2);
let w = Math.abs(x2 - x1);
let h = Math.abs(y2 - y1);

this.drawRect(x, y, w, h, part.color);
}
}
}

// Main draw function to render the plane
draw() {
// Clearing the canvas before drawing
this.ctx.clearRect(0, 0, this.width, this.height);

// this.ctx.translate(this.width / 2, this.height / 2);
// this.ctx.rotate(this.angle);
// this.ctx.translate(-this.width / 2, -this.height / 2);
this.drawInstrument();
this.ctx.resetTransform();
}

// Function to change the color of a plane part
setColor(partName, newColor) {
if (this.parts[partName]) {
this.parts[partName].color = newColor;
this.draw();
}
}

resetDefaults() {
document.getElementById("outer").value = this.parts["outer"].color = '#770619';
document.getElementById("innerMain").value = this.parts["innerMain"].color = '#ac322e';
document.getElementById("innerHighlight").value = this.parts["innerHighlight"].color = '#d85665';
document.getElementById("innerDarkHighlight").value = this.parts["innerDarkHighlight"].color = '#8c0308';
document.getElementById("aroundWindshield").value = this.parts["aroundWindshield"].color = '#570101';
document.getElementById("windshield").value = this.parts["windshield"].color = '#0ba0d2';
document.getElementById("propeller").value = this.parts["propeller"].color = '#333333';
document.getElementById("propellerBlades").value = this.parts["propellerBlades"].color = '#b3b3b3';
this.draw();
}
}

130 changes: 130 additions & 0 deletions engine/Instruments/Speedometer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
class Speedometer extends BaseInstrument {
constructor(canvasId) {
super(canvasId);

this.parts = {
outerRing: {
color: '#333333',
coords: [
[-1 * -40, -1 * -80, -1 * 40, -1 * 80],
[-1 * -100, -1 * -60, -1 * 100, -1 * 40],
[-1 * -60, -1 * -100, -1 * 60, -1 * 80],
[-1 * -80, -1 * -80, -1 * 80, -1 * 60],
]
},
innerRing: {
color: '#666666',
coords: [
[-1 * -30, -1 * -70, -1 * 30, -1 * 70],
[-1 * -90, -1 * -50, -1 * 90, -1 * 30],
[-1 * -50, -1 * -90, -1 * 50, -1 * 70],
[-1 * -70, -1 * -70, -1 * 70, -1 * 50],
]
},
rangeIndicator1: {
color: '#00ff00',
coords: [
[-70, -15, -50, 5]
]
},
rangeIndicator2: {
color: '#AAff00',
coords: [
[-25, -40, -45, -20]
]
},
rangeIndicator3: {
color: '#ffff00',
coords: [
[-10, -50, 10, -30]
]
},
rangeIndicator4: {
color: '#ffaa00',
coords: [
[25, -40, 45, -20]
]
},
rangeIndicator5: {
color: '#ff0000',
coords: [
[50, -15, 70, 5]
]
},
needle: {
color: '#ffffff',
coords: []
},
centerCircle: {
color: '#333333',
coords: [
[-10, 20, 10, 40]
]
}
};

this.needleState = 0;
this.needleCoords = {
0: [
[-70, -5, -50, 5],
[-50, 5, -30, 15],
[-30, 15, -10, 25],
[-10, 25, 10, 35],
[10, 35, 20, 45]
],
25: [
[-35, -50, -45, -40],
[-35, -20, -25, -40],
[-15, -20, -25, 0],
[-5, 0, -15, 20],
[-5, 20, 5, 30],
[5, 30, 15, 50]
],
50: [
[-5, -50, 5, 50]
],
75: [
[-1 * -35, -50, -1 * -45, -40],
[-1 * -35, -20, -1 * -25, -40],
[-1 * -15, -20, -1 * -25, 0],
[-1 * -5, 0, -1 * -15, 20],
[-1 * -5, 20, -1 * 5, 30],
[-1 * 5, 30, -1 * 15, 50]
],
100: [
[-1 * -70, -5, -1 * -50, 5],
[-1 * -50, 5, -1 * -30, 15],
[-1 * -30, 15, -1 * -10, 25],
[-1 * -10, 25, -1 * 10, 35],
[-1 * 10, 35, -1 * 20, 45]
],
}

this.parts.needle.coords = this.needleCoords[this.needleState];

this.draw();
}

draw() {
super.drawInstrument();
}
}

const speedometer = new Speedometer("speedometerCanvas");
speedometer.draw();

function updateSpeedometerNeedle(needleAnglePercent) {
needleAnglePercent = Math.min(needleAnglePercent, 100);
needleAnglePercent = Math.max(needleAnglePercent, 0);

let stateCount = Object.keys(speedometer.needleCoords).length - 1;
let needleState = stateCount * (needleAnglePercent / 100);
needleState = Math.floor(needleState) * (100 / stateCount);

speedometer.needleState = needleState;
let needleCoords = speedometer.needleCoords[needleState];
speedometer.parts.needle.coords = needleCoords;

speedometer.draw();
}

5 changes: 5 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
<body>
<div id="canvas-container">
<canvas id="planeCanvas"></canvas>
<div id="instrumentCanvases">
<canvas id="speedometerCanvas"></canvas>
</div>
<canvas id="canvas"></canvas>
</div>
<div id="menu">
Expand Down Expand Up @@ -159,6 +162,8 @@ <h3>Settings</h3>
<script src="engine/CommandHandler.js"></script>
<script src="engine/Commands.js"></script>
<script src="engine/Plane.js"></script>
<script src="engine/Instruments/BaseInstrument.js"></script>
<script src="engine/Instruments/Speedometer.js"></script>
<script src="engine/Controls.js"></script>
<script src="engine/Ui.js"></script>
</footer>
Expand Down

0 comments on commit b99c971

Please sign in to comment.