Skip to content

Commit 8cca2d2

Browse files
committed
add Map Editor
1 parent 230dddd commit 8cca2d2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+13354
-2
lines changed

.github/workflows/build.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ jobs:
2424
python setup.py
2525
npm install
2626
npm run build
27+
mkdir -p dist/editor
28+
29+
- name: Install and Build Editor
30+
run: |
31+
cd map-o-matic-v2
32+
npm install
33+
npm run build
34+
cd ../port
35+
cp -r ../map-o-matic-v2/dist/* dist/editor/
2736
2837
- name: Deploy 🚀
2938
uses: JamesIves/github-pages-deploy-action@v4

.github/workflows/run-tests.yml

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Run Jest Tests
2+
3+
# This workflow will run on pushes and pull requests to the main branch
4+
on:
5+
push:
6+
branches:
7+
- '*'
8+
pull_request:
9+
branches:
10+
- '*'
11+
12+
jobs:
13+
test:
14+
# Runs on the latest version of Ubuntu
15+
runs-on: ubuntu-latest
16+
17+
# Steps to be executed
18+
steps:
19+
# Step 1: Checkout the code from the repository
20+
- name: Checkout code
21+
uses: actions/checkout@v3
22+
23+
# Step 2: Set up Node.js
24+
- name: Set up Node.js
25+
uses: actions/setup-node@v3
26+
with:
27+
node-version: '22.9.0' # Use the version your project requires
28+
29+
# Step 3: Install dependencies
30+
- name: Install dependencies
31+
run: |
32+
git submodule update --init --recursive
33+
cd map-o-matic-v2
34+
npm install
35+
36+
# Step 4: Run Jest tests
37+
- name: Run Jest tests
38+
run: |
39+
cd map-o-matic-v2
40+
npm run test

.gitignore

+10-1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,13 @@ dist-ssr
2525

2626
assets
2727
.vscode
28-
translate-objects
28+
translate-objects
29+
30+
*/*.pdf
31+
docs/main.pdf
32+
docs/engine/collision.pdf
33+
docs/main.pdf
34+
docs/engine/main.pdf
35+
36+
*.pdf
37+
*.tsbuildinfo

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
### **[Play it HERE in your Browser!](https://mattbruv.github.io/ccsr)**
99

1010
This is a modern port of the Shockwave game series Cartoon Cartoon Summer Resort.
11+
It also includes Scooby Doo Hollywood Horror Part 1 and Part 2, as well as a fully featured map editor.
1112

1213
**Cartoon Cartoon Summer Resort** is the name of a series of four episodic Adventure Games formerly hosted on Cartoon Network's official website, featuring characters from their Cartoon Cartoons original programming. The game was created and released in summer 2000 tying in to the first Big Pick. Each playable character was from one of the shorts selected that could have become a full fleged series during the promotion.
1314

File renamed without changes.

docs/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# CCSR Documentation
2+
3+
This is a (currently incomplete)
4+
book which serves as documentation
5+
of all of the niche or previously unknown intricate details about the CCSR games and their history.
6+
7+
It is written with [Typst](https://typst.app/), and produces a PDF book.

docs/engine/collision.typ

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#pagebreak()
2+
3+
== Collision System
4+
5+
The repetitive background music likely takes the number one spot as far as things which made the Cartoon Cartoon Summer Resort games memorable. The second place spot for most memorable feature can safely be given to the game's collision detection system.
6+
7+
The average player has undoubtedly come across Cartoon Cartoon Summer Resort's questionable collision system after spending some time playing the game.
8+
The collision system often seems illogical and random, which leads to confusion and frustration among players.
9+
10+
Normally, objects that look like you can't walk on them don't let you walk on them. For example, trees, shrubs, and buildings are examples of objects that logically should have collision,
11+
and most of the time this is true.
12+
But as you may have experienced, there are #underline([many]) examples where this is not true.
13+
14+
Here are a few visual examples from just the first episode which are particularly egrigious. Game screenshots are shown on the left, and their corresponding collision maps are shown on the right (collision screenshots are taken from Map-o-Matic-v2, the map editor I made).
15+
Red areas are non-walkable and have collision, while green areas are walkable and do not have collision.
16+
Sorry for the readers who are red-green colorblind, as if it couldn't be confusing enough already.
17+
18+
#grid(
19+
columns: (50%, 50%),
20+
row-gutter: 3%,
21+
22+
image("collision/bad-1.png"),
23+
image("collision/bad-1-coll.png"),
24+
25+
image("collision/bad-2.png"),
26+
image("collision/bad-2-coll.png"),
27+
28+
image("collision/bad-3.png"),
29+
image("collision/bad-3-coll.png"),
30+
31+
)
32+
33+
When we look at the game screenshots on the left without considering the collision maps on the right,
34+
it looks totally absurd.
35+
The player character is climbing on the roofs of buildings, over shrubs, palm trees, and in the middle of areas that look like they should be completely out of bounds.
36+
37+
The bounds are a lot more clear when we look at the collision maps, but it still doesn't make sense as to why those specific areas are walkable while others aren't.
38+
Why is there no collision in these areas?
39+
There are 3 simple causes which account for almost all of the broken collision detection.
40+
41+
Despite the seemingly complicated and illogical collision consistency, the collision system is surprisingly very logical and consistent.
42+
It just needs to be understood to be used effectively.
43+
The real problem with the collision system is that it is not very intuitive, but once you understand it, it's impossible to mess things up.
44+
45+
46+
=== The Three Causes of Broken Collision
47+
48+
Here are the three causes of broken collision, we will go through each one by one, in the order of least complicated to most complicated. As far as I'm aware, these three causes make up the entirety of the glitchy collision in the games.
49+
50+
+ *Bad Map Connections* -- a walkable part of a map connects to an unwalkable part of a neighboring map
51+
+ *Incorrectly Typed Objects* -- Objects are incorrectly marked as `FLOR` (walkable) instead of `WALL` (non-walkable)
52+
+ *`FLOR` Overlap* -- Objects are ordered incorrectly in the map data.
53+
54+
55+
==== 1. Bad Map Connections
56+
57+
This is the simplest to understand cause of bad collision.
58+
A bad map connection as a spot on a map which is walkable, and by walking on it and walking into a neighboring map,
59+
the player is panned over and glitched into a non-walkable area on the new map.
60+
61+
Consider the following area:
62+
63+
#grid(
64+
columns: (50%, 50%),
65+
column-gutter: 3%,
66+
image("collision/connection-1.png"),
67+
image("collision/connection-2.png")
68+
)
69+
70+
In the image on the left, from episode 1,
71+
we can see that the bottom map has a walkable grassy space
72+
above the shrubs which are beside the building.
73+
If we were to align the player on that tile, and walk upwards,
74+
the player would be panned into the above map.
75+
The spot directly above in the top map is occupied
76+
by a palm tree, which has collision detection.
77+
This results in the player being stuck in the palm tree if he enters the map from below it.
78+
In cases like this, the player is almost softlocked, but can usually always escape by going in the reverse direction that he came in by returning to the previous map.
79+
80+
Comparing the first image from Episode 1 on the left with the right image from Episode 2, we can see that the developers intentionally extended the flowers to now block that area, most likely because they recognized this issue after releasing the first game and it's simple to fix.
81+
82+
This can be avoided by always making the tiles which border each other between maps have the same type.
83+
A walkable tile at the edge of one map should always
84+
lead to a walkable tile on the neighboring map,
85+
and likewise for non-walkable tiles.
86+
This bug happens when you walk into a non-walkable tile.
87+
88+
89+
This cause of bad collision is simple to understand, and comes down to bad map design.
90+
It seems like this type of issue didn't happen too often in practice.
91+
Here is another example which existed in Episodes 1 & 2, but the developers fixed in Episode 3:
92+
93+
#image("collision/connection-3.png")
94+
#image("collision/connection-4.png")
95+
96+
We can see that there is a grass tile which borders on a palm tree, but this was fixed in episode 3 by removing the two palm trees from the map on the right.
97+
Virtual deforestation!
98+
99+
==== 2. Incorrectly Typed Objects
100+
101+
The second reason is due to game objects having the incorrect collision type.
102+
This is also easy to understand.
103+
104+
==== 3. `FLOR` Overlap
105+
106+

docs/engine/collision/bad-1-coll.png

582 KB
Loading

docs/engine/collision/bad-1.png

101 KB
Loading

docs/engine/collision/bad-2-coll.png

475 KB
Loading

docs/engine/collision/bad-2.png

97.1 KB
Loading

docs/engine/collision/bad-3-coll.png

515 KB
Loading

docs/engine/collision/bad-3.png

92.5 KB
Loading
894 KB
Loading
1.09 MB
Loading
803 KB
Loading
627 KB
Loading

docs/engine/main.typ

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
3+
= CCSR Engine
4+
5+
== Director Basics
6+
7+
=== Lingo Objects
8+
9+
== Map Format
10+
11+
// gConMove = [#none, #AUTO, #push, #pull, #movex, #movey]
12+
13+
#include "collision.typ"

docs/intro/main.typ

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
= Cartoon Cartoon Summer Resort
3+
4+
== Introduction
5+
6+
Introduction to CCSR
7+
8+
== History
9+
10+
https://www.reddit.com/r/programming/comments/9m18v2/fixing_a_bug_in_an_18_year_old_shockwave_game/
11+
12+
https://news.ycombinator.com/item?id=18158674
13+
14+
15+
== Episode 1
16+
17+
== Episode 2
18+
19+
== Episode 3
20+
21+
== Episode 4

docs/main.typ

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// #include "cover.typ"
2+
3+
#set figure(gap: 1em)
4+
#set page(numbering: "1")
5+
6+
#outline(indent: 2em)
7+
8+
#include "intro/main.typ"
9+
#include "engine/main.typ"

map-o-matic-v2/.gitignore

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?

map-o-matic-v2/README.md

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Map-o-Matic-v2
2+
3+
Map-o-Matic-v2 is a fully featured map editor for games built on the Cartoon Cartoon Summer Resort engine.
4+
It supports exporting map data which is completely compatible with both the original Shockwave games built in Macromedia Director and my modern port of the game, as both parse the map data in the same way.
5+
6+
![](images/screenshot.png)
7+
8+
## Features
9+
* Load and explore projects for CCSR Episodes 1, 2, 3, 4, and Scooby Doo Hollywood Horror 1 & 2.
10+
* Create and edit projects
11+
* Create and edit maps
12+
* Create and edit map objects, game events, and collision
13+
* View collision maps
14+
* View a flowchart of game events
15+
* Export screenshots of the game world
16+
* Manage texture images
17+
18+
## Development
19+
20+
Contributions are welcome, and encouraged. Feel free to open a PR for a feature, improvement, or bug fix.
21+
22+
The map editor is built with [TypeScript](https://www.typescriptlang.org/),
23+
[React](https://react.dev/),
24+
[Mantine](https://mantine.dev/),
25+
[pixi.js](https://pixijs.com/) for 2D rendering,
26+
and [Cytoscape.js](https://js.cytoscape.org/) for rendering the directed acyclic event graph.
27+
28+
It makes heavy use of the [immer](https://immerjs.github.io/immer/) library to easily produce edited copies of immutable state, instead of having to use spread syntax a billion times in deeply nested objects to create copies of state.
29+
30+
Setting up a development should be as easy as cloning this repo, and then running `npm install` and `npm run dev`.

map-o-matic-v2/eslint.config.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import js from '@eslint/js'
2+
import globals from 'globals'
3+
import reactHooks from 'eslint-plugin-react-hooks'
4+
import reactRefresh from 'eslint-plugin-react-refresh'
5+
import tseslint from 'typescript-eslint'
6+
7+
export default tseslint.config(
8+
{ ignores: ['dist'] },
9+
{
10+
extends: [js.configs.recommended, ...tseslint.configs.recommended],
11+
files: ['**/*.{ts,tsx}'],
12+
languageOptions: {
13+
ecmaVersion: 2020,
14+
globals: globals.browser,
15+
},
16+
plugins: {
17+
'react-hooks': reactHooks,
18+
'react-refresh': reactRefresh,
19+
},
20+
rules: {
21+
...reactHooks.configs.recommended.rules,
22+
'react-refresh/only-export-components': [
23+
'warn',
24+
{ allowConstantExport: true },
25+
],
26+
},
27+
},
28+
)

map-o-matic-v2/images/screenshot.png

480 KB
Loading

map-o-matic-v2/index.html

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!doctype html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8" />
6+
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
8+
<title>Map-O-Matic v2</title>
9+
</head>
10+
11+
<body>
12+
<div id="root"></div>
13+
<script type="module" src="/src/main.tsx"></script>
14+
</body>
15+
16+
</html>

map-o-matic-v2/jest.config.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/** @type {import('ts-jest').JestConfigWithTsJest} **/
2+
export default {
3+
testEnvironment: "node",
4+
transform: {
5+
"^.+.tsx?$": ["ts-jest",{}],
6+
},
7+
};

0 commit comments

Comments
 (0)