Ditching animation.jsx, and replace with WebM. Concept is already on Porchese
This commit is contained in:
parent
1693567813
commit
43dd81842e
8 changed files with 31 additions and 370 deletions
|
@ -8,7 +8,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
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!”
|
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: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 3
|
goTo: 3
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
option:
|
option:
|
||||||
- text: Sure!
|
- text: Sure!
|
||||||
goTo: 4
|
goTo: 4
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
|
|
||||||
- id: 4
|
- id: 4
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: “Seems like people have been losing their stuff a lot lately. I can’t think of who would do it though, since we all know each other.”
|
text: “Seems like people have been losing their stuff a lot lately. I can’t think of who would do it though, since we all know each other.”
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 8
|
goTo: 8
|
||||||
|
|
||||||
|
@ -55,14 +55,14 @@
|
||||||
goTo: 9
|
goTo: 9
|
||||||
- text: "I don’t know either, I’m not familiar with anyone."
|
- text: "I don’t know either, I’m not familiar with anyone."
|
||||||
goTo: 10
|
goTo: 10
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
|
|
||||||
- id: 9
|
- id: 9
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: “No! I don’t think so! But people might think it’s you because you’re new. It’s unfair but it’s just how it is sometimes.”
|
text: “No! I don’t think so! But people might think it’s you because you’re new. It’s unfair but it’s just how it is sometimes.”
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 11
|
goTo: 11
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: “Yeah I know. It’s ok. People will calm down. You don’t have to worry!”
|
text: “Yeah I know. It’s ok. People will calm down. You don’t have to worry!”
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 11
|
goTo: 11
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: “Hey, why are people saying that the thief might be me? How could it even be me? Did someone tell everyone it was me?”
|
text: “Hey, why are people saying that the thief might be me? How could it even be me? Did someone tell everyone it was me?”
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 17
|
goTo: 17
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "What? I don’t know, people started talking, but I did say it can’t be you. But it is strange that it happens around you."
|
text: "What? I don’t know, people started talking, but I did say it can’t be you. But it is strange that it happens around you."
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 18
|
goTo: 18
|
||||||
|
|
||||||
|
@ -126,14 +126,14 @@
|
||||||
goTo: 19
|
goTo: 19
|
||||||
- text: "But... I haven’t done anything."
|
- text: "But... I haven’t done anything."
|
||||||
goTo: 20
|
goTo: 20
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
|
|
||||||
- id: 19
|
- id: 19
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "Ha? Are you trying to say that I might be the one who spread the rumor? How could you! Even though I was the one who befriended and defended you."
|
text: "Ha? Are you trying to say that I might be the one who spread the rumor? How could you! Even though I was the one who befriended and defended you."
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 22
|
goTo: 22
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "Calm down! If you are innocent, which I think you are, people will figure it out and calm down as well!"
|
text: "Calm down! If you are innocent, which I think you are, people will figure it out and calm down as well!"
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 21
|
goTo: 21
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "I have to go, see you later!"
|
text: "I have to go, see you later!"
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 22
|
goTo: 22
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "I’ll try asking a classmate about this."
|
text: "I’ll try asking a classmate about this."
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 23
|
goTo: 23
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "Hey sorry to bother but can you tell me what Porsche has been telling everyone these days?"
|
text: "Hey sorry to bother but can you tell me what Porsche has been telling everyone these days?"
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 24
|
goTo: 24
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "Uhhh I’m not sure but they keep saying stuff like how things keep disappearing right after you transferred here. But they did say it probably isn’t you though."
|
text: "Uhhh I’m not sure but they keep saying stuff like how things keep disappearing right after you transferred here. But they did say it probably isn’t you though."
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 25
|
goTo: 25
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "Ok, things keep disappearing and everyone has been saying it’s you, and this time it’s my pencil case! Maybe you should just admit it already?"
|
text: "Ok, things keep disappearing and everyone has been saying it’s you, and this time it’s my pencil case! Maybe you should just admit it already?"
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 29
|
goTo: 29
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "I understand everyone’s concern right now, but I really did not take anything from anyone."
|
text: "I understand everyone’s concern right now, but I really did not take anything from anyone."
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 31
|
goTo: 31
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "I don’t know why and how the rumor started, but I think it’s because I’m new here."
|
text: "I don’t know why and how the rumor started, but I think it’s because I’m new here."
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 32
|
goTo: 32
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "It’s hurtful to think that some of you would believe that I would steal..."
|
text: "It’s hurtful to think that some of you would believe that I would steal..."
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 33
|
goTo: 33
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "After conferring with your classmates, you decided to speak with Porsche alone about the origin of the rumor."
|
text: "After conferring with your classmates, you decided to speak with Porsche alone about the origin of the rumor."
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 37
|
goTo: 37
|
||||||
|
|
||||||
|
@ -261,7 +261,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "The evidence pointed to them as the one who started it, yet they continue to deny it."
|
text: "The evidence pointed to them as the one who started it, yet they continue to deny it."
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 38
|
goTo: 38
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@
|
||||||
type: conversation
|
type: conversation
|
||||||
name: Porsche
|
name: Porsche
|
||||||
text: "As much as you want Porsche to just admit it, you take a deep breath and choose to..."
|
text: "As much as you want Porsche to just admit it, you take a deep breath and choose to..."
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: 39
|
goTo: 39
|
||||||
|
|
||||||
|
@ -281,7 +281,7 @@
|
||||||
goTo: 40
|
goTo: 40
|
||||||
- text: "Distance yourself from Porsche."
|
- text: "Distance yourself from Porsche."
|
||||||
goTo: 43
|
goTo: 43
|
||||||
sprite: "_Porsche_normal.zip"
|
sprite: "F_Porsche_normal.webm"
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
|
|
||||||
- id: 40
|
- id: 40
|
||||||
|
@ -318,4 +318,4 @@
|
||||||
type: story
|
type: story
|
||||||
text: "But for now, you are determined to set clear boundaries to protect yourself, so situations like this don't happen again."
|
text: "But for now, you are determined to set clear boundaries to protect yourself, so situations like this don't happen again."
|
||||||
background: "bg-hallway.png"
|
background: "bg-hallway.png"
|
||||||
goTo: end
|
goTo: end
|
||||||
|
|
|
@ -6,7 +6,6 @@ import './css/global.css';
|
||||||
import HomePage from './pages/homePage.jsx';
|
import HomePage from './pages/homePage.jsx';
|
||||||
import WarningPage from './pages/warningPage.jsx';
|
import WarningPage from './pages/warningPage.jsx';
|
||||||
import NamePage from './pages/namePage.jsx';
|
import NamePage from './pages/namePage.jsx';
|
||||||
import Animation from './pages/components/animation.jsx';
|
|
||||||
import IntroductionPage from './pages/introductionPage.jsx';
|
import IntroductionPage from './pages/introductionPage.jsx';
|
||||||
import PlayVideo from './pages/components/playVideo.jsx'
|
import PlayVideo from './pages/components/playVideo.jsx'
|
||||||
import VitualNovelHandler from './pages/vistualNovelHandler.jsx';
|
import VitualNovelHandler from './pages/vistualNovelHandler.jsx';
|
||||||
|
@ -19,7 +18,6 @@ createRoot(document.getElementById('root')).render(
|
||||||
<Route path="/" element={<HomePage />} />
|
<Route path="/" element={<HomePage />} />
|
||||||
<Route path="/warn" element={<WarningPage />} />
|
<Route path="/warn" element={<WarningPage />} />
|
||||||
<Route path="/name" element={<NamePage />} />
|
<Route path="/name" element={<NamePage />} />
|
||||||
<Route path="/sprite" element={<Animation />} />
|
|
||||||
<Route path='/video' element={<PlayVideo />} />
|
<Route path='/video' element={<PlayVideo />} />
|
||||||
<Route path="/introduction" element={<IntroductionPage />} />
|
<Route path="/introduction" element={<IntroductionPage />} />
|
||||||
<Route path='/vs/:char/:step' element={<VitualNovelHandler />} />
|
<Route path='/vs/:char/:step' element={<VitualNovelHandler />} />
|
||||||
|
|
|
@ -1,210 +0,0 @@
|
||||||
import React, { useEffect, useState, useRef } from 'react';
|
|
||||||
import JSZip from 'jszip';
|
|
||||||
|
|
||||||
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; // 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}`;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const loadImages = async () => {
|
|
||||||
const zip = new JSZip();
|
|
||||||
try {
|
|
||||||
const response = await fetch(urlSource);
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Network response was not ok');
|
|
||||||
}
|
|
||||||
const data = await response.arrayBuffer();
|
|
||||||
const zipContent = await zip.loadAsync(data);
|
|
||||||
|
|
||||||
const imgPromises = [];
|
|
||||||
zipContent.forEach((relativePath, file) => {
|
|
||||||
if (file.name.endsWith('.webp')) {
|
|
||||||
imgPromises.push(
|
|
||||||
file.async('base64').then(base64 => {
|
|
||||||
const img = new Image();
|
|
||||||
img.src = `data:image/webp;base64,${base64}`;
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
img.onload = () => resolve(img);
|
|
||||||
img.onerror = reject;
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const imgElements = await Promise.all(imgPromises);
|
|
||||||
if (imgElements.length === 0) {
|
|
||||||
console.error('No images found in the ZIP file.');
|
|
||||||
}
|
|
||||||
|
|
||||||
imageElementsRef.current = imgElements;
|
|
||||||
setImages(imgElements);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error loading images:', error);
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
loadImages();
|
|
||||||
}, [urlSource]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (images.length > 0) {
|
|
||||||
const canvas = canvasRef.current;
|
|
||||||
const gl = canvas.getContext('webgl');
|
|
||||||
if (!gl) {
|
|
||||||
console.error("WebGL is not supported.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
const vertexShaderSource = `
|
|
||||||
attribute vec2 a_position;
|
|
||||||
attribute vec2 a_texCoord;
|
|
||||||
varying vec2 v_texCoord;
|
|
||||||
void main() {
|
|
||||||
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
||||||
v_texCoord = a_texCoord;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
const fragmentShaderSource = `
|
|
||||||
precision mediump float;
|
|
||||||
uniform sampler2D u_texture;
|
|
||||||
varying vec2 v_texCoord;
|
|
||||||
void main() {
|
|
||||||
gl_FragColor = texture2D(u_texture, v_texCoord);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const createShader = (source, type) => {
|
|
||||||
const shader = gl.createShader(type);
|
|
||||||
gl.shaderSource(shader, source);
|
|
||||||
gl.compileShader(shader);
|
|
||||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
||||||
console.error('Shader compile error:', gl.getShaderInfoLog(shader));
|
|
||||||
}
|
|
||||||
return shader;
|
|
||||||
};
|
|
||||||
|
|
||||||
const vertexShader = createShader(vertexShaderSource, gl.VERTEX_SHADER);
|
|
||||||
const fragmentShader = createShader(fragmentShaderSource, gl.FRAGMENT_SHADER);
|
|
||||||
|
|
||||||
const shaderProgram = gl.createProgram();
|
|
||||||
gl.attachShader(shaderProgram, vertexShader);
|
|
||||||
gl.attachShader(shaderProgram, fragmentShader);
|
|
||||||
gl.linkProgram(shaderProgram);
|
|
||||||
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
|
|
||||||
console.error('Program link error:', gl.getProgramInfoLog(shaderProgram));
|
|
||||||
}
|
|
||||||
gl.useProgram(shaderProgram);
|
|
||||||
|
|
||||||
const positionBuffer = gl.createBuffer();
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
|
||||||
const vertices = new Float32Array([
|
|
||||||
-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);
|
|
||||||
|
|
||||||
const positionLocation = gl.getAttribLocation(shaderProgram, "a_position");
|
|
||||||
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
|
|
||||||
gl.enableVertexAttribArray(positionLocation);
|
|
||||||
|
|
||||||
const texCoordBuffer = gl.createBuffer();
|
|
||||||
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
|
|
||||||
const texCoords = new Float32Array([
|
|
||||||
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);
|
|
||||||
|
|
||||||
const texCoordLocation = gl.getAttribLocation(shaderProgram, "a_texCoord");
|
|
||||||
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;
|
|
||||||
|
|
||||||
const elapsed = timestamp - lastFrameTime;
|
|
||||||
if (elapsed > frameRate) {
|
|
||||||
currentFrameRef.current = (currentFrameRef.current + 1) % images.length;
|
|
||||||
loadTexture(imageElementsRef.current[currentFrameRef.current]);
|
|
||||||
lastFrameTime = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
||||||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
||||||
|
|
||||||
animationRef.current = requestAnimationFrame(animate);
|
|
||||||
};
|
|
||||||
|
|
||||||
animationRef.current = requestAnimationFrame(animate);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
if (animationRef.current) {
|
|
||||||
cancelAnimationFrame(animationRef.current);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}, [images]);
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <div>Loading...</div>;
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<canvas
|
|
||||||
ref={canvasRef}
|
|
||||||
style={{ height: h, width: w }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Animation;
|
|
|
@ -1,46 +0,0 @@
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
|
||||||
import anime from 'animejs';
|
|
||||||
|
|
||||||
const startNumber = 1000;
|
|
||||||
const endNumber = 1239;
|
|
||||||
const imageCount = endNumber - startNumber + 1;
|
|
||||||
const images = [];
|
|
||||||
|
|
||||||
for (let i = startNumber; i <= endNumber; i++) {
|
|
||||||
const formattedNumber = String(i).padStart(5, '0');
|
|
||||||
images.push(import(`../../assets/characters/F_porche_akimbo_AME/Porsche${formattedNumber}.png`));
|
|
||||||
}
|
|
||||||
|
|
||||||
const CharacterAnimation = () => {
|
|
||||||
const totalFrames = imageCount;
|
|
||||||
const frameDuration = 20;
|
|
||||||
const [currentFrame, setCurrentFrame] = useState(0);
|
|
||||||
const [loadedImages, setLoadedImages] = useState([]);
|
|
||||||
const characterRef = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
Promise.all(images).then((resolvedImages) => {
|
|
||||||
setLoadedImages(resolvedImages.map(image => image.default));
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
setCurrentFrame((prevFrame) => (prevFrame + 1) % totalFrames);
|
|
||||||
}, frameDuration);
|
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<img
|
|
||||||
ref={characterRef}
|
|
||||||
src={loadedImages[currentFrame]}
|
|
||||||
alt="Character Animation"
|
|
||||||
style={{ width: '200px', height: 'auto' }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default CharacterAnimation;
|
|
|
@ -1,81 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import JSZip from 'jszip';
|
|
||||||
|
|
||||||
const TestAnimation = () => {
|
|
||||||
const [images, setImages] = useState([]);
|
|
||||||
const [currentFrame, setCurrentFrame] = useState(0);
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const frameRate = 60;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const loadImages = async () => {
|
|
||||||
const zip = new JSZip();
|
|
||||||
try {
|
|
||||||
const response = await fetch('src/assets/mainCharacters/M_Porsche_cross_arm.zip');
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Network response was not ok');
|
|
||||||
}
|
|
||||||
const data = await response.arrayBuffer();
|
|
||||||
const zipContent = await zip.loadAsync(data);
|
|
||||||
|
|
||||||
const imgPromises = [];
|
|
||||||
zipContent.forEach((relativePath, file) => {
|
|
||||||
if (file.name.endsWith('.webp')) {
|
|
||||||
imgPromises.push(
|
|
||||||
file.async('base64').then(base64 => {
|
|
||||||
return `data:image/webp;base64,${base64}`;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const imgUrls = await Promise.all(imgPromises);
|
|
||||||
|
|
||||||
// console.log('Loaded images:', imgUrls);
|
|
||||||
|
|
||||||
if (imgUrls.length === 0) {
|
|
||||||
console.error('No images found in the ZIP file.');
|
|
||||||
}
|
|
||||||
|
|
||||||
setImages(imgUrls);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error loading images:', error);
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
loadImages();
|
|
||||||
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (images.length > 0) {
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
setCurrentFrame((prevFrame) => (prevFrame + 1) % images.length);
|
|
||||||
}, frameRate);
|
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
|
||||||
}
|
|
||||||
}, [images]);
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <div>Loading...</div>;
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
|
||||||
{images.length > 0 ? (
|
|
||||||
<img
|
|
||||||
src={images[currentFrame]}
|
|
||||||
alt={`Animation frame ${currentFrame + 1}`}
|
|
||||||
style={{ maxWidth: '500px', height: 'auto' }}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div>No images to display.</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TestAnimation;
|
|
|
@ -4,19 +4,17 @@ import '../css/global.css';
|
||||||
import '../css/textBox.css';
|
import '../css/textBox.css';
|
||||||
import '../css/nameBox.css';
|
import '../css/nameBox.css';
|
||||||
import '../css/conversation.css'
|
import '../css/conversation.css'
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
|
||||||
import Animation from './components/animation.jsx';
|
|
||||||
|
|
||||||
function ConversationPage({data , onClicked}) {
|
function ConversationPage({data , onClicked}) {
|
||||||
const backgroundSRC = `${import.meta.env.VITE_ASSETS_URL}/${data.background}`
|
const backgroundSRC = `${import.meta.env.VITE_ASSETS_URL}/${data.background}`
|
||||||
const [name] = useState(() => {
|
const [name] = useState(() => {
|
||||||
return sessionStorage.getItem("name") || '';
|
return sessionStorage.getItem("name") || '';
|
||||||
});
|
});
|
||||||
const { char } = useParams();
|
|
||||||
|
|
||||||
const DialogText = data.text.replace("{name}", name);
|
const DialogText = data.text.replace("{name}", name);
|
||||||
const DialogName = data.name.replace("{name}", name);
|
const DialogName = data.name.replace("{name}", name);
|
||||||
const videoPath = `https://dl.techtransthai.org/fsob-assets/F_${char}_normal.webm`;
|
const videoPath = `${import.meta.env.VITE_ASSETS_URL}/${data.sprite}`; // data.sprite return webm file name
|
||||||
|
|
||||||
// https://dl.techtransthai.org/fsob-assets/F_Porsche_normal.webm
|
// https://dl.techtransthai.org/fsob-assets/F_Porsche_normal.webm
|
||||||
//console.log(data.sprite);
|
//console.log(data.sprite);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import '../css/global.css';
|
import '../css/global.css';
|
||||||
import BlackButton from './components/customButton';
|
import BlackButton from './components/customButton';
|
||||||
import Animation from './components/animation.jsx';
|
|
||||||
import PlayVideo from './components/playVideo.jsx';
|
import PlayVideo from './components/playVideo.jsx';
|
||||||
import LoadingScene from './components/loadingScene.jsx';
|
import LoadingScene from './components/loadingScene.jsx';
|
||||||
import IntroductionData from './components/introductionData.jsx';
|
import IntroductionData from './components/introductionData.jsx';
|
||||||
|
|
|
@ -4,10 +4,10 @@ import '../css/global.css';
|
||||||
import '../css/textBox.css';
|
import '../css/textBox.css';
|
||||||
import '../css/nameBox.css';
|
import '../css/nameBox.css';
|
||||||
import '../css/option.css'
|
import '../css/option.css'
|
||||||
import Animation from './components/animation.jsx';
|
|
||||||
|
|
||||||
function OptionPage({data , onClicked}) {
|
function OptionPage({data , onClicked}) {
|
||||||
const backgroundSRC = `${import.meta.env.VITE_ASSETS_URL}/${data.background}`
|
const backgroundSRC = `${import.meta.env.VITE_ASSETS_URL}/${data.background}`
|
||||||
|
const videoPath = `${import.meta.env.VITE_ASSETS_URL}/${data.sprite}`; // data.sprite return webm file name
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -24,7 +24,10 @@ function OptionPage({data , onClicked}) {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className='spriteBox'>
|
<div className='spriteBox'>
|
||||||
<Animation src={`F${data.sprite}`}/>
|
<video width="200%" height="200%" autoPlay loop muted>
|
||||||
|
<source src={videoPath} type="video/webm" />
|
||||||
|
Your browser does not support the video tag.
|
||||||
|
</video>
|
||||||
</div>
|
</div>
|
||||||
<div className='optionSection'>
|
<div className='optionSection'>
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue