-
- {JSON.stringify(printedState, jsonReplacer, 2)}
-
+
+
+
+
);
@@ -75,18 +32,3 @@ function App({onCommand, game}) {
export default App;
-function jsonReplacer(key, value) {
- if(value instanceof Set)
- return Array.from(value)
-
- if(value instanceof Map)
- return Array.from(value).reduce((obj, [key, value]) => {
- obj[key] = value;
- return obj;
- }, {});
-
- if(key === 'messages' && Array.isArray(value) && value.length)
- return ['...']
-
- return value
-}
diff --git a/src/components/App/App.module.css b/src/components/App/App.module.css
index c5f0a59..1d3a501 100644
--- a/src/components/App/App.module.css
+++ b/src/components/App/App.module.css
@@ -1,72 +1,29 @@
-.app {
- min-height: 100vh;
+.screen {
display: flex;
flex-direction: row;
-}
-
-.playArea {
- flex: 1;
- display: flex;
- flex-direction: column;
- max-height: 100vh;
- user-select: none;
-}
-
-.output {
- overflow-y: auto;
- padding: 16px;
- padding-bottom: 0;
- min-height: 16px;
-}
-
-.input {
- padding: 16px;
- padding-top: 0;
position: relative;
- left: -1px;
- font-weight: bold;
+ width: 600px;
+ height: 400px;
+ background: black;
+ image-rendering: pixelated;
}
-.input input {
- background: transparent;
- border: none;
- box-shadow: none;
- outline: none;
- width: 100%;
- text-indent: 16px;
- font-family: inherit;
- font-weight: bold;
- font-size: 16px;
- position: relative;
- top: -1px;
- left: -1px;
-}
-
-.input::before {
+.overlay {
position: absolute;
- left: 16px;
-}
+ top: 0;
+ right: 0;
+ left: 0;
+ bottom: 0;
-.infoArea {
- width: 300px;
- overflow-x: hidden;
- overflow-y: scroll;
- max-height: 100vh;
-}
-
-.command {
- font-weight: bold;
- position: relative;
- text-indent: 16px;
- white-space: pre;
+ opacity: .4;
+ overflow: hidden;
+ pointer-events: none;
+ mix-blend-mode: screen;
}
-.command::before {
- position: absolute;
- left: -16px;
-}
-
-.command::before, .input::before {
- content: '> ';
- font-weight: bold;
+.overlay img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ filter: brightness(2.5);
}
diff --git a/src/components/App/background.png b/src/components/App/background.png
new file mode 100644
index 0000000..03ea4b7
Binary files /dev/null and b/src/components/App/background.png differ
diff --git a/src/components/Text/ReflectedText.js b/src/components/Text/ReflectedText.js
new file mode 100644
index 0000000..a5f4fc4
--- /dev/null
+++ b/src/components/Text/ReflectedText.js
@@ -0,0 +1,30 @@
+import React, {useLayoutEffect, useRef} from 'react'
+import ReactMarkdown from 'react-markdown'
+import styles from './Text.module.css'
+
+export default function Text({messages, currentInput, currentScroll}) {
+ const outputRef = useRef()
+
+ useLayoutEffect(() => {
+ outputRef.current.scrollTop = currentScroll
+ }, [currentScroll])
+
+ return (
+
+
+ {messages.map((message, i) => {
+ if(message.type === 'message')
+ return
{message.message}
+
+ if(message.type === 'command')
+ return
{message.command}
+
+ return null
+ })}
+
+
+
+
+
+ )
+}
diff --git a/src/components/Text/Text.js b/src/components/Text/Text.js
new file mode 100644
index 0000000..3931987
--- /dev/null
+++ b/src/components/Text/Text.js
@@ -0,0 +1,64 @@
+import React, {useState, useEffect, useRef} from 'react'
+import ReactMarkdown from 'react-markdown'
+import styles from './Text.module.css'
+import Reflection from './ReflectedText'
+
+export default function Text({messages, handleCommand}) {
+ const inputRef = useRef()
+ const outputRef = useRef()
+ const textRef = useRef()
+
+ const [currentInput, setCurrentInput] = useState('')
+ const [currentScroll, setCurrentScroll] = useState(0)
+
+ function onSubmit(ev) {
+ if(ev) ev.preventDefault()
+
+ if(!inputRef.current?.value.trim())
+ return;
+
+ if(inputRef.current){
+ handleCommand(inputRef.current.value)
+ inputRef.current.value = ''
+ setCurrentInput('')
+ }
+
+ if(outputRef.current) {
+ setImmediate(() => outputRef.current.scrollTop = outputRef.current.scrollHeight)
+ setCurrentScroll(outputRef.current.scrollHeight)
+ }
+ }
+
+ useEffect(() => {
+ const playArea = textRef.current
+
+ function onClick() {
+ inputRef.current.focus()
+ }
+
+ playArea.addEventListener('click', onClick)
+ return () => playArea.removeEventListener('click', onClick)
+ }, [])
+
+ return (
+ <>
+
+
setCurrentScroll(outputRef.current?.scrollTop)} className={styles.output}>
+ {messages.map((message, i) => {
+ if(message.type === 'message')
+ return
{message.message}
+
+ if(message.type === 'command')
+ return
{message.command}
+
+ return null
+ })}
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/Text/Text.module.css b/src/components/Text/Text.module.css
new file mode 100644
index 0000000..7414b48
--- /dev/null
+++ b/src/components/Text/Text.module.css
@@ -0,0 +1,80 @@
+.playArea {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ max-height: 100%;
+ user-select: none;
+}
+
+.reflectedArea {
+ display: flex;
+ flex-direction: column;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ transform: scale(.14, .12);
+ margin-top: -3px;
+ pointer-events: none;
+ opacity: .2;
+ filter: blur(2px);
+ overflow: hidden;
+}
+
+.output {
+ overflow-y: auto;
+ padding: 16px;
+ padding-bottom: 0;
+ min-height: 16px;
+}
+
+.input {
+ padding: 16px;
+ padding-top: 0;
+ position: relative;
+ font-weight: bold;
+}
+
+.input input {
+ background: transparent;
+ border: none;
+ box-shadow: none;
+ outline: none;
+ width: 100%;
+ text-indent: 16px;
+ font-family: inherit;
+ font-weight: bold;
+ font-size: 16px;
+ position: relative;
+ top: -1px;
+ left: -1px;
+ color: inherit;
+}
+
+.input::before {
+ position: absolute;
+ left: 16px;
+}
+
+.command {
+ font-weight: bold;
+ position: relative;
+ text-indent: 16px;
+ white-space: pre;
+}
+
+.command::before {
+ position: absolute;
+ left: -16px;
+}
+
+.command::before, .input::before {
+ content: '> ';
+ font-weight: bold;
+}
+
+/**
+ * Shadow
+ */
+.playArea {
+
+}
diff --git a/src/engine/Game.ts b/src/engine/Game.ts
index b436ddc..f8dfe52 100644
--- a/src/engine/Game.ts
+++ b/src/engine/Game.ts
@@ -158,13 +158,11 @@ export default class Game {
findObjectsInRoom(name : string | undefined) : Item [] {
let items : Item [] = []
- console.log(items)
for(const item of this.getState().items.values())
if(item.location === name)
items.push(item)
- console.log(items)
return items;
}
diff --git a/src/engine/Parser.ts b/src/engine/Parser.ts
index 64bf82d..0583c7e 100644
--- a/src/engine/Parser.ts
+++ b/src/engine/Parser.ts
@@ -60,8 +60,6 @@ export default class Parser {
}
handleError(invalidCommands: InvalidCommandDetails []) {
- console.log(invalidCommands)
-
if(!invalidCommands.length){
throw new Error("I'm unsure what you're trying to do")
}
@@ -73,7 +71,6 @@ export default class Parser {
}
this.game.say(mostValid.reason)
- console.log(mostValid)
}
understand(name : string) : VerbBuilder {
diff --git a/src/hooks/useWindowSize.js b/src/hooks/useWindowSize.js
new file mode 100644
index 0000000..3825118
--- /dev/null
+++ b/src/hooks/useWindowSize.js
@@ -0,0 +1,23 @@
+import { useState, useEffect } from 'react';
+
+export default function useWindowSize() {
+ const [windowSize, setWindowSize] = useState(getSize);
+
+ useEffect(() => {
+ function handleResize() {
+ setWindowSize(getSize());
+ }
+
+ window.addEventListener('resize', handleResize);
+ return () => window.removeEventListener('resize', handleResize);
+ }, []);
+
+ return windowSize;
+}
+
+function getSize() {
+ return {
+ width: window.innerWidth,
+ height: window.innerHeight
+ };
+}
diff --git a/src/index.css b/src/index.css
index 6e8a07a..c9ba7be 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,3 +1,16 @@
html, body {
margin: 0;
+ background: black;
+ color: white;
+}
+
+#root {
+ display: flex;
+ min-height: 100vh;
+ align-items: center;
+ justify-content: center;
+ background: black;
+ /* font-family: 'VT323', monospace; */
+ font-family: 'Share Tech Mono', monospace;
+ overflow: hidden;
}