diff --git a/public/yml/DialogPorsche.yml b/public/yml/DialogPorsche.yml index 96b6782..03219e4 100644 --- a/public/yml/DialogPorsche.yml +++ b/public/yml/DialogPorsche.yml @@ -8,8 +8,8 @@ type: conversation name: Porsche text: ”Hi! I haven’t seen you around before so you must be new. I’m Porsche. Why don’t you sit with me and my friends? We'll tell you about the school!” - sprite: "" - background: "" + sprite: "_Porsche_normal.zip" + background: "bg-hallway.png" goTo: 3 - id: 3 diff --git a/src/css/conversation.css b/src/css/conversation.css new file mode 100644 index 0000000..b415a66 --- /dev/null +++ b/src/css/conversation.css @@ -0,0 +1,9 @@ +.spriteBox { + height: 50vh; + width: 30vw; +} +@media (max-width: 768px) { + .spriteBox { + width: 75vw; + } +} \ No newline at end of file diff --git a/src/css/nameBox.css b/src/css/nameBox.css new file mode 100644 index 0000000..622135a --- /dev/null +++ b/src/css/nameBox.css @@ -0,0 +1,16 @@ +.nameBox { + display: flex; + justify-content: center; + align-items: center; + width: 20vw; + min-width: 100px; + background-color: #8391b8; + color: white; + border-style: solid; + border-color: #8391b8; + border-width: 5px; + border-radius: -10px; + position: absolute; + transform: translateY(-40px); + z-index: 2; +} diff --git a/src/css/textBox.css b/src/css/textBox.css index 8850286..6f3376f 100644 --- a/src/css/textBox.css +++ b/src/css/textBox.css @@ -9,13 +9,5 @@ border-color: #8391b8; border-width: 5px; border-radius: 30px; + padding: 50px; } - -@media (max-width: 768px) { - .textBox.title { - margin-top: 50vh; - } - .textBox.title.small { - margin-top: 50vh; - } -} \ No newline at end of file diff --git a/src/pages/components/animation.jsx b/src/pages/components/animation.jsx index 35ec36c..6e06d56 100644 --- a/src/pages/components/animation.jsx +++ b/src/pages/components/animation.jsx @@ -1,22 +1,19 @@ import React, { useEffect, useState, useRef } from 'react'; import JSZip from 'jszip'; - -const Animation = ({ src = "M_Porsche_cross_arm.zip", animationWidth = "500px" }) => { +const Animation = ({ src = "M_Porsche_cross_arm.zip", h = '100%', w = '100%' }) => { const [images, setImages] = useState([]); const [loading, setLoading] = useState(true); - const frameRate = 1000 / 24; // Original frame rate (24 FPS) + const frameRate = 1000 / 24; // 24 FPS const canvasRef = useRef(null); const animationRef = useRef(null); const currentFrameRef = useRef(0); const imageElementsRef = useRef([]); const urlSource = `${import.meta.env.VITE_ASSETS_URL}/${src}`; - // Load images from the ZIP file useEffect(() => { const loadImages = async () => { const zip = new JSZip(); - // console.log(import.meta.env.VITE_ASSETS_URL); try { const response = await fetch(urlSource); if (!response.ok) { @@ -42,24 +39,22 @@ const Animation = ({ src = "M_Porsche_cross_arm.zip", animationWidth = "500px" } }); const imgElements = await Promise.all(imgPromises); - if (imgElements.length === 0) { console.error('No images found in the ZIP file.'); } - imageElementsRef.current = imgElements; // Store preloaded images - setImages(imgElements); // Set images state + imageElementsRef.current = imgElements; + setImages(imgElements); } catch (error) { console.error('Error loading images:', error); } finally { - setLoading(false); + setLoading(false); } }; loadImages(); }, [urlSource]); - // WebGL setup and animation loop useEffect(() => { if (images.length > 0) { const canvas = canvasRef.current; @@ -69,17 +64,21 @@ const Animation = ({ src = "M_Porsche_cross_arm.zip", animationWidth = "500px" } return; } - // Set up WebGL context (basic) - gl.clearColor(0.0, 0.0, 0.0, 0.0); - gl.clear(gl.COLOR_BUFFER_BIT); + const rect = canvas.getBoundingClientRect(); + const dpr = window.devicePixelRatio || 1; + canvas.width = rect.width * dpr; + canvas.height = rect.height * dpr; gl.viewport(0, 0, canvas.width, canvas.height); - // Enable blending + canvas.style.width = `${rect.width}px`; + canvas.style.height = `${rect.height}px`; + + gl.clearColor(0.0, 0.0, 0.0, 0.0); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - // gl.blendFunc(gl.SRC_COLOR, gl.DST_COLOR); - // Shader program const vertexShaderSource = ` attribute vec2 a_position; attribute vec2 a_texCoord; @@ -103,7 +102,7 @@ const Animation = ({ src = "M_Porsche_cross_arm.zip", animationWidth = "500px" } gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - console.error('ERROR compiling shader', gl.getShaderInfoLog(shader)); + console.error('Shader compile error:', gl.getShaderInfoLog(shader)); } return shader; }; @@ -116,18 +115,17 @@ const Animation = ({ src = "M_Porsche_cross_arm.zip", animationWidth = "500px" } gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { - console.error('ERROR linking program', gl.getProgramInfoLog(shaderProgram)); + console.error('Program link error:', gl.getProgramInfoLog(shaderProgram)); } gl.useProgram(shaderProgram); - // Create buffer and set up attributes const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); const vertices = new Float32Array([ - -1.0, -1.0, // Bottom-left - 1.0, -1.0, // Bottom-right - -1.0, 1.0, // Top-left - 1.0, 1.0 // Top-right + -1.0, -1.0, + 1.0, -1.0, + -1.0, 1.0, + 1.0, 1.0, ]); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); @@ -135,33 +133,13 @@ const Animation = ({ src = "M_Porsche_cross_arm.zip", animationWidth = "500px" } gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(positionLocation); - // Create texture and load image - const texture = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - const loadTexture = (image) => { - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); - - gl.generateMipmap(gl.TEXTURE_2D); - }; - - loadTexture(imageElementsRef.current[0]); // Initially load the first image - - // Texture coordinates const texCoordBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer); const texCoords = new Float32Array([ - 0.0, 1.0, // Bottom-left (now corresponds to top-left of the image) - 1.0, 1.0, // Bottom-right (now corresponds to top-right of the image) - 0.0, 0.0, // Top-left (now corresponds to bottom-left of the image) - 1.0, 0.0 // Top-right (now corresponds to bottom-right of the image) + 0.0, 1.0, + 1.0, 1.0, + 0.0, 0.0, + 1.0, 0.0, ]); gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW); @@ -169,9 +147,28 @@ const Animation = ({ src = "M_Porsche_cross_arm.zip", animationWidth = "500px" } gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(texCoordLocation); + const texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + // Optionally use NEAREST for sharper image: + // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + const uTextureLocation = gl.getUniformLocation(shaderProgram, "u_texture"); + const loadTexture = (image) => { + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + gl.generateMipmap(gl.TEXTURE_2D); + }; + + loadTexture(imageElementsRef.current[0]); + let lastFrameTime = 0; + const animate = (timestamp) => { if (lastFrameTime === 0) lastFrameTime = timestamp; @@ -202,18 +199,12 @@ const Animation = ({ src = "M_Porsche_cross_arm.zip", animationWidth = "500px" } return
Loading...
; } else { return ( -
- -
+ ); } }; export default Animation; - - \ No newline at end of file diff --git a/src/pages/conversationPage.jsx b/src/pages/conversationPage.jsx index 00298f6..49c2128 100644 --- a/src/pages/conversationPage.jsx +++ b/src/pages/conversationPage.jsx @@ -2,29 +2,36 @@ import { useEffect, useState } from 'react'; import '../css/global.css'; import '../css/textBox.css'; +import '../css/nameBox.css'; +import '../css/conversation.css' +import Animation from './components/animation.jsx'; function ConversationPage({data , onClicked}) { const backgroundSRC = `${import.meta.env.VITE_ASSETS_URL}/${data.background}` return (
-
- {data.name} +
+
-
+
+
+ {data.name} +
+
+
{data.text}
diff --git a/src/pages/vistualNovelHandler.jsx b/src/pages/vistualNovelHandler.jsx index 1ab06cc..3d80925 100644 --- a/src/pages/vistualNovelHandler.jsx +++ b/src/pages/vistualNovelHandler.jsx @@ -4,6 +4,7 @@ import { useNavigate, useParams } from 'react-router-dom'; import '../css/global.css'; import { fetchYamlData } from './components/fetchYamlData'; import StoryPage from './storyPage'; +import ConversationPage from './conversationPage.jsx'; import LoadingScene from './components/loadingScene.jsx'; function VitualNovelHandler() { @@ -58,7 +59,7 @@ function VitualNovelHandler() { case "story": return ; case "conversation": - return
conversation
; + return ; case "option": return
option
; default: @@ -67,7 +68,7 @@ function VitualNovelHandler() { }; return ( -
+
{renderComponent(currentStepData.type)}
);