|
1 | | -<!DOCTYPE html> |
| 1 | +<!doctype html> |
2 | 2 | <html lang="en"> |
3 | 3 | <head> |
4 | 4 | <meta charset="utf-8"> |
| 5 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 6 | + <meta name="color-scheme" content="dark"> |
5 | 7 | <title>Space Travel</title> |
6 | 8 | <style> |
7 | 9 | body { |
8 | 10 | background: black; |
| 11 | + width: 100%; |
| 12 | + height: 100%; |
| 13 | + margin: 0; |
| 14 | + position: absolute; |
| 15 | + touch-action: none; |
| 16 | + user-select: none; |
| 17 | + -webkit-user-select: none; |
9 | 18 | } |
10 | 19 | canvas { |
11 | | - position: absolute; |
| 20 | + display: block; |
| 21 | + margin: 0 auto; |
12 | 22 | max-width: 100%; |
13 | 23 | max-height: 100%; |
| 24 | + position: relative; |
14 | 25 | top: 50%; |
15 | | - left: 50%; |
16 | | - transform: translate(-50%, -50%); |
| 26 | + transform: translateY(-50%); |
| 27 | + touch-action: none; |
| 28 | + user-select: none; |
| 29 | + -webkit-user-select: none; |
17 | 30 | } |
18 | 31 | </style> |
19 | 32 | </head> |
20 | 33 | <body> |
21 | 34 | <canvas id="canvas"></canvas> |
22 | 35 | <script>Module = { canvas }</script> |
23 | 36 | <script src="st.js"></script> |
| 37 | + <script> |
| 38 | + const intro = |
| 39 | + "Welcome to Space Travel\n\n" + |
| 40 | + "Travel to other planets and land slowly.\n\n"; |
| 41 | + |
| 42 | + const instructions = |
| 43 | + intro + |
| 44 | + "The arrow keys control your ship's acceleration and yaw.\n" + |
| 45 | + "The keys 3 and 4 control thrust.\n\n" + |
| 46 | + "If you crash, the bottom-right indicator will flash CL. " + |
| 47 | + "Press 2 to try again."; |
| 48 | + |
| 49 | + const touchInstructions = |
| 50 | + intro + |
| 51 | + "Swipe vertically and horizontally to control your ship's acceleration and yaw.\n" + |
| 52 | + "Tap the top and bottom of the screen to control thrust.\n\n" + |
| 53 | + "If you crash, the bottom-right indicator will flash CL. " + |
| 54 | + "Tap anywhere to try again."; |
| 55 | + |
| 56 | + let started = false; |
| 57 | + let crashed = false; |
| 58 | + |
| 59 | + Module.oncrash = () => (crashed = true); |
| 60 | + |
| 61 | + document.body.onclick = () => window.alert(instructions); |
| 62 | + |
| 63 | + function press(code, duration = 50) { |
| 64 | + canvas.dispatchEvent(new KeyboardEvent("keydown", { code, bubbles: true })); |
| 65 | + setTimeout( |
| 66 | + () => |
| 67 | + canvas.dispatchEvent(new KeyboardEvent("keyup", { code, bubbles: true })), |
| 68 | + duration |
| 69 | + ); |
| 70 | + } |
| 71 | + |
| 72 | + const touches = new Map(); |
| 73 | + |
| 74 | + document.body.ontouchstart = (e) => { |
| 75 | + e.preventDefault(); |
| 76 | + |
| 77 | + if (!started) { |
| 78 | + window.alert(touchInstructions); |
| 79 | + started = true; |
| 80 | + return; |
| 81 | + } |
| 82 | + |
| 83 | + if (crashed) { |
| 84 | + press("Digit2"); |
| 85 | + crashed = false; |
| 86 | + return; |
| 87 | + } |
| 88 | + |
| 89 | + for (const t of e.changedTouches) |
| 90 | + touches.set(t.identifier, { x: t.pageX, y: t.pageY }); |
| 91 | + }; |
| 92 | + |
| 93 | + document.body.ontouchmove = (e) => { |
| 94 | + e.preventDefault(); |
| 95 | + |
| 96 | + for (const t of e.changedTouches) { |
| 97 | + const touch = touches.get(t.identifier); |
| 98 | + if (!touch) continue; |
| 99 | + |
| 100 | + const dx = t.pageX - touch.x; |
| 101 | + const dy = t.pageY - touch.y; |
| 102 | + |
| 103 | + const distance = Math.hypot(dx, dy); |
| 104 | + |
| 105 | + if (Math.abs(dx) > Math.abs(dy)) |
| 106 | + press(dx < 0 ? "ArrowLeft" : "ArrowRight", 50 * distance); |
| 107 | + else { |
| 108 | + if (distance < 10) continue; |
| 109 | + press(dy > 0 ? "ArrowUp" : "ArrowDown", 50 * distance); |
| 110 | + } |
| 111 | + |
| 112 | + touch.x = t.pageX; |
| 113 | + touch.y = t.pageY; |
| 114 | + touch.handled = true; |
| 115 | + } |
| 116 | + }; |
| 117 | + |
| 118 | + document.body.ontouchend = (e) => { |
| 119 | + e.preventDefault(); |
| 120 | + |
| 121 | + for (const t of e.changedTouches) { |
| 122 | + const touch = touches.get(t.identifier); |
| 123 | + touches.delete(t.identifier); |
| 124 | + if (!touch || touch.handled) continue; |
| 125 | + press(2 * e.pageY < window.innerHeight ? "Digit3" : "Digit4"); |
| 126 | + } |
| 127 | + }; |
| 128 | + |
| 129 | + document.body.ontouchcancel = (e) => { |
| 130 | + e.preventDefault(); |
| 131 | + for (const t of e.changedTouches) touches.delete(t.identifier); |
| 132 | + }; |
| 133 | + </script> |
24 | 134 | </body> |
25 | 135 | </html> |
0 commit comments