name selection

This commit is contained in:
ad044 2021-02-09 21:26:08 +04:00
parent ef3b4ce367
commit 68a43c39de
12 changed files with 392 additions and 81 deletions

View file

@ -150,7 +150,7 @@ const BootAnimation = (props: BootAnimationProps) => {
setBackgroundFloatingTextShown(true);
//4200
}, 4200);
}, 0);
}
}, [bootBackgroundTextTex, currentBootStatusTextTex.offset, props.visible]);

View file

@ -1,4 +1,4 @@
import React, { Suspense, useEffect, useMemo, useRef } from "react";
import React, { useEffect, useMemo, useRef } from "react";
import authorizeHeaderUnderline from "../../static/sprite/authorize_header_underline.png";
import authorizeGlass from "../../static/sprite/authorize_glass.png";
import authorizeGlassUnderline from "../../static/sprite/authorize_glass_underline.png";
@ -11,6 +11,7 @@ import * as THREE from "three";
import { OrbitControls } from "@react-three/drei";
import { useStore } from "../../store";
import usePrevious from "../../hooks/usePrevious";
import StaticJpCharacter from "../TextRenderer/StaticJpCharacter";
type BootAuthorizeUserProps = {
visible: boolean;
@ -94,6 +95,8 @@ const BootAuthorizeUser = (props: BootAuthorizeUserProps) => {
}
}, [activeLetterMap.offset, letterIdx, prevData]);
const playerName = useStore((state) => state.playerName.split(""));
return (
<>
{props.visible && (
@ -146,6 +149,11 @@ const BootAuthorizeUser = (props: BootAuthorizeUserProps) => {
/>
</sprite>
<group position={[playerName.length * -0.25 - 0.2, -0.27, 0]}>
{playerName.map((char, idx) => (
<StaticJpCharacter char={char} charIdx={idx} key={idx} />
))}
</group>
<sprite
scale={[2, 0.01, 0]}
position={[-1.06, -0.42, 0]}

View file

@ -21,10 +21,8 @@ const PermissionDenied = memo(() => {
<group scale={[0.08, 0.7, 0]} position={[-1, 0.19, 0]}>
{"Permission denied".split("").map((letter, idx) => (
<StaticOrangeLetter
color={"orange"}
letter={letter}
letterIdx={idx}
scale={[1.5, 0.25, 0.25]}
key={idx}
/>
))}

View file

@ -0,0 +1,53 @@
import orangeFont from "../../static/sprite/orange_jp_font.png";
import * as THREE from "three";
import { useLoader } from "react-three-fiber";
import jp_font_json from "../../resources/font_data/jp_font.json";
import React, { memo, useMemo } from "react";
const StaticJpCharacter = memo((props: { char: string; charIdx: number }) => {
const colorTexture: THREE.Texture = useLoader(
THREE.TextureLoader,
orangeFont
);
const charData = useMemo(
() => jp_font_json.glyphs[props.char as keyof typeof jp_font_json.glyphs],
[props.char]
);
const geom = useMemo(() => {
const geometry = new THREE.PlaneBufferGeometry();
const uvAttribute = geometry.attributes.uv;
for (let i = 0; i < uvAttribute.count; i++) {
let u = uvAttribute.getX(i);
let v = uvAttribute.getY(i);
u = (u * charData[2]) / 240 + charData[0] / 240;
v = (v * charData[3]) / 96 + (1 - charData[1] / 96 - 16 / 96);
uvAttribute.setXY(i, u, v);
}
return geometry;
}, [charData]);
return (
<mesh
position={[props.charIdx / 4, 0, 0]}
scale={[0.25, 0.25, 0]}
geometry={geom}
renderOrder={205}
>
<meshBasicMaterial
map={colorTexture}
attach="material"
transparent={true}
side={THREE.FrontSide}
depthTest={false}
/>
</mesh>
);
});
export default StaticJpCharacter;

View file

@ -5,12 +5,7 @@ import orange_font_json from "../../resources/font_data/big_font.json";
import React, { memo, useMemo } from "react";
const StaticOrangeLetter = memo(
(props: {
color: string;
letter: string;
letterIdx: number;
scale: number[];
}) => {
(props: { letter: string; letterIdx: number }) => {
const colorTexture: THREE.Texture = useLoader(
THREE.TextureLoader,
orangeFont
@ -75,7 +70,7 @@ const StaticOrangeLetter = memo(
return (
<mesh
position={[props.letterIdx * 1.6, -letterData[4] / 50, 0]}
scale={props.scale as [number, number, number]}
scale={[1.5, 0.25, 0.25]}
geometry={geom}
renderOrder={205}
>

View file

@ -1,3 +1,6 @@
import authorize_user_letters from "../../resources/authorize_user_letters.json";
import handleNameSelection from "../../utils/handleNameSelection";
const handleBootSceneKeyPress = (bootSceneContext: any) => {
const {
keyPress,
@ -6,6 +9,7 @@ const handleBootSceneKeyPress = (bootSceneContext: any) => {
activePromptComponent,
promptVisible,
authorizeUserLetterIdx,
playerName,
} = bootSceneContext;
if (promptVisible) {
@ -38,7 +42,14 @@ const handleBootSceneKeyPress = (bootSceneContext: any) => {
case "authorize_user":
switch (keyPress) {
case "X":
return { event: "authorize_user_back" };
if (playerName.length > 0) {
return {
event: "update_player_name",
playerName: playerName.slice(0, -1),
};
} else {
return { event: "authorize_user_back" };
}
case "LEFT":
// if utmost left, break
if ([0, 13, 26, 39, 52].includes(authorizeUserLetterIdx)) break;
@ -85,7 +96,19 @@ const handleBootSceneKeyPress = (bootSceneContext: any) => {
authorizeUserLetterIdx: authorizeUserLetterIdx - 13,
};
}
case "CIRCLE":
const chosenCharacter =
authorize_user_letters[
authorizeUserLetterIdx.toString() as keyof typeof authorize_user_letters
];
const newName = handleNameSelection(playerName, chosenCharacter);
if (newName !== undefined)
return { event: "update_player_name", playerName: newName };
break;
}
break;
}
}
};

View file

@ -7,9 +7,12 @@ const bootManager = (eventState: any) => {
const setAuthorizeUserLetterIdx = useStore.getState()
.setAuthorizeUserLetterIdx;
const setPlayerName = useStore.getState().setPlayerName;
const dispatchAction = (eventState: {
event: string;
authorizeUserLetterIdx: number;
playerName: string;
}) => {
switch (eventState.event) {
case "main_menu_up":
@ -30,6 +33,14 @@ const bootManager = (eventState: any) => {
action: () =>
setAuthorizeUserLetterIdx(eventState.authorizeUserLetterIdx),
};
case "authorize_user_back":
return {
action: () => setPlayerName(""),
};
case "update_player_name":
return {
action: () => setPlayerName(eventState.playerName),
};
}
};

View file

@ -1,69 +1,67 @@
{
"letters": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64
]
"0": "ッ",
"1": "ャ",
"2": "ァ",
"3": "ワ",
"4": "ラ",
"5": "ヤ",
"6": "マ",
"7": "ハ",
"8": "ナ",
"9": "タ",
"10": "サ",
"11": "カ",
"12": "ア",
"13": "",
"14": "",
"15": "ィ",
"16": "",
"17": "リ",
"18": "",
"19": "ミ",
"20": "ヒ",
"21": "ニ",
"22": "チ",
"23": "シ",
"24": "キ",
"25": "イ",
"26": "゛",
"27": "ュ",
"28": "ゥ",
"29": "",
"30": "ル",
"31": "ユ",
"32": "ム",
"33": "フ",
"34": "ヌ",
"35": "ツ",
"36": "ス",
"37": "ク",
"38": "ウ",
"39": "゜",
"40": "",
"41": "ェ",
"42": "",
"43": "レ",
"44": "",
"45": "メ",
"46": "ヘ",
"47": "ネ",
"48": "テ",
"49": "セ",
"50": "ケ",
"51": "エ",
"52": "ー",
"53": "ョ",
"54": "ォ",
"55": "ン",
"56": "ロ",
"57": "ヨ",
"58": "モ",
"59": "ホ",
"60": "",
"61": "ト",
"62": "ソ",
"63": "コ",
"64": "オ"
}

View file

@ -0,0 +1,92 @@
{
"kerning": 2,
"height": 21,
"baseline": 4,
"glyphs": {
"ア": [0, 0, 16, 16, 0],
"イ": [16, 0, 16, 16, 0],
"ウ": [32, 0, 16, 16, 0],
"エ": [48, 0, 16, 16, 0],
"オ": [64, 0, 16, 16, 0],
"カ": [80, 0, 16, 16, 0],
"キ": [96, 0, 16, 16, 0],
"ク": [112, 0, 16, 16, 0],
"ケ": [128, 0, 16, 16, 0],
"コ": [144, 0, 16, 16, 0],
"サ": [160, 0, 16, 16, 0],
"シ": [176, 0, 16, 16, 0],
"ス": [192, 0, 16, 16, 0],
"セ": [208, 0, 16, 16, 0],
"ソ": [224, 0, 16, 16, 0],
"タ": [0, 16, 16, 16, 0],
"チ": [16, 16, 16, 16, 0],
"ツ": [32, 16, 16, 16, 0],
"テ": [48, 16, 16, 16, 0],
"ト": [64, 16, 16, 16, 0],
"ナ": [80, 16, 16, 16, 0],
"ニ": [96, 16, 16, 16, 0],
"ヌ": [112, 16, 16, 16, 0],
"ネ": [128, 16, 16, 16, 0],
"": [144, 16, 16, 16, 0],
"ハ": [160, 16, 16, 16, 0],
"ヒ": [176, 16, 16, 16, 0],
"フ": [192, 16, 16, 16, 0],
"ヘ": [208, 16, 16, 16, 0],
"ホ": [224, 16, 16, 16, 0],
"マ": [0, 32, 16, 16, 0],
"ミ": [16, 32, 16, 16, 0],
"ム": [32, 32, 16, 16, 0],
"メ": [48, 32, 16, 16, 0],
"モ": [64, 32, 16, 16, 0],
"ヤ": [80, 32, 16, 16, 0],
"ユ": [96, 32, 16, 16, 0],
"ヨ": [112, 32, 16, 16, 0],
"ラ": [128, 32, 16, 16, 0],
"リ": [144, 32, 16, 16, 0],
"ル": [160, 32, 16, 16, 0],
"レ": [176, 32, 16, 16, 0],
"ロ": [192, 32, 16, 16, 0],
"ワ": [208, 32, 16, 16, 0],
"ン": [224, 32, 16, 16, 0],
"ッ": [0, 48, 16, 16, 0],
"ャ": [16, 48, 16, 16, 0],
"ュ": [32, 48, 16, 16, 0],
"ョ": [48, 48, 16, 16, 0],
"ガ": [64, 48, 16, 16, 0],
"ギ": [80, 48, 16, 16, 0],
"グ": [96, 48, 16, 16, 0],
"ゲ": [112, 48, 16, 16, 0],
"ゴ": [128, 48, 16, 16, 0],
"ザ": [144, 48, 16, 16, 0],
"ジ": [160, 48, 16, 16, 0],
"ズ": [176, 48, 16, 16, 0],
"ゼ": [192, 48, 16, 16, 0],
"ゾ": [208, 48, 16, 16, 0],
"ダ": [224, 48, 16, 16, 0],
"ヂ": [0, 64, 16, 16, 0],
"ヅ": [16, 64, 16, 16, 0],
"デ": [32, 64, 16, 16, 0],
"ド": [48, 64, 16, 16, 0],
"バ": [64, 64, 16, 16, 0],
"ビ": [80, 64, 16, 16, 0],
"ブ": [96, 64, 16, 16, 0],
"ベ": [112, 64, 16, 16, 0],
"ボ": [128, 64, 16, 16, 0],
"パ": [144, 64, 16, 16, 0],
"ピ": [160, 64, 16, 16, 0],
"プ": [176, 64, 16, 16, 0],
"ペ": [192, 64, 16, 16, 0],
"ポ": [208, 64, 16, 16, 0],
"ァ": [0, 80, 16, 16, 0],
"ィ": [16, 80, 16, 16, 0],
"ゥ": [32, 80, 16, 16, 0],
"ェ": [48, 80, 16, 16, 0],
"ォ": [64, 80, 16, 16, 0],
"ー": [80, 80, 16, 16, 0]
}
}

View file

@ -16,11 +16,11 @@ const BootScene = () => {
setTimeout(() => {
setAccelaVisible(false);
// 2000
}, 2000);
}, 0);
setTimeout(() => {
setMainMenuVisible(true);
//6200
}, 6200);
}, 0);
}, []);
return (

View file

@ -82,6 +82,9 @@ type State = {
// gate scene
gateLvl: number;
// player name
playerName: string;
// boot scene
mainMenuComponentMatrix: ["authorize_user", "load_data"];
mainMenuComponentMatrixIdx: 0 | 1;
@ -235,6 +238,9 @@ export const useStore = create(
// gate scene
gateLvl: 0,
// player name
playerName: "",
// boot scene
mainMenuComponentMatrix: ["authorize_user", "load_data"],
mainMenuComponentMatrixIdx: 0,
@ -389,6 +395,9 @@ export const useStore = create(
// gate scene setters
incrementGateLvl: () => set((state) => ({ gateLvl: state.gateLvl + 1 })),
// player name setters
setPlayerName: (to: string) => set(() => ({ playerName: to })),
// boot scene setters
setBootSubscene: (to: "load_data" | "authorize_user" | "main_menu") =>
set(() => ({ bootSubscene: to })),
@ -528,6 +537,7 @@ export const getBootSceneContext = () => {
return {
...getPromptContext(),
playerName: state.playerName,
subscene: state.bootSubscene,
activeMainMenuComponent:
state.mainMenuComponentMatrix[state.mainMenuComponentMatrixIdx],

View file

@ -0,0 +1,123 @@
// huge thanks to oo for help with this!!
const handleNameSelection = (currentString: string, newCharacter: string) => {
// characters that cannot be the first letter
const cantBeFirst = [
"ン",
"ァ",
"ィ",
"ゥ",
"ェ",
"ォ",
"ャ",
"ュ",
"ョ",
"ッ",
"゛",
"゜",
"ー",
];
if (currentString.length === 0 && cantBeFirst.includes(newCharacter)) return;
const lastChar = currentString.slice(-1);
//「ー」 cannot be added to 「ッ」 and 「ン」
if (newCharacter === "ー") {
if (lastChar === "ッ" || lastChar === "ン" || lastChar === "ー") return;
else return currentString.concat(newCharacter);
}
// characters that can be followed by the lowercase characters
const fstLowerCharSet = ["ャ", "ュ", "ョ"];
const fstSetAppendable = [
"キ",
"シ",
"チ",
"ニ",
"ヒ",
"ミ",
"リ",
// dakuten
"ギ",
"ジ",
"ヂ",
"ビ",
//handakuten
"ピ",
];
const sndLowerCharSet = ["ァ", "ィ", "ゥ", "ェ", "ォ"];
const sndSetAppendable = ["フ"];
if (fstLowerCharSet.includes(newCharacter)) {
if (fstSetAppendable.includes(lastChar))
return currentString.concat(newCharacter);
else return;
} else if (sndLowerCharSet.includes(newCharacter)) {
if (sndSetAppendable.includes(lastChar))
return currentString.concat(newCharacter);
else return;
}
// for 「ッ」, it can added to any character except itself
if (newCharacter === "ッ") {
if (lastChar !== "ッ") return currentString.concat(newCharacter);
else return;
}
// characters that can be modified with dakuten
if (newCharacter === "゛") {
const modifiableByDakuten = {
: "ガ",
: "ギ",
: "グ",
: "ゲ",
: "ゴ",
: "ザ",
: "ジ",
: "ズ",
: "ゼ",
: "ゾ",
: "ダ",
: "ヂ",
: "ヅ",
: "デ",
: "ド",
: "バ",
: "ビ",
: "ブ",
: "ベ",
: "ボ",
};
const modified =
modifiableByDakuten[lastChar as keyof typeof modifiableByDakuten];
if (modified) return currentString.slice(0, -1) + modified;
else return;
}
// will look into this
//*Although 「ヂ、ヅ」 are included in the character table that Ad posted, I couldn't select them.
// characters that can be modified with handakuten
if (newCharacter === "゜") {
const modifiableByHandakuten = {
: "パ",
: "ピ",
: "プ",
: "ペ",
: "ポ",
};
const modified =
modifiableByHandakuten[lastChar as keyof typeof modifiableByHandakuten];
if (modified) return currentString.slice(0, -1) + modified;
else return;
}
return currentString.concat(newCharacter);
};
export default handleNameSelection;