Compare commits

..

3 commits

9 changed files with 165 additions and 8 deletions

View file

@ -9,6 +9,8 @@ An in-dev game that I plan to make a shooter game out of.
Ui theming is based on Catppucin Mocha. You can find the colors [here](https://github.com/catppuccin/catppuccin) and the style guide [here](https://github.com/catppuccin/catppuccin/blob/main/docs/style-guide.md) Ui theming is based on Catppucin Mocha. You can find the colors [here](https://github.com/catppuccin/catppuccin) and the style guide [here](https://github.com/catppuccin/catppuccin/blob/main/docs/style-guide.md)
I should put this in the game sometime, but the option to open the configuration menu is O and the debug menu is F4. You can hold alt in the debug menu to get information when hovering over objects.
# Hacks # Hacks
* I get a strange error about private identifiers in [`./src/ReplicatedStorage/ecs/state.ts`](./src/ReplicatedStorage/ecs/state.ts) * I get a strange error about private identifiers in [`./src/ReplicatedStorage/ecs/state.ts`](./src/ReplicatedStorage/ecs/state.ts)
* I decided to omit the "TS" folder from [`./default.project.json:40`](./default.project.json) due to the script override not working in Health.server.ts in StarterCharacterScripts. * I decided to omit the "TS" folder from [`./default.project.json:40`](./default.project.json) due to the script override not working in Health.server.ts in StarterCharacterScripts.

View file

@ -3,6 +3,7 @@ import { useEffect, useCallback, useMemo, useMutable } from "@rbxts/roact-hooked
import { acrylicInstance } from "./acrylicInstance" import { acrylicInstance } from "./acrylicInstance"
import { Lighting, Workspace } from "@rbxts/services" import { Lighting, Workspace } from "@rbxts/services"
import Make from "@rbxts/make" import Make from "@rbxts/make"
import { useRootSelector } from "ReplicatedStorage/ui/store/hooks/useUiProducer"
const cylinderAngleOffset = CFrame.Angles(0, math.rad(90), 0) const cylinderAngleOffset = CFrame.Angles(0, math.rad(90), 0)
@ -34,7 +35,7 @@ Make("DepthOfFieldEffect", {
Parent: Lighting Parent: Lighting
}) })
function acrylic(props: acrylicProps): Roact.Element { function AcrylicComponent(props: acrylicProps): Roact.Element {
const { radius, distance } = props const { radius, distance } = props
const spreadableProps = { ...props } as Partial<acrylicProps> const spreadableProps = { ...props } as Partial<acrylicProps>
@ -161,4 +162,20 @@ function acrylic(props: acrylicProps): Roact.Element {
) )
} }
function acrylic(props: acrylicProps): Roact.Element {
const { radius, distance } = props
const spreadableProps = { ...props } as Partial<acrylicProps>
delete spreadableProps.radius
delete spreadableProps.distance
const enabled = useRootSelector((state) => state.configProducer.acrylicBlur)
return <>
{
enabled && <AcrylicComponent radius={radius} distance={distance}/>
}
</>
}
export default acrylic export default acrylic

View file

@ -1,4 +1,5 @@
import { UseProducerHook, useProducer } from "@rbxts/roact-reflex" import { UseProducerHook, UseSelectorHook, useProducer, useSelector } from "@rbxts/roact-reflex"
import { rootProducer } from "../producer" import { rootProducer } from "../producer"
export const useUiProducer: UseProducerHook<rootProducer> = useProducer export const useRootProducer: UseProducerHook<rootProducer> = useProducer
export const useRootSelector: UseSelectorHook<rootProducer> = useSelector

View file

@ -0,0 +1,16 @@
import { createProducer } from "@rbxts/reflex"
export interface ConfigState {
readonly acrylicBlur: boolean
}
const initialState: ConfigState = {
acrylicBlur: false
}
export const configProducer = createProducer(initialState, {
toggleAcrylic: (state) => ({
...state,
acrylicBlur: !state.acrylicBlur
})
})

View file

@ -1,9 +1,10 @@
import { InferDispatchers, InferState, combineProducers, loggerMiddleware } from "@rbxts/reflex" import { InferDispatchers, InferState, combineProducers, loggerMiddleware } from "@rbxts/reflex"
import { configProducer } from "./config"
export type rootProducer = typeof producer export type rootProducer = typeof producer
export type rootState = InferState<rootProducer> export type rootState = InferState<rootProducer>
export type rootDispatchers = InferDispatchers<rootProducer> export type rootDispatchers = InferDispatchers<rootProducer>
export const producer = combineProducers({ export const producer = combineProducers({
configProducer
}).applyMiddleware(loggerMiddleware) }).applyMiddleware(loggerMiddleware)

View file

@ -0,0 +1,113 @@
import Roact from "@rbxts/roact"
import Padding from "ReplicatedStorage/ui/components/padding"
import Acrylic from "ReplicatedStorage/ui/components/acrylic"
import { ContextActionService, HttpService } from "@rbxts/services"
import { Spring } from "@rbxts/flipper"
import { useGroupMotor } from "@rbxts/roact-hooked-plus"
import { useEffect } from "@rbxts/roact-hooked"
import { useRootProducer } from "ReplicatedStorage/ui/store/hooks/useUiProducer"
interface ConfigProps extends Roact.JsxInstanceProperties<Frame> {
shown: boolean
Event?: Roact.JsxInstanceEvents<Frame>
Change?: Roact.JsxInstanceChangeEvents<Frame>
}
const CONFIG_DEFAULT = [new Spring(1.5, { frequency: 6 })]
const CONFIG_ACTIVE = [new Spring(.5, { frequency: 6 })]
function config(props: ConfigProps): Roact.Element {
const { toggleAcrylic } = useRootProducer()
let { shown } = props
const spreadableProps = { ...props } as Partial<ConfigProps>
delete spreadableProps.shown
const [slotPosYMap, setPosYGoal] = useGroupMotor([1.5, 6])
const slotPosY = slotPosYMap.map((t) => t[0])
useEffect(() => {
const guid = HttpService.GenerateGUID(false)
ContextActionService.BindAction(
guid,
(_, userInputState) => {
if (Enum.UserInputState.Begin === userInputState) {
shown = !shown
if (shown) {
setPosYGoal(CONFIG_ACTIVE)
} else {
setPosYGoal(CONFIG_DEFAULT)
}
}
},
false,
Enum.KeyCode.P
)
})
return (
<frame
{...spreadableProps}
AnchorPoint={new Vector2(.5, .5)}
Position={
slotPosY.map((posY) => {
return new UDim2(.5, 0, posY, 0)
})
}
BackgroundTransparency={1}
Size={new UDim2(.4, 0, .7, 0)}
Key={"Config"}
>
<Acrylic
radius={5}
distance={0.001}
/>
<frame
AnchorPoint={new Vector2(0, 0)}
Position={new UDim2(0, 0, 0, 0)}
Size={new UDim2(1, 0, 1, 0)}
BackgroundTransparency={.7}
BackgroundColor3={Color3.fromHex("#1e1e2e")}
>
<uilistlayout
Padding={new UDim(0, 5)}
VerticalAlignment={Enum.VerticalAlignment.Top}
HorizontalAlignment={Enum.HorizontalAlignment.Left}
FillDirection={Enum.FillDirection.Vertical}
/>
<uicorner
CornerRadius={new UDim(0, 5)}
/>
<Padding
padding={new UDim(0, 5)}
/>
<textbutton
Size={new UDim2(1, 0, .1, 0)}
Font={Enum.Font.Gotham}
TextXAlignment={Enum.TextXAlignment.Left}
BackgroundTransparency={.5}
BackgroundColor3={Color3.fromHex("#11111b")}
AutoButtonColor={false}
TextColor3={Color3.fromHex("#cdd6f4")}
TextScaled
Text={"Toggle acrylic UI"}
Event={{
Activated: (): void => {toggleAcrylic()}
}}
>
<Padding
paddingY={new UDim(.3, 0)}
paddingX={new UDim(0, 5)}
/>
<uicorner
CornerRadius={new UDim(0, 5)}
/>
</textbutton>
</frame>
</frame>
)
}
export default config

View file

@ -62,19 +62,19 @@ function slot(props: SlotProps): Roact.Element {
return ( return (
<frame <frame
BackgroundColor3={Color3.fromHex("#11111b")} BackgroundColor3={Color3.fromHex("#1e1e2e")}
BackgroundTransparency={slotBgTransparency} BackgroundTransparency={slotBgTransparency}
Size={new UDim2(1, 0, 1, 0)} Size={new UDim2(1, 0, 1, 0)}
> >
<Acrylic <Acrylic
radius={2} radius={5}
distance={0.001} distance={0.001}
/> />
<uiaspectratioconstraint <uiaspectratioconstraint
AspectRatio={slotRatio} AspectRatio={slotRatio}
/> />
<uicorner <uicorner
CornerRadius={new UDim(0, 2)} CornerRadius={new UDim(0, 5)}
/> />
<frame BackgroundTransparency={1} Size={new UDim2(1, 0, 1, 0)}> <frame BackgroundTransparency={1} Size={new UDim2(1, 0, 1, 0)}>
<Padding <Padding

View file

@ -1,5 +1,6 @@
import Roact from "@rbxts/roact" import Roact from "@rbxts/roact"
import Hotbar from "./hotbar/hotbar" import Hotbar from "./hotbar/hotbar"
import Config from "./config/config"
import { withHookDetection } from "@rbxts/roact-hooked" import { withHookDetection } from "@rbxts/roact-hooked"
interface MainProps extends Roact.JsxInstanceEvents<ScreenGui> { interface MainProps extends Roact.JsxInstanceEvents<ScreenGui> {
@ -19,6 +20,12 @@ export default function main(props: MainProps): Roact.Element {
AnchorPoint={new Vector2(0.5, 1)} AnchorPoint={new Vector2(0.5, 1)}
Size={new UDim2(1, 0, 0.2, 0)} Size={new UDim2(1, 0, 0.2, 0)}
/> />
<Config
shown={false}
AnchorPoint={new Vector2(.5, .5)}
Position={new UDim2(.5, 0, .5, 0)}
Size={new UDim2(.4, 0, .7, 0)}
/>
</screengui> </screengui>
) )
} }

View file

@ -5,7 +5,7 @@
"downlevelIteration": true, "downlevelIteration": true,
"jsx": "react", "jsx": "react",
"jsxFactory": "Roact.createElement", "jsxFactory": "Roact.createElement",
"jsxFragmentFactory": "Roact.Fragment", "jsxFragmentFactory": "Roact.createFragment",
"module": "commonjs", "module": "commonjs",
"moduleResolution": "Node", "moduleResolution": "Node",
"noLib": true, "noLib": true,