Compare commits

...

4 Commits

17
.gitignore vendored

@ -130,3 +130,20 @@ dist
.yarn/install-state.gz
.pnp.*
# Vue / Vite project
.DS_Store
dist-ssr
*.local
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
pnpm-debug.log*
/cypress/videos/
/cypress/screenshots/
__screenshots__/

3
.gitmodules vendored

@ -0,0 +1,3 @@
[submodule "i-love-x-engine"]
path = i-love-x-engine
url = https://git.pack.house/pack.house/i-love-x-engine.git

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}

@ -1,2 +1,42 @@
# i-love-breda
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
## Recommended Browser Setup
- Chromium-based browsers (Chrome, Edge, Brave, etc.):
- [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
- [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters)
- Firefox:
- [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/)
- [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/)
## Type Support for `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
## Customize configuration
See [Vite Configuration Reference](https://vite.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Type-Check, Compile and Minify for Production
```sh
npm run build
```

1
env.d.ts vendored

@ -0,0 +1 @@
/// <reference types="vite/client" />

@ -0,0 +1,26 @@
{
"maxTotalTime": 1800,
"games": [
{ "mission": "connect-quest", "timeLimit": 300 },
{ "mission": "memory", "timeLimit": 300 },
{ "mission": "puzzle", "timeLimit": 300 },
{ "mission": "quiz", "timeLimit": 300 }
],
"modes": {
"standard": {
"maxTotalTime": 1800,
"description": "Standard flow",
"sequence": "pick",
"games": ["connect-quest", "memory", "puzzle", "quiz"],
"rounds": 3,
"coaches": ["default"]
}
},
"coaches": {
"default": {
"coach": "default",
"languages": ["en"]
}
}
}

@ -0,0 +1 @@
Subproject commit 3c8066204005918735c3a37340fb8a126b793981

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

2902
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,33 @@
{
"name": "i-love-breda",
"version": "0.0.0",
"private": true,
"type": "module",
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"scripts": {
"dev": "vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --build",
"electron:dev": "cd i-love-x-engine && yarn dev",
"electron:dev:npm": "cd i-love-x-engine && npm run dev"
},
"dependencies": {
"vue": "^3.5.25"
},
"devDependencies": {
"@tsconfig/node24": "^24.0.3",
"@types/node": "^24.10.1",
"@vitejs/plugin-vue": "^6.0.2",
"@vue/tsconfig": "^0.8.1",
"npm-run-all2": "^8.0.4",
"typescript": "~5.9.0",
"vite": "^7.2.4",
"vite-plugin-vue-devtools": "^8.0.5",
"vue-tsc": "^3.1.5"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -0,0 +1,93 @@
<template>
<div id="app">
<DefaultScreens :dev-preview="true" :preview-height-ratio="0.5">
<template #left>
<BootjeSideScreen v-if="isBootjeGame" />
<SideScreenMiniGame
v-else-if="isPuzzleGame"
player-id="player1"
screen-id="left"
:controller-number="1"
/>
<QuizSideScreen v-else-if="isQuizGame" />
<GlassGameSideScreen v-else-if="isGlassGame" />
<SideScoreScreen v-else />
</template>
<template #fullscreen></template>
<GameFlow ref="gameFlowRef" :games="games" @flow-changed="handleFlowChanged" />
<template #right>
<BootjeSideScreen v-if="isBootjeGame" />
<SideScreenMiniGame
v-else-if="isPuzzleGame"
player-id="player2"
screen-id="right"
:controller-number="2"
/>
<QuizSideScreen v-else-if="isQuizGame" />
<GlassGameSideScreen v-else-if="isGlassGame" />
<SideScoreScreen v-else />
</template>
</DefaultScreens>
</div>
</template>
<script setup lang="ts">
import { computed, markRaw, ref } from "vue";
import DefaultScreens from "../i-love-x-engine/src/components/ScreenXCube.vue";
import GameFlow from "../i-love-x-engine/core/GameFlow.vue";
// Challenges
import ConnectQuest from "../i-love-x-engine/src/challenges/connect-quest/ConnectQuest.vue";
import CatchGame from "../i-love-x-engine/src/challenges/CatchGame/CatchGame.vue";
import Puzzle from "../i-love-x-engine/src/challenges/puzzle/puzzle.vue";
import TowerGame from "../i-love-x-engine/src/challenges/Tower/TowerGame.vue";
import GlassGame from "../i-love-x-engine/src/challenges/GlassGame/views/Intro.vue";
import Quiz from "../i-love-x-engine/src/challenges/Quiz/Quiz.vue";
import Bootje from "../i-love-x-engine/src/challenges/bootje/views/Race.vue";
// Side Screens
import SideScreenMiniGame from "../i-love-x-engine/src/challenges/puzzle-mini-game/SideScreenMiniGame.vue";
import SideScoreScreen from "../i-love-x-engine/src/challenges/scorescreen/SideScoreScreen.vue";
import BootjeSideScreen from "../i-love-x-engine/src/challenges/bootje/views/SideScreen.vue";
import QuizSideScreen from "../i-love-x-engine/src/challenges/Quiz/views/SideScreen.vue";
import GlassGameSideScreen from "../i-love-x-engine/src/challenges/GlassGame/views/GlassGameSideScreen.vue";
const games: Record<string, any> = {
"connect-quest": markRaw(ConnectQuest),
"catch-game": markRaw(CatchGame),
puzzle: markRaw(Puzzle),
"tower-game": markRaw(TowerGame),
"glass-game": markRaw(GlassGame),
quiz: markRaw(Quiz),
bootje: markRaw(Bootje),
};
const gameFlowRef = ref<any>(null);
const currentGameIndex = ref(0);
const isPuzzleGame = computed(
() => currentGameIndex.value === 2 && gameFlowRef.value?.selectedGame === "puzzle",
);
const isBootjeGame = computed(
() => currentGameIndex.value === 2 && gameFlowRef.value?.selectedGame === "bootje",
);
const isQuizGame = computed(
() =>
currentGameIndex.value === 4 ||
(currentGameIndex.value === 2 && gameFlowRef.value?.selectedGame === "quiz"),
);
const isGlassGame = computed(
() => currentGameIndex.value === 2 && gameFlowRef.value?.selectedGame === "glass-game",
);
const handleFlowChanged = (index: number) => {
currentGameIndex.value = index;
};
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 KiB

@ -0,0 +1,47 @@
/* Dutch theme override for engine CatchGame.vue */
/* This file overrides the engine's CatchGame.css to use Dutch assets */
.play-area {
background-image: url('../catchgame/frozenLake.png') !important;
background-size: cover !important;
background-repeat: no-repeat !important;
background-position: center !important;
}
/* Remove borders and shadows from players, use different colored skaters */
.player {
width: 15% !important;
height: 15%!important;
background-size: contain !important;
background-repeat: no-repeat !important;
background-position: center !important;
border: none !important;
box-shadow: none !important;
background-color: transparent !important;
}
/* Different colored skaters for each player position - using data attribute instead of nth-child */
.player[data-player-id="0"] { background-image: url('../catchgame/red-ice-skater.png') !important; }
.player[data-player-id="1"] { background-image: url('../catchgame/green-ice-skater.png') !important; }
.player[data-player-id="2"] { background-image: url('../catchgame/blue-ice-skater.png') !important; }
.player[data-player-id="3"] { background-image: url('../catchgame/yellow-ice-skater.png') !important; }
.player[data-player-id="4"] { background-image: url('../catchgame/pink-ice-skater.png') !important; }
.player[data-player-id="5"] { background-image: url('../catchgame/cyan-ice-skater.png') !important; }
.player[data-player-id="6"] { background-image: url('../catchgame/orange-ice-skater.png') !important; }
.player[data-player-id="7"] { background-image: url('../catchgame/purple-ice-skater.png') !important; }
/* Fallback for any additional players */
.player[data-player-id]:not([data-player-id="0"]):not([data-player-id="1"]):not([data-player-id="2"]):not([data-player-id="3"]):not([data-player-id="4"]):not([data-player-id="5"]):not([data-player-id="6"]):not([data-player-id="7"]) { background-image: url('../catchgame/ice-skater.png') !important; }
/* Remove borders and shadows from falling objects (stroopwafels) */
.falling-object {
width: 4% !important;
height: 4%!important;
background-image: url('../catchgame/stroopwafel.png') !important;
background-size: contain !important;
background-repeat: no-repeat !important;
background-position: center !important;
border: none !important;
box-shadow: none !important;
background-color: transparent !important;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

@ -0,0 +1,4 @@
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')

@ -0,0 +1,11 @@
export const PLAYER_NAMES = [
{ name: "Player 1", color: "#ff0000" },
{ name: "Player 2", color: "#00ff00" },
{ name: "Player 3", color: "#0000ff" },
{ name: "Player 4", color: "#ffff00" },
{ name: "Player 5", color: "#ff00ff" },
{ name: "Player 6", color: "#00ffff" },
{ name: "Player 7", color: "#ff8800" },
{ name: "Player 8", color: "#8800ff" },
];

@ -0,0 +1,13 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"paths": {
"@/*": ["./src/*"],
"@src/*": ["./src/*"]
}
}
}

@ -0,0 +1,11 @@
{
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
}
]
}

@ -0,0 +1,19 @@
{
"extends": "@tsconfig/node24/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*",
"eslint.config.*"
],
"compilerOptions": {
"noEmit": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}

@ -0,0 +1,19 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
'@src': fileURLToPath(new URL('./src', import.meta.url)),
},
},
})

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save