Compare commits

..
2 Commits
Author SHA1 Message Date
Douwe 2eef84eb03 Restructure to classic static-site layout, add project-card component, fix bugs
- Move wwwroot/ to public/ with assets/ grouping (css, js, img, fonts, vid)
- Inline section includes into index.html, drop runtime fetch loading
- Add project-card web component to replace repeated project markup
- Fix IntersectionObserver options placement bug in nav highlight
- Fix @font-face syntax, invalid 5-digit hex colors, 75x border-radius typo
- Remove dead css link (home.css), unused purple/orange color vars
- Fix typos, replace inline styles with classes, serve favicon
2026-09-24 14:22:54 +00:00
douwe 8ab6193103 Merge pull request 'Changed to nginx based server removing need for hosting software. Project is pure front-end.' (#1) from nginx into main
Reviewed-on: #1
2026-09-23 12:53:02 +00:00
34 changed files with 385 additions and 293 deletions
+43
View File
@@ -2,3 +2,46 @@
The main landing page for all my projects. The main landing page for all my projects.
You can find it at [www.douwco.be](https://www.douwco.be) You can find it at [www.douwco.be](https://www.douwco.be)
Pure static front-end site served by nginx. No build step required.
## Structure
```
public/ Site root (served by nginx)
├── index.html Single page: home, about, apps, games
├── favicon.ico
└── assets/
├── css/ douwco.css (branding), style.css (layout)
├── js/ index.js (nav, copyright), project-card.js (web component)
├── img/ Logos, screenshots, icons
├── fonts/ Righteous + Montserrat (self-hosted)
└── vid/ Demo videos
```
## Development
Any static file server works, e.g.:
```bash
docker compose up # site on http://localhost:8080
```
or natively:
```bash
python3 -m http.server -d public 8080
```
## Adding a project card
Use the `project-card` component in `public/index.html`:
```html
<project-card
image="/assets/img/my_project.png"
image-alt="My Project"
title="My Project"
description="Some text with a [[link label|https://example.com]].">
</project-card>
```
+1 -1
View File
@@ -4,7 +4,7 @@ FROM nginx:alpine
RUN rm /usr/share/nginx/html/index.html RUN rm /usr/share/nginx/html/index.html
# Copy static website files # Copy static website files
COPY wwwroot/ /usr/share/nginx/html/ COPY public/ /usr/share/nginx/html/
# Expose port 80 # Expose port 80
EXPOSE 80 EXPOSE 80
+36
View File
@@ -0,0 +1,36 @@
@font-face {
font-family: 'Righteous';
src: url('/assets/fonts/Righteous-Regular.ttf') format('truetype');
font-display: swap;
}
@font-face {
font-family: 'Montserrat';
src: url('/assets/fonts/Montserrat-Regular.ttf') format('truetype');
font-display: swap;
}
@font-face {
font-family: 'Montserrat';
src: url('/assets/fonts/Montserrat-Bold.ttf') format('truetype');
font-weight: bold;
font-display: swap;
}
:root {
--background-clr: #283e3e;
--background-accent-clr: #324f4f;
--blue-clr: #47bcdf;
--green-clr: #6ede9a;
--white-clr: #ffffff;
}
body {
font-family: 'Montserrat', sans-serif;
background-color: var(--background-clr);
color: var(--white-clr);
}
.title {
font-family: 'Righteous', sans-serif;
}
@@ -1,13 +1,12 @@
/* ===== Base Styles ===== */ /* ===== Base Styles ===== */
html, body {
html, body{
height: 100%; height: 100%;
margin: 0; margin: 0;
padding: 0; padding: 0;
font-size: 25px; font-size: 25px;
} }
body{ body {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
@@ -21,7 +20,7 @@ main {
} }
a { a {
color: var(--blue-clr) color: var(--blue-clr)
} }
footer { footer {
@@ -30,17 +29,21 @@ footer {
width: 100%; width: 100%;
} }
footer > Div { footer > div {
justify-content: space-between justify-content: space-between
} }
footer > Div > p { footer > div > p {
font-size: 16px; font-size: 16px;
margin: 10px 25px 10px 25px; margin: 10px 25px 10px 25px;
} }
/* ===== Container Layouts ===== */ .flag {
height: 16px;
vertical-align: middle;
}
/* ===== Container Layouts ===== */
.vert_container { .vert_container {
display: flex; display: flex;
} }
@@ -51,12 +54,12 @@ footer > Div > p {
} }
} }
.vert_container.centered{ .vert_container.centered {
align-items: center; align-items: center;
justify-content: space-around; justify-content: space-around;
} }
.vert_container.start{ .vert_container.start {
align-items: flex-start; align-items: flex-start;
justify-content: space-around; justify-content: space-around;
} }
@@ -74,7 +77,8 @@ footer > Div > p {
/* ===== Navigationbar ===== */ /* ===== Navigationbar ===== */
.nav_option { .nav_option {
font-family: monsterrat_bold; font-family: 'Montserrat', sans-serif;
font-weight: bold;
color: var(--white-clr); color: var(--white-clr);
text-decoration: none; text-decoration: none;
font-size: 36px; font-size: 36px;
@@ -89,7 +93,7 @@ footer > Div > p {
padding-right: 10px; padding-right: 10px;
} }
.nav_option:hover{ .nav_option:hover {
background-color: var(--background-accent-clr); background-color: var(--background-accent-clr);
} }
@@ -139,6 +143,11 @@ footer > Div > p {
.title { .title {
font-size: 100px; font-size: 100px;
} }
.tagline {
font-size: 26px;
width: 400px;
}
} }
.tagline { .tagline {
@@ -156,17 +165,6 @@ footer > Div > p {
margin-left: 7px; margin-left: 7px;
} }
@media (max-width: 1200px) {
.title {
font-size: 100px;
}
.tagline {
font-size: 26px;
width: 400px;
}
}
.content-box { .content-box {
background-color: var(--background-accent-clr); background-color: var(--background-accent-clr);
margin: 50px 20px 20px; margin: 50px 20px 20px;
@@ -189,40 +187,44 @@ footer > Div > p {
height: 150px; height: 150px;
object-fit: cover; object-fit: cover;
margin-right: 15px; margin-right: 15px;
border-radius: 75x; border-radius: 75px;
float: left; float: left;
} }
/* ===== Images ===== */ /* ===== Images ===== */
.icon { .icon {
vertical-align: middle; vertical-align: middle;
padding: 10px; padding: 10px;
} }
.icon.small { .icon.small {
height: 45px; height: 45px;
} }
.icon.medium { .icon.medium {
height: 100px; height: 100px;
} }
.icon.large { .icon.large {
height: 250px; height: 250px;
} }
@media (max-width: 1200px) { @media (max-width: 1200px) {
.icon.large.toggle { .icon.large.toggle {
height: 150px; height: 150px;
} }
} }
.image {
.image{
margin: 30px; margin: 30px;
} }
.image.large{
.image.large {
width: 40%; width: 40%;
} }
.image.small{
.image.small {
width: 25%; width: 25%;
} }
@@ -230,7 +232,8 @@ footer > Div > p {
.image.large { .image.large {
width: 80%; width: 80%;
} }
.image.small{
.image.small {
width: 50%; width: 50%;
} }
} }
@@ -239,5 +242,3 @@ footer > Div > p {
position: sticky; position: sticky;
top: 20px top: 20px
} }

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Before

Width:  |  Height:  |  Size: 296 KiB

After

Width:  |  Height:  |  Size: 296 KiB

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Before

Width:  |  Height:  |  Size: 327 KiB

After

Width:  |  Height:  |  Size: 327 KiB

Before

Width:  |  Height:  |  Size: 8.1 MiB

After

Width:  |  Height:  |  Size: 8.1 MiB

Before

Width:  |  Height:  |  Size: 984 KiB

After

Width:  |  Height:  |  Size: 984 KiB

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 123 KiB

@@ -1,30 +1,31 @@
// Setup the navigation bar document.addEventListener('DOMContentLoaded', () => {
function setupNavigationHighlight(){ setupNavigationHighlight();
setupNavigationClicks();
setupCopyright();
});
function setupNavigationHighlight() {
const sections = document.querySelectorAll('.scroll_section'); const sections = document.querySelectorAll('.scroll_section');
const navOptions = document.querySelectorAll('.nav_option'); const navOptions = document.querySelectorAll('.nav_option');
const observer = new IntersectionObserver((entries) => { const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => { entries.forEach(entry => {
if (entry.isIntersecting) { if (entry.isIntersecting) {
const sectionId = entry.target.id; const sectionId = entry.target.id;
window.history.pushState(null, null, `#${sectionId}`); window.history.replaceState(null, null, `#${sectionId}`);
navOptions.forEach(link => { navOptions.forEach(link => {
link.classList.remove('active'); link.classList.toggle('active', link.getAttribute('href') === `#${sectionId}`);
if (link.getAttribute('href') === `#${sectionId}`) {
link.classList.add('active');
}
}); });
} }
}), {threshold: 0.5}; });
}) }, {
threshold: 0.5
sections.forEach(section => {
observer.observe(section);
}); });
sections.forEach(section => observer.observe(section));
} }
function setupNavigationClickObserver() { function setupNavigationClicks() {
const navLinks = document.querySelectorAll('.nav_option'); document.querySelectorAll('.nav_option').forEach(link => {
navLinks.forEach(link => {
link.addEventListener('click', (event) => { link.addEventListener('click', (event) => {
event.preventDefault(); event.preventDefault();
@@ -39,9 +40,6 @@ function setupNavigationClickObserver() {
}); });
} }
setupNavigationHighlight(); function setupCopyright() {
setupNavigationClickObserver(); document.getElementById('copyright').textContent = `© ${new Date().getFullYear()} - douwco.be`;
}
// Set copyright year
const currentYear = new Date().getFullYear();
document.getElementById('copyright').textContent = `© ${currentYear} - douwco.be`;
+101
View File
@@ -0,0 +1,101 @@
class ProjectCard extends HTMLElement {
static get observedAttributes() {
return ['image', 'image-alt', 'title', 'description'];
}
constructor() {
super();
this.attachShadow({ mode: 'open' });
this._rendered = false;
}
connectedCallback() {
this._render();
}
attributeChangedCallback() {
if (this._rendered) {
this._render();
}
}
_render() {
this._rendered = true;
const alt = this.getAttribute('image-alt') || '';
const title = this.getAttribute('title') || '';
const description = this.getAttribute('description') || '';
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
}
.content-box {
background-color: var(--background-accent-clr, #324f4f);
margin: 50px 20px 20px;
padding: 20px;
border-radius: 20px;
}
.content-box p {
margin: 0;
}
.intro-text {
font-weight: bolder;
font-size: 28px;
color: var(--green-clr, #6ede9a);
}
.project-thumb {
width: 150px;
height: 150px;
object-fit: cover;
margin-right: 15px;
border-radius: 75px;
float: left;
}
::slotted(p) { margin: 0; }
</style>
<div class="content-box">
<img class="project-thumb" src="${this._escapeAttribute(this.getAttribute('image') || '')}" alt="${this._escapeAttribute(alt)}">
<p><span class="intro-text"></span><slot></slot></p>
</div>`;
this.shadowRoot.querySelector('.intro-text').textContent = title;
this._renderDescription(description);
}
_renderDescription(description) {
const slot = this.shadowRoot.querySelector('slot');
slot.textContent = '';
const linkPattern = /\[\[([^|\]]+)\|([^\]]+)\]\]/g;
let lastIndex = 0;
let match;
while ((match = linkPattern.exec(description)) !== null) {
if (match.index > lastIndex) {
slot.appendChild(document.createTextNode(description.slice(lastIndex, match.index)));
}
const link = document.createElement('a');
link.href = match[2];
link.textContent = match[1];
if (match[2].startsWith('http')) {
link.target = '_blank';
link.rel = 'noopener';
}
slot.appendChild(link);
lastIndex = match.index + match[0].length;
if (linkPattern.lastIndex === match.index) {
linkPattern.lastIndex++;
}
}
if (lastIndex < description.length) {
slot.appendChild(document.createTextNode(description.slice(lastIndex)));
}
}
_escapeAttribute(value) {
return value
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/</g, '&lt;');
}
}
customElements.define('project-card', ProjectCard);

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

+150
View File
@@ -0,0 +1,150 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="description" content="Douwco - portfolio and projects of Douwe, PhD student at KU Leuven and game developer."/>
<title>Douwco</title>
<link rel="icon" href="/favicon.ico"/>
<link rel="stylesheet" href="/assets/css/douwco.css"/>
<link rel="stylesheet" href="/assets/css/style.css"/>
<script src="/assets/js/project-card.js" defer></script>
<script src="/assets/js/index.js" defer></script>
</head>
<body>
<header>
<nav>
<div class="vert_container centered">
<a class="nav_option" href="#home"><img class="icon medium" src="/assets/img/douwco_logo.png" alt="Douwco logo"></a>
<a class="nav_option" href="#about_me">
<img class="icon small" src="/assets/img/icons/user.png" alt="">
<p>About <span>Me</span></p>
</a>
<a class="nav_option" href="#apps">
<img class="icon small" src="/assets/img/icons/projects_icon.png" alt="">
<p>Douwco <span>Apps</span></p>
</a>
<a class="nav_option" href="#games">
<img class="icon small" src="/assets/img/icons/devicegamepad2.png" alt="">
<p>My <span>Games</span></p>
</a>
</div>
</nav>
</header>
<main class="scroll_container">
<section id="home" class="scroll_section">
<div class="vert_container revert start">
<div class="panel">
<div class="section-title">
<img class="icon large toggle" src="/assets/img/douwco_logo.png" alt="">
<div class="text-section">
<h1 class="title">Douwco</h1>
<div class="tagline">
<p class="green-text">Because</p>
<p class="normal-text">nerds build their own homeserver.</p>
</div>
</div>
</div>
<div class="content-box">
<p>
<span class="intro-text">Welcome to the Douwco website.</span> <br>
Ever wondered what machine the website you are visiting is run on? Well this time you know, just look to the image.
This small homeserver hosts several open-source services like Nextcloud, Gitea, Overleaf community and of course this
website. <br> <br>
Here I showcase my portfolio and all the games I've created over the years. If you are
a family member you can also find the different services in the Douwco Apps tab.
</p>
</div>
</div>
<img class="image stick large" src="/assets/img/server_image.png" alt="The homeserver running this website">
</div>
</section>
<section id="about_me" class="scroll_section">
<div class="vert_container start">
<img class="image stick small" src="/assets/img/me_img.png" alt="Portrait of Douwe">
<div class="panel">
<h1>Hi, I'm Douwe</h1>
<p>
A <span class="green-text">PhD student</span> at KU Leuven with a passion for game development and software independence.
<br><br>
Currently I'm working on:
</p>
<project-card image="/assets/img/rollability.png" image-alt="RollAbility"
title="RollAbility"
description="For my PhD research at KU Leuven, I'm developing RollAbility, a therapeutic exergame that bridges player autonomy with clinical guidelines to enhance wheelchair training.
Developed in collaboration with therapists, RollAbility is a game built onto a clinical protocol and controlled by an actual powered wheelchair. The game connects to the RollAbility App which allows therapists to control the training session in real-time.
[[Read the paper|https://dl.acm.org/doi/abs/10.1145/3748621]] or [[watch the video|https://www.youtube.com/watch?v=8y9XFdSN_04]].">
</project-card>
<project-card image="/assets/img/alcove.png" image-alt="Alcove"
title="Alcove"
description="Alcove is an interreg project between Flemish, Walloon and French universities and hospitals that aims to build a device that detects lung cancer through a breath test.
My role is to create a user interface for the device. This UI has to work both on android phones and on embedded linux devices.
[[Read more about Alcove|https://alcove.crosss3.eu/nl/]].">
</project-card>
<p><span class="green-text">However</span> in the past I also worked on:</p>
<project-card image="/assets/img/godot_addons.png" image-alt="Godot tools"
title="Godot Addons"
description="I published two small addons to the godot asset library.
One addon called [[Godot Visual Studio Debugger|https://godotengine.org/asset-library/asset/3505]] which allows you to dynamically run the current scene open in the Godot editor directly in Visual Studio Debugger.
The second addon called [[Godot Test Scenes|https://godotengine.org/asset-library/asset/3420]] extends the Godot editor with an additional run mode, this mode runs an associated test scene to the currently open one in the editor.
They are both open source:
[[Godot Test Scenes|https://github.com/DouweRavers/godot_test_scene]] and [[Godot Visual Studio Debugger|https://github.com/DouweRavers/godot_visualstudio_debugger/tree/main]].">
</project-card>
<project-card image="/assets/img/kingfisher.png" image-alt="Kingfisher"
title="Kingfisher"
description="The project [[Kingfisher|https://kingfisher-game.com/]] is a game built by PossilbyPixels that raises awareness about Autism. It is a story-based action / puzzle game for PC and mobile.
My role in the project was to build minigames that occur throughout the story and also to develop tools to help development.
One of the tools I made for this project was a suburban neighborhood generator. This tool allowed us to draw streets in the editor which then were automatically filled with procedurally generated houses and gardens. You can see a demo in [[this video|/assets/vid/procedural_streets.mp4]].
You can wishlist the game on [[Steam|https://store.steampowered.com/app/4197280/Kingfisher_An_Autism_Tale/]]!">
</project-card>
<project-card image="/assets/img/ludum_dare.png" image-alt="Ludum Dare"
title="Ludum Dare"
description="Between 2019 and 2024, I participated regularly in the Ludum Dare event. This event was all about creating games under tight deadlines of 48 hours and with no external resources such as audio or 3D art.
After each event I published my game on [[Itch.io|https://coffeeplanet.itch.io/]] where they are still available for play. In the future I want to migrate them to this website.
I want to especially highlight [[Cobor goes farming|https://coffeeplanet.itch.io/ludum-dare-51]] and [[Windy the Indie|https://coffeeplanet.itch.io/windy-the-indie]].">
</project-card>
<project-card image="/assets/img/thesis_tool.png" image-alt="Planet Tool"
title="Masterthesis: Planet Tool"
description="For my Masterthesis at Group T KU Leuven I made a tool for Unity that creates a procedural planet terrain.
The main challenge of this project was to optimize the algorithm to work as fast as possible. For this I leveraged GPU compute shaders to process large chunks of data at once.
You can find the tool and my thesis paper [[here|https://github.com/DouweRavers/ThesisProject-ThePlanetEngine/tree/main]].">
</project-card>
<project-card image="/assets/img/wizard_gloves.png" image-alt="Wizard Gloves"
title="Masterproject: Wizard Gloves"
description="In another project during my masters we explored gesture-based interactions in virtual environments.
For this project we developed a prototype using Unity and custom wearable hardware to enable magic-like hand gestures for interfacing with a story game.
See the game [[here|/assets/vid/wizard_gloves.mp4]] or you can find the game and paper [[here|https://github.com/DouweRavers/MasterProject-WizardsGlovesAdventure/tree/main]].">
</project-card>
</div>
</div>
</section>
<section id="apps" class="scroll_section">
<h1>Douwco Apps</h1>
<div class="content-box">
<p>
Under construction...
</p>
</div>
</section>
<section id="games" class="scroll_section">
<h1>My Games</h1>
<div class="content-box">
<p>
Under construction...
</p>
</div>
</section>
</main>
<footer>
<div class="vert_container">
<p id="copyright"></p>
<p>Made and hosted in <img class="flag" src="/assets/img/icons/europe.png" alt="the EU"></p>
</div>
</footer>
</body>
</html>
-37
View File
@@ -1,37 +0,0 @@
@font-face {
font-family: righteous;
src: url(/fonts/Righteous-Regular.ttf);
format('truetype');
}
@font-face {
font-family: monsterrat_regular;
src: url(/fonts/Montserrat-Regular.ttf);
format('truetype');
}
@font-face {
font-family: monsterrat_bold;
src: url(/fonts/Montserrat-Bold.ttf);
format('truetype');
}
:root {
--background-clr: #283e3e;
--background-accent-clr: #324f4f;
--blue-clr: #47bcdf;
--green-clr: #6ede9a;
--purple-clr: #a48da;
--orange-clr: #e2a661;
--white-clr: #ffffff;
}
body {
font-family: monsterrat_regular;
background-color: var(--background-clr);
color: var(--white-clr);;
}
.title{
font-family: righteous;
}
-82
View File
@@ -1,82 +0,0 @@
<div class="vert_container start">
<img class="image stick small" src="/img/me_img.png" alt="Image">
<div class="panel">
<h1>Hi, I'm Douwe</h1>
<p>
A <span style="color: var(--green-clr);">PhD student</span> at KU Leuven with a passion for game development and software independence.
<br><br>
Currently I'm working on:
</p>
<div class="content-box">
<img class="project-thumb" src="/img/rollability.png" alt="RollAbility">
<p>
<span class="intro-text">RollAbility</span> <br>
For my PhD research at KU Leuven, I'm developing RollAbility a therapeutic exergame that bridges player autonomy with clinical guidelines to enhance wheelchair training.
<br><br>Developed in collaboration with therapists, RollAbility is a game build onto a clinical protocol
and controlled by an actual powered wheelchair. The game connects to the RollAbility App which allows therapists
to control the training session in real-time.
<br><br><a href="https://dl.acm.org/doi/abs/10.1145/3748621" target="_blank">Read the paper</a> or <a href="https://www.youtube.com/watch?v=8y9XFdSN_04" target="_blank">Watch the video</a>.
</p>
</div>
<div class="content-box">
<img class="project-thumb" src="/img/alcove.png" alt="Alcove">
<p>
<span class="intro-text">Alcove</span> <br>
Alcove is a interreg project between Flemish, Walloon and French universities and hospitals that aims to build a device that detects lung cancer through a breath test.
<br><br>My role is to create a user interface for the device. This UI has to work on both android phones as on embedded linux devices.
<br><br><a href="https://alcove.crosss3.eu/nl/" target="_blank">Read more about Alcove</a>.
</p>
</div>
<p><span style="color: var(--green-clr);">However</span> in the past I also worked on:</p>
<div class="content-box">
<img class="project-thumb" src="/img/godot_addons.png" alt="Godot tools">
<p>
<span class="intro-text">Godot Addons</span> <br>
I published two small addons to the godot asset library.
<br><br>One addon called <a href="https://godotengine.org/asset-library/asset/3505">Godot Visual Studio Debugger</a> which allows you to dynammicaly run the current scene open in the Godot editor directly in Visual Studio Debugger.
<br><br>The second addons called <a href="https://godotengine.org/asset-library/asset/3420">Godot Test Scenes</a> extends the Godot editor with an additional run mode, this mode runs a associated test scene to the currently open one in the editor.
<br><br>They are both open source:
<br><a href="https://github.com/DouweRavers/godot_test_scene">Godot Test Scenes</a> and <a href="https://github.com/DouweRavers/godot_visualstudio_debugger/tree/main">Godot Visual Studio Debugger</a>
</p>
</div>
<div class="content-box">
<img class="project-thumb" src="/img/kingfisher.png" alt="Kingfisher">
<p>
<span class="intro-text">Kingfisher</span> <br>
The project <a href="https://kingfisher-game.com/">Kingfisher</a> is a game build by <a>PossilbyPixels</a> that rises awareness about Autism. It is a storybased action / puzzle game for PC and mobile.
<br><br>My role in the project was to build minigames that occur throughout the story and also to develop tools to help development.
<br><br>One of the tools I made for this project was a suburban neigborhood generator. This tool allowed us to draw streets in the editor which then were automaticly filled with procedural generated houses and gardens. You can see a demo in <a href="/vid/procedural_streets.mp4">this video</a>.
<br><br>You can wishlist the game on <a href="https://store.steampowered.com/app/4197280/Kingfisher_An_Autism_Tale/">Steam</a>!
</p>
</div>
<div class="content-box">
<img class="project-thumb" src="/img/ludum_dare.png" alt="Ludum Dare">
<p>
<span class="intro-text">Ludum Dare</span> <br>
Between 2019 and 2024, I participated regulary into the Ludum Dare Event. This event was all about creating games under tight deadlines of 48 hours and with no external resources such as audio or 3D art.
<br><br>After each event I published my game on <a href="https://coffeeplanet.itch.io/">Itch.io</a> where they are still availble for play. In the future I want to migrate them to this website.
<br><br>I want to especially highlight <a href="https://coffeeplanet.itch.io/ludum-dare-51">Cobor goes farming</a> and <a href="https://coffeeplanet.itch.io/windy-the-indie">Windy the Indy</a>
</p>
</div>
<div class="content-box">
<img class="project-thumb" src="/img/thesis_tool.png" alt="Planet Tool">
<p>
<span class="intro-text">Masterthesis: Planet Tool</span> <br>
For my Masterthesis at Group T KU Leuven I made a tool for Unity that creates a procedural planet terrain.
<br><br>The main challenge of this project was to optimize the algorithm to work as fast as possible. For this I leveraged GPU compute shaders to process large chunks of data at once.
<br><br>You can find the tool and my thesis paper <a href="https://github.com/DouweRavers/ThesisProject-ThePlanetEngine/tree/main">here</a>.
</p>
</div>
<div class="content-box">
<img class="project-thumb" src="/img/wizard_gloves.png" alt="Wizard Gloves">
<p>
<span class="intro-text">Masterproject: Wizard Gloves</span> <br>
In another project during my masters we explored gesture-based interactions in virtual environments.
<br><br>For this project we developed a prototype using Unity and custom wearable hardware to enable magic-like hand gestures for interfacing with a story game.
<br><br>See the game <a href="/vid/wizard_gloves.mp4">here</a> or you can find the game and paper <a href="https://github.com/DouweRavers/MasterProject-WizardsGlovesAdventure/tree/main">here</a>
</p>
</div>
</div>
</div>
-6
View File
@@ -1,6 +0,0 @@
<h1>Douwco Apps</h1>
<div class="content-box">
<p>
Under construction...
</p>
</div>
-6
View File
@@ -1,6 +0,0 @@
<h1>My Games</h1>
<div class="content-box">
<p>
Under construction...
</p>
</div>
-25
View File
@@ -1,25 +0,0 @@
<div class="vert_container revert start">
<div class="panel">
<div class="section-title">
<img class="icon large toggle" src="/img/douwco_logo.png" alt="Image">
<div class="text-section">
<h1 class="title">Douwco</h1>
<div class="tagline">
<p class="green-text">Because </p>
<p class="normal-text">nerds build their own homeserver.</p>
</div>
</div>
</div>
<div class="content-box">
<p>
<span class="intro-text">Welcome to the Douwco website.</span> <br>
Ever wondered what machine the website you are visiting is run on? Well this time you know, just look to the image.
This small homeserver hosts several open-source services like Nextcloud, Gitea, Overleaf community and ofcourse this
website. <br> <br>
Here I showcase my portfolio and all the games I've created over the years. If you are
a family member you can also find the different services in the Douwco Apps tab.
</p>
</div>
</div>
<img class="image stick large" src="/img/server_image.png" alt="Image">
</div>
-49
View File
@@ -1,49 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Douwco</title>
<link rel="stylesheet" href="/css/style.css" />
<link rel="stylesheet" href="/css/douwco.css" />
<link rel="stylesheet" href="css/home.css">
</head>
<body>
<header>
<nav>
<div class="vert_container centered">
<a class="nav_option" href="#home"><img class="icon medium" src="/img/douwco_logo.png"></a>
<a class="nav_option" href="#about_me">
<img class="icon small" src="/img/icons/user.png" alt="Icon">
<p>About <span>Me</span></p>
</a>
<a class="nav_option" href="#apps">
<img class="icon small" src="/img/icons/projects_icon.png" alt="Icon">
<p>Douwco <span>Apps</span></p>
</a>
<a class="nav_option" href="#games">
<img class="icon small" src="/img/icons/devicegamepad2.png" alt="Icon">
<p>My <span>Games</span></p>
</a>
</div>
</nav>
</header>
<main class="scroll_container">
<section id="home" class="scroll_section observed" data-section-name="home"></section>
<section id="about_me" class="scroll_section observed" data-section-name="about_me"></section>
<section id="apps" class="scroll_section observed" data-section-name="apps"></section>
<section id="games" class="scroll_section observed" data-section-name="games"></section>
</main>
<footer>
<div class="vert_container">
<p id="copyright"></p>
<p>Made and hosted in 🇪🇺</p>
</div>
</footer>
<script src="/js/main.js"></script>
<script src="/js/index.js"></script>
</body>
</html>
-32
View File
@@ -1,32 +0,0 @@
// JIT file loading
function include_file(filename, id) {
fetch(`includes/${filename}.html`)
.then(response => response.text())
.then(html => { document.getElementById(id).innerHTML = html; })
.catch(err => console.error('Error loading include:', err));
}
function setupIntersectionObserver() {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const element = entry.target;
const name = element.getAttribute('data-section-name');
include_file(name, element.id);
observer.unobserve(element);
}
});
}, {
threshold: 0.05,
rootMargin: "0px 0px -50px 0px"
});
const observedSections = document.querySelectorAll('.observed');
if (observedSections.length === 0) {
console.error('No elements with class "observed" found!');
} else {
observedSections.forEach(section => { observer.observe(section); });
}
}
setupIntersectionObserver();