CoOp:Anything
게임을 검색해 협동 플레이 가능한 모드·단계·품질·커뮤니티 평점을 확인합니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Bitsy game engine clone, written in modern C++
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A headless C++ reimplementation of the Bitsy game engine — the little engine for little games, worlds, and stories.
citsy is engine only. It does not link against 32blit or any other graphics or audio library. Instead, it exposes a small Host System API that a separate front-end (your renderer, your platform layer) implements. The engine owns game logic, simulation, scripting, and framebuffers; the host owns pixels on screen, input devices, and speakers.
Note: citsy is an independent C++ reimplementation of Bitsy, written to behave like the reference JavaScript engine. Its built-in fonts come from Bitsy (MIT, © Bitsy authors). Thanks to Adam Le Doux and the Bitsy contributors. citsy is not affiliated with Adam Le Doux or the official Bitsy project. Game data produced by the Bitsy editor (
.bitsyfiles) is the intended interchange format.
Bitsy is a browser-based tool for making tiny tile-based adventure games. The reference implementation couples the editor, JavaScript engine, and web renderer together. bitsybox shows that the engine can run on desktop by implementing a thin system layer (originally SDL + Duktape).
citsy takes that separation further:
| Layer | Responsibility |
|---|---|
| citsy core | Parse .bitsy data, simulate the world, run dialog scripts, produce memory buffers and audio parameters |
| Host backend | Map buffers to textures, poll input, play sound, present frames (32blit, MockHost, custom) |
This makes the engine embeddable in game jams, retro handhelds, test harnesses, and server-side validators without dragging in a windowing library.
std::span, std::optional, std::variant, RAII, no raw owning pointers in public APIs.Host interface mirrors the Bitsy System API used by bitsybox and the web runtime.The documentation website is at https://chili-chip.github.io/citsy/ (source in docs/):
| Guide | Contents |
|---|---|
| Getting started | Clone, build, and embed the engine |
| Architecture | Layering, modules, data flow, memory blocks, Host interface |
| Host API | Buttons, buffers, present(), MockHost |
| Tools & build | CMake options, compilers, dependencies, build targets |
| Testing | Running tests, writing tests, fixtures, MockHost |
| Bitsy data model | Entity types, properties, file syntax, relationships |
| Dialog scripting | Pages, lists, actions, inventory, {end} / {exit} |
| Gameplay | Movement, items, exits, endings, text settings |
| Sound | Blips, tunes, and the two pulse channels |
For agent-oriented conventions, see AGENTS.md.
┌─────────────────────────────────────────────────────────────┐
│ Your application │
│ (main loop, window, scaling, file picker, etc.) │
└──────────────────────────┬──────────────────────────────────┘
│ implements
▼
┌─────────────────────────────────────────────────────────────┐
│ Host backend │
│ 32blit · headless mock · your platform │
│ - input polling - audio output │
│ - buffer → texture blit - logging │
└──────────────────────────┬──────────────────────────────────┘
│ Host interface
▼
┌─────────────────────────────────────────────────────────────┐
│ citsy core │
│ Engine · Renderer (logical) · Dialog VM · Parser │
│ - game simulation - memory blocks (video/map/text) │
│ - script execution - palette & tile cache │
└──────────────────────────┬──────────────────────────────────┘
│ reads
▼
┌─────────────────────────────────────────────────────────────┐
│ .bitsy game data │
└─────────────────────────────────────────────────────────────┘
Each frame follows the same contract as the reference engine:
dt in milliseconds) and current input state.The engine never calls platform APIs directly.
The host implements citsy::Host — a C++ analogue of the bitsy global object from the Bitsy System API. The engine calls into the host for input and time; the host reads memory blocks and audio state that the engine owns.
| Name | Value | Meaning |
|---|---|---|
kTileSize | 8 | Pixels per tile edge |
kMapSize | 16 | Room width/height in tiles |
kVideoSize | 128 | Main framebuffer edge in pixels (16 × 8) |
kGfxVideo | 0 | Direct per-pixel framebuffer mode |
kGfxMap | 1 | Tilemap mode (normal gameplay) |
kTxtHirez | 0 | Default text; 2× pixel scale (twice the display resolution) |
kTxtLorez | 1 | Chunky text; 4× pixel scale (same resolution as the display) |
| Code | Action |
|---|---|
Up | Move avatar / menu up |
Down | Move avatar / menu down |
Left | Move avatar / menu left |
Right | Move avatar / menu right |
Ok | Interact, advance dialog |
Menu | Restart (host reloads the game) |
The host normalizes keyboard, gamepad, and touch into these six logical buttons.
The engine maintains fixed logical buffers. The host reads them after each update; the engine may resize the textbox buffer when dialog layout changes.
| Block | Size (typical) | Purpose |
|---|---|---|
Video | 128 × 128 | Per-pixel color indices in kGfxVideo mode |
Textbox | w × h (dynamic) | Dialog text rendered as color indices |
Map1 | 16 × 16 | Primary tilemap (tile IDs) |
Map2 | 16 × 16 | Overlay tilemap (sprites/items layer) |
Tile[n] | 8 × 8 each | Cached tile pixel patterns |
Sound1, Sound2 | — | Channel frequency, volume, pulse, duration |
Color indices refer to the active palette (see Palettes).
namespace citsy {
struct Color { std::uint8_t r, g, b; };
struct SoundChannel {
bool active;
int duration_ms;
int frequency_hz;
float volume; // 0.0 – 1.0
PulseWave pulse; // 1/8, 1/4, 1/2 duty
};
enum class GraphicsMode { Video, Map };
enum class TextMode { HiRez, LoRez };
class Host {
public:
virtual ~Host() = default;
// Called once at startup
virtual void on_engine_ready() {}
// Time & input — host → engine
virtual double delta_time_ms() const = 0;
virtual bool button(Button code) const = 0;
// Optional: host logging sink
virtual void log(std::string_view message) {}
// Called after each engine step — host reads engine state
virtual void present(
GraphicsMode gfx_mode,
TextMode txt_mode,
std::span<const Color> palette,
std::span<const std::uint8_t> video, // 128×128 indices
std::span<const std::uint8_t> map1, // 16×16 tile IDs
std::span<const std::uint8_t> map2,
TextboxView textbox, // may be hidden
SoundChannel sound1,
SoundChannel sound2
) = 0;
};
} // namespace citsy
Backends implement present() differently:
channels[]. See the companion citsy-32blit player.When a game or transition changes colors, the engine updates its internal palette and passes the full RGB table to present(). Hosts should not assume a fixed 3-color palette — extended palettes (COL 3, COL 4, …) are supported in modern Bitsy data.
Modules inside the core library:
| Module | Role |
|---|---|
parser/ | Load and serialize .bitsy text; validate segments |
model/ | Game, Room, Tile, Sprite, Item, Dialogue, Variable, … |
engine/ | Main loop, avatar movement, collision, room transitions |
dialog/ | Script interpreter: variables, conditionals, lists, {print*}, {ava}/{pal}/{exit}/{end} |
render/ | Logical renderer — fills video/map/textbox memory blocks (no GPU) |
font/ | Bitsy's built-in fonts, custom .bitsyfont glyph rendering into textbox buffer, Arabic letter joining |
sound/ | Two-channel square-wave parameter generation (blips + tunes) |
transition/ | Room transition effects (fade, wave, tunnel, slide) in video mode |
kGfxMap — Default gameplay. Engine composes the room from tile IDs in Map1, then draws sprites and items into Map2 or directly to output according to Bitsy rules.kGfxVideo — Used during transitions and special effects. Engine writes individual pixel color indices into the Video buffer.The host chooses how to interpret buffers based on the gfx_mode argument to present().
Dialog is not just text — it is Bitsy's lightweight game logic language. The engine evaluates:
{print …} / {say …} expressions{name = value}, {count = count + 1}{sequence} / {cycle} / {shuffle} and - cond ? / - else{item}, {ava}, {pal}, {tune}, {blip}, {exit}, {end}, {property locked}{printSprite}, {printTile}, {printItem}{wvy}, {shk}, {rbw}, {clr} / {clr1} / {clr2} / {clr3}Scripts are parsed from DLG segments in game data. src/dialog/script.cpp is a port of Bitsy 8.15's script.js, and tests/parity plays the same games in the Bitsy engine and in citsy to check they match.
A Bitsy game is a collection of typed segments in a plain-text .bitsy file. See docs/bitsy/data-model.md for the full reference: every entity type, property, file syntax example, relationship diagram, and C++ struct mapping.
Quick summary of core entities:
| Entity | Description |
|---|---|
Palette (PAL) | Named color sets (background, tile, sprite, plus optional extended colors) |
Tile (TIL) | 8×8 pixel art; optional wall flag, animation frames (> separator), color index |
Sprite (SPR) | Animated 8×8 character or object; avatar is always id A |
Item (ITM) | Collectible 8×8 object with inventory semantics |
Room (ROOM) | 16×16 grid of tile IDs, plus placed items, exits, and endings |
Exit (EXT) | Warp tile: target room, position, optional dialog, transition effect |
Dialogue (DLG) | Script attached to sprites, items, or exits |
Variable (VAR) | Global number or string state |
Ending (END) | End-game message (top-level) or tile trigger (room sub-key) |
citsy targets import of standard .bitsy files exported from the editor.
| Feature | Target support |
|---|---|
# BITSY VERSION header | Yes |
Comma-separated room format (! ROOM_FORMAT) | Yes |
| Legacy contiguous room format (single-char tile IDs) | Yes |
SET vs ROOM (historical naming) | Yes |
| Multi-frame animation | Yes |
Extended palettes (COL n) | Yes |
| Variables and dialog scripting | Yes |
Custom fonts (FONT / .bitsyfont) | Yes |
TEXT_DIRECTION RTL | Yes |
| Sound (engine generates channel params; host plays audio) | Yes |
Exact version targets will be documented as compatibility tests land in tests/data/.
citsy/
├── include/citsy/ # Public headers
│ ├── engine.hpp # Main Engine class
│ ├── host.hpp # Host interface
│ ├── types.hpp # Color, Button, memory block views
│ └── version.hpp
├── src/
│ ├── parser/ # .bitsy lexer / parser
│ ├── model/ # Data structures
│ ├── engine/ # Simulation & game loop
│ ├── dialog/ # Script interpreter
│ ├── render/ # Logical framebuffer compositor
│ ├── font/ # .bitsyfont + Bitsy's built-in fonts
│ ├── sound/ # Blips and tunes → channel params
│ └── transition/ # Exit transition effects
├── backends/
│ └── mock/ # Test double (header-only)
├── tests/
│ ├── unit/
│ └── data/ # Sample .bitsy files
├── examples/
│ └── minimal/ # Load a game with MockHost
├── CMakeLists.txt
└── README.md
The citsy CMake target is a static or shared library with no link dependency on 32blit or similar. Display hosts are separate projects that link citsy and their platform library.
Requirements:
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
ctest --test-dir build
See docs/tools.md for CMake options, build targets, and dependency details. See docs/testing.md for test filtering, fixtures, and writing new tests.
The 32blit reference player is a separate repository: citsy-32blit.
#include <citsy/engine.hpp>
#include <citsy/host.hpp>
class MyHost : public citsy::Host {
public:
double delta_time_ms() const override { return dt_; }
bool button(citsy::Button b) const override { return keys_[b]; }
void present(/* ... */) override {
// Blit video/map buffers to your display
// Play sound1 / sound2 if active
}
void set_delta(double dt) { dt_ = dt; }
void set_key(citsy::Button b, bool down) { keys_[b] = down; }
private:
double dt_ = 0;
bool keys_[6] = {};
};
int main() {
auto game_data = citsy::load_file("my_game.bitsy");
citsy::Engine engine(std::move(game_data));
MyHost host;
engine.start();
while (engine.is_running()) {
host.set_delta(16.667); // ~60 fps
engine.update(host);
// host.present() was called from engine.update()
}
}
The Phase 4 host lives in citsy-32blit (from the chili-chip/game-template). It implements citsy::Host with the 32blit SDK, so the same binary runs on desktop SDL and on VGC Zero / 32blit hardware.
cd ../citsy-32blit
cmake --preset linux
cmake --build --preset linux
./out/build/linux/citsy-32blit.elf
A bundled playable.bitsy starts automatically. MENU opens a list of .bitsy files (bundled assets, files next to the binary, or --launch_path). See that repo’s README for controls and how games are packed.
Development is staged toward practical compatibility with games made in current Bitsy versions.
Phase 0 — Foundation
.bitsy parser and in-memory Game modelHost interface and MockHostPhase 1 — Playable core
Phase 2 — Scripting & state
Phase 3 — Polish
Phase 4 — 32blit player
Compatibility fixtures will be drawn from the Bitsy community and existing open-source parsers such as bitsy-parser.
citsy is released under the MIT License.
The built-in font data is derived from Bitsy, also MIT licensed; its copyright notice is kept in LICENSE. Games you create with the Bitsy editor remain yours.
Host.bitsy from packed assets, disk, or --launch_path