feat/switch-assets #86

Merged
legonzaur merged 22 commits from feat/switch-assets into main 2024-05-21 19:09:34 +00:00
156 changed files with 956 additions and 25 deletions
+1 -3
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import goStore, { setReady, oauth2_register_discord, setup_websocket, heron_cookie_login } from "@/netcode";
import goStore, { oauth2_register_discord, setup_websocket, heron_cookie_login } from "@/netcode";
await setup_websocket()
@@ -10,8 +10,6 @@ useHead
: 'Héron Realms',
})
const heron_session = useCookie('heron_session')
const route = useRoute()
+34
View File
@@ -0,0 +1,34 @@
#ifdef GL_ES
precision mediump float;
#endif
#define FBM_OCTAVES 6
#include "lygia/generative/fbm.glsl"
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform vec3 u_color_start;
uniform vec3 u_color_end;
uniform vec2 u_offset;
uniform float u_time;
void main(){
vec2 st=(gl_FragCoord.xy+u_offset)/u_resolution;
vec2 q=vec2(0.);
q.x=fbm(st);
q.y=fbm(st+vec2(1.));
q=q*.5+.5;
vec2 r=vec2(0.);
r.x=fbm(st+1.*q+vec2(1.7,9.2)+.00515*u_time);
r.y=fbm(st+1.*q+vec2(8.3,2.8)+.0126*u_time);
r=r*.5+.5;
float f=fbm(st+r);
vec3 color=mix(u_color_start,u_color_end,f*.3);
gl_FragColor=vec4(color,1.);
}
+158
View File
@@ -0,0 +1,158 @@
<script setup lang="ts">
import noise from "~/assets/shaders/noise.frag?raw"
const canvas = ref<HTMLCanvasElement | null>(null)
const settingsStore = useSettingsStore()
declare const webglUtils: {
createProgramFromSources: (gl: WebGLRenderingContext, array: [string, string]) => WebGLProgram,
resizeCanvasToDisplaySize: (e: HTMLCanvasElement | OffscreenCanvas) => any
}
declare const resolveLygiaAsync: (source: string) => Promise<string>
export interface Props {
colorStart?: [number, number, number]
colorEnd?: [number, number, number]
}
const props = withDefaults(defineProps<Props>(), {
colorStart: () => [0, .3, 0],
colorEnd: () => [0, 1, 0]
})
const targetFramerate = 1000 / settingsStore.shaderFramerate
const interval = ref<ReturnType<typeof setInterval>>()
let fragmentShader = await resolveLygiaAsync(noise);
async function main(canvas: HTMLCanvasElement, fragmentShader2: string) {
// Get A WebGL context
/** @type {HTMLCanvasElement} */
const gl = canvas.getContext("webgl");
if (!gl) {
return;
}
const vs = `attribute vec4 a_position;void main() {gl_Position = a_position;}`;
// setup GLSL program
const program = webglUtils.createProgramFromSources(gl, [vs, fragmentShader2]);
// look up where the vertex data needs to go.
const positionAttributeLocation = gl.getAttribLocation(program, "a_position");
// look up uniform locations
const offset = gl.getUniformLocation(program, "u_offset");
const resolutionLocation = gl.getUniformLocation(program, "u_resolution");
const colorStart = gl.getUniformLocation(program, "u_color_start");
const quality = gl.getUniformLocation(program, "u_quality");
const colorEnd = gl.getUniformLocation(program, "u_color_end");
const timeLocation = gl.getUniformLocation(program, "u_time");
// Create a buffer to put three 2d clip space points in
const positionBuffer = gl.createBuffer();
// Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// fill it with a 2 triangles that cover clipspace
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-1, -1, // first triangle
1, -1,
-1, 1,
-1, 1, // second triangle
1, -1,
1, 1,
]), gl.STATIC_DRAW);
const gl2 = gl
function render(time: number) {
time *= 0.001; // convert to seconds
webglUtils.resizeCanvasToDisplaySize(gl2.canvas);
// Tell WebGL how to convert from clip space to pixels
gl2.viewport(0, 0, gl2.canvas.width, gl2.canvas.height);
// Tell it to use our program (pair of shaders)
gl2.useProgram(program);
// Turn on the attribute
gl2.enableVertexAttribArray(positionAttributeLocation);
// Bind the position buffer.
gl2.bindBuffer(gl2.ARRAY_BUFFER, positionBuffer);
// Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
gl2.vertexAttribPointer(
positionAttributeLocation,
2, // 2 components per iteration
gl2.FLOAT, // the data is 32bit floats
false, // don't normalize the data
0, // 0 = move forward size * sizeof(type) each iteration to get the next position
0, // start at the beginning of the buffer
);
const bounds = canvas.getBoundingClientRect()
const aspectRatio = Math.max(window.screen.width, window.screen.height) * devicePixelRatio
gl2.uniform2f(offset, bounds.left, -bounds.bottom);
// console.log(canvas.getBoundingClientRect().left * window.devicePixelRatio)
gl2.uniform1i(quality, settingsStore.shaderQuality)
gl2.uniform2f(resolutionLocation, aspectRatio, aspectRatio);
gl2.uniform3f(colorStart, props.colorStart[0], props.colorStart[1], props.colorStart[2]);
gl2.uniform3f(colorEnd, props.colorEnd[0], props.colorEnd[1], props.colorEnd[2]);
gl2.uniform1f(timeLocation, time);
gl2.drawArrays(
gl2.TRIANGLES,
0, // offset
6, // num vertices to process
);
}
clearInterval(interval.value)
interval.value = setInterval(() => requestAnimationFrame(render), targetFramerate)
}
async function reloadShader() {
nextTick(() => {
if (!canvas.value) { return }
let fragmentShader2 = fragmentShader.replace("#define FBM_OCTAVES 6", "#define FBM_OCTAVES " + settingsStore.shaderQuality);
clearInterval(interval.value)
main(canvas.value, fragmentShader2);
})
}
watch(() => settingsStore.shaderQuality, (newValue, oldValue) => {
reloadShader()
})
watch(() => settingsStore.shaderFramerate, (newValue, oldValue) => {
reloadShader()
})
onMounted(async () => {
reloadShader()
})
onUnmounted(() => {
clearInterval(interval.value)
})
</script>
<template>
<canvas v-if="settingsStore.shaderQuality != 0" ref="canvas" id="background">test</canvas>
</template>
<style scoped>
#background {
left: 0;
position: absolute;
height: 100%;
width: 100%;
}
</style>
+3 -1
View File
@@ -5,6 +5,7 @@ export interface Props {
card_id: number | undefined
}
const settingsStore = useSettingsStore()
const props = defineProps<Props>()
const card: Ref<Element | null> = ref(null)
@@ -32,7 +33,8 @@ const y = computed(() => {
<template>
<div :class="`card_overlay`" :style="`top: ${y}px; left: ${x}px`" ref="card">
<img :class="`card_image`" v-if="props.card_id"
:src="'/cards/' + props.card_id.toString().padStart(3, '0') + '.png'" draggable="false">
:src="`/cards/${settingsStore.cardStyle}/` + props.card_id.toString().padStart(3, '0') + '.png'"
draggable="false">
<!-- <img :class="`card_image`" v-if="!props.card_id" :src="'/cards/background.png'" draggable="false"> -->
</div>
+5 -1
View File
@@ -1,5 +1,6 @@
<script setup lang="ts">
import goStore from '~/netcode';
import { useSettingsStore } from '~/stores/settingsStore';
export interface Props {
card_id: number | undefined
@@ -16,6 +17,8 @@ const props = withDefaults(defineProps<Props>(), {
const emit = defineEmits(["click"])
const settingsStore = useSettingsStore()
const childCount = ref<number>(0)
function cardClick() {
@@ -48,7 +51,8 @@ watch(
<slot></slot>
</div>
<img :class="`card_image`" v-if="props.card_id"
:src="'/cards/' + props.card_id.toString().padStart(3, '0') + '.png'" draggable="false">
:src="`/cards/${settingsStore.cardStyle}/` + props.card_id.toString().padStart(3, '0') + '.png'"
draggable="false">
<img :class="`card_image`" v-if="!props.card_id" :src="'/cards/background.png'" draggable="false">
+14 -14
View File
@@ -41,6 +41,7 @@ watch(
})
const showResults = ref(false)
const showOptions = ref(false)
const isWinner = ref(false)
function showLoserScreen() {
@@ -62,20 +63,23 @@ function showWinnerScreen() {
<MarketCards></MarketCards>
</div>
<div id="player_list">
<AnimatedBackground />
<PlayerListElement v-for="p in goStore.current_game?.players" :player="p">
</PlayerListElement>
</div>
<div id="current_player"
:class="(goStore.current_game?.current_turn && (goStore.current_game?.current_turn === goStore.self?.team)) ? 'self' : ''">
<PlayerSlot v-for="p in current_players" :player="p"></PlayerSlot>
<div id="current_player">
<template v-for="p in current_players">
<AnimatedBackground :color-start="goStore.self == p ? [.0, .3, .3] : undefined"
:color-end="goStore.self == p ? [.0, 1, 1] : undefined" />
<PlayerSlot :player="p"></PlayerSlot>
</template>
</div>
</div>
<ResultDialog
:isVisible="showResults"
:won="isWinner"
:players="goStore.current_game?.players"
<ResultDialog :isVisible="showResults" :won="isWinner" :players="goStore.current_game?.players"
@close="showResults = false">
</ResultDialog>
<GlobalOverlay></GlobalOverlay>
<SelfView></SelfView>
</template>
@@ -95,22 +99,18 @@ function showWinnerScreen() {
overflow: auto;
position: relative;
isolation: isolate;
}
#current_player.self {
background-image: url('../images/bg-grass.png');
background: url('/images/bg-darkgrass.png');
}
#market {
grid-area: market;
background-image: url("/images/bg-sand.png");
padding: 10px;
border-bottom: 3px solid black;
;
}
#current_player {
grid-area: current_player;
background-image: url("/images/bg-darkgrass.png");
}
#player_list {
+31
View File
@@ -0,0 +1,31 @@
<script setup lang="ts">
import goStore from '~/netcode';
const displayOptions = ref(false)
</script>
<template>
<div :class="`card_overlay`" ref="card">
<img class="settings_button" src="/settings.png" alt="settings" @click="displayOptions = true"/>
</div>
<OptionsDialog :isVisible="displayOptions" @close="displayOptions = false" />
</template>
<style scoped>
.card_overlay {
/* display: none; */
position: fixed;
z-index: 999;
display: flex;
pointer-events: none;
/* top: left: */
top: 0;
}
.settings_button {
pointer-events: all;
width: 30px;
padding: 5px;
}
</style>
+4
View File
@@ -7,10 +7,12 @@ const isTurn = computed(() => goStore.self && goStore.current_game?.started && (
const clientStore = useClientSideStore()
const buyableFiregem = computed(() => goStore?.current_game?.gem_stack.at(-1))
</script>
<template>
<div id="market">
<AnimatedBackground :color-end="[1, 1, 0]" :color-start="[.3, .3, 0]"></AnimatedBackground>
<CardPreview :tilted="false" :card_id="undefined"></CardPreview>
<div class="separator"></div>
<CardPreview :tilted="false" :card_id="c?.card_id" v-for="c in goStore.current_game?.market"
@@ -60,6 +62,8 @@ const buyableFiregem = computed(() => goStore?.current_game?.gem_stack.at(-1))
z-index: 2;
position: relative;
gap: 2px;
padding: 10px;
;
}
.separator {
+129
View File
@@ -0,0 +1,129 @@
<script setup lang="ts">
const settingsStore = useSettingsStore()
export interface Props {
isVisible: boolean;
}
const props = withDefaults(defineProps<Props>(), {
})
const emit = defineEmits(['close'])
const close = () => {
emit('close')
}
watch(() => settingsStore.shaderQuality, async () => {
console.log(settingsStore.shaderQuality)
})
</script>
<template>
<div v-if="isVisible" class="dialog-overlay" @click="close">
<div class="dialog-box" @click.stop>
<div class="dialog-header">
<h3>Visuals</h3>
</div>
<div class="dialog-header">
<span>Toggle Card Style</span>
</div>
<div class="dialog-body">
<button @click="settingsStore.switchCardStyles">Toggle Card style</button>
</div>
<div class="dialog-header">
<h3>Graphics</h3>
</div>
<div class="dialog-header">
<span>Shader Quality</span>
</div>
<div class="dialog-body">
<input type="range" min="0" max="10" v-model="settingsStore.shaderQuality">
</div>
<div class="dialog-footer">
<span>
<template v-if="settingsStore.shaderQuality == 0">
Disabled
</template>
<template v-if="settingsStore.shaderQuality > 0">
{{ settingsStore.shaderQuality }}
</template>
</span>
</div>
<div class="dialog-header">
<span>Shader Framerate</span>
</div>
<div class="dialog-body">
<input type="range" min="10" max="60" step="5" v-model="settingsStore.shaderFramerate"
:disabled="settingsStore.shaderQuality == 0">
</div>
<div class="dialog-footer">
<span>{{ settingsStore.shaderFramerate }} fps</span>
</div>
</div>
</div>
</template>
<style scoped>
.dialog-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
display: grid;
}
.dialog-box {
background-image: url('../images/bg-grass.png');
padding: 0 20px;
border-radius: 5px;
width: 800px;
border-radius: 30px;
max-width: 100%;
color: white;
text-align: center;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
display: grid;
grid-template-columns: 33% 33% 33%;
}
.dialog-box h3 {
font-size: 30px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
width: 100%;
padding: 10px 0;
color: white;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
}
.dialog-header,
.dialog-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
}
.dialog-header {
grid-column-start: 1;
}
.dialog-body {
padding: 10px 0;
grid-column-start: 2;
}
.dialog-footer {
grid-column-start: 3;
}
</style>
+3 -1
View File
@@ -18,6 +18,7 @@ const props = defineProps<Props>()
<template>
<div :class="`player_list_element ${goStore.self === props.player ? 'self' : ''}`">
<AnimatedBackground v-if="goStore.self === props.player" :color-start="[.0, .3, .3]" :color-end="[.0, 1, 1]" />
<div class="button" id="player_list_buttons">
<div class="main_button" @click="show('main')">
<div class="tooltip">Board</div>
@@ -119,10 +120,11 @@ const props = defineProps<Props>()
"button player";
border-bottom: 5px solid black;
min-height: 200px;
position: relative;
}
.player_list_element.self {
background-image: url('../images/bg-grass.png');
background-image: url('/images/bg-grass.png');
}
.view {
+1 -1
View File
@@ -92,7 +92,7 @@ function check_for_guard(player: Player) {
</script>
<template>
<div :class="`player ${isPlayerTurn ? 'turn' : ''} ${discard_unwrapped ? 'discard_unwrapped' : ''}`">
<div class="player" :class="{ turn: isPlayerTurn, discard_unwrapped, self: isSelf }">
<template v-if="!hide_stack_and_discard">
<div class="stack">
+1 -1
View File
@@ -66,7 +66,7 @@ const close = () => {
}
.dialog-box {
background-image: url('../images/bg-grass.png');
background-image: url('/images/bg-grass.png');
padding: 0 20px;
border-radius: 5px;
width: 800px;
+10
View File
@@ -10,5 +10,15 @@ export default defineNuxtConfig({
},
modules: [
'@pinia/nuxt',
'@pinia-plugin-persistedstate/nuxt',
],
app: {
head: {
script: [{
src: "/webgl-utils.js"
}, {
src: "https://lygia.xyz/resolve.js"
}]
}
},
})
+28
View File
@@ -12,6 +12,9 @@
"pinia": "^2.1.7",
"vue": "^3.4.21",
"vue-router": "^4.3.0"
},
"devDependencies": {
"@pinia-plugin-persistedstate/nuxt": "^1.2.0"
}
},
"node_modules/@ampproject/remapping": {
@@ -2093,6 +2096,21 @@
"node": ">=0.10"
}
},
"node_modules/@pinia-plugin-persistedstate/nuxt": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@pinia-plugin-persistedstate/nuxt/-/nuxt-1.2.0.tgz",
"integrity": "sha512-2rtgx5viGSMQMCoFYZMHguA2FhFKCUvw0PwETfqQegsWeBHlqk1/D0G/9xqep8Hq+c1BuFx+jNLJzoLXtYfivg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nuxt/kit": "^3.8.0",
"defu": "^6.1.2",
"pinia-plugin-persistedstate": ">=3.2.0"
},
"peerDependencies": {
"@pinia/nuxt": "^0.5.0"
}
},
"node_modules/@pinia/nuxt": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@pinia/nuxt/-/nuxt-0.5.1.tgz",
@@ -7803,6 +7821,16 @@
}
}
},
"node_modules/pinia-plugin-persistedstate": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.2.1.tgz",
"integrity": "sha512-MK++8LRUsGF7r45PjBFES82ISnPzyO6IZx3CH5vyPseFLZCk1g2kgx6l/nW8pEBKxxd4do0P6bJw+mUSZIEZUQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"pinia": "^2.0.0"
}
},
"node_modules/pinia/node_modules/vue-demi": {
"version": "0.14.7",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
+3
View File
@@ -15,5 +15,8 @@
"pinia": "^2.1.7",
"vue": "^3.4.21",
"vue-router": "^4.3.0"
},
"devDependencies": {
"@pinia-plugin-persistedstate/nuxt": "^1.2.0"
}
}
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More