This project represents a japanese style idle game.
Short project name: zlig (stands for zen-landscape-idle-game)
Current deployment on:
main: https://zlig.net/dev: https://zlig-git-dev-toddetv-projects.vercel.app/If you like this project and want to support us, we would be very happy to see you as a sponsor on GitHub ❤️
You can find the Sponsor button on the top right of the GitHub project page.
Thanks a lot for the support <3
sudo rm -rf build dist .output .datasudo rm -rf node_modulesDevelopment VM ID from Thorsten for this project: 014
(Only interesting to him.)
The following softwares are required for development:
(The versions listed were the ones I most recently used for development and testing. So try sticking with them.)
| software | command for version output | my version at last use | information |
|---|---|---|---|
| Ubuntu | lsb_release -a or cat /etc/os-release | 22.04.4 LTS | OS |
| Linux | uname -r | 5.15.0-125-generic | Linux Kernel |
| VSCode | code -v | 1.93.2 | IDE |
| nvm | nvm -v | v0.40.1 | Node Version Manager |
| Node | node -v (old nodejs --version) | v22.13.0 | NodeJS/ Node.js |
| npm | npm -v | v10.9.2 | |
| npx | npx -v | v10.9.2 | |
| pnpm | pnpm -v | v10.0.0 |
In the browser install:
git pull{Ctrl}+{Shift}+{P} -> >Preferences: Open Settings (UI) -> search for keyboard.dispatch and set it to keyCode{Ctrl}+{Shift}+{X})@recommended.vscode/extensions.json for configuring some of the extensionsYou have not yet finished authorizing [...] Would you like to try a different way? (local server) click Yes and use this alternative login mechanic.Cancel to trigger the dialog faster.)pnpm ibuild area and building area (not building lot nor building place).This project uses antfu/eslint-config for eslint most of the files. The following extend it:
prettier for the file types that eslint cannot handle.Keep in mind that the plugin names are renamed, see Plugins Rename, e.g.:
-// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
+// eslint-disable-next-line ts/consistent-type-definitions
type foo = { bar: 2 }
Why I don't use Prettier for every file type
This project uses the following icon collections in descending order, try sticking to them and use from top to bottom. Tipp: Favorite them and use the search over all item collections at once: https://icon-sets.iconify.design/?list=favorite
| full name | shorthand | license | note |
|---|---|---|---|
phosphor | ph | MIT | |
Material Design Icons | mdi | Apache 2.0 (commercial use is allowed, no attribution required) | |
Material Line Icons | line-md | MIT | animated icons |
Use draco compression in Blender on glTF 2 files:
File -> Export -> glTF 2.0 (.glb/.gltf)Format to glTF Seperate (.gltf + .bin + textures)Remember Export Settings to trueData set Compression to trueCompression set the compression level between 0-6 (0=less compression; 6=strongest compression)6 most of the time - only when morphing between models, this should be set to 0.Do not import from three directly but from the direct source instead. Example:
-import { MeshLambertMaterial } from 'three'
+import { MeshLambertMaterial } from 'three/src/materials/MeshLambertMaterial.js'
Seems to work for types, but better use the direct import from the source folder (see above):
<script setup lang="ts">
import type * as THREE from 'three'
</script>
<script setup lang="ts">
import { something } from '@tresjs/cientos'
import { something } from '@tresjs/core'
// import { something } from '@tresjs/nuxt'
// import { something } from '@tresjs/post-processing'
import { something } from 'three'
import { something } from 'three/src/[...].js'
import { something } from 'three-stdlib'
</script>
*.gltf model filesMethod 1: With direct useGLTF
<script setup lang="ts">
import useGLTF from '@/composables/useGLTF.js'
const { scenes } = await useGLTF('/MyModel/MyModel.gltf')
</script>
<template>
<primitive :object="scenes.someScene" />
</template>
*.gltf models, along with their corresponding *.bin and texture files, are located in /public/.
The useGLTF fetches it over HTTPuseGLTF, no extra layers or wrappersMethod 2: With generated helper wrappers and type definitions
<script setup lang="ts">
import modelLoader from '@/assets/models/someSubfolder/someModel.gltf'
const { scenes } = await modelLoader
</script>
<template>
<primitive :object="scenes.someScene" />
</template>
All *.gltf models, along with their corresponding *.bin and texture files, are located in /src/assets/models/.
To generate helper wrappers and type definitions, run:
pnpm run generate:gltf-models
This script scans all model files in the source folder, deconstructs the GLTF JSON representation, and places
the generated types in ./node_modules/.tmp/model-types/, ensuring only imported models are included in the
final product.
The script runs automatically:
.gltf file changespnpm iNearly type safe GLTF file representations.
Importing models is type-safe, and builds will fail if a model is missing.
Only the used models are bundled in the final product.
On runtime: Runs useGLTF under the hood. So 100% correct objects and usage, no extra layer.
In dev: Scans the *.gltf file on its own, so the generated typing has redundant code and could be different
from what is present on runtime. So be careful when using and test/ double check it!
Example: In gltfModel.scenes.someScene.traversed.Object the typing only hints real objects and not each
primitive that is used to build up the objects. But in runtime these primitives are also present in the
traversed.Object - but funnily enough not all ... that is the reason I left away all primitives, just to be sure.
For already loaded and parsed models the GLTF loader returns a cached version. So primitive uses then the same
model which means the single instance is unmounted and mounted again with other coordinates.
Solution: clone it
<script setup lang="ts">
// ...
const model = scenes.someScene.Object.someObject.clone()
</script>
<template>
<primitive :object="model" />
</template>
Example shadow configuration below. The so generated shadows currently have heavy artifacts, so we bake the shadows in this project. But here is an example configuration for shadows:
<script setup lang="ts">
import { DirectionalLightShadow } from 'three/src/lights/DirectionalLightShadow.js'
nodes.MyObject.castShadow = true
nodes.MyObject.receiveShadow = true
nodes.MyGroundPlane.receiveShadow = true
const directionalLightShadow = new DirectionalLightShadow()
directionalLightShadow.mapSize.width = 4096
directionalLightShadow.mapSize.height = 4096
directionalLightShadow.normalBias = 0.1
directionalLightShadow.bias = 0.002
</script>
<template>
<Suspense>
<TresCanvas shadows>
<!-- ... -->
<TresDirectionalLight
cast-shadow
:intensity="3.0"
:position="[4, 8, 4]"
:shadow="directionalLightShadow"
/>
<TresAmbientLight :intensity="0.3" />
<!-- ... -->
</TresCanvas>
</Suspense>
</template>
Normally, you could use the packages @tresjs/post-processing and postprocessing in combination for postprocessing
TresJS/ ThreeJS. Unfortunately, they are currently not compatible with TresJS core >v4, see
comment on issue #16 and
issue #32.
Will use the build command out of /package.json.
Building, deploying and hosting is done via Vercel.
Project founder & head of project:
Honorable mentions to people that helped this project:
Respectable mentions to projects that helped this project:
Used programs/ softwares, services and dependencies - besides the ones in ./package.json:
Used assets/ materials including images and 3D models:
14:
19:
KayKit - Medieval Hexagon PackCopyright (c) 2024-present, Thorsten Seyschab
This project, including original code and models, is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (CC BY-NC-SA 4.0). Under this license, others are allowed to remix, adapt, and build upon this work non-commercially, provided they credit the project founder and license any derivative works under the same terms.
Please note that this license applies only to the original content authored by the project’s creators. Third-party libraries, assets, 3D models, and other materials utilized in this project are listed under "Attribution/ Contribution" above and remain the property of their original creators, licensed under their respective terms.
The project founder reserves the right to modify the terms of this license or to offer different licensing arrangements for specific use cases.
For the full license text, please see the LICENSE file.
If you are interested in discussing a different licensing arrangement for individual use cases, please feel free to reach out. Custom licensing may be available, but it is not guaranteed.