diff --git a/README.md b/README.md index cca8247..9fd6e87 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,8 @@ This component first renders all the controls that match the given model of metr - Deploy landing legs when near landing, or the user must deploy them at the right speed and altitude. - Navigate craters, hills, and boulders - Massive lateral speed +- Rapid orbits can affect day/night cycling +- The higher the altitude, the more round the terrain! - Use a parallax or exponentially scaled background, so that the terrain rushes up to the lander as it approaches. - Use a fixed fuel-tank, too much thrusting = running out of fuel quicker. - Explore multiple planets, with different environments: diff --git a/assets/css/wc/game-controls.css b/assets/css/wc/game-controls.css deleted file mode 100644 index fd4c057..0000000 --- a/assets/css/wc/game-controls.css +++ /dev/null @@ -1,23 +0,0 @@ -game-controls { - display: block; - position: absolute; - inset-block-start: 0; - inset-inline-start: 0; - inset-inline-end: 0; - z-index: 2; - block-size: calc(3 * var(--unit_root)); - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-around; - background-color: hsl(0, 0%, 20%); - text-align: center; - opacity: 0.5; -} - -game-controls form { - display: flex; - flex-direction: row; - justify-content: space-between; - gap: calc(1 * var(--unit_root)); -} \ No newline at end of file diff --git a/assets/css/wc/game-instruments.css b/assets/css/wc/game-instruments.css new file mode 100644 index 0000000..f446055 --- /dev/null +++ b/assets/css/wc/game-instruments.css @@ -0,0 +1,30 @@ +game-instruments { + display: block; +} + +.instrument { + display: block; + position: absolute; + z-index: 20; + border: 2px solid hsl(0, 0%, 50%); + background-color: black; + box-shadow: inset 0 0 0 2px hsla(0, 0%, 0%, 0.5); +} + +.instrument::after { + display: block; + position: absolute; + inset-block-start: calc(-1em - 6px); + inset-inline-start: -2px; + inset-inline-end: -2px; + line-height: 1; + text-align: center; + content: attr(label); + font-size: 0.875rem; + font-weight: 700; + text-transform: uppercase; + color: black; + border: 2px solid hsl(0, 0%, 50%); + background-color: hsl(0, 0%, 50%); + border-radius: 2px 2px 0 0; +} \ No newline at end of file diff --git a/assets/css/wc/instrument-fuel.css b/assets/css/wc/instrument-fuel.css new file mode 100644 index 0000000..423b026 --- /dev/null +++ b/assets/css/wc/instrument-fuel.css @@ -0,0 +1,16 @@ +instrument-fuel { + inset-block-end: calc(0.5 * var(--unit_root)); + inset-inline-end: calc(5.5 * var(--unit_root)); + inline-size: calc(2 * var(--unit_root)); + block-size: calc(10 * var(--unit_root)); + background-image: linear-gradient(hsl(198.74deg 100% 50%), hsl(218.79deg 100% 50%)); + background-clip: content-box; +} + +instrument-fuel-amount { + display: block; + position: absolute; + inset: 0; + inset-block-end: calc(var(--lander_fuel) * 1%); + background-color: black; +} \ No newline at end of file diff --git a/assets/css/wc/instrument-map.css b/assets/css/wc/instrument-map.css new file mode 100644 index 0000000..1f33dbf --- /dev/null +++ b/assets/css/wc/instrument-map.css @@ -0,0 +1,35 @@ +instrument-map { + inset-block-end: calc(0.5 * var(--unit_root)); + inset-inline-start: calc(0.5 * var(--unit_root)); + inline-size: calc(7 * var(--unit_root)); + block-size: calc(10 * var(--unit_root)); +} + +instrument-map-lander { + display: block; + position: absolute; + inline-size: calc(0.5 * var(--unit_root)); + block-size: calc(0.5 * var(--unit_root)); + inset-block-end: calc(var(--lander_position_y) * 1%); + inset-inline-start: calc(var(--lander_position_x) * 1%); + border-radius: calc(0.125 * var(--unit_root)); + transition-property: inset-block-end, inset-inline-start; + transition-duration: 0.05s; + transition-timing-function: linear; + transform: translateX(-50%); + background-color: orange; +} + +.notification { + text-transform: uppercase; + font-weight: 700; + opacity: 0; +} + +.notification.warning { + color: gold; +} + +.notification.error { + color: red; +} \ No newline at end of file diff --git a/assets/css/wc/instrument-rotation.css b/assets/css/wc/instrument-rotation.css new file mode 100644 index 0000000..0aaa3d3 --- /dev/null +++ b/assets/css/wc/instrument-rotation.css @@ -0,0 +1,46 @@ +instrument-rotation { + inset-block-end: calc(0.5 * var(--unit_root)); + inset-inline-start: 50%; + transform: translateX(-50%); + inline-size: calc(10 * var(--unit_root)); + block-size: calc(2 * var(--unit_root)); + background-color: white; +} + +instrument-rotation-amount { + /* + The input `--lander_rotation` can be an integer between -100 (full-left rotation) and 100 (full-right rotation). + The closer the value is 0, the better. + */ + + --rotation-indicator-position: calc(50 - (var(--lander_rotation) / 2)); + + /* + We want to use hue degrees, where: + -100 0 100 + <-----------------------------------------------> + 0deg 120deg 0deg + (Red) (Green) (Red) + */ + + /* First strip any negative sign from the rotation amount */ + --rotation-normalised: calc( + var(--lander_rotation) * var(--lander_rotation) / 10000 + ); + + --rotation-indicator-danger-level: calc( + 120 - (var(--rotation-normalised) * 120) + ); + + display: block; + position: absolute; + inset-block-start: 0; + inset-block-end: 0; + inset-inline-end: calc(var(--rotation-indicator-position) * 1%); + inline-size: 6px; + transition-property: inset-block-end; + transition-duration: 0.05s; + transition-timing-function: linear; + background-color: grey; + background-color: hsl(calc(var(--rotation-indicator-danger-level) * 1deg), 100%, 50%); +} \ No newline at end of file diff --git a/assets/css/wc/instrument-thruster.css b/assets/css/wc/instrument-thruster.css new file mode 100644 index 0000000..726eeea --- /dev/null +++ b/assets/css/wc/instrument-thruster.css @@ -0,0 +1,19 @@ +instrument-thruster { + inset-block-end: calc(0.5 * var(--unit_root)); + inset-inline-end: calc(0.5 * var(--unit_root)); + inline-size: calc(4 * var(--unit_root)); + block-size: calc(10 * var(--unit_root)); + background-image: linear-gradient(hsl(0deg, 100%, 50%), hsl(40deg, 100%, 50%)); + background-clip: content-box; +} + +instrument-thruster-amount { + display: block; + position: absolute; + inset: 0; + inset-block-end: calc(var(--lander_thruster) * 1%); + transition-property: inset-block-end; + transition-duration: 0.05s; + transition-timing-function: linear; + background-color: black; +} \ No newline at end of file diff --git a/assets/css/wc/lander-vehicle.css b/assets/css/wc/lander-vehicle.css index 793b28b..fa327f4 100644 --- a/assets/css/wc/lander-vehicle.css +++ b/assets/css/wc/lander-vehicle.css @@ -10,7 +10,7 @@ lander-vehicle { transition-duration: 0.05s; transition-timing-function: linear; transform: - translate(-50%, -50%) + translateX(-50%) rotate( calc(var(--lander_rotation) * 1deg) ); diff --git a/assets/css/wc/lunar-surface.css b/assets/css/wc/lunar-surface.css index 1ddd9c5..4feee59 100644 --- a/assets/css/wc/lunar-surface.css +++ b/assets/css/wc/lunar-surface.css @@ -1,9 +1,10 @@ lunar-surface { display: block; - background-color: hsl(0, 0%, 20%); block-size: calc(10 * var(--unit_root)); position: absolute; inset-block-end: 0; inset-inline-start: 0; inset-inline-end: 0; + background-color: hsl(0, 0%, 20%); + background-image: linear-gradient(hsl(0, 0%, 20%), hsl(0, 0%, 10%) 50%); } \ No newline at end of file diff --git a/assets/css/wc/star-field.css b/assets/css/wc/star-field.css deleted file mode 100644 index 6968800..0000000 --- a/assets/css/wc/star-field.css +++ /dev/null @@ -1,10 +0,0 @@ -star-field { - display: block; - position: absolute; - inset: 0; - background-image: linear-gradient( - hsla(0, 0%, 100%, 0.1), - hsla(0, 0%, 100%, 0.01) - ); - background-repeat: repeat-x; -} \ No newline at end of file diff --git a/assets/mjs/index.mjs b/assets/mjs/index.mjs index c0c1fad..0315060 100644 --- a/assets/mjs/index.mjs +++ b/assets/mjs/index.mjs @@ -1,11 +1,11 @@ import GameEngine from './wc/game-engine.mjs?date=2023-12-26'; -import GameControls from './wc/game-controls.mjs?date=2023-12-26'; +import GameInstruments from './wc/game-instruments.mjs?date=2023-12-26'; import LanderVehicle from './wc/lander-vehicle.mjs?date=2023-12-26'; const customElementMappings = { 'game-engine': GameEngine, - 'game-controls': GameControls, - 'lander-vehicle': LanderVehicle, + 'game-instruments': GameInstruments, + 'lander-vehicle': LanderVehicle, } for (const [customElementName, customElementClass] of Object.entries(customElementMappings)) { diff --git a/assets/mjs/model.mjs b/assets/mjs/model.mjs index 6900d37..7f9de69 100644 --- a/assets/mjs/model.mjs +++ b/assets/mjs/model.mjs @@ -1,8 +1,6 @@ export const MODEL = { position_x: { name: 'X Position', - type: 'integer', - formElement: 'range', initial: 50, min: 0, max: 100, @@ -10,17 +8,13 @@ export const MODEL = { }, position_y: { name: 'Y Position', - type: 'integer', - formElement: 'range', initial: 60, min: 0, - max: 120, + max: 100, affects: 'lander', }, rotation: { name: 'Rotation', - type: 'integer', - formElement: 'range', initial: 0, min: -100, max: 100, @@ -28,8 +22,6 @@ export const MODEL = { }, running: { name: 'Running', - type: 'boolean', - formElement: 'radio', initial: 'true', labelTrue: 'Running', labelFalse: 'Stopped', @@ -37,8 +29,6 @@ export const MODEL = { }, speed: { name: 'Speed', - type: 'integer', - formElement: 'range', initial: 50, min: 0, max: 100, @@ -46,8 +36,6 @@ export const MODEL = { }, thruster: { name: 'Thruster', - type: 'integer', - formElement: 'range', initial: 0, min: 0, max: 100, @@ -58,22 +46,22 @@ export const MODEL = { export const KEYMAP = { 'ArrowUp': { affects: 'thruster', - change: 1, + change: 5, active: false, }, 'ArrowDown': { affects: 'thruster', - change: -1, + change: -5, active: false, }, 'ArrowLeft': { affects: 'rotation', - change: -1, + change: -5, active: false, }, 'ArrowRight': { affects: 'rotation', - change: 1, + change: 5, active: false, }, }; \ No newline at end of file diff --git a/assets/mjs/wc/game-controls.mjs b/assets/mjs/wc/game-controls.mjs deleted file mode 100644 index 0bb6bad..0000000 --- a/assets/mjs/wc/game-controls.mjs +++ /dev/null @@ -1,66 +0,0 @@ -import GameElement from './game-element.mjs'; -import { MODEL } from './../model.mjs'; -import { dispatchEventWithDetails } from './../events.mjs'; - -export default class GameControls extends GameElement { - #formElements = MODEL; - - createRangeControl(keyName, modelValue) { - let controlId = `rng_${keyName}`; - - return `
-
- - -
`; - } - - createRadioControl(keyName, modelValue, state) { - let controlId = `rdo_${keyName}_${state}`; - let labelValue = state === 'true' ? modelValue.labelTrue : modelValue.labelFalse; - - return ``; - } - - createRadioControlGroup(keyName, modelValue) { - let htmlString = ''; - - if (modelValue.type === 'boolean') { - htmlString = `
- ${this.createRadioControl(keyName, modelValue, 'true')} - ${this.createRadioControl(keyName, modelValue, 'false')} - -
`; - } - - return htmlString; - } - - createFormControls() { - let form = document.createElement('form'); - - Object.keys(this.#formElements).forEach((key) => { - let value = this.#formElements[key]; - - switch (value.formElement) { - case 'range': - form.innerHTML += this.createRangeControl(key, value); - break; - case 'radio': - form.innerHTML += this.createRadioControlGroup(key, value); - break; - } - }); - - this.appendChild(form); - this.dispatchEvent(new Event('FormElementsAdded', { bubbles: true })); - } - - connectedCallback() { - super.connectedCallback(); - this.createFormControls(); - } -} - diff --git a/assets/mjs/wc/game-engine.mjs b/assets/mjs/wc/game-engine.mjs index 5989423..e1e1499 100644 --- a/assets/mjs/wc/game-engine.mjs +++ b/assets/mjs/wc/game-engine.mjs @@ -1,5 +1,5 @@ -import GameElement from './game-element.mjs'; -import { MODEL, KEYMAP } from './../model.mjs'; +import GameElement from './game-element.mjs?date=2023-12-26'; +import { MODEL, KEYMAP } from './../model.mjs?date=2023-12-26'; const keyboardEventsToWatch = ['keydown', 'keyup']; @@ -128,7 +128,7 @@ export default class GameEngine extends GameElement { connectedCallback() { super.connectedCallback(); - this.addEventListener('FormElementsAdded', this.setInitialValuesAndStart, {once: true}); + this.addEventListener('InstrumentationAdded', this.setInitialValuesAndStart, {once: true}); document.addEventListener('keydown', this.handleGameStateKeyboardInupts); } diff --git a/assets/mjs/wc/game-instruments.mjs b/assets/mjs/wc/game-instruments.mjs new file mode 100644 index 0000000..7406ce0 --- /dev/null +++ b/assets/mjs/wc/game-instruments.mjs @@ -0,0 +1,9 @@ +import GameElement from './game-element.mjs?date=2023-12-26'; + +export default class GameInstruments extends GameElement { + connectedCallback() { + super.connectedCallback(); + this.dispatchEvent(new Event('InstrumentationAdded', { bubbles: true })); + } +} + diff --git a/assets/mjs/wc/lander-vehicle.mjs b/assets/mjs/wc/lander-vehicle.mjs index 5f55dcb..c47100e 100644 --- a/assets/mjs/wc/lander-vehicle.mjs +++ b/assets/mjs/wc/lander-vehicle.mjs @@ -1,4 +1,4 @@ -import GameElement from './game-element.mjs'; +import GameElement from './game-element.mjs?date=2023-12-26'; export default class LanderVehicle extends GameElement { connectedCallback() { diff --git a/index.html b/index.html index fe1de99..59064b6 100644 --- a/index.html +++ b/index.html @@ -6,14 +6,34 @@ + - + + + + Low altitude + Weak signal + Signal lost + + + + + + + + + + + @@ -54,7 +74,4 @@ - - - - \ No newline at end of file + \ No newline at end of file