feat: New game screen
- Basic layout - Menu structure - First screen - Add RandomPixelCanvas class
This commit is contained in:
parent
c518672db0
commit
a1b5aa8c59
4 changed files with 356 additions and 3 deletions
|
|
@ -554,6 +554,62 @@ function zeroFill(number, width) {
|
||||||
// Retrieved 2026-03-08, License - CC BY-SA 4.0
|
// Retrieved 2026-03-08, License - CC BY-SA 4.0
|
||||||
const delay = ms => new Promise(res => setTimeout(res, ms));
|
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
|
// CONCEPTS
|
||||||
|
|
||||||
// NOTE: Benutzt private Zuweisungen
|
// NOTE: Benutzt private Zuweisungen
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ title: Menu
|
||||||
tags:
|
tags:
|
||||||
- game
|
- game
|
||||||
---
|
---
|
||||||
{% assign bodyClass = 'body_game' -%}
|
{% assign bodyClass = 'body_menu' -%}
|
||||||
{% layout 'hippie/simple.liquid' %}
|
{% layout 'hippie/simple.liquid' %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
|
@ -14,7 +14,7 @@ tags:
|
||||||
<p>Additional name</p>
|
<p>Additional name</p>
|
||||||
</hgroup>
|
</hgroup>
|
||||||
<ul class="link">
|
<ul class="link">
|
||||||
<li><a href="#new">Neues Spiel</a></li>
|
<li><a href="./new.html">Neues Spiel</a></li>
|
||||||
<li><a href="#continue">Spiel fortsetzen</a></li>
|
<li><a href="#continue">Spiel fortsetzen</a></li>
|
||||||
<li><a href="#options">Einstellungen</a></li>
|
<li><a href="#options">Einstellungen</a></li>
|
||||||
<li><a href="#quit">Spiel beenden</a></li>
|
<li><a href="#quit">Spiel beenden</a></li>
|
||||||
|
|
|
||||||
146
source/screens/demo/examples/game/new.liquid
Normal file
146
source/screens/demo/examples/game/new.liquid
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
---
|
||||||
|
title: TFW
|
||||||
|
---
|
||||||
|
{% assign bodyClass = 'body_tfw' -%}
|
||||||
|
{% layout 'hippie/simple.liquid' %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<header class="io">
|
||||||
|
<button data-action="escape">☰</button>
|
||||||
|
<button data-action="previous"><</button>
|
||||||
|
<button data-action="quest">Quests</button>
|
||||||
|
<button data-action="region">Regions</button>
|
||||||
|
<button data-action="vendor">Vendors</button>
|
||||||
|
<button data-action="manufacture">Manufacture</button>
|
||||||
|
<button data-action="character">Characters</button>
|
||||||
|
<button data-action="stash">Stash</button>
|
||||||
|
<button data-action="secret">Secret Storage</button>
|
||||||
|
<button data-action="squad">Squads</button>
|
||||||
|
<button data-action="ready">Ready Room</button>
|
||||||
|
<button data-action="next">></button>
|
||||||
|
</header>
|
||||||
|
<div>
|
||||||
|
<main>
|
||||||
|
<nav>
|
||||||
|
<div class="important">Filter</div>
|
||||||
|
<input placeholder="Search" type="text">
|
||||||
|
<div>
|
||||||
|
<p>Quest type</p>
|
||||||
|
<menu>
|
||||||
|
<li></li>
|
||||||
|
</menu>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col class="l">
|
||||||
|
<col class="q">
|
||||||
|
<col class="t">
|
||||||
|
</colgroup>
|
||||||
|
<tr>
|
||||||
|
<th>Location</th>
|
||||||
|
<th>Quest</th>
|
||||||
|
<th>Type</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>Scorched Earth</span>
|
||||||
|
<div class="background"></div>
|
||||||
|
</td>
|
||||||
|
<td>...</td>
|
||||||
|
<td class="subtle">Available</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>Location name</span>
|
||||||
|
<div id="location" class="background"></div>
|
||||||
|
</td>
|
||||||
|
<td>...</td>
|
||||||
|
<td class="subtle">Available</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<table>
|
||||||
|
<colgroup>
|
||||||
|
<col class="l">
|
||||||
|
<col class="q">
|
||||||
|
<col class="s">
|
||||||
|
</colgroup>
|
||||||
|
<tr>
|
||||||
|
<th colspan="3">Active quests (Max.: 4)</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="background"></div>
|
||||||
|
</td>
|
||||||
|
<td>King Of Kings</td>
|
||||||
|
<td class="subtle">Active</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="background"></div>
|
||||||
|
</td>
|
||||||
|
<td>Garage Days Pt. 1</td>
|
||||||
|
<td class="subtle success">Complete</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2>King Of Kings</h2>
|
||||||
|
<p>A hijacked medium mech dubbed the "Rat King" ...</p>
|
||||||
|
<hr class="dotted">
|
||||||
|
<p>Collect Rat King residue.</p>
|
||||||
|
<hr>
|
||||||
|
<p>Multiple rig container upgrades, 5000 CR, 5000 XP, 2 days of water, + Scav faction
|
||||||
|
rating</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<footer class="io">
|
||||||
|
<button data-action="back">Back</button>
|
||||||
|
<button data-action="accept">Accept</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block assets %}
|
||||||
|
<script src="/vendor/hippie-script.js"></script>
|
||||||
|
<script src="/js/globals.js"></script>
|
||||||
|
<script src="/js/app.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{%- block script %}
|
||||||
|
{{ block.super -}}
|
||||||
|
<script>
|
||||||
|
const menu = document.querySelector('body > header');
|
||||||
|
const locations = document.querySelectorAll('main table .background');
|
||||||
|
|
||||||
|
menu.addEventListener('click', (event) => {
|
||||||
|
const buttons = menu.querySelectorAll('button');
|
||||||
|
const buttonTarget = event.target.closest('button');
|
||||||
|
|
||||||
|
if (buttonTarget && event.button === 0) {
|
||||||
|
for (button of buttons) {
|
||||||
|
button.classList.remove('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonTarget.classList.add('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
locations.forEach(element => {
|
||||||
|
const blur = randomIntFrom(0, 4);
|
||||||
|
const grayscale = randomFloatFrom(0, 1);
|
||||||
|
|
||||||
|
new RandomPixelCanvas(element, {
|
||||||
|
width: Math.floor(element.parentElement.clientWidth),
|
||||||
|
height: Math.floor(element.parentElement.clientHeight),
|
||||||
|
colors: ['#fad803', '#d30a51', '#273f8b', '#b7e0f0', '#52bed1', '#0c85ff'],
|
||||||
|
filter: 'grayscale(' + grayscale + ') blur(' + blur + 'px)'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -29,7 +29,7 @@ $steps: (0, 14.28, 28.57, 42.85, 57.14, 71.43, 100);
|
||||||
animation: fadeColor 16s infinite linear;
|
animation: fadeColor 16s infinite linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
.body_game {
|
.body_menu {
|
||||||
@extend .h_full_view;
|
@extend .h_full_view;
|
||||||
background-color: hotpink;
|
background-color: hotpink;
|
||||||
|
|
||||||
|
|
@ -71,4 +71,155 @@ $steps: (0, 14.28, 28.57, 42.85, 57.14, 71.43, 100);
|
||||||
left: 0;
|
left: 0;
|
||||||
border-radius: hippie.$radius_basic;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue