Skip to content

Commit

Permalink
Some refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gataquadrada committed Apr 14, 2022
1 parent cf856dc commit 0100b6c
Show file tree
Hide file tree
Showing 9 changed files with 382 additions and 174 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
assets/backups/*
node_modules/*
node_modules
backups
package*.json
41 changes: 22 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Low cost sprite based V-Tubing

A lightweight script, that uses sprites and allows you to have a VTube character you can control with Stream Deck and Touch Portal buttons.
Working on a video demo.
A lightweight Sprite based VTube environment, that you can control with Stream Deck and Touch Portal buttons.

If you like de content, consider [buying me a ☕](https://www.buymeacoffee.com/mazeakin).

## Requirements

Expand All @@ -11,12 +12,19 @@ Working on a video demo.

## Instalation/Usage

#### If you don't want to fiddle with any of the manual parts, here is a [Windows version](https://github.com/Mazeakin/Maze-Static-VTube/releases) you can just download and use.

First, install the required Node dependencies in the project folder:
`npm i ws socket.io express`

Then, run the main script:
`node app.js`

## Making it visible on OBS

Simply add the `http://127.0.0.1:3000/` address as OBS Browser source.
That's all.

## Using with Stream Deck

1. Point to the (running) webservice;
Expand All @@ -38,17 +46,9 @@ Then, run the main script:
- Use `last` to jump to the last frame recorded in the `frames.json` file.
- Use `random` to jump to a random frame recorded in the `frames.json` file.

## Making it visible on OBS

Simply add the `http://127.0.0.1:3000/` address as OBS Browser source.
That's all.

## Character editor.

By opening the `http://127.0.0.1:3000/map` URL (after starting the server), you'll find a character editor.

> I am still working on a way to streamline the process of changing your spritesheet image (with an "upload" button).
> But, for now, you need to replace the `assets/character.png` file by hand.
By opening the `http://127.0.0.1:3000/map` URL (after starting the server) or by opening the [APP](https://github.com/Mazeakin/Maze-Static-VTube/releases), you'll find a character editor.

![map-1.png](tutorial/map-1.png)

Expand All @@ -61,25 +61,29 @@ By opening the `http://127.0.0.1:3000/map` URL (after starting the server), you'
- Reorganize frames (drag and drop).
- Click sprites in the timeline to quickly navigate and preview.
- Toggle the timeline.
- Save (replaces your current `frames.json` file, but makes a backup once a day inside the `assets/backups` folder).
- Save (replaces your current `frames.json` file, but makes a backup once a day inside the `backups` folder).

## Mapping the character by hand

1. You'll need the `X` and `Y` coordinates, plus the `width` and `height` of each frame, in order to map it correctly (use CSS background-position as reference);
2. Then, proceed to fill the `frames` array inside the `assets/frames.json` file.
_First, you are brave._

- You'll need the `X` and `Y` coordinates, plus the `width` and `height` of each frame, in order to map it correctly (use CSS background-position as reference, top left is `X-0` and `Y-0`);
- Then, proceed to fill the `frames` array inside the `assets/frames.json` file.

## Replacing a spritesheet
## Replacing a spritesheet by hand

Just replace the `assets/character.png` file.

## Todo

- ⬜ Support uploading new spritesheet to the editor.
- 🟨 Code cleanup.
- ⬜ Make replacing a frame in the editor less annoying.
- ⬜ Support for small movement when microphone is detected.
- ⬜ Support for loop through predefined frames when microphone is detected.
- ⬜ Support for second set of frames for mouth movement when microphone is detected.
- ⬜ Support for idle set of frames.
- ✅ Support for uploading new spritesheet to the editor.
- ✅ Character preview inside the editor.
- ✅ Character editor.
- ✅ "first", "last" and "random" actions.
- ✅ "flip" and "unflip" actions.
Expand Down Expand Up @@ -110,7 +114,7 @@ A: Yes. But I'd appreciate if you shared your customization with everyone else.
Q: _I see a lot of unused code. Are you adding new stuff?_
A: Yes. I may send commits with placeholder code I am working on.

Q: _Can I message you on if I have issues or suggestions?_
Q: _Can I message you if I have issues or suggestions?_
A: Sure. You can open an issue here, or message me on [Discord](https://discord.gg/eYfSNQT) or [Twitter](https://twitter.com/Mazeakin).

## Credits
Expand All @@ -120,6 +124,5 @@ A: Sure. You can open an issue here, or message me on [Discord](https://discord.

## Known bugs

- One to two pixels as margin error are randomly added/removed when saving from the editor.
- One to two pixels as margin error are randomly added/removed when saving from the editor. That means you need to fiddle with positions, till you get the perfect frame.
- The sprite frame actually working flawless (despite the item above) in the animation screen is actually a bug.
- That means you need to fidget with positions, till you get the perfect frame.
50 changes: 39 additions & 11 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ const { Server } = require("socket.io")
const io = new Server(server)
const WebSocket = require("ws")
const fs = require("fs")
const bodyParser = require("body-parser")

app.use(bodyParser.json({ limit: "50mb" }))
app.use(bodyParser.urlencoded({ limit: "50mb", extended: true }))
app.use(express.json())
app.use(express.urlencoded({ extended: true }))

app.use("/assets", express.static("assets"))

app.get("/", (req, res) => {
res.sendFile(__dirname + "/pages/index.htm")
res.sendFile(__dirname + "/pages/player.htm")
})

app.get("/character", (req, res) => {
Expand All @@ -27,33 +30,58 @@ app.get("/map", (req, res) => {

app.post("/map", (req, res) => {
try {
if (!fs.existsSync("assets/backups")) {
fs.mkdirSync("assets/backups")
if (!fs.existsSync("backups")) {
fs.mkdirSync("backups")
}

var d = new Date()
const date = `${d.getFullYear()}_${("0" + (d.getMonth() + 1)).slice(-2)}_${(
"0" + d.getDate()
).slice(-2)}`

if (!fs.existsSync(`assets/backups/frames-${date}.json`)) {
if (!fs.existsSync(`backups/${date}-frames.json`)) {
fs.copyFile(
"assets/frames.json",
`assets/backups/frames-${date}.json`,
`backups/${date}-frames.json`,
(err) => {}
)

fs.copyFile(
"assets/character.png",
`backups/${date}-character.png`,
(err) => {}
)
}
} catch (err) {
console.error(err)
}

fs.writeFile("assets/frames.json", JSON.stringify(req.body), (err) => {
if (err) {
console.error(err)
res.send("err")
return
if (req.body.spritesheet) {
const spritesheet = req.body.spritesheet.replace(
/^data:image\/png;base64,/,
""
)

fs.writeFile("assets/character.png", spritesheet, "base64", function (err) {
if (err) {
console.error(err)
res.send("err")
return
}
})
}

fs.writeFile(
"assets/frames.json",
JSON.stringify({ frames: req.body.frames }),
(err) => {
if (err) {
console.error(err)
res.send("err")
return
}
}
})
)

res.json({ ok: true })
})
Expand Down
Binary file added assets/character-demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 8 additions & 1 deletion assets/frames.json
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
{"frames":[{"w":"258px","h":"437px","p":"-56px -76.99999237060547px"},{"w":"268px","h":"437px","p":"-314px -76.99999237060547px"},{"w":"360px","h":"437px","p":"-573px -77.99999237060547px"}]}
{
"frames": [
{ "w": "260px", "h": "439px", "p": "-56px -76.99999237060547px" },
{ "w": "270px", "h": "439px", "p": "-314px -76.99999237060547px" },
{ "w": "362px", "h": "439px", "p": "-573px -77.99999237060547px" },
{ "w": "253px", "h": "132px", "p": "-971.5px -206.50000762939453px" }
]
}
Loading

0 comments on commit 0100b6c

Please sign in to comment.