Compare commits
5 commits
main
...
test-anima
Author | SHA1 | Date | |
---|---|---|---|
6b62ebe64f | |||
e4704c62f3 | |||
bdec78f7c6 | |||
f9165a1c93 | |||
22ffb870e8 |
40 changed files with 744 additions and 11 deletions
107
package-lock.json
generated
107
package-lock.json
generated
|
@ -8,6 +8,8 @@
|
|||
"name": "fifty-shades-of-bully",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"animejs": "^3.2.2",
|
||||
"jszip": "^3.10.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^7.0.2"
|
||||
|
@ -1373,6 +1375,12 @@
|
|||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/animejs": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/animejs/-/animejs-3.2.2.tgz",
|
||||
"integrity": "sha512-Ao95qWLpDPXXM+WrmwcKbl6uNlC5tjnowlaRYtuVDHHoygjtIPfDUoK9NthrlZsQSKjZXlmji2TrBUAVbiH0LQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
|
@ -1711,6 +1719,12 @@
|
|||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
|
@ -2645,6 +2659,12 @@
|
|||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immediate": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
|
@ -2672,6 +2692,12 @@
|
|||
"node": ">=0.8.19"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/internal-slot": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
|
||||
|
@ -3155,6 +3181,18 @@
|
|||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jszip": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
||||
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
|
||||
"license": "(MIT OR GPL-3.0-or-later)",
|
||||
"dependencies": {
|
||||
"lie": "~3.3.0",
|
||||
"pako": "~1.0.2",
|
||||
"readable-stream": "~2.3.6",
|
||||
"setimmediate": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||
|
@ -3179,6 +3217,15 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lie": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
||||
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immediate": "~3.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||
|
@ -3431,6 +3478,12 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
|
@ -3527,6 +3580,12 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
|
@ -3631,6 +3690,27 @@
|
|||
"react-dom": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream/node_modules/isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/reflect.getprototypeof": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
|
||||
|
@ -3757,6 +3837,12 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/safe-regex-test": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
|
||||
|
@ -3834,6 +3920,12 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/setimmediate": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
|
@ -3886,6 +3978,15 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string.prototype.matchall": {
|
||||
"version": "4.0.11",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz",
|
||||
|
@ -4168,6 +4269,12 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.4.11",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz",
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"dev": "vite --host",
|
||||
"build": "vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"animejs": "^3.2.2",
|
||||
"jszip": "^3.10.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^7.0.2"
|
||||
|
|
BIN
src/assets/introduction/1_NPC+pillar.zip
Normal file
BIN
src/assets/introduction/1_NPC+pillar.zip
Normal file
Binary file not shown.
BIN
src/assets/introduction/2_F_Porsche.zip
Normal file
BIN
src/assets/introduction/2_F_Porsche.zip
Normal file
Binary file not shown.
BIN
src/assets/introduction/2_M_Porsche.zip
Normal file
BIN
src/assets/introduction/2_M_Porsche.zip
Normal file
Binary file not shown.
BIN
src/assets/introduction/3_F_Patt.zip
Normal file
BIN
src/assets/introduction/3_F_Patt.zip
Normal file
Binary file not shown.
BIN
src/assets/introduction/3_M_Patt.zip
Normal file
BIN
src/assets/introduction/3_M_Patt.zip
Normal file
Binary file not shown.
BIN
src/assets/introduction/4_NPC+hallway.zip
Normal file
BIN
src/assets/introduction/4_NPC+hallway.zip
Normal file
Binary file not shown.
BIN
src/assets/introduction/5_F_Pie.zip
Normal file
BIN
src/assets/introduction/5_F_Pie.zip
Normal file
Binary file not shown.
BIN
src/assets/introduction/5_M_Pie.zip
Normal file
BIN
src/assets/introduction/5_M_Pie.zip
Normal file
Binary file not shown.
BIN
src/assets/introduction/6_Classroom.zip
Normal file
BIN
src/assets/introduction/6_Classroom.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/F Porche cross arm_AME.zip
Normal file
BIN
src/assets/mainCharacters/F Porche cross arm_AME.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/F porche akimbo_AME.zip
Normal file
BIN
src/assets/mainCharacters/F porche akimbo_AME.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/F porche hands up_AME.zip
Normal file
BIN
src/assets/mainCharacters/F porche hands up_AME.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/F porche normal_AME.zip
Normal file
BIN
src/assets/mainCharacters/F porche normal_AME.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/F porche shock_AME.zip
Normal file
BIN
src/assets/mainCharacters/F porche shock_AME.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/F porche shrug_AME.zip
Normal file
BIN
src/assets/mainCharacters/F porche shrug_AME.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/F porche think_AME.zip
Normal file
BIN
src/assets/mainCharacters/F porche think_AME.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/F porche upset akimbo_AME.zip
Normal file
BIN
src/assets/mainCharacters/F porche upset akimbo_AME.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/F porche wave_AME.zip
Normal file
BIN
src/assets/mainCharacters/F porche wave_AME.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/M_Porsche_akimbo.zip
Normal file
BIN
src/assets/mainCharacters/M_Porsche_akimbo.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/M_Porsche_cross_arm.zip
Normal file
BIN
src/assets/mainCharacters/M_Porsche_cross_arm.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/M_Porsche_hands_up.zip
Normal file
BIN
src/assets/mainCharacters/M_Porsche_hands_up.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/M_Porsche_normal.zip
Normal file
BIN
src/assets/mainCharacters/M_Porsche_normal.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/M_Porsche_shock.zip
Normal file
BIN
src/assets/mainCharacters/M_Porsche_shock.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/M_Porsche_shrug.zip
Normal file
BIN
src/assets/mainCharacters/M_Porsche_shrug.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/M_Porsche_think.zip
Normal file
BIN
src/assets/mainCharacters/M_Porsche_think.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/M_Porsche_upset_akimbo.zip
Normal file
BIN
src/assets/mainCharacters/M_Porsche_upset_akimbo.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters/M_Porsche_wave.zip
Normal file
BIN
src/assets/mainCharacters/M_Porsche_wave.zip
Normal file
Binary file not shown.
BIN
src/assets/mainCharacters_pow2/M_porsche_cross_arm_power2.zip
Normal file
BIN
src/assets/mainCharacters_pow2/M_porsche_cross_arm_power2.zip
Normal file
Binary file not shown.
|
@ -9,7 +9,9 @@
|
|||
|
||||
border: none;
|
||||
border-radius: 30px;
|
||||
padding: 8px 52px 8px 52px;
|
||||
/* padding: 8px 52px 8px 52px; */
|
||||
height: 51px;
|
||||
width: 249;
|
||||
transition-duration: 0.2s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
}
|
||||
|
||||
html * {
|
||||
background-color: rgb(var(--black));
|
||||
/* background-color: rgb(var(--black)); */
|
||||
color: rgb(var(--white));
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background-color: rgb(var(--black));
|
||||
}
|
||||
|
||||
.title {
|
||||
|
@ -22,6 +23,10 @@ body {
|
|||
font-weight: 900;
|
||||
text-align: center;
|
||||
}
|
||||
.title.medium{
|
||||
font-size: 24pt;
|
||||
}
|
||||
|
||||
.body {
|
||||
font-family: "Source Sans 3";
|
||||
font-size: 24pt;
|
||||
|
|
21
src/css/spriteAnimation.css
Normal file
21
src/css/spriteAnimation.css
Normal file
|
@ -0,0 +1,21 @@
|
|||
.character {
|
||||
width: 624px; /* Width of a single frame */
|
||||
height: 814px; /* Height of a single frame */
|
||||
background-color: wheat;
|
||||
/* overflow: hidden; */
|
||||
/* Ensure only one frame is visible */
|
||||
}
|
||||
|
||||
.spriteAnimation {
|
||||
width: 9984px;
|
||||
animation: moveSprite 1s steps(16) infinite; /* 240 total frames */
|
||||
}
|
||||
|
||||
@keyframes moveSprite {
|
||||
form{
|
||||
transform: translate3d(0,0,0)
|
||||
}
|
||||
to{
|
||||
transform: translate3d(-100%,0,0);
|
||||
}
|
||||
}
|
21
src/main.jsx
21
src/main.jsx
|
@ -1,11 +1,14 @@
|
|||
import * as React from 'react';
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||||
import './css/global.css'
|
||||
import HomePage from './pages/homePage.jsx'
|
||||
import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
||||
import './css/global.css';
|
||||
import HomePage from './pages/homePage.jsx';
|
||||
import WarningPage from './pages/warningPage.jsx';
|
||||
import NamePage from './pages/namePage.jsx';
|
||||
import Animation from './pages/components/animation.jsx';
|
||||
import IntroductionPage from './pages/introductionPage.jsx';
|
||||
|
||||
|
||||
createRoot(document.getElementById('root')).render(
|
||||
<StrictMode>
|
||||
|
@ -13,8 +16,12 @@ createRoot(document.getElementById('root')).render(
|
|||
<Routes>
|
||||
<Route path="/" element={<HomePage />} />
|
||||
<Route path="/warn" element={<WarningPage />} />
|
||||
<Route path="/name" element={<NamePage />}/>
|
||||
<Route path="/name" element={<NamePage />} />
|
||||
<Route path="/sprite" element={<Animation />} />
|
||||
<Route path="/introduction" element={<IntroductionPage />} />
|
||||
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</StrictMode>,
|
||||
)
|
||||
);
|
||||
|
|
403
src/pages/components/animation.jsx
Normal file
403
src/pages/components/animation.jsx
Normal file
|
@ -0,0 +1,403 @@
|
|||
//version 1
|
||||
// import React, { useEffect, useState } from 'react';
|
||||
// import JSZip from 'jszip';
|
||||
|
||||
// const Animation = ({src="src/assets/mainCharacters/M_Porsche_cross_arm.zip" ,animationWidth="500px"}) => {
|
||||
// const [images, setImages] = useState([]);
|
||||
// const [currentFrame, setCurrentFrame] = useState(0);
|
||||
// const [loading, setLoading] = useState(true);
|
||||
// const frameRate = 1000/24;
|
||||
|
||||
// useEffect(() => {
|
||||
// const loadImages = async () => {
|
||||
// const zip = new JSZip();
|
||||
// try {
|
||||
// const response = await fetch(src);
|
||||
// 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);
|
||||
|
||||
// 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: animationWidth, height: 'auto' }}
|
||||
// />
|
||||
// ) : (
|
||||
// <div>No images to display.</div>
|
||||
// )}
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
|
||||
// export default Animation;
|
||||
|
||||
//version 2
|
||||
// import React, { useEffect, useState, useRef } from 'react';
|
||||
// import JSZip from 'jszip';
|
||||
|
||||
// const Animation = ({ src = "src/assets/mainCharacters/M_Porsche_cross_arm.zip", animationWidth = "500px" }) => {
|
||||
// const [images, setImages] = useState([]);
|
||||
// const [loading, setLoading] = useState(true);
|
||||
// const frameRate = 1000 / 24; // Original frame rate (24 FPS)
|
||||
// const canvasRef = useRef(null);
|
||||
// const animationRef = useRef(null);
|
||||
// const currentFrameRef = useRef(0);
|
||||
// const imageElementsRef = useRef([]);
|
||||
|
||||
// useEffect(() => {
|
||||
// const loadImages = async () => {
|
||||
// const zip = new JSZip();
|
||||
// try {
|
||||
// const response = await fetch(src);
|
||||
// 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 img; // Return the Image object
|
||||
// })
|
||||
// );
|
||||
// }
|
||||
// });
|
||||
|
||||
// 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
|
||||
// } catch (error) {
|
||||
// console.error('Error loading images:', error);
|
||||
// } finally {
|
||||
// setLoading(false);
|
||||
// }
|
||||
// };
|
||||
|
||||
// loadImages();
|
||||
// }, [src]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (images.length > 0) {
|
||||
// const canvas = canvasRef.current;
|
||||
// const ctx = canvas.getContext('2d');
|
||||
// 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;
|
||||
// lastFrameTime = timestamp;
|
||||
// }
|
||||
|
||||
// // Clear the canvas
|
||||
// ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
// // Draw the current frame
|
||||
// ctx.drawImage(imageElementsRef.current[currentFrameRef.current], 0, 0, canvas.width, canvas.height);
|
||||
|
||||
// animationRef.current = requestAnimationFrame(animate);
|
||||
// };
|
||||
|
||||
// animationRef.current = requestAnimationFrame(animate);
|
||||
|
||||
// return () => {
|
||||
// if (animationRef.current) {
|
||||
// cancelAnimationFrame(animationRef.current);
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// }, [images]);
|
||||
|
||||
// if (loading) {
|
||||
// return <div>Loading...</div>;
|
||||
// } else {
|
||||
// return (
|
||||
// <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||
// <canvas
|
||||
// ref={canvasRef}
|
||||
// width={'500px'}
|
||||
// height={'700'} // Maintain aspect ratio (example: 16:9)
|
||||
// style={{ maxWidth: animationWidth, height: 'auto' }}
|
||||
// />
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
|
||||
// export default Animation;
|
||||
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import JSZip from 'jszip';
|
||||
|
||||
const Animation = ({ src = "src/assets/mainCharacters_pow2/M_porsche_cross_arm_power2.zip", animationWidth = "500px" }) => {
|
||||
const [images, setImages] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const frameRate = 1000 / 24; // Original frame rate (24 FPS)
|
||||
const canvasRef = useRef(null);
|
||||
const animationRef = useRef(null);
|
||||
const currentFrameRef = useRef(0);
|
||||
const imageElementsRef = useRef([]);
|
||||
|
||||
// Load images from the ZIP file
|
||||
useEffect(() => {
|
||||
const loadImages = async () => {
|
||||
const zip = new JSZip();
|
||||
try {
|
||||
const response = await fetch(src);
|
||||
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; // Store preloaded images
|
||||
setImages(imgElements); // Set images state
|
||||
} catch (error) {
|
||||
console.error('Error loading images:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
loadImages();
|
||||
}, [src]);
|
||||
|
||||
// WebGL setup and animation loop
|
||||
useEffect(() => {
|
||||
if (images.length > 0) {
|
||||
const canvas = canvasRef.current;
|
||||
const gl = canvas.getContext('webgl');
|
||||
if (!gl) {
|
||||
console.error("WebGL is not supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up WebGL context (basic)
|
||||
gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Enable blending
|
||||
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;
|
||||
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('ERROR compiling shader', 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('ERROR linking program', 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
|
||||
]);
|
||||
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);
|
||||
|
||||
// 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)
|
||||
]);
|
||||
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 uTextureLocation = gl.getUniformLocation(shaderProgram, "u_texture");
|
||||
|
||||
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 (
|
||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
width={'1920'}
|
||||
height={'1080'} // Maintain aspect ratio (example: 16:9)
|
||||
style={{ maxWidth: animationWidth, height: 'auto' }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Animation;
|
||||
|
||||
|
46
src/pages/components/testAnimation_manyfiles.jsx
Normal file
46
src/pages/components/testAnimation_manyfiles.jsx
Normal file
|
@ -0,0 +1,46 @@
|
|||
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;
|
81
src/pages/components/testAnimation_onefile.jsx
Normal file
81
src/pages/components/testAnimation_onefile.jsx
Normal file
|
@ -0,0 +1,81 @@
|
|||
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;
|
58
src/pages/introductionPage.jsx
Normal file
58
src/pages/introductionPage.jsx
Normal file
|
@ -0,0 +1,58 @@
|
|||
import { useState } from 'react'
|
||||
import '../css/global.css'
|
||||
import BlackButton from './components/customButton'
|
||||
import Animation from './components/animation.jsx';
|
||||
|
||||
function IntroductionPage() {
|
||||
return(
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '100vh',
|
||||
maxWidth:"100vw",
|
||||
flexDirection: 'column',
|
||||
}}>
|
||||
<div style={{position:"absolute"}}>
|
||||
<Animation src='src/assets/introduction/6_Classroom.zip' animationWidth='100vw'/>
|
||||
</div>
|
||||
<div style={{position:"absolute"}}>
|
||||
<Animation src='src/assets/introduction/5_M_Pie.zip' animationWidth='100vw'/>
|
||||
</div>
|
||||
<div style={{position:"absolute"}}>
|
||||
<Animation src='src/assets/introduction/4_NPC+hallway.zip' animationWidth='100vw'/>
|
||||
</div>
|
||||
<div style={{position:"absolute"}}>
|
||||
<Animation src='src/assets/introduction/3_M_Patt.zip' animationWidth='100vw'/>
|
||||
</div>
|
||||
<div style={{position:"absolute"}}>
|
||||
<Animation src='src/assets/introduction/2_M_Porsche.zip' animationWidth='100vw'/>
|
||||
</div>
|
||||
<div style={{position:"absolute"}}>
|
||||
<Animation src='src/assets/introduction/1_NPC+pillar.zip' animationWidth='100vw'/>
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100vw",
|
||||
height: "100vh",
|
||||
background: "rgba(var(--black), 0.5)",
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
zIndex: 1 // Ensure this is above other elements
|
||||
}}>
|
||||
<label style={{color:"rgb(var(--white))", fontWeight:"bold"}}>
|
||||
You are a new student who just <br />
|
||||
transfered to this school not long ago. <br />
|
||||
You don't know anyone yet, <br />
|
||||
but eventually you meet...
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default IntroductionPage
|
|
@ -29,7 +29,7 @@ function NamePage() {
|
|||
name==''?
|
||||
<></>
|
||||
:
|
||||
<BlackButton text="Continue" to='/name'/>
|
||||
<BlackButton text="Continue" to='/introduction'/>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -4,4 +4,5 @@ import react from '@vitejs/plugin-react'
|
|||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
assetsInclude: ['**/*.zip'],
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue