Repository navigation
Expand file tree
/
Copy pathlander.js
More file actions
111 lines (97 loc) · 3.56 KB
/
Copy pathlander.js
File metadata and controls
111 lines (97 loc) · 3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Get references to the DOM elements we need to manipulate:
let rocket = document.getElementById('rocket')
let heightDisplay = document.getElementById('height')
let speedDisplay = document.getElementById('speed')
let attitudeDisplay = document.getElementById('attitude')
let retroButton = document.getElementById('retro')
let leftButton = document.getElementById('thrustLeft')
let rightButton = document.getElementById('thrustRight')
// Set up initial state of rocket ship:
let pos = { x: 0, y: window.innerHeight - 44 }
let attitude = Math.PI / 2
let retro = false
let thruster = 0
let speed = { x: 30, y: 0 }
// Create a variable to record animation time:
let lastTime
// Attach event listeners:
retroButton.addEventListener('pointerdown', startBurn)
retroButton.addEventListener('pointerleave', endBurn)
retroButton.addEventListener('pointerup', endBurn)
leftButton.addEventListener('pointerdown', () => startThrust(-1))
leftButton.addEventListener('pointerup', endThrust)
leftButton.addEventListener('pointerleave', endThrust)
rightButton.addEventListener('pointerdown', () => startThrust(1))
rightButton.addEventListener('pointerup', endThrust)
rightButton.addEventListener('pointerleave', endThrust)
function startBurn() {
retro = true
retroButton.innerText = 'Active'
}
function endBurn() {
retro = false
retroButton.innerText = 'Inactive'
}
function startThrust(n) {
thruster = n
}
function endThrust() {
thruster = 0
}
// Here's where we move the rocket ... This function is called on every
// animation frame:
function moveRocket(time) {
if (lastTime) {
// Calculate delta time, in seconds, since last frame
let deltaT = (time - lastTime) / 1000
// If thruster active, adjust rocket attitude
if (thruster) {
attitude += thruster * deltaT
rocket.style.transform = `rotate(${attitude}rad)`
attitudeDisplay.innerText =
((attitude * 180) / Math.PI).toFixed(0) + ' deg'
}
// Calculate acceleration by adding retro thrust to Moon gravity
let acceleration = { x: 0, y: -1.625 }
if (retro) {
acceleration.x -= 10 * Math.cos(attitude + Math.PI / 2)
acceleration.y += 10 * Math.sin(attitude + Math.PI / 2)
}
// Now calculate the rocket's new position and speed
pos.x += speed.x * deltaT + 0.5 * acceleration.x * deltaT ** 2
pos.y += speed.y * deltaT + 0.5 * acceleration.y * deltaT ** 2
speed.x += acceleration.x * deltaT
speed.y += acceleration.y * deltaT
// Combine X and Y speed to get net speed
const netSpeed = Math.sqrt(speed.x ** 2 + speed.y ** 2)
// Update elements
rocket.style.left = pos.x + 'px'
rocket.style.bottom = Math.max(pos.y, 0) + 'px'
heightDisplay.innerText = pos.y.toFixed(4)
speedDisplay.innerText = netSpeed.toFixed(2)
// If the rocket strays outside the window then stop animation with
// an alert message
if (pos.x < 0 || pos.x > window.innerWidth || pos.y > window.innerHeight) {
window.alert('Lost contact with lander')
return
}
// Otherwise check if we've reached the Moon surface
else if (pos.y <= 0) {
if (netSpeed > 10) window.alert('Oops! Travelling too fast!')
else {
if (Math.abs((attitude * 180) / Math.PI) > 15) {
window.alert('Rocket fell over!')
} else {
rocket.style.transform = 'rotate(0deg)'
window.alert('Perfect landing')
}
}
return
}
}
// Note the timestamp of this animation frame, and request another
lastTime = time
window.requestAnimationFrame(moveRocket)
}
// Start the animation
window.requestAnimationFrame(moveRocket)