diff --git a/source/code/hippie/app.js b/source/code/hippie/app.js
index eb6eda9..2b46f36 100644
--- a/source/code/hippie/app.js
+++ b/source/code/hippie/app.js
@@ -554,6 +554,62 @@ function zeroFill(number, width) {
// Retrieved 2026-03-08, License - CC BY-SA 4.0
const delay = ms => new Promise(res => setTimeout(res, ms));
+class RandomPixelCanvas {
+ constructor(containerElement, options = {}) {
+ this.container = containerElement;
+ this.width = options.width || 400;
+ this.height = options.height || 300;
+ this.colors = options.colors || ['#000000', '#ffffff'];
+ this.filter = options.filter || '';
+ this.canvas = this.createCanvas();
+
+ this.fillWithRandomPixels();
+ }
+
+ createCanvas() {
+ const canvas = document.createElement('canvas');
+ canvas.width = this.width;
+ canvas.height = this.height;
+ canvas.style.filter = this.filter;
+
+ this.container.appendChild(canvas);
+
+ return canvas;
+ }
+
+ fillWithRandomPixels() {
+ const ctx = this.canvas.getContext('2d');
+ const imageData = ctx.createImageData(this.width, this.height);
+ const data = imageData.data;
+
+ for (let i = 0; i < data.length; i += 4) {
+ const color = this.getRandomColor();
+ const rgb = this.hexToRgb(color);
+
+ data[i] = rgb.r; // Red
+ data[i + 1] = rgb.g; // Green
+ data[i + 2] = rgb.b; // Blue
+ data[i + 3] = 255; // Alpha
+ }
+
+ ctx.putImageData(imageData, 0, 0);
+ }
+
+ getRandomColor() {
+ return this.colors[Math.floor(Math.random() * this.colors.length)];
+ }
+
+ hexToRgb(hex) {
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+
+ return result ? {
+ r: parseInt(result[1], 16),
+ g: parseInt(result[2], 16),
+ b: parseInt(result[3], 16)
+ } : {r: 0, g: 0, b: 0};
+ }
+}
+
// CONCEPTS
// NOTE: Benutzt private Zuweisungen
diff --git a/source/screens/demo/examples/game/menu.liquid b/source/screens/demo/examples/game/menu.liquid
index 7852bdb..34e00e7 100644
--- a/source/screens/demo/examples/game/menu.liquid
+++ b/source/screens/demo/examples/game/menu.liquid
@@ -3,7 +3,7 @@ title: Menu
tags:
- game
---
-{% assign bodyClass = 'body_game' -%}
+{% assign bodyClass = 'body_menu' -%}
{% layout 'hippie/simple.liquid' %}
{% block body %}
@@ -14,7 +14,7 @@ tags:
Additional name
- - Neues Spiel
+ - Neues Spiel
- Spiel fortsetzen
- Einstellungen
- Spiel beenden
diff --git a/source/screens/demo/examples/game/new.liquid b/source/screens/demo/examples/game/new.liquid
new file mode 100644
index 0000000..a799fef
--- /dev/null
+++ b/source/screens/demo/examples/game/new.liquid
@@ -0,0 +1,146 @@
+---
+title: TFW
+---
+{% assign bodyClass = 'body_tfw' -%}
+{% layout 'hippie/simple.liquid' %}
+
+{% block body %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | Location |
+ Quest |
+ Type |
+
+
+ |
+ Scorched Earth
+
+ |
+ ... |
+ Available |
+
+
+ |
+ Location name
+
+ |
+ ... |
+ Available |
+
+
+
+
+
+
+
+
+
+
+
+ | Active quests (Max.: 4) |
+
+
+ |
+
+ |
+ King Of Kings |
+ Active |
+
+
+ |
+
+ |
+ Garage Days Pt. 1 |
+ Complete |
+
+
+
+
+
+
King Of Kings
+
A hijacked medium mech dubbed the "Rat King" ...
+
+
Collect Rat King residue.
+
+
Multiple rig container upgrades, 5000 CR, 5000 XP, 2 days of water, + Scav faction
+ rating
+
+
+
+
+{% endblock %}
+
+{% block assets %}
+
+
+
+{% endblock %}
+
+{%- block script %}
+{{ block.super -}}
+
+{% endblock %}
\ No newline at end of file
diff --git a/source/style/modules/_game.scss b/source/style/modules/_game.scss
index 1c24812..7ad3f4d 100644
--- a/source/style/modules/_game.scss
+++ b/source/style/modules/_game.scss
@@ -29,7 +29,7 @@ $steps: (0, 14.28, 28.57, 42.85, 57.14, 71.43, 100);
animation: fadeColor 16s infinite linear;
}
-.body_game {
+.body_menu {
@extend .h_full_view;
background-color: hotpink;
@@ -71,4 +71,155 @@ $steps: (0, 14.28, 28.57, 42.85, 57.14, 71.43, 100);
left: 0;
border-radius: hippie.$radius_basic;
}
+}
+
+.body_tfw {
+ @extend .h_full_view;
+
+ display: flex;
+ flex-flow: column nowrap;
+
+ th,
+ .important {
+ color: white;
+ background-color: hippie.basic_color(echo);
+ }
+
+ .important {
+ padding: hippie.$space_half;
+ border-block: hippie.$width_border_basic solid hippie.$color_back_basic;
+ font-weight: bold;
+ }
+
+ .subtle {
+ @extend .txt_smaller;
+
+ color: hippie.$color_darkest;
+ text-transform: uppercase;
+ }
+
+ .success {
+ color: hippie.basic_color(alpha);
+ }
+
+ & > header {
+ & > button.active {
+ border-color: hippie.$color_highlight_basic;
+ color: hippie.$color_highlight_basic;
+ background-color: hippie.$color_action_basic;
+ }
+
+ & > button:not(:first-child, :last-child, :nth-child(2)) {
+ flex: 1;
+ }
+ }
+
+ & > div {
+ display: flex;
+ flex-flow: column nowrap;
+ flex: auto;
+ min-height: 0;
+
+ & > main {
+ display: flex;
+ flex-flow: row nowrap;
+ flex: auto;
+ gap: hippie.$space_double;
+ min-height: 0;
+
+ & > div:first-child {
+ flex: 1;
+ }
+
+ & > div:last-child {
+ flex: 2;
+ }
+
+ & > div:nth-child(2) {
+ flex: 4;
+ display: flex;
+ flex-flow: column nowrap;
+ gap: hippie.$space_basic;
+ min-height: 0;
+
+ div:first-child {
+ flex: auto;
+ overflow: auto;
+ min-height: 0;
+ }
+
+ div:last-child {
+ flex: 0 0 auto;
+ }
+ }
+
+ nav {
+ & > *:not(:last-child) {
+ margin-bottom: hippie.$space_basic;
+ }
+
+ input:not([type="checkbox"], [type="range"]) {
+ @extend .input_io;
+ }
+ }
+
+ table {
+ table-layout: fixed;
+ width: 100%;
+ margin: 0;
+
+ th {
+ text-align: center;
+ }
+
+ td {
+ position: relative;
+ height: 4em;
+ vertical-align: top;
+
+ span {
+ z-index: map.get(hippie.$z-indexes, "content-bottom");
+ position: relative;
+ color: white;
+ }
+
+ canvas {
+ z-index: map.get(hippie.$z-indexes, "default");
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ }
+
+ &:last-child {
+ text-align: center;
+ vertical-align: middle;
+ }
+ }
+
+ .l {
+ width: 30%;
+ }
+
+ .q {
+ width: 50%;
+ }
+
+ .t, .s {
+ width: 20%;
+ }
+ }
+ }
+
+ & > footer {
+ justify-content: space-between;
+ padding: hippie.$space_basic;
+
+ & > button:last-child {
+ //margin-left: auto;
+ padding-inline: 2em;
+ }
+ }
+ }
}
\ No newline at end of file