arcade-ai 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -28
- package/SKILL.md +17 -2
- package/package.json +1 -1
- package/reference/arcade-api.md +19 -0
- package/src/cli.js +4 -3
- package/src/commands/init.js +13 -2
- package/src/studio/server.js +34 -1
- package/src/template/blank/game/README.md +1 -0
- package/src/template/flappy/game/README.md +1 -0
- package/src/template/flappy/game/assets.json +0 -0
- package/src/template/flappy/game/images.g.jres +18 -0
- package/src/template/flappy/game/images.g.ts +160 -0
- package/src/template/flappy/game/main.ts +61 -0
- package/src/template/flappy/game/pxt.json +18 -0
- package/src/template/platformer/game/README.md +1 -0
- package/src/template/platformer/game/assets.json +1 -0
- package/src/template/platformer/game/images.g.jres +18 -0
- package/src/template/platformer/game/images.g.ts +74 -0
- package/src/template/platformer/game/main.ts +141 -0
- package/src/template/platformer/game/pxt.json +21 -0
- package/src/template/platformer/game/tilemap.g.jres +71 -0
- package/src/template/platformer/game/tilemap.g.ts +197 -0
- package/src/template/game/README.md +0 -2
- /package/src/template/{game → blank/game}/assets.json +0 -0
- /package/src/template/{game → blank/game}/main.ts +0 -0
- /package/src/template/{game → blank/game}/pxt.json +0 -0
package/README.md
CHANGED
|
@@ -1,30 +1,154 @@
|
|
|
1
1
|
# arcade-ai
|
|
2
2
|
|
|
3
|
-
AI-driven scaffold and live studio for Microsoft MakeCode Arcade games.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
##
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
3
|
+
AI-driven scaffold and live studio for Microsoft MakeCode Arcade games. It ships as:
|
|
4
|
+
|
|
5
|
+
- a reusable skill (`SKILL.md` + `reference/`) that tells an AI agent how to build Arcade games safely;
|
|
6
|
+
- an npm CLI (`aca`) that creates projects, runs a local live studio, and checks the MakeCode editor protocol.
|
|
7
|
+
|
|
8
|
+
## What It Does
|
|
9
|
+
|
|
10
|
+
- Generates a pure TypeScript MakeCode Arcade project.
|
|
11
|
+
- Adds the right AI rule file for your tool: `CLAUDE.md`, `.trae/project_rules.md`, or `AGENTS.md`.
|
|
12
|
+
- Starts a local studio that embeds the official MakeCode Arcade editor.
|
|
13
|
+
- Keeps `game/main.ts` and Arcade resource files synchronized with the editor.
|
|
14
|
+
- Provides an offline reference for Arcade APIs, limits, project format, and known pitfalls.
|
|
15
|
+
|
|
16
|
+
## Install The CLI
|
|
17
|
+
|
|
18
|
+
Use it directly with `npx`:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx arcade-ai init my-game --tool agents
|
|
22
|
+
cd my-game
|
|
23
|
+
npx aca dev
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
If the npm package has not been published yet, run it from GitHub:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npx --yes github:guolin/arcade-ai init my-game --tool agents
|
|
30
|
+
cd my-game
|
|
31
|
+
npx --yes github:guolin/arcade-ai dev
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Or install it in a project:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install -D arcade-ai
|
|
38
|
+
npx aca init my-game --tool claude
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Commands
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
aca init [dir] [--tool claude|trae|agents]
|
|
45
|
+
aca dev [--port 8080]
|
|
46
|
+
aca check [--url <makecode-url>]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- `aca init` creates the Arcade project, copies `reference/`, and writes the tool-specific rule file.
|
|
50
|
+
- `aca dev` runs the local studio with live preview and editor-to-disk synchronization.
|
|
51
|
+
- `aca check` verifies the MakeCode editor handshake and rendering path. This needs network access and Puppeteer.
|
|
52
|
+
|
|
53
|
+
## Install The Skill
|
|
54
|
+
|
|
55
|
+
The skill is the repo root: `SKILL.md` plus the `reference/` directory. Keep those together when installing.
|
|
56
|
+
|
|
57
|
+
### Workbudy
|
|
58
|
+
|
|
59
|
+
Workbudy should start from the dedicated guide, not only the repository homepage:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
https://github.com/guolin/arcade-ai/blob/main/WORKBUDDY.md
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
That page points Workbudy to the raw `SKILL.md` and every file under `reference/`. It also gives a prompt you can paste directly into Workbudy.
|
|
66
|
+
|
|
67
|
+
Until the npm package is published, create projects from GitHub:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npx --yes github:guolin/arcade-ai init my-game --tool agents
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
After npm publishing, this shorter command is equivalent:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npx arcade-ai init my-game --tool agents
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then make sure Workbudy reads:
|
|
80
|
+
|
|
81
|
+
- `my-game/AGENTS.md`
|
|
82
|
+
- `my-game/reference/`
|
|
83
|
+
|
|
84
|
+
In Workbudy prompts, ask it to follow `AGENTS.md` and use `reference/` before writing Arcade APIs it is unsure about. Run the studio with:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
cd my-game
|
|
88
|
+
npx aca dev
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Codex
|
|
92
|
+
|
|
93
|
+
For Codex, install the skill into your Codex skills directory:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
mkdir -p ~/.codex/skills
|
|
97
|
+
git clone <this-repo-url> ~/.codex/skills/arcade-ai
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Restart Codex after installation so it can discover the new skill. To create a project with Codex-friendly rules:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npx arcade-ai init my-game --tool agents
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Codex should then read `AGENTS.md` in the generated project and use the installed `arcade-ai` skill whenever you ask it to build or modify a MakeCode Arcade game.
|
|
107
|
+
|
|
108
|
+
### Claude Code
|
|
109
|
+
|
|
110
|
+
Use the Claude Code plugin marketplace when this repo is published as a plugin:
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
/plugin marketplace
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Search for `arcade-ai`, install it, then restart or open a new Claude Code session if prompted.
|
|
117
|
+
|
|
118
|
+
For a manual local install, copy or clone this repo as a skill:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
mkdir -p ~/.claude/skills
|
|
122
|
+
git clone <this-repo-url> ~/.claude/skills/arcade-ai
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Create Claude-specific project rules with:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npx arcade-ai init my-game --tool claude
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Claude Code will use `CLAUDE.md` in the generated project plus the installed `arcade-ai` skill.
|
|
132
|
+
|
|
133
|
+
## Typical Workflow
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npx arcade-ai init space-runner --tool claude
|
|
137
|
+
cd space-runner
|
|
138
|
+
npx aca dev
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Then ask your AI agent to edit `game/main.ts`. Keep the studio open while the agent works; preview refreshes automatically.
|
|
142
|
+
|
|
143
|
+
## Rules For AI Agents
|
|
144
|
+
|
|
145
|
+
- Only write game code in `game/main.ts`.
|
|
146
|
+
- Store resources in `game/assets.json`; do not inline large art assets into JavaScript.
|
|
147
|
+
- Keep the project TypeScript-only: do not add `main.blocks`.
|
|
148
|
+
- Use named tilemaps or built-in tiles for maps.
|
|
149
|
+
- Read `reference/arcade-api.md`, `reference/limits.md`, and `reference/pitfalls.md` when unsure.
|
|
150
|
+
- Do not invent MakeCode Arcade APIs.
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
MIT
|
package/SKILL.md
CHANGED
|
@@ -12,12 +12,27 @@ description: Use when building or modifying a Microsoft MakeCode Arcade game —
|
|
|
12
12
|
- 用户想做 / 改 arcade 游戏、像素小游戏、makecode 游戏时。
|
|
13
13
|
|
|
14
14
|
## 怎么用(三个命令)
|
|
15
|
-
1. 起项目:`npx arcade-ai init <dir> [--tool claude|trae|agents]`
|
|
16
|
-
|
|
15
|
+
1. 起项目:`npx arcade-ai init <dir> [--template blank|platformer|flappy] [--tool claude|trae|agents]`
|
|
16
|
+
|
|
17
|
+
**执行 init 前,先问用户想做哪种游戏,根据回答选模板:**
|
|
18
|
+
- `--template blank`(**默认**):空白项目,只有最简单的精灵和地图引用,适合从零开始。
|
|
19
|
+
- `--template platformer`:横版平台跳跃,含地图、敌人、重力跳跃,推荐有明确玩法时选。
|
|
20
|
+
- `--template flappy`:Flappy Bird 风格,管道障碍 + 重力下坠,推荐单一机制练习。
|
|
21
|
+
|
|
22
|
+
生成纯 TS 脚手架,并把规则文件与 `reference/` 一并拷进项目。
|
|
17
23
|
2. 起 studio:在项目目录 `npx aca dev` —— 浏览器实时预览,AI 改 `game/main.ts` 自动刷新;
|
|
18
24
|
在编辑器里改代码/画精灵也会回写磁盘(双向)。
|
|
19
25
|
3. 协议自检:`npx aca check` —— 验证官方编辑器握手 + 代码真渲染(联网,需 puppeteer)。
|
|
20
26
|
|
|
27
|
+
## 接手项目时必须先读文档
|
|
28
|
+
拿到一个 arcade 项目(或准备写代码)时,**第一步读以下文件,不要跳过**:
|
|
29
|
+
- `reference/arcade-api.md` —— 有哪些 API、怎么用
|
|
30
|
+
- `reference/pitfalls.md` —— 哪些写法会翻车(踩坑成本极高)
|
|
31
|
+
- `reference/limits.md` —— 内存/尺寸/功能硬限制
|
|
32
|
+
- `reference/project-format.md` —— 文件格式约定(pxt.json / assets.json)
|
|
33
|
+
|
|
34
|
+
读完再动手,遇到不确认的 API 回来查,不要靠记忆臆造。
|
|
35
|
+
|
|
21
36
|
## 写代码硬约束(违反会翻车)
|
|
22
37
|
- 代码只写 `game/main.ts`;资源(精灵/地图,4-bit 16 色)走 `game/assets.json`,不内联大图到 JS。
|
|
23
38
|
- **纯 TS 项目**:`game/` 里不要 `main.blocks`,`pxt.json` 的 `files` 也不列它,
|
package/package.json
CHANGED
package/reference/arcade-api.md
CHANGED
|
@@ -85,6 +85,8 @@
|
|
|
85
85
|
## 6. 游戏信息 (Info)
|
|
86
86
|
处理分数、生命值和计时器。
|
|
87
87
|
|
|
88
|
+
> **重要**:以下 API 调用后,Arcade HUD 会**自动在屏幕角落渲染分数、心形血条、倒计时**,无需写任何显示代码。不要用 `game.showLongText` 或自定义 sprite 手搓 UI——那是重复造轮子。
|
|
89
|
+
|
|
88
90
|
- **设置/修改分数**:
|
|
89
91
|
`info.setScore(0)`
|
|
90
92
|
`info.changeScoreBy(10)`
|
|
@@ -95,6 +97,23 @@
|
|
|
95
97
|
`info.startCountdown(30)` (30秒)
|
|
96
98
|
`info.onCountdownEnd(function() { game.over(false) })`
|
|
97
99
|
|
|
100
|
+
## 6b. 持久化存储与历史最高分 (Settings)
|
|
101
|
+
MakeCode Arcade 提供 `settings` 命名空间,数据持久化到设备 flash(浏览器模拟器对应 localStorage)。
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// 历史最高分示例
|
|
105
|
+
const best = settings.readNumber("highScore") || 0;
|
|
106
|
+
if (info.score() > best) {
|
|
107
|
+
settings.writeNumber("highScore", info.score());
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- `settings.writeNumber(key, value)` / `settings.readNumber(key)`
|
|
112
|
+
- `settings.writeString(key, value)` / `settings.readString(key)`
|
|
113
|
+
- `settings.exists(key)` / `settings.remove(key)`
|
|
114
|
+
|
|
115
|
+
> **没有内置排行榜 UI**:`settings` 只是 key-value 存储,多名玩家排行榜需要自己用 sprite/text 实现显示逻辑。
|
|
116
|
+
|
|
98
117
|
## 7. 地图 Tilemap(两条可靠路线,外加一个会崩的禁区)
|
|
99
118
|
|
|
100
119
|
> ⚠️ **禁区**:`tiles.createTilemap(hex`...`, img`...`, [内联 img tile], ...)` —— **把内联 `img` 当图块会让官方编辑器崩溃**(Oops 重载循环)。编辑器的 tilemap 解析器只接受“命名图块资源”,不接受随手写的内联 img。已实测确认。详见 pitfalls 坑5。
|
package/src/cli.js
CHANGED
|
@@ -9,6 +9,7 @@ export function parseArgs(argv) {
|
|
|
9
9
|
strict: false,
|
|
10
10
|
options: {
|
|
11
11
|
tool: { type: 'string' },
|
|
12
|
+
template: { type: 'string' },
|
|
12
13
|
port: { type: 'string' },
|
|
13
14
|
url: { type: 'string' },
|
|
14
15
|
},
|
|
@@ -19,9 +20,9 @@ export function parseArgs(argv) {
|
|
|
19
20
|
|
|
20
21
|
const HELP = `arcade-ai (aca)
|
|
21
22
|
用法:
|
|
22
|
-
aca init [dir] [--tool claude|trae|agents]
|
|
23
|
-
aca dev [--port 8080]
|
|
24
|
-
aca check [--url <makecode-url>]
|
|
23
|
+
aca init [dir] [--template blank|platformer|flappy] [--tool claude|trae|agents] 起脚手架(默认: blank)
|
|
24
|
+
aca dev [--port 8080] 起本地 studio
|
|
25
|
+
aca check [--url <makecode-url>] 自检 postMessage 协议`;
|
|
25
26
|
|
|
26
27
|
export async function run(argv) {
|
|
27
28
|
const { command, positionals, options } = parseArgs(argv);
|
package/src/commands/init.js
CHANGED
|
@@ -21,14 +21,25 @@ function writeRules(dest, tool) {
|
|
|
21
21
|
writeFileSync(target, content, 'utf8');
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
const TEMPLATES = ['platformer', 'flappy', 'blank'];
|
|
25
|
+
const DEFAULT_TEMPLATE = 'blank';
|
|
26
|
+
|
|
24
27
|
export default async function init(ctx) {
|
|
25
28
|
const dest = ctx.positionals[0] || 'arcade-game';
|
|
29
|
+
const tpl = ctx.options.template || DEFAULT_TEMPLATE;
|
|
30
|
+
|
|
31
|
+
if (!TEMPLATES.includes(tpl)) {
|
|
32
|
+
console.error(`未知模板: ${tpl},可选: ${TEMPLATES.join(', ')}`);
|
|
33
|
+
return 1;
|
|
34
|
+
}
|
|
35
|
+
|
|
26
36
|
mkdirSync(dest, { recursive: true });
|
|
27
|
-
|
|
37
|
+
// 每个模板是完整的 game/ 目录,直接拷贝
|
|
38
|
+
cpSync(join(templateDir, tpl, 'game'), join(dest, 'game'), { recursive: true });
|
|
28
39
|
copyFileSync(join(templateDir, 'package.json'), join(dest, 'package.json'));
|
|
29
40
|
// 把知识库拷进项目,使其自包含、跨工具可查(Trae/其它 AI 裸读项目也能用)
|
|
30
41
|
cpSync(referenceDir, join(dest, 'reference'), { recursive: true });
|
|
31
42
|
writeRules(dest, ctx.options.tool);
|
|
32
|
-
console.log(`✅ 已创建 ${dest}
|
|
43
|
+
console.log(`✅ 已创建 ${dest}(模板: ${tpl})\n cd ${dest} && npx aca dev`);
|
|
33
44
|
return 0;
|
|
34
45
|
}
|
package/src/studio/server.js
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import { createServer } from 'node:http';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
2
3
|
import { readFileSync } from 'node:fs';
|
|
3
4
|
import { readProject, writeProject } from '../project-io.js';
|
|
4
5
|
import { createWatcher } from './watcher.js';
|
|
5
6
|
|
|
7
|
+
function hashFiles(files) {
|
|
8
|
+
const h = createHash('sha1');
|
|
9
|
+
for (const k of Object.keys(files).sort()) h.update(k + '\0' + (files[k] ?? ''));
|
|
10
|
+
return h.digest('hex');
|
|
11
|
+
}
|
|
12
|
+
|
|
6
13
|
export function startStudio({ gameDir, port = 0, hostHtmlPath }) {
|
|
7
14
|
const clients = new Set();
|
|
15
|
+
let lastAiWriteAt = 0; // AI 写盘时刻
|
|
16
|
+
let lastPushedHash = ''; // 最后一次推给编辑器的内容 hash
|
|
17
|
+
|
|
8
18
|
const watcher = createWatcher(gameDir, () => {
|
|
19
|
+
lastAiWriteAt = Date.now();
|
|
9
20
|
for (const res of clients) res.write('data: changed\n\n');
|
|
10
21
|
});
|
|
11
22
|
|
|
@@ -15,16 +26,38 @@ export function startStudio({ gameDir, port = 0, hostHtmlPath }) {
|
|
|
15
26
|
res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
|
|
16
27
|
res.end(readFileSync(hostHtmlPath));
|
|
17
28
|
} else if (req.method === 'GET' && url === '/api/project') {
|
|
29
|
+
const files = readProject(gameDir);
|
|
30
|
+
lastPushedHash = hashFiles(files);
|
|
18
31
|
res.writeHead(200, { 'content-type': 'application/json' });
|
|
19
|
-
res.end(JSON.stringify({ files
|
|
32
|
+
res.end(JSON.stringify({ files }));
|
|
20
33
|
} else if (req.method === 'POST' && url === '/api/save') {
|
|
21
34
|
let body = '';
|
|
22
35
|
req.on('data', (c) => (body += c));
|
|
23
36
|
req.on('end', () => {
|
|
24
37
|
try {
|
|
25
38
|
const { files } = JSON.parse(body || '{}');
|
|
39
|
+
|
|
40
|
+
// 时间层:AI 写盘后 2 秒内的 save 是旧 iframe 临死前的遗留,丢弃
|
|
41
|
+
const msSinceAiWrite = Date.now() - lastAiWriteAt;
|
|
42
|
+
if (lastAiWriteAt > 0 && msSinceAiWrite < 2000) {
|
|
43
|
+
console.log(`[save] 忽略(AI 写盘后 ${msSinceAiWrite}ms,旧 iframe 遗留)`);
|
|
44
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
45
|
+
res.end(JSON.stringify({ success: true }));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 内容层:编辑器把我们推出去的内容原样还回来(echo),跳过落盘
|
|
50
|
+
const incomingHash = hashFiles(files || {});
|
|
51
|
+
if (incomingHash === lastPushedHash) {
|
|
52
|
+
console.log('[save] 忽略(内容与上次推送一致,echo)');
|
|
53
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
54
|
+
res.end(JSON.stringify({ success: true }));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
26
58
|
watcher.pause(600);
|
|
27
59
|
const written = writeProject(gameDir, files);
|
|
60
|
+
lastPushedHash = incomingHash;
|
|
28
61
|
const incoming = Object.keys(files || {});
|
|
29
62
|
const dropped = incoming.filter((f) => !written.includes(f));
|
|
30
63
|
console.log(`[save] 收到 ${incoming.length} 文件,落盘 ${written.length}`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Blank Game
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Flappy Bird Game
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"myImages.image1": {
|
|
3
|
+
"id": "myImages.image1",
|
|
4
|
+
"data": "hwQQABAAAAAAAAAAu8sMAAAAAAC93csAAAAAAN3c3QwAAAAAXcXdywAAsLtb1dzNAAC7VVtV3M0AsFtVvVXbzQCw1dFVvdXNALAV/1VVVc2wu/W/RVVVxVu8VdVEVVXFtbBV3URVVbULANtERFVVuwAA8ExEW9ULAAAAALSwuwAAAAAACwAAAA==",
|
|
5
|
+
"dataEncoding": "base64",
|
|
6
|
+
"namespace": "myImages.",
|
|
7
|
+
"mimeType": "image/x-mkcd-f4",
|
|
8
|
+
"displayName": "playerImage"
|
|
9
|
+
},
|
|
10
|
+
"anim1": {
|
|
11
|
+
"id": "anim1",
|
|
12
|
+
"data": "YzgwMDEwMDAxMDAwMDYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBiMDU1MGIwMDAwMDAwMGJiYmJiYjAwMDAwMDAwYjA1YjU1NTUwYjAwYjBiYmJiNTU1NTU1YjUwMGIwNWQ1YjU1NTU1NWI1MDAwMDViYjVkNWYxZDVmNDAwMDBkYjU1MWJmZjQ1YzQwMGJiYmQ1NWQ1YmY0NDQ0MGJkYmNkNWRiNTQ1NDQ0NGI0ZGNkZGNjNWI1NTU1NTUwYmJjZGRkZDVkNTU1NTU1MGJjMGRkZGRkZDU1NTVkNTBiMDBiY2RkZGQ1ZDU1YmIwMDAwYzBjY2NjY2NiYzBiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDViMGIwMDAwMDAwMDAwYjBiNTAwMDAwMDAwMDBiYmJiYmIwMDAwMDAwMGIwNWI1NTU1MGIwMGIwYmJiYjU1NTU1NWI1MDBiMDVkNWI1NTU1NTViNTAwMDA1YmI1ZDVmMWQ1ZjQwMDAwZGI1NTFiZmY0NWM0MDBiYmJkNTVkNWJmNDQ0NGI0ZGJjZDVkYjU0NTQ0NDQwYmRjZGRjYzViNTU1NTU1MGJiY2RkZGQ1ZDU1NTU1NTBiYzBkZGRkZGQ1NTU1ZDUwYjAwYmNkZGRkNWQ1NWJiMDAwMGMwY2NjY2NjYmMwYjAwMDAwMDAwMDAwMDViMGIwMDAwMDAwMDAwYjBiNTAwMDAwMDAwMDAwMGIwMGMwMDAwMDAwMDAwYmJiYmJiMDAwMDAwMDBiMDViNTU1NTBiMDAwMDAwYmJkNWYxNTVmZDAwMDAwMDViMTVmZmQ1YzQwMDAwMDA1YmQ1YmZkZDQ0MDBkYmRkYmI1ZDU1NDQ0NGI0YmI1ZDU1NWI0NTQ0NDQwYmRiNWM1NWQ1NTU1NWI1MDBkY2NkNWRiNTU1NTU1NTBiYmNkZGNjNWI1NTU1NTUwYmMwZGRkZGRkNTU1NWQ1MGIwMGJjZGRkZDVkNTViYjAwMDBjMGNjY2NjY2JjMGIwMDAwMDAwMDAwMDA1YjBiMDAwMDAwMDAwMGIwYjUwMDAwMDAwMDAwYmJiYmJiMDAwMDAwMDBiMDViNTU1NTBiMDAwMDAwYmJkNWYxZDVjNDAwMDAwMDViMTVmZmRkNDRiNDAwMDA1YmQ1YmY0NDQ0MGIwMGIwNWQ1NTQ1NDRiNDAwMDBkYjVkNTU1NTU1YjUwMGIwZGRkZDU1NTU1NTU1MGJkYmRkYmI1YjU1NTU1NTBiZGNiZDU1Y2Q1NTU1NTUwYmJjZGJkNWRjNTU1NTU1MGJiMDU1Y2JkZDU1NTVkNTBiYmJjY2RjZGQ1ZDU1YmIwMDAwYzBjY2NjY2NiYzBiMDAwMDAwMDAwMDAwNWIwYjAwMDAwMDAwMDBiMGI1MDAwMDAwMDAwMGJiYmJiYjAwMDAwMDAwYjA1YjU1NTUwYjAwMDAwMGJiZDVmMWQ1YzQwMDAwMDA1YjE1ZmZkZDQ0YjQwMDAwNWJkNWJmNDQ0NDBiMDBiMDVkNTU0NTQ0YjQwMGIwZGJkZDU1NTU1NWI1MDBkYmRkYmI1YjU1NTU1NTBiZGNiZDU1Y2Q1NTU1NTUwYmJjZGJkNWRjNTU1NTU1MGJiYzU1Y2JkZDU1NTU1NTBiYmJjY2RjZGQ1NTU1ZDUwYjAwMDBjY2RkNWQ1NWJiMDAwMDAwMDBjY2NjYmMwYjAwMDAwMDAwMDAwMDViMGIwMDAwMDAwMDAwYjBiNTAwMDAwMDAwMDBiYmJiYmIwMDAwMDAwMGIwNWI1NTU1MGIwMDAwMDBiYmQ1ZjE1NWZkMDAwMDAwNWIxNWZmZDVjNDAwMDAwMDViZDViZmRkNDQwMGIwYmI1ZDU1NTU0NDQ0YjRkYmRkYmI1ZDQ1NDQ0NDBiYmI1ZDU1NWI1NTU1YjUwMGRjNWM1NWQ1NTU1NTU1MGJiY2NkNWRiNTU1NTU1NTBiYzBkZGNjZGI1NTU1ZDUwYjAwYmNkZGRkNWQ1NWJiMDAwMGMwY2NjY2NjYmMwYjAwMDAwMDAwMDAwMDAwMDAwMA==",
|
|
13
|
+
"dataEncoding": "base64",
|
|
14
|
+
"namespace": "myAnimations.",
|
|
15
|
+
"mimeType": "application/mkcd-animation",
|
|
16
|
+
"displayName": "playerAnimation"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// Auto-generated code. Do not edit.
|
|
2
|
+
namespace myImages {
|
|
3
|
+
|
|
4
|
+
helpers._registerFactory("image", function(name: string) {
|
|
5
|
+
switch(helpers.stringTrim(name)) {
|
|
6
|
+
case "image1":
|
|
7
|
+
case "playerImage":return img`
|
|
8
|
+
. . . . . . . . . . b 5 b . . .
|
|
9
|
+
. . . . . . . . . b 5 b . . . .
|
|
10
|
+
. . . . . . . . . b c . . . . .
|
|
11
|
+
. . . . . . b b b b b b . . . .
|
|
12
|
+
. . . . . b b 5 5 5 5 5 b . . .
|
|
13
|
+
. . . . b b 5 d 1 f 5 5 d f . .
|
|
14
|
+
. . . . b 5 5 1 f f 5 d 4 c . .
|
|
15
|
+
. . . . b 5 5 d f b d d 4 4 . .
|
|
16
|
+
b d d d b b d 5 5 5 4 4 4 4 4 b
|
|
17
|
+
b b d 5 5 5 b 5 5 4 4 4 4 4 b .
|
|
18
|
+
b d c 5 5 5 5 d 5 5 5 5 5 b . .
|
|
19
|
+
c d d c d 5 5 b 5 5 5 5 5 5 b .
|
|
20
|
+
c b d d c c b 5 5 5 5 5 5 5 b .
|
|
21
|
+
. c d d d d d d 5 5 5 5 5 d b .
|
|
22
|
+
. . c b d d d d d 5 5 5 b b . .
|
|
23
|
+
. . . c c c c c c c c b b . . .
|
|
24
|
+
`;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
helpers._registerFactory("animation", function(name: string) {
|
|
30
|
+
switch(helpers.stringTrim(name)) {
|
|
31
|
+
case "playerAnimation":
|
|
32
|
+
case "anim1":return [img`
|
|
33
|
+
. . . . . . . . . . . . . . . .
|
|
34
|
+
. . . . . . . . . . . . . . . .
|
|
35
|
+
. . . . . . . . . b 5 5 b . . .
|
|
36
|
+
. . . . . . b b b b b b . . . .
|
|
37
|
+
. . . . . b b 5 5 5 5 5 b . . .
|
|
38
|
+
. b b b b b 5 5 5 5 5 5 5 b . .
|
|
39
|
+
. b d 5 b 5 5 5 5 5 5 5 5 b . .
|
|
40
|
+
. . b 5 5 b 5 d 1 f 5 d 4 f . .
|
|
41
|
+
. . b d 5 5 b 1 f f 5 4 4 c . .
|
|
42
|
+
b b d b 5 5 5 d f b 4 4 4 4 b .
|
|
43
|
+
b d d c d 5 5 b 5 4 4 4 4 4 4 b
|
|
44
|
+
c d d d c c b 5 5 5 5 5 5 5 b .
|
|
45
|
+
c b d d d d d 5 5 5 5 5 5 5 b .
|
|
46
|
+
. c d d d d d d 5 5 5 5 5 d b .
|
|
47
|
+
. . c b d d d d d 5 5 5 b b . .
|
|
48
|
+
. . . c c c c c c c c b b . . .
|
|
49
|
+
`, img`
|
|
50
|
+
. . . . . . . . . . . . . . . .
|
|
51
|
+
. . . . . . . . . . b 5 b . . .
|
|
52
|
+
. . . . . . . . . b 5 b . . . .
|
|
53
|
+
. . . . . . b b b b b b . . . .
|
|
54
|
+
. . . . . b b 5 5 5 5 5 b . . .
|
|
55
|
+
. b b b b b 5 5 5 5 5 5 5 b . .
|
|
56
|
+
. b d 5 b 5 5 5 5 5 5 5 5 b . .
|
|
57
|
+
. . b 5 5 b 5 d 1 f 5 d 4 f . .
|
|
58
|
+
. . b d 5 5 b 1 f f 5 4 4 c . .
|
|
59
|
+
b b d b 5 5 5 d f b 4 4 4 4 4 b
|
|
60
|
+
b d d c d 5 5 b 5 4 4 4 4 4 b .
|
|
61
|
+
c d d d c c b 5 5 5 5 5 5 5 b .
|
|
62
|
+
c b d d d d d 5 5 5 5 5 5 5 b .
|
|
63
|
+
. c d d d d d d 5 5 5 5 5 d b .
|
|
64
|
+
. . c b d d d d d 5 5 5 b b . .
|
|
65
|
+
. . . c c c c c c c c b b . . .
|
|
66
|
+
`, img`
|
|
67
|
+
. . . . . . . . . . b 5 b . . .
|
|
68
|
+
. . . . . . . . . b 5 b . . . .
|
|
69
|
+
. . . . . . . . . b c . . . . .
|
|
70
|
+
. . . . . . b b b b b b . . . .
|
|
71
|
+
. . . . . b b 5 5 5 5 5 b . . .
|
|
72
|
+
. . . . b b 5 d 1 f 5 5 d f . .
|
|
73
|
+
. . . . b 5 5 1 f f 5 d 4 c . .
|
|
74
|
+
. . . . b 5 5 d f b d d 4 4 . .
|
|
75
|
+
b d d d b b d 5 5 5 4 4 4 4 4 b
|
|
76
|
+
b b d 5 5 5 b 5 5 4 4 4 4 4 b .
|
|
77
|
+
b d c 5 5 5 5 d 5 5 5 5 5 b . .
|
|
78
|
+
c d d c d 5 5 b 5 5 5 5 5 5 b .
|
|
79
|
+
c b d d c c b 5 5 5 5 5 5 5 b .
|
|
80
|
+
. c d d d d d d 5 5 5 5 5 d b .
|
|
81
|
+
. . c b d d d d d 5 5 5 b b . .
|
|
82
|
+
. . . c c c c c c c c b b . . .
|
|
83
|
+
`, img`
|
|
84
|
+
. . . . . . . . . . b 5 b . . .
|
|
85
|
+
. . . . . . . . . b 5 b . . . .
|
|
86
|
+
. . . . . . b b b b b b . . . .
|
|
87
|
+
. . . . . b b 5 5 5 5 5 b . . .
|
|
88
|
+
. . . . b b 5 d 1 f 5 d 4 c . .
|
|
89
|
+
. . . . b 5 5 1 f f d d 4 4 4 b
|
|
90
|
+
. . . . b 5 5 d f b 4 4 4 4 b .
|
|
91
|
+
. . . b d 5 5 5 5 4 4 4 4 b . .
|
|
92
|
+
. . b d d 5 5 5 5 5 5 5 5 b . .
|
|
93
|
+
. b d d d d 5 5 5 5 5 5 5 5 b .
|
|
94
|
+
b d d d b b b 5 5 5 5 5 5 5 b .
|
|
95
|
+
c d d b 5 5 d c 5 5 5 5 5 5 b .
|
|
96
|
+
c b b d 5 d c d 5 5 5 5 5 5 b .
|
|
97
|
+
. b 5 5 b c d d 5 5 5 5 5 d b .
|
|
98
|
+
b b c c c d d d d 5 5 5 b b . .
|
|
99
|
+
. . . c c c c c c c c b b . . .
|
|
100
|
+
`, img`
|
|
101
|
+
. . . . . . . . . . b 5 b . . .
|
|
102
|
+
. . . . . . . . . b 5 b . . . .
|
|
103
|
+
. . . . . . b b b b b b . . . .
|
|
104
|
+
. . . . . b b 5 5 5 5 5 b . . .
|
|
105
|
+
. . . . b b 5 d 1 f 5 d 4 c . .
|
|
106
|
+
. . . . b 5 5 1 f f d d 4 4 4 b
|
|
107
|
+
. . . . b 5 5 d f b 4 4 4 4 b .
|
|
108
|
+
. . . b d 5 5 5 5 4 4 4 4 b . .
|
|
109
|
+
. b b d d d 5 5 5 5 5 5 5 b . .
|
|
110
|
+
b d d d b b b 5 5 5 5 5 5 5 b .
|
|
111
|
+
c d d b 5 5 d c 5 5 5 5 5 5 b .
|
|
112
|
+
c b b d 5 d c d 5 5 5 5 5 5 b .
|
|
113
|
+
c b 5 5 b c d d 5 5 5 5 5 5 b .
|
|
114
|
+
b b c c c d d d 5 5 5 5 5 d b .
|
|
115
|
+
. . . . c c d d d 5 5 5 b b . .
|
|
116
|
+
. . . . . . c c c c c b b . . .
|
|
117
|
+
`, img`
|
|
118
|
+
. . . . . . . . . . b 5 b . . .
|
|
119
|
+
. . . . . . . . . b 5 b . . . .
|
|
120
|
+
. . . . . . b b b b b b . . . .
|
|
121
|
+
. . . . . b b 5 5 5 5 5 b . . .
|
|
122
|
+
. . . . b b 5 d 1 f 5 5 d f . .
|
|
123
|
+
. . . . b 5 5 1 f f 5 d 4 c . .
|
|
124
|
+
. . . . b 5 5 d f b d d 4 4 . .
|
|
125
|
+
. b b b d 5 5 5 5 5 4 4 4 4 4 b
|
|
126
|
+
b d d d b b d 5 5 4 4 4 4 4 b .
|
|
127
|
+
b b d 5 5 5 b 5 5 5 5 5 5 b . .
|
|
128
|
+
c d c 5 5 5 5 d 5 5 5 5 5 5 b .
|
|
129
|
+
c b d c d 5 5 b 5 5 5 5 5 5 b .
|
|
130
|
+
. c d d c c b d 5 5 5 5 5 d b .
|
|
131
|
+
. . c b d d d d d 5 5 5 b b . .
|
|
132
|
+
. . . c c c c c c c c b b . . .
|
|
133
|
+
. . . . . . . . . . . . . . . .
|
|
134
|
+
`];
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
helpers._registerFactory("song", function(name: string) {
|
|
140
|
+
switch(helpers.stringTrim(name)) {
|
|
141
|
+
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
helpers._registerFactory("json", function(name: string) {
|
|
147
|
+
switch(helpers.stringTrim(name)) {
|
|
148
|
+
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
}
|
|
154
|
+
// Auto-generated code. Do not edit.
|
|
155
|
+
|
|
156
|
+
// Auto-generated code. Do not edit.
|
|
157
|
+
namespace myTiles {
|
|
158
|
+
|
|
159
|
+
}
|
|
160
|
+
// Auto-generated code. Do not edit.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Use SpriteKind.create() to create a unique kind for each Sprite
|
|
2
|
+
const GateKind = SpriteKind.create();
|
|
3
|
+
const PlayerKind = SpriteKind.create();
|
|
4
|
+
|
|
5
|
+
scene.setBackgroundColor(9);
|
|
6
|
+
showControls();
|
|
7
|
+
startGame();
|
|
8
|
+
|
|
9
|
+
function showControls() {
|
|
10
|
+
// showLongText automatically pauses until A is pressed
|
|
11
|
+
game.showLongText("Press A to jump\n \nTry to avoid the gates!", DialogLayout.Center);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function startGame() {
|
|
15
|
+
// Create the player sprite using the "playerImage" asset
|
|
16
|
+
const mySprite = sprites.create(assets.image`playerImage`, PlayerKind);
|
|
17
|
+
mySprite.left = 4;
|
|
18
|
+
mySprite.setFlag(SpriteFlag.StayInScreen, true);
|
|
19
|
+
mySprite.ay = 500;
|
|
20
|
+
|
|
21
|
+
// When A is pressed, make the player sprite jump and play a flapping animation
|
|
22
|
+
controller.A.onEvent(ControllerButtonEvent.Pressed, () => {
|
|
23
|
+
mySprite.vy = -100;
|
|
24
|
+
animation.runImageAnimation(mySprite, assets.animation`playerAnimation`, 50)
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Spawn a gate every 2 seconds
|
|
28
|
+
game.onUpdateInterval(2000, () => {
|
|
29
|
+
// Create a gate with an empty image that spans the height of the screen
|
|
30
|
+
const gate = sprites.create(image.create(12, screen.height), GateKind);
|
|
31
|
+
|
|
32
|
+
// Select a y value for our gate opening to start
|
|
33
|
+
const gapHeight = 50;
|
|
34
|
+
const gapStart = randint(0, screen.height - gapHeight);
|
|
35
|
+
|
|
36
|
+
// Draw the gate on the empty image
|
|
37
|
+
gate.image.fillRect(2, 0, 8, screen.height, 6);
|
|
38
|
+
gate.image.fillRect(2, gapStart, 8, 50, 0);
|
|
39
|
+
gate.image.fillRect(0, gapStart - 5, 12, 5, 6);
|
|
40
|
+
gate.image.fillRect(0, gapStart + gapHeight, 12, 5, 6);
|
|
41
|
+
|
|
42
|
+
// Move the gate to the right side of the screen and give it velocity
|
|
43
|
+
gate.left = screen.width;
|
|
44
|
+
gate.vx = -50;
|
|
45
|
+
|
|
46
|
+
// Turn on the AutoDestroy flag so that gates are automatically destroyed
|
|
47
|
+
// when they leave the screen
|
|
48
|
+
gate.setFlag(SpriteFlag.AutoDestroy, true);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// End the game when the player overlaps a gate
|
|
52
|
+
sprites.onOverlap(PlayerKind, GateKind, (sprite, otherSprite) => {
|
|
53
|
+
game.over();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// When a gate is auto destroyed, increase our score by 1
|
|
57
|
+
sprites.onDestroyed(GateKind, () => {
|
|
58
|
+
info.changeScoreBy(1);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "flappy-game",
|
|
3
|
+
"description": "Flappy Bird style game template",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"device": "*"
|
|
6
|
+
},
|
|
7
|
+
"files": [
|
|
8
|
+
"main.ts",
|
|
9
|
+
"README.md",
|
|
10
|
+
"assets.json",
|
|
11
|
+
"images.g.jres",
|
|
12
|
+
"images.g.ts"
|
|
13
|
+
],
|
|
14
|
+
"supportedTargets": [
|
|
15
|
+
"arcade"
|
|
16
|
+
],
|
|
17
|
+
"preferredEditor": "tsprj"
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Platformer Game
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"myImages.image1": {
|
|
3
|
+
"id": "myImages.image1",
|
|
4
|
+
"data": "hwQOAA4AAAAAAAD7/w8AAAAAAN/d+wAAAAAA+//9AAAAAAAA8Pv/AM7M7/6/2/0A3jvb3bLdDwDevdPfLb0PAMDd3f0t3f0AAL/d3Svd/wAA393dK90PAMDd3f0t3Q8A3r3T3y3b/QDeO9vd+///AM7M7/4PAAAA",
|
|
5
|
+
"dataEncoding": "base64",
|
|
6
|
+
"namespace": "myImages.",
|
|
7
|
+
"mimeType": "image/x-mkcd-f4",
|
|
8
|
+
"displayName": "playerImage"
|
|
9
|
+
},
|
|
10
|
+
"myImages.image2": {
|
|
11
|
+
"id": "myImages.image2",
|
|
12
|
+
"data": "hwQQABAAAAAAAAAAAPD/AAAAAAAAwLEAAAD//w8f+wAA/929/B+xAPAbEd29H/sA8BERvRzM8Q8fERHxH73/Dx8REdER+///HxER0RGx//8fERHxH/v///AREb0czbEP8BsR3b0f+wAA/929/B+xAAAA//8PH/sAAAAAAADPsQAAAAAAAPD/AA==",
|
|
13
|
+
"dataEncoding": "base64",
|
|
14
|
+
"namespace": "myImages.",
|
|
15
|
+
"mimeType": "image/x-mkcd-f4",
|
|
16
|
+
"displayName": "enemyImage"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Auto-generated code. Do not edit.
|
|
2
|
+
namespace myImages {
|
|
3
|
+
|
|
4
|
+
helpers._registerFactory("image", function(name: string) {
|
|
5
|
+
switch(helpers.stringTrim(name)) {
|
|
6
|
+
case "image1":
|
|
7
|
+
case "playerImage":return img`
|
|
8
|
+
. . . . e e e . . . . e e e
|
|
9
|
+
. . . . c d d c . . c d d c
|
|
10
|
+
. . . . c b d d f f d d b c
|
|
11
|
+
. . . . c 3 b d b d d b 3 c
|
|
12
|
+
. . . . f b 3 d d d d 3 b f
|
|
13
|
+
. . . . e d d d d d d d d e
|
|
14
|
+
b f b . e d f d d d d f d e
|
|
15
|
+
f d f . f d d f d d f d d f
|
|
16
|
+
f d f . f 2 d d b b d d b f
|
|
17
|
+
f d f f b b 2 2 2 2 2 2 f .
|
|
18
|
+
f b d b b d d d d d d b f .
|
|
19
|
+
. f f f d d b d d d d d f .
|
|
20
|
+
. . . f d f f d f f f d f .
|
|
21
|
+
. . . f f . . f f . . f f .
|
|
22
|
+
`;
|
|
23
|
+
case "image2":
|
|
24
|
+
case "enemyImage":return img`
|
|
25
|
+
. . . . . . f f f f . . . . . .
|
|
26
|
+
. . . . f f 1 1 1 1 f f . . . .
|
|
27
|
+
. . . f b 1 1 1 1 1 1 b f . . .
|
|
28
|
+
. . . f 1 1 1 1 1 1 1 1 f . . .
|
|
29
|
+
. . f d 1 1 1 1 1 1 1 1 d f . .
|
|
30
|
+
. . f d 1 1 1 1 1 1 1 1 d f . .
|
|
31
|
+
. . f d d d 1 1 1 1 d d d f . .
|
|
32
|
+
. . f b d b f d d f b d b f . .
|
|
33
|
+
. . f c d c f 1 1 f c d c f . .
|
|
34
|
+
. . . f b 1 1 1 1 1 1 b f . . .
|
|
35
|
+
. . f f f c d b 1 b d f f f f .
|
|
36
|
+
f c 1 1 1 c b f b f c 1 1 1 c f
|
|
37
|
+
f 1 b 1 b 1 f f f f 1 b 1 b 1 f
|
|
38
|
+
f b f b f f f f f f b f b f b f
|
|
39
|
+
. . . . . f f f f f f . . . . .
|
|
40
|
+
. . . . . . . f f f . . . . . .
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
helpers._registerFactory("animation", function(name: string) {
|
|
47
|
+
switch(helpers.stringTrim(name)) {
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
helpers._registerFactory("song", function(name: string) {
|
|
54
|
+
switch(helpers.stringTrim(name)) {
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
helpers._registerFactory("json", function(name: string) {
|
|
61
|
+
switch(helpers.stringTrim(name)) {
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
// Auto-generated code. Do not edit.
|
|
69
|
+
|
|
70
|
+
// Auto-generated code. Do not edit.
|
|
71
|
+
namespace myTiles {
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
// Auto-generated code. Do not edit.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// Use SpriteKind.create() to create a unique kind for each sprite
|
|
2
|
+
const PlayerKind = SpriteKind.create();
|
|
3
|
+
const EnemyKind = SpriteKind.create();
|
|
4
|
+
|
|
5
|
+
// The Y acceleration of the player and enemies in pixel/second^2
|
|
6
|
+
const GRAVITY = 1000;
|
|
7
|
+
|
|
8
|
+
// The move speed of the player in pixels/second
|
|
9
|
+
const MOVE_SPEED = 100;
|
|
10
|
+
|
|
11
|
+
// The jump height in pixels
|
|
12
|
+
const JUMP_HEIGHT = 32;
|
|
13
|
+
|
|
14
|
+
// The height the player bounces when they jump on an enemy
|
|
15
|
+
const BOUNCE_HEIGHT = 16;
|
|
16
|
+
|
|
17
|
+
// The move speed of enemies in pixels/second
|
|
18
|
+
const ENEMY_SPEED = 50;
|
|
19
|
+
|
|
20
|
+
let player: Sprite;
|
|
21
|
+
startGame();
|
|
22
|
+
|
|
23
|
+
function startGame() {
|
|
24
|
+
// Set the background color to cyan
|
|
25
|
+
scene.setBackgroundColor(9);
|
|
26
|
+
|
|
27
|
+
loadTilemap();
|
|
28
|
+
createPlayer();
|
|
29
|
+
registerEvents();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function loadTilemap () {
|
|
33
|
+
// Load the tilemap asset
|
|
34
|
+
scene.setTileMapLevel(assets.tilemap`level`);
|
|
35
|
+
|
|
36
|
+
// Loop over all enemySpawn tiles and create enemy sprites at
|
|
37
|
+
// those locations
|
|
38
|
+
for (let location of tiles.getTilesByType(assets.tile`enemySpawn`)) {
|
|
39
|
+
const enemy = sprites.create(assets.image`enemyImage`, EnemyKind);
|
|
40
|
+
enemy.x = location.x;
|
|
41
|
+
enemy.y = location.y;
|
|
42
|
+
enemy.ay = GRAVITY;
|
|
43
|
+
|
|
44
|
+
// Hide the enemy spawn tile
|
|
45
|
+
tiles.setTileAt(location, assets.tile`transparency16`);
|
|
46
|
+
|
|
47
|
+
// Randomly make the enemy move left or right
|
|
48
|
+
if (Math.percentChance(50)) {
|
|
49
|
+
enemy.vx = ENEMY_SPEED;
|
|
50
|
+
} else {
|
|
51
|
+
enemy.vx = 0 - ENEMY_SPEED;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function createPlayer() {
|
|
57
|
+
// Create the player sprite using the playerImage asset
|
|
58
|
+
player = sprites.create(assets.image`playerImage`, PlayerKind);
|
|
59
|
+
|
|
60
|
+
// Set the acceleration in the Y direction equal to our gravity
|
|
61
|
+
player.ay = GRAVITY;
|
|
62
|
+
|
|
63
|
+
// Move the sprite with buttons, but only in the X direction
|
|
64
|
+
controller.moveSprite(player, MOVE_SPEED, 0);
|
|
65
|
+
|
|
66
|
+
// Follow the player with the camera. The camera is automatically
|
|
67
|
+
// boxed within the tilemap
|
|
68
|
+
scene.cameraFollowSprite(player);
|
|
69
|
+
|
|
70
|
+
// Place the player on top of the playerSpawn tile
|
|
71
|
+
tiles.placeOnRandomTile(player, assets.tile`playerSpawn`);
|
|
72
|
+
|
|
73
|
+
// Hide the player spawn tile
|
|
74
|
+
tiles.setTileAt(player.tilemapLocation(), assets.tile`transparency16`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function registerEvents () {
|
|
78
|
+
// Jump on A button press
|
|
79
|
+
controller.A.onEvent(ControllerButtonEvent.Pressed, () => {
|
|
80
|
+
// First make sure the player is on the ground
|
|
81
|
+
if (player.isHittingTile(CollisionDirection.Bottom)) {
|
|
82
|
+
doJump(player, JUMP_HEIGHT);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// When the player overlaps lava, end the game
|
|
87
|
+
scene.onOverlapTile(PlayerKind, assets.tile`lava`, (sprite, location) => {
|
|
88
|
+
onPlayerDied();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// When the player overlaps the treasure chest, win the game
|
|
92
|
+
scene.onOverlapTile(PlayerKind, assets.tile`treasureChest`, (sprite, location) => {
|
|
93
|
+
game.over(true);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Handle player overlapping with an enemy
|
|
97
|
+
sprites.onOverlap(PlayerKind, EnemyKind, (sprite, otherSprite) => {
|
|
98
|
+
// Check to see if the player is jumping on the enemy
|
|
99
|
+
if (sprite.vy > 0 && sprite.bottom < otherSprite.top + 8) {
|
|
100
|
+
// Destroy the enemy and bounce the player
|
|
101
|
+
otherSprite.destroy();
|
|
102
|
+
doJump(sprite, BOUNCE_HEIGHT);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
// If the player isn't jumping on top of the enemy, take damage
|
|
106
|
+
onPlayerDied();
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Bounce enemies off of each other when they overlap
|
|
111
|
+
sprites.onOverlap(EnemyKind, EnemyKind, (sprite, otherSprite) => {
|
|
112
|
+
if (sprite.x < otherSprite.x) {
|
|
113
|
+
sprite.right = otherSprite.left;
|
|
114
|
+
sprite.vx = -ENEMY_SPEED;
|
|
115
|
+
otherSprite.vx = ENEMY_SPEED;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
otherSprite.right = sprite.left;
|
|
119
|
+
otherSprite.vx = -ENEMY_SPEED;
|
|
120
|
+
sprite.vx = ENEMY_SPEED;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Also bounce enemies off of walls
|
|
125
|
+
scene.onHitWall(EnemyKind, (sprite, location) => {
|
|
126
|
+
if (sprite.isHittingTile(CollisionDirection.Left)) {
|
|
127
|
+
sprite.vx = ENEMY_SPEED;
|
|
128
|
+
}
|
|
129
|
+
else if (sprite.isHittingTile(CollisionDirection.Right)) {
|
|
130
|
+
sprite.vx = -ENEMY_SPEED;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function doJump (sprite: Sprite, height: number) {
|
|
136
|
+
sprite.vy = -Math.sqrt(2 * height * GRAVITY);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function onPlayerDied () {
|
|
140
|
+
game.reset();
|
|
141
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "platformer-game",
|
|
3
|
+
"description": "Platform game template with tilemap, enemies, and player",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"device": "*",
|
|
6
|
+
"color-coded-tilemap": "*"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"main.ts",
|
|
10
|
+
"README.md",
|
|
11
|
+
"assets.json",
|
|
12
|
+
"images.g.jres",
|
|
13
|
+
"images.g.ts",
|
|
14
|
+
"tilemap.g.jres",
|
|
15
|
+
"tilemap.g.ts"
|
|
16
|
+
],
|
|
17
|
+
"supportedTargets": [
|
|
18
|
+
"arcade"
|
|
19
|
+
],
|
|
20
|
+
"preferredEditor": "tsprj"
|
|
21
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"myTiles.transparency16": {
|
|
3
|
+
"id": "myTiles.transparency16",
|
|
4
|
+
"data": "hwQQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
|
|
5
|
+
"dataEncoding": "base64",
|
|
6
|
+
"namespace": "myTiles.",
|
|
7
|
+
"mimeType": "image/x-mkcd-f4",
|
|
8
|
+
"tilemapTile": true
|
|
9
|
+
},
|
|
10
|
+
"myTiles.tile1": {
|
|
11
|
+
"id": "myTiles.tile1",
|
|
12
|
+
"data": "hwQQABAAAADdHd0d3R3dHRER3R0REd0d3R3dHd0d3R3dHd0d3R3dHd0d3R3dHd0d3R0REd0dERHdHd0d3R3dHd0d3R3dHd0d3R3dHd0d3R0REd0dERHdHd0d3R3dHd0d3R3dHd0d3R3dHd0d3R3dHd0dERHdHRER3R3dHd0d3R3dHd0d3R3dHQ==",
|
|
13
|
+
"dataEncoding": "base64",
|
|
14
|
+
"namespace": "myTiles.",
|
|
15
|
+
"mimeType": "image/x-mkcd-f4",
|
|
16
|
+
"tilemapTile": true,
|
|
17
|
+
"displayName": "brick"
|
|
18
|
+
},
|
|
19
|
+
"myTiles.tile2": {
|
|
20
|
+
"id": "myTiles.tile2",
|
|
21
|
+
"data": "hwQQABAAAAAAu7u7y7y7C7Du7u677M6760Tk7rvs7rtLRETuu+zuC0tERO677O4LS0RE7rvs7gtLRETuu8vuC0tERO7NvO4LS0RE7s287gtLRETuu8vuC0tERO677O4LS0RE7rvs7gtLRETuu+zuC+tE5O677O67sO7u7rvszrsAu7u7y7y7Cw==",
|
|
22
|
+
"dataEncoding": "base64",
|
|
23
|
+
"namespace": "myTiles.",
|
|
24
|
+
"mimeType": "image/x-mkcd-f4",
|
|
25
|
+
"tilemapTile": true,
|
|
26
|
+
"displayName": "treasureChest"
|
|
27
|
+
},
|
|
28
|
+
"myTiles.tile3": {
|
|
29
|
+
"id": "myTiles.tile3",
|
|
30
|
+
"data": "hwQQABAAAABVJERCRVREREUiREJVVVVVJCIiVEVFVVUiJERVRCJURCJCVEQiQiJFIkRFJCIkJEUiVEUiJEIiRUJUJCIiIkJFREUkIiIiQkVCRSJEIiRCRUJFIkQiIlJFQlVEIiJCVCRCRVVFRFRVJERVRFVVVUQiVEREVEVVJEJVRCJCRVQkQg==",
|
|
31
|
+
"dataEncoding": "base64",
|
|
32
|
+
"namespace": "myTiles.",
|
|
33
|
+
"mimeType": "image/x-mkcd-f4",
|
|
34
|
+
"tilemapTile": true,
|
|
35
|
+
"displayName": "lava"
|
|
36
|
+
},
|
|
37
|
+
"myTiles.tile4": {
|
|
38
|
+
"id": "myTiles.tile4",
|
|
39
|
+
"data": "hwQQABAAAAAAAAAAAAAAAAAAAAD7/w8AAAAAAN/d+wAAAAAA+//9AAAAAAAA8Pv/AM7M7/6/2/0A3jvb3bLdDwDevdPfLb0PAMDd3f0t3f0AAL/d3Svd/wAA393dK90PAMDd3f0t3Q8A3r3T3y3b/QDeO9vd+///AM7M7/4PAAAAAAAAAAAAAA==",
|
|
40
|
+
"dataEncoding": "base64",
|
|
41
|
+
"namespace": "myTiles.",
|
|
42
|
+
"mimeType": "image/x-mkcd-f4",
|
|
43
|
+
"tilemapTile": true,
|
|
44
|
+
"displayName": "playerSpawn"
|
|
45
|
+
},
|
|
46
|
+
"myTiles.tile5": {
|
|
47
|
+
"id": "myTiles.tile5",
|
|
48
|
+
"data": "hwQQABAAAAAAAAAAAPD/AAAAAAAAwLEAAAD//w8f+wAA/929/B+xAPAbEd29H/sA8BERvRzM8Q8fERHxH73/Dx8REdER+///HxER0RGx//8fERHxH/v///AREb0czbEP8BsR3b0f+wAA/929/B+xAAAA//8PH/sAAAAAAADPsQAAAAAAAPD/AA==",
|
|
49
|
+
"dataEncoding": "base64",
|
|
50
|
+
"namespace": "myTiles.",
|
|
51
|
+
"mimeType": "image/x-mkcd-f4",
|
|
52
|
+
"tilemapTile": true,
|
|
53
|
+
"displayName": "enemySpawn"
|
|
54
|
+
},
|
|
55
|
+
"level1": {
|
|
56
|
+
"id": "level1",
|
|
57
|
+
"data": "MTAyYTAwMDgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDIwMDAwMDAwMDAwMDAwMDAwMDEwMTAwMDAwMTAxMDEwMDAwMDEwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDEwMTAwMDAwNDAwMDAwMDAxMDEwMTAwMDAwMDAwMDAwMDAwMDEwMTAxMDAwMDAwMDAwNTAwMDAwMDAxMDEwMDAwMDUwMDAwMDUwMDAwMDAwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAzMDMwMzAzMDMwMzAzMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDIwMDIyMDIyMDAyMjAwMDAwMDAwMDAwMDAwMDAwMDAwMjAyMjAwMDAwMDIyMDIwMDAwMDAyMjAyMDAwMDAwMjAwMjAwMDAwMDAwMjIyMjIyMjIyMjIyMDIwMDAwMDAyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMg==",
|
|
58
|
+
"dataEncoding": "base64",
|
|
59
|
+
"namespace": "myTiles.",
|
|
60
|
+
"mimeType": "application/mkcd-tilemap",
|
|
61
|
+
"displayName": "level",
|
|
62
|
+
"tileset": [
|
|
63
|
+
"myTiles.transparency16",
|
|
64
|
+
"myTiles.tile1",
|
|
65
|
+
"myTiles.tile2",
|
|
66
|
+
"myTiles.tile3",
|
|
67
|
+
"myTiles.tile4",
|
|
68
|
+
"myTiles.tile5"
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// Auto-generated code. Do not edit.
|
|
2
|
+
namespace myImages {
|
|
3
|
+
|
|
4
|
+
helpers._registerFactory("image", function(name: string) {
|
|
5
|
+
switch(helpers.stringTrim(name)) {
|
|
6
|
+
case "myTiles.transparency16":return img`
|
|
7
|
+
. . . . . . . . . . . . . . . .
|
|
8
|
+
. . . . . . . . . . . . . . . .
|
|
9
|
+
. . . . . . . . . . . . . . . .
|
|
10
|
+
. . . . . . . . . . . . . . . .
|
|
11
|
+
. . . . . . . . . . . . . . . .
|
|
12
|
+
. . . . . . . . . . . . . . . .
|
|
13
|
+
. . . . . . . . . . . . . . . .
|
|
14
|
+
. . . . . . . . . . . . . . . .
|
|
15
|
+
. . . . . . . . . . . . . . . .
|
|
16
|
+
. . . . . . . . . . . . . . . .
|
|
17
|
+
. . . . . . . . . . . . . . . .
|
|
18
|
+
. . . . . . . . . . . . . . . .
|
|
19
|
+
. . . . . . . . . . . . . . . .
|
|
20
|
+
. . . . . . . . . . . . . . . .
|
|
21
|
+
. . . . . . . . . . . . . . . .
|
|
22
|
+
. . . . . . . . . . . . . . . .
|
|
23
|
+
`;
|
|
24
|
+
case "myTiles.tile1":
|
|
25
|
+
case "brick":return img`
|
|
26
|
+
d 1 d d d d d d d 1 d d d d d d
|
|
27
|
+
d 1 d d d d d d d 1 d d d d d d
|
|
28
|
+
d 1 d d d d d d d 1 d d d d d d
|
|
29
|
+
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
|
30
|
+
d d d d d 1 d d d d d d d 1 d d
|
|
31
|
+
d d d d d 1 d d d d d d d 1 d d
|
|
32
|
+
d d d d d 1 d d d d d d d 1 d d
|
|
33
|
+
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
|
34
|
+
d 1 d d d d d d d 1 d d d d d d
|
|
35
|
+
d 1 d d d d d d d 1 d d d d d d
|
|
36
|
+
d 1 d d d d d d d 1 d d d d d d
|
|
37
|
+
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
|
38
|
+
d d d d d 1 d d d d d d d 1 d d
|
|
39
|
+
d d d d d 1 d d d d d d d 1 d d
|
|
40
|
+
d d d d d 1 d d d d d d d 1 d d
|
|
41
|
+
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
|
|
42
|
+
`;
|
|
43
|
+
case "myTiles.tile2":
|
|
44
|
+
case "treasureChest":return img`
|
|
45
|
+
. . b b b b b b b b b b b b . .
|
|
46
|
+
. b e 4 4 4 4 4 4 4 4 4 4 e b .
|
|
47
|
+
b e 4 4 4 4 4 4 4 4 4 4 4 4 e b
|
|
48
|
+
b e 4 4 4 4 4 4 4 4 4 4 4 4 e b
|
|
49
|
+
b e 4 4 4 4 4 4 4 4 4 4 4 4 e b
|
|
50
|
+
b e e 4 4 4 4 4 4 4 4 4 4 e e b
|
|
51
|
+
b e e e e e e e e e e e e e e b
|
|
52
|
+
b e e e e e e e e e e e e e e b
|
|
53
|
+
b b b b b b b d d b b b b b b b
|
|
54
|
+
c b b b b b b c c b b b b b b c
|
|
55
|
+
c c c c c c b c c b c c c c c c
|
|
56
|
+
b e e e e e c b b c e e e e e b
|
|
57
|
+
b e e e e e e e e e e e e e e b
|
|
58
|
+
b c e e e e e e e e e e e e c b
|
|
59
|
+
b b b b b b b b b b b b b b b b
|
|
60
|
+
. b b . . . . . . . . . . b b .
|
|
61
|
+
`;
|
|
62
|
+
case "myTiles.tile3":
|
|
63
|
+
case "lava":return img`
|
|
64
|
+
5 5 4 2 2 2 2 2 4 2 2 2 2 4 4 5
|
|
65
|
+
5 4 2 2 2 2 2 4 4 4 4 4 4 4 5 5
|
|
66
|
+
4 2 2 4 2 4 4 4 5 5 5 5 5 5 4 4
|
|
67
|
+
2 2 2 2 4 4 5 5 4 4 4 5 4 5 4 4
|
|
68
|
+
4 4 2 4 4 5 5 4 4 2 2 4 5 4 4 2
|
|
69
|
+
4 4 2 4 5 4 4 2 2 2 2 4 5 4 4 2
|
|
70
|
+
2 2 4 5 4 4 2 2 2 4 4 2 5 5 4 2
|
|
71
|
+
4 4 5 5 4 2 2 2 2 4 4 2 4 5 5 4
|
|
72
|
+
5 5 5 4 2 2 4 2 2 2 2 2 4 5 5 5
|
|
73
|
+
4 5 4 4 2 2 2 2 2 2 2 2 4 5 4 4
|
|
74
|
+
4 5 5 2 2 4 2 2 2 4 2 2 4 5 5 4
|
|
75
|
+
5 5 4 2 4 2 4 2 2 2 2 4 5 5 5 5
|
|
76
|
+
4 5 5 4 2 4 2 2 2 2 2 4 5 4 4 4
|
|
77
|
+
4 5 5 5 2 2 2 4 4 4 5 5 5 4 2 2
|
|
78
|
+
4 5 5 4 5 5 5 5 5 5 5 4 4 2 2 2
|
|
79
|
+
4 5 5 4 4 4 4 4 4 4 4 2 2 2 4 4
|
|
80
|
+
`;
|
|
81
|
+
case "myTiles.tile4":
|
|
82
|
+
case "playerSpawn":return img`
|
|
83
|
+
. . . . . . . . . . . . . . . .
|
|
84
|
+
. . . . . . . . . . . . . . . .
|
|
85
|
+
. . . . . e e e . . . . e e e .
|
|
86
|
+
. . . . . c d d c . . c d d c .
|
|
87
|
+
. . . . . c b d d f f d d b c .
|
|
88
|
+
. . . . . c 3 b d b d d b 3 c .
|
|
89
|
+
. . . . . f b 3 d d d d 3 b f .
|
|
90
|
+
. . . . . e d d d d d d d d e .
|
|
91
|
+
. b f b . e d f d d d d f d e .
|
|
92
|
+
. f d f . f d d f d d f d d f .
|
|
93
|
+
. f d f . f 2 d d b b d d b f .
|
|
94
|
+
. f d f f b b 2 2 2 2 2 2 f . .
|
|
95
|
+
. f b d b b d d d d d d b f . .
|
|
96
|
+
. . f f f d d b d d d d d f . .
|
|
97
|
+
. . . . f d f f d f f f d f . .
|
|
98
|
+
. . . . f f . . f f . . f f . .
|
|
99
|
+
`;
|
|
100
|
+
case "myTiles.tile5":
|
|
101
|
+
case "enemySpawn":return img`
|
|
102
|
+
. . . . . . f f f f . . . . . .
|
|
103
|
+
. . . . f f 1 1 1 1 f f . . . .
|
|
104
|
+
. . . f b 1 1 1 1 1 1 b f . . .
|
|
105
|
+
. . . f 1 1 1 1 1 1 1 1 f . . .
|
|
106
|
+
. . f d 1 1 1 1 1 1 1 1 d f . .
|
|
107
|
+
. . f d 1 1 1 1 1 1 1 1 d f . .
|
|
108
|
+
. . f d d d 1 1 1 1 d d d f . .
|
|
109
|
+
. . f b d b f d d f b d b f . .
|
|
110
|
+
. . f c d c f 1 1 f c d c f . .
|
|
111
|
+
. . . f b 1 1 1 1 1 1 b f . . .
|
|
112
|
+
. . f f f c d b 1 b d f f f f .
|
|
113
|
+
f c 1 1 1 c b f b f c 1 1 1 c f
|
|
114
|
+
f 1 b 1 b 1 f f f f 1 b 1 b 1 f
|
|
115
|
+
f b f b f f f f f f b f b f b f
|
|
116
|
+
. . . . . f f f f f f . . . . .
|
|
117
|
+
. . . . . . . f f f . . . . . .
|
|
118
|
+
`;
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
helpers._registerFactory("animation", function(name: string) {
|
|
124
|
+
switch(helpers.stringTrim(name)) {
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
helpers._registerFactory("song", function(name: string) {
|
|
131
|
+
switch(helpers.stringTrim(name)) {
|
|
132
|
+
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
helpers._registerFactory("json", function(name: string) {
|
|
138
|
+
switch(helpers.stringTrim(name)) {
|
|
139
|
+
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
}
|
|
145
|
+
// Auto-generated code. Do not edit.
|
|
146
|
+
|
|
147
|
+
// Auto-generated code. Do not edit.
|
|
148
|
+
namespace myTiles {
|
|
149
|
+
//% fixedInstance jres blockIdentity=images._tile
|
|
150
|
+
export const transparency16 = image.ofBuffer(hex``);
|
|
151
|
+
//% fixedInstance jres blockIdentity=images._tile
|
|
152
|
+
export const tile1 = image.ofBuffer(hex``);
|
|
153
|
+
//% fixedInstance jres blockIdentity=images._tile
|
|
154
|
+
export const tile2 = image.ofBuffer(hex``);
|
|
155
|
+
//% fixedInstance jres blockIdentity=images._tile
|
|
156
|
+
export const tile3 = image.ofBuffer(hex``);
|
|
157
|
+
//% fixedInstance jres blockIdentity=images._tile
|
|
158
|
+
export const tile4 = image.ofBuffer(hex``);
|
|
159
|
+
//% fixedInstance jres blockIdentity=images._tile
|
|
160
|
+
export const tile5 = image.ofBuffer(hex``);
|
|
161
|
+
|
|
162
|
+
helpers._registerFactory("tilemap", function(name: string) {
|
|
163
|
+
switch(helpers.stringTrim(name)) {
|
|
164
|
+
case "level":
|
|
165
|
+
case "level1":return tiles.createTilemap(hex`2a000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000101000001010100000101000000000000000000000000000000000000000000010101000004000000010101000000000000000101010000000005000000010100000500000500000001010101010101010101010101030303030303030101010101010101010101010101010101010101010101010101`, img`
|
|
166
|
+
..........................................
|
|
167
|
+
..........................................
|
|
168
|
+
..........................................
|
|
169
|
+
..........................................
|
|
170
|
+
..........................................
|
|
171
|
+
.......22..222..22.....................222
|
|
172
|
+
......222.......222........22.........2222
|
|
173
|
+
222222222.......22222222222222222222222222
|
|
174
|
+
`, [myTiles.transparency16,myTiles.tile1,myTiles.tile2,myTiles.tile3,myTiles.tile4,myTiles.tile5], TileScale.Sixteen);
|
|
175
|
+
}
|
|
176
|
+
return null;
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
helpers._registerFactory("tile", function(name: string) {
|
|
180
|
+
switch(helpers.stringTrim(name)) {
|
|
181
|
+
case "transparency16":return myTiles.transparency16;
|
|
182
|
+
case "brick":
|
|
183
|
+
case "tile1":return myTiles.tile1;
|
|
184
|
+
case "treasureChest":
|
|
185
|
+
case "tile2":return myTiles.tile2;
|
|
186
|
+
case "lava":
|
|
187
|
+
case "tile3":return myTiles.tile3;
|
|
188
|
+
case "playerSpawn":
|
|
189
|
+
case "tile4":return myTiles.tile4;
|
|
190
|
+
case "enemySpawn":
|
|
191
|
+
case "tile5":return myTiles.tile5;
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
}
|
|
197
|
+
// Auto-generated code. Do not edit.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|