create-spud 0.0.1
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/example/bun.lock +208 -0
- package/example/demo.html +21 -0
- package/example/index.html +21 -0
- package/example/package.json +22 -0
- package/example/public/favicon.svg +1 -0
- package/example/public/poster.webp +0 -0
- package/example/readme.md +52 -0
- package/example/src/assets/audio/menu-music.mp3 +0 -0
- package/example/src/assets/audio/shoot.wav +0 -0
- package/example/src/assets/images/sprite.png +0 -0
- package/example/src/audio.ts +36 -0
- package/example/src/demo.ts +40 -0
- package/example/src/gameplay.ts +47 -0
- package/example/src/helpers.ts +14 -0
- package/example/src/index.ts +46 -0
- package/example/src/sprite.ts +52 -0
- package/example/src/state.ts +5 -0
- package/example/tsconfig.json +37 -0
- package/example/vite.config.ts +24 -0
- package/index.ts +164 -0
- package/package.json +24 -0
- package/readme.md +35 -0
package/example/bun.lock
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 1,
|
|
3
|
+
"configVersion": 1,
|
|
4
|
+
"workspaces": {
|
|
5
|
+
"": {
|
|
6
|
+
"name": "spud-game-template",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@spud.gg/api": "0.0.24",
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"sharp": "0.34.5",
|
|
12
|
+
"svgo": "4.0.0",
|
|
13
|
+
"typescript": "^5",
|
|
14
|
+
"vite": "8.0.0-beta.10",
|
|
15
|
+
"vite-plugin-image-optimizer": "2.0.3",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
"packages": {
|
|
20
|
+
"@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
|
|
21
|
+
|
|
22
|
+
"@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
|
23
|
+
|
|
24
|
+
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
|
25
|
+
|
|
26
|
+
"@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="],
|
|
27
|
+
|
|
28
|
+
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
|
|
29
|
+
|
|
30
|
+
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="],
|
|
31
|
+
|
|
32
|
+
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="],
|
|
33
|
+
|
|
34
|
+
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="],
|
|
35
|
+
|
|
36
|
+
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="],
|
|
37
|
+
|
|
38
|
+
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="],
|
|
39
|
+
|
|
40
|
+
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="],
|
|
41
|
+
|
|
42
|
+
"@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="],
|
|
43
|
+
|
|
44
|
+
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="],
|
|
45
|
+
|
|
46
|
+
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="],
|
|
47
|
+
|
|
48
|
+
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="],
|
|
49
|
+
|
|
50
|
+
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="],
|
|
51
|
+
|
|
52
|
+
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="],
|
|
53
|
+
|
|
54
|
+
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="],
|
|
55
|
+
|
|
56
|
+
"@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="],
|
|
57
|
+
|
|
58
|
+
"@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="],
|
|
59
|
+
|
|
60
|
+
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="],
|
|
61
|
+
|
|
62
|
+
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="],
|
|
63
|
+
|
|
64
|
+
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="],
|
|
65
|
+
|
|
66
|
+
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="],
|
|
67
|
+
|
|
68
|
+
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="],
|
|
69
|
+
|
|
70
|
+
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="],
|
|
71
|
+
|
|
72
|
+
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="],
|
|
73
|
+
|
|
74
|
+
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="],
|
|
75
|
+
|
|
76
|
+
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
|
|
77
|
+
|
|
78
|
+
"@oxc-project/runtime": ["@oxc-project/runtime@0.110.0", "", {}, "sha512-4t5lYmPneAGKGN7zDhK2iQrn+Ax3DXLCNqVr3z6K2VqemKWfQTlLyzjgjilxZmwFAKe65qI4WG7Bsj05UgUHaA=="],
|
|
79
|
+
|
|
80
|
+
"@oxc-project/types": ["@oxc-project/types@0.110.0", "", {}, "sha512-6Ct21OIlrEnFEJk5LT4e63pk3btsI6/TusD/GStLi7wYlGJNOl1GI9qvXAnRAxQU9zqA2Oz+UwhfTOU2rPZVow=="],
|
|
81
|
+
|
|
82
|
+
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.1", "", { "os": "android", "cpu": "arm64" }, "sha512-He6ZoCfv5D7dlRbrhNBkuMVIHd0GDnjJwbICE1OWpG7G3S2gmJ+eXkcNLJjzjNDpeI2aRy56ou39AJM9AD8YFA=="],
|
|
83
|
+
|
|
84
|
+
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YzJdn08kSOXnj85ghHauH2iHpOJ6eSmstdRTLyaziDcUxe9SyQJgGyx/5jDIhDvtOcNvMm2Ju7m19+S/Rm1jFg=="],
|
|
85
|
+
|
|
86
|
+
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cIvAbqM+ZVV6lBSKSBtlNqH5iCiW933t1q8j0H66B3sjbe8AxIRetVqfGgcHcJtMzBIkIALlL9fcDrElWLJQcQ=="],
|
|
87
|
+
|
|
88
|
+
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-rVt+B1B/qmKwCl1XD02wKfgh3vQPXRXdB/TicV2w6g7RVAM1+cZcpigwhLarqiVCxDObFZ7UgXCxPC7tpDoRog=="],
|
|
89
|
+
|
|
90
|
+
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.1", "", { "os": "linux", "cpu": "arm" }, "sha512-69YKwJJBOFprQa1GktPgbuBOfnn+EGxu8sBJ1TjPER+zhSpYeaU4N07uqmyBiksOLGXsMegymuecLobfz03h8Q=="],
|
|
91
|
+
|
|
92
|
+
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-9JDhHUf3WcLfnViFWm+TyorqUtnSAHaCzlSNmMOq824prVuuzDOK91K0Hl8DUcEb9M5x2O+d2/jmBMsetRIn3g=="],
|
|
93
|
+
|
|
94
|
+
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-UvApLEGholmxw/HIwmUnLq3CwdydbhaHHllvWiCTNbyGom7wTwOtz5OAQbAKZYyiEOeIXZNPkM7nA4Dtng7CLw=="],
|
|
95
|
+
|
|
96
|
+
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.1", "", { "os": "linux", "cpu": "x64" }, "sha512-uVctNgZHiGnJx5Fij7wHLhgw4uyZBVi6mykeWKOqE7bVy9Hcxn0fM/IuqdMwk6hXlaf9fFShDTFz2+YejP+x0A=="],
|
|
97
|
+
|
|
98
|
+
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.1", "", { "os": "linux", "cpu": "x64" }, "sha512-T6Eg0xWwcxd/MzBcuv4Z37YVbUbJxy5cMNnbIt/Yr99wFwli30O4BPlY8hKeGyn6lWNtU0QioBS46lVzDN38bg=="],
|
|
99
|
+
|
|
100
|
+
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.1", "", { "os": "none", "cpu": "arm64" }, "sha512-PuGZVS2xNJyLADeh2F04b+Cz4NwvpglbtWACgrDOa5YDTEHKwmiTDjoD5eZ9/ptXtcpeFrMqD2H4Zn33KAh1Eg=="],
|
|
101
|
+
|
|
102
|
+
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-2mOxY562ihHlz9lEXuaGEIDCZ1vI+zyFdtsoa3M62xsEunDXQE+DVPO4S4x5MPK9tKulG/aFcA/IH5eVN257Cw=="],
|
|
103
|
+
|
|
104
|
+
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-oQVOP5cfAWZwRD0Q3nGn/cA9FW3KhMMuQ0NIndALAe6obqjLhqYVYDiGGRGrxvnjJsVbpLwR14gIUYnpIcHR1g=="],
|
|
105
|
+
|
|
106
|
+
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.1", "", { "os": "win32", "cpu": "x64" }, "sha512-Ydsxxx++FNOuov3wCBPaYjZrEvKOOGq3k+BF4BPridhg2pENfitSRD2TEuQ8i33bp5VptuNdC9IzxRKU031z5A=="],
|
|
107
|
+
|
|
108
|
+
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.1", "", {}, "sha512-UTBjtTxVOhodhzFVp/ayITaTETRHPUPYZPXQe0WU0wOgxghMojXxYjOiPOauKIYNWJAWS2fd7gJgGQK8GU8vDA=="],
|
|
109
|
+
|
|
110
|
+
"@spud.gg/api": ["@spud.gg/api@0.0.24", "", {}, "sha512-QyNEBehQWpQf72wEk050yeo1CaFec6H4mDEXs270qjioGWhbmIOc5GHnYsNa+M26LMk88Slv3VQAEOrHG6tO/w=="],
|
|
111
|
+
|
|
112
|
+
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
|
113
|
+
|
|
114
|
+
"ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="],
|
|
115
|
+
|
|
116
|
+
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
|
|
117
|
+
|
|
118
|
+
"commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="],
|
|
119
|
+
|
|
120
|
+
"css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="],
|
|
121
|
+
|
|
122
|
+
"css-tree": ["css-tree@3.1.0", "", { "dependencies": { "mdn-data": "2.12.2", "source-map-js": "^1.0.1" } }, "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w=="],
|
|
123
|
+
|
|
124
|
+
"css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="],
|
|
125
|
+
|
|
126
|
+
"csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="],
|
|
127
|
+
|
|
128
|
+
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
|
129
|
+
|
|
130
|
+
"dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="],
|
|
131
|
+
|
|
132
|
+
"domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
|
|
133
|
+
|
|
134
|
+
"domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
|
|
135
|
+
|
|
136
|
+
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
|
|
137
|
+
|
|
138
|
+
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
|
139
|
+
|
|
140
|
+
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
|
141
|
+
|
|
142
|
+
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
|
143
|
+
|
|
144
|
+
"lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="],
|
|
145
|
+
|
|
146
|
+
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="],
|
|
147
|
+
|
|
148
|
+
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="],
|
|
149
|
+
|
|
150
|
+
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="],
|
|
151
|
+
|
|
152
|
+
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="],
|
|
153
|
+
|
|
154
|
+
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="],
|
|
155
|
+
|
|
156
|
+
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="],
|
|
157
|
+
|
|
158
|
+
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="],
|
|
159
|
+
|
|
160
|
+
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="],
|
|
161
|
+
|
|
162
|
+
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="],
|
|
163
|
+
|
|
164
|
+
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="],
|
|
165
|
+
|
|
166
|
+
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="],
|
|
167
|
+
|
|
168
|
+
"mdn-data": ["mdn-data@2.12.2", "", {}, "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA=="],
|
|
169
|
+
|
|
170
|
+
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
|
171
|
+
|
|
172
|
+
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
|
|
173
|
+
|
|
174
|
+
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
|
175
|
+
|
|
176
|
+
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
|
177
|
+
|
|
178
|
+
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
|
179
|
+
|
|
180
|
+
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
|
181
|
+
|
|
182
|
+
"rolldown": ["rolldown@1.0.0-rc.1", "", { "dependencies": { "@oxc-project/types": "=0.110.0", "@rolldown/pluginutils": "1.0.0-rc.1" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.1", "@rolldown/binding-darwin-arm64": "1.0.0-rc.1", "@rolldown/binding-darwin-x64": "1.0.0-rc.1", "@rolldown/binding-freebsd-x64": "1.0.0-rc.1", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.1", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.1", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.1", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.1", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.1", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.1", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.1", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.1", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.1" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-M3AeZjYE6UclblEf531Hch0WfVC/NOL43Cc+WdF3J50kk5/fvouHhDumSGTh0oRjbZ8C4faaVr5r6Nx1xMqDGg=="],
|
|
183
|
+
|
|
184
|
+
"sax": ["sax@1.4.4", "", {}, "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw=="],
|
|
185
|
+
|
|
186
|
+
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
|
187
|
+
|
|
188
|
+
"sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="],
|
|
189
|
+
|
|
190
|
+
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
|
191
|
+
|
|
192
|
+
"svgo": ["svgo@4.0.0", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.4.1" }, "bin": "./bin/svgo.js" }, "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw=="],
|
|
193
|
+
|
|
194
|
+
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
|
195
|
+
|
|
196
|
+
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
|
197
|
+
|
|
198
|
+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
199
|
+
|
|
200
|
+
"vite": ["vite@8.0.0-beta.10", "", { "dependencies": { "@oxc-project/runtime": "0.110.0", "fdir": "^6.5.0", "lightningcss": "^1.30.2", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rolldown": "1.0.0-rc.1", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-YXbwlvG+57+LRRJBJYCHki0Z1LWRkPEy3khQ0ZphzW5aJaz17fFBCeefOtHC5VgRuLbG155+lq98I+BjeizQ5Q=="],
|
|
201
|
+
|
|
202
|
+
"vite-plugin-image-optimizer": ["vite-plugin-image-optimizer@2.0.3", "", { "dependencies": { "ansi-colors": "^4.1.3", "pathe": "^2.0.3" }, "peerDependencies": { "sharp": ">=0.34.0", "svgo": ">=4", "vite": ">=5" }, "optionalPeers": ["sharp", "svgo"] }, "sha512-1vrFOTcpSvv6DCY7h8UXab4wqMAjTJB/ndOzG/Kmj1oDOuPF6mbjkNQoGzzCEYeWGe7qU93jc8oQqvoJ57al3A=="],
|
|
203
|
+
|
|
204
|
+
"csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="],
|
|
205
|
+
|
|
206
|
+
"csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>game_name</title>
|
|
8
|
+
<style>
|
|
9
|
+
canvas {
|
|
10
|
+
position: fixed;
|
|
11
|
+
inset: 0;
|
|
12
|
+
height: 100vh;
|
|
13
|
+
width: 100vw;
|
|
14
|
+
/* pixel_art_canvas_css */
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<script type="module" src="/src/demo.ts"></script>
|
|
20
|
+
</body>
|
|
21
|
+
</html>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>game_name</title>
|
|
8
|
+
<style>
|
|
9
|
+
canvas {
|
|
10
|
+
position: fixed;
|
|
11
|
+
inset: 0;
|
|
12
|
+
height: 100vh;
|
|
13
|
+
width: 100vw;
|
|
14
|
+
/* pixel_art_canvas_css */
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<script type="module" src="/src/index.ts"></script>
|
|
20
|
+
</body>
|
|
21
|
+
</html>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "game_slug",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"dev:demo": "vite --open /demo.html",
|
|
9
|
+
"build": "tsc && vite build",
|
|
10
|
+
"preview": "vite preview"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@spud.gg/api": "0.0.24"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"sharp": "0.34.5",
|
|
17
|
+
"svgo": "4.0.0",
|
|
18
|
+
"typescript": "^5",
|
|
19
|
+
"vite": "8.0.0-beta.10",
|
|
20
|
+
"vite-plugin-image-optimizer": "2.0.3"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><defs><style>.cls-1{fill:#2f0007;}.cls-2{fill:#fff;}</style></defs><title>102565_VECTOR_DT_R_01</title><rect class="cls-1" y="7.8" width="32" height="16.36" rx="8.2"/><rect class="cls-2" x="1.7" y="9.5" width="28.6" height="13.03" rx="6.5"/><path class="cls-1" d="M7.4,11.6h0A1.4,1.4,0,0,1,8.8,13v5.7a1.4,1.4,0,0,1-1.4,1.4h0a1.3,1.3,0,0,1-1.3-1.4V13A1.3,1.3,0,0,1,7.4,11.6Z"/><path class="cls-1" d="M11.8,15.8h0a1.4,1.4,0,0,1-1.4,1.4H4.7a1.4,1.4,0,0,1-1.4-1.4h0a1.3,1.3,0,0,1,1.4-1.3h5.7A1.3,1.3,0,0,1,11.8,15.8Z"/><circle class="cls-1" cx="20.7" cy="16" r="1.7"/><circle class="cls-1" cx="23.8" cy="12.8" r="1.7"/><circle class="cls-1" cx="23.8" cy="19.2" r="1.7"/><circle class="cls-1" cx="27.1" cy="16" r="1.7"/><ellipse class="cls-1" cx="14" cy="17.9" rx="1" ry="0.9"/><ellipse class="cls-1" cx="17" cy="17.9" rx="1" ry="0.9"/></svg>
|
|
Binary file
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# game_name
|
|
2
|
+
|
|
3
|
+
# Getting started
|
|
4
|
+
|
|
5
|
+
Useful scripts:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# (re)install dependencies
|
|
9
|
+
bun i
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# start the local development server
|
|
14
|
+
bun dev
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# start the local development server and open the demo.html directly
|
|
19
|
+
bun run dev:demo
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# prepare a production build
|
|
24
|
+
bun run build
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
# Resources:
|
|
28
|
+
|
|
29
|
+
- **Game assets**
|
|
30
|
+
- [itch.io game assets](https://itch.io/game-assets)
|
|
31
|
+
|
|
32
|
+
- **Audio**
|
|
33
|
+
- [sfxr.me sfx generator](https://pro.sfxr.me/)
|
|
34
|
+
- [OpenGameArt cc0 sound effects](https://opengameart.org/art-search-advanced?keys=&title=&field_art_tags_tid_op=or&field_art_tags_tid=&name=&field_art_type_tid%5B%5D=13&field_art_licenses_tid%5B%5D=4)
|
|
35
|
+
|
|
36
|
+
- **Animation**
|
|
37
|
+
- [easings.net](https://easings.net/)
|
|
38
|
+
|
|
39
|
+
- **Sprites & pixel art**
|
|
40
|
+
- [Aseprite](https://www.aseprite.org/)
|
|
41
|
+
- [Pixel planet generator (itch.io)](https://deep-fold.itch.io/pixel-planet-generator)
|
|
42
|
+
|
|
43
|
+
- **Fonts**
|
|
44
|
+
- [Google Fonts](https://fonts.google.com/)
|
|
45
|
+
- [Font Squirrel](https://www.fontsquirrel.com/)
|
|
46
|
+
|
|
47
|
+
- **Documentation for dev tools & APIs used in this project**
|
|
48
|
+
- [Vite docs](https://vite.dev/)
|
|
49
|
+
- [Bun docs](https://bun.com/docs)
|
|
50
|
+
- [TypeScript handbook](https://www.typescriptlang.org/docs/handbook/intro.html)
|
|
51
|
+
- [MDN Canvas API tutorial](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial)
|
|
52
|
+
- [@spud.gg/api (npm)](https://www.npmjs.com/package/@spud.gg/api)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { audio } from "@spud.gg/api";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
when you import binary assets using vite, you'll get a url string.
|
|
5
|
+
read more at https://vite.dev/guide/assets#importing-asset-as-url
|
|
6
|
+
*/
|
|
7
|
+
import shootAudioUrl from "./assets/audio/shoot.wav";
|
|
8
|
+
import menuMusicUrl from "./assets/audio/menu-music.mp3";
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
use createSounds for short, snappy SFX that you want pre-buffered
|
|
12
|
+
for low-latency playback. we recommend creating your own effects
|
|
13
|
+
using a tool like https://pro.sfxr.me/
|
|
14
|
+
*/
|
|
15
|
+
export const sfx = audio.createSounds({
|
|
16
|
+
shoot: {
|
|
17
|
+
url: shootAudioUrl,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
createMusic is for longer tracks that can
|
|
23
|
+
stream and don't need frame-perfect timing.
|
|
24
|
+
*/
|
|
25
|
+
export const menuMusic = audio.createMusic({
|
|
26
|
+
url: menuMusicUrl,
|
|
27
|
+
loop: true,
|
|
28
|
+
volume: 0.4,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
in spud demo mode (spud.isDemoMode === true), audio methods are no-ops.
|
|
33
|
+
that means you can always call sfx("...").play() or music.play() without
|
|
34
|
+
adding conditional checks; the demo stays silent automatically.
|
|
35
|
+
*/
|
|
36
|
+
menuMusic.play();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*
|
|
2
|
+
demo.ts is the entry point for the demo.html file, which displays a
|
|
3
|
+
non-interactive demo of your game. it should be a minimal preview
|
|
4
|
+
version of your game that starts automatically and does not play any
|
|
5
|
+
sounds, use local storage, or handle inputs.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { draw, update } from "./gameplay";
|
|
9
|
+
import { state } from "./state";
|
|
10
|
+
import { resizeCanvasForDpi } from "./helpers";
|
|
11
|
+
|
|
12
|
+
const canvas = document.createElement("canvas");
|
|
13
|
+
document.body.appendChild(canvas);
|
|
14
|
+
|
|
15
|
+
const ctx = canvas.getContext("2d", { alpha: false })!;
|
|
16
|
+
/* pixel_art_image_smoothing */
|
|
17
|
+
|
|
18
|
+
let lastFrameTime = 0;
|
|
19
|
+
let timeToProcessPhysics = 0;
|
|
20
|
+
|
|
21
|
+
function gameLoop(now: number) {
|
|
22
|
+
const dt = Math.min(now - lastFrameTime, 100); // clamp time delta to 100ms in case the user switched tabs
|
|
23
|
+
lastFrameTime = now;
|
|
24
|
+
|
|
25
|
+
resizeCanvasForDpi(ctx);
|
|
26
|
+
|
|
27
|
+
{
|
|
28
|
+
timeToProcessPhysics += dt;
|
|
29
|
+
const physicsTickMs = 1000 / 120; // process physics updates at a fixed 120hz time step
|
|
30
|
+
while (timeToProcessPhysics > physicsTickMs) {
|
|
31
|
+
timeToProcessPhysics -= physicsTickMs;
|
|
32
|
+
update(state, physicsTickMs);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
draw(state, ctx);
|
|
37
|
+
requestAnimationFrame(gameLoop); // queue up the next tick
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
requestAnimationFrame(gameLoop);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Button, gamepads } from "@spud.gg/api";
|
|
2
|
+
import { State } from "./state";
|
|
3
|
+
/* moon_sprite_import */
|
|
4
|
+
/* audio_import */
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
the update loop runs in a fixed time-step and should be used for any
|
|
8
|
+
state updates. `dt` is the time since the last update call.
|
|
9
|
+
*/
|
|
10
|
+
export function update(state: State, dt: number) {
|
|
11
|
+
state.elapsedSeconds += dt / 1000;
|
|
12
|
+
if (gamepads.anyPlayer.buttonJustPressed(Button.RightTrigger)) {
|
|
13
|
+
/* audio_shoot_sfx */
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function draw(state: State, ctx: CanvasRenderingContext2D) {
|
|
18
|
+
const { width, height } = ctx.canvas.getBoundingClientRect();
|
|
19
|
+
const center = {
|
|
20
|
+
x: width / 2,
|
|
21
|
+
y: height / 2,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// clear out the background
|
|
25
|
+
ctx.fillStyle = "#0b0d1a";
|
|
26
|
+
ctx.fillRect(0, 0, width, height);
|
|
27
|
+
|
|
28
|
+
// write some text
|
|
29
|
+
ctx.fillStyle = "white";
|
|
30
|
+
ctx.textAlign = "center";
|
|
31
|
+
ctx.textBaseline = "middle";
|
|
32
|
+
ctx.font = "32px sans-serif";
|
|
33
|
+
ctx.fillText("hello, gamer", center.x, center.y);
|
|
34
|
+
|
|
35
|
+
// draw an orbiting circle
|
|
36
|
+
const moon = {
|
|
37
|
+
radius: 30,
|
|
38
|
+
orbitRadius: 100,
|
|
39
|
+
get x() {
|
|
40
|
+
return center.x + Math.cos(state.elapsedSeconds) * moon.orbitRadius;
|
|
41
|
+
},
|
|
42
|
+
get y() {
|
|
43
|
+
return center.y + Math.sin(state.elapsedSeconds) * moon.orbitRadius;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
/* moon_sprite_draw */
|
|
47
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
by default, canvas rendering is blurry on high-dpi screens.
|
|
3
|
+
this fixes it by scaling the pixel buffer by the devicePixelRatio
|
|
4
|
+
and then setting a matching transform so that the drawing coords
|
|
5
|
+
can stay in CSS pixels.
|
|
6
|
+
|
|
7
|
+
see also: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas
|
|
8
|
+
*/
|
|
9
|
+
export function resizeCanvasForDpi(ctx: CanvasRenderingContext2D) {
|
|
10
|
+
const { width, height } = ctx.canvas.getBoundingClientRect();
|
|
11
|
+
ctx.canvas.width = width * window.devicePixelRatio;
|
|
12
|
+
ctx.canvas.height = height * window.devicePixelRatio;
|
|
13
|
+
ctx.setTransform(window.devicePixelRatio, 0, 0, window.devicePixelRatio, 0, 0);
|
|
14
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*
|
|
2
|
+
index.ts is the main entry point for your game. it's responsible for
|
|
3
|
+
setting up the canvas and the two main game loops: a 120hz fixed time
|
|
4
|
+
step physics/update loop, and a variable framerate draw cycle.
|
|
5
|
+
see also:
|
|
6
|
+
- https://gafferongames.com/post/fix_your_timestep/
|
|
7
|
+
- https://gist.github.com/HipHopHuman/3e9b4a94b30ac9387d9a99ef2d29eb1a
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { spud, gamepads } from "@spud.gg/api";
|
|
11
|
+
import { draw, update } from "./gameplay";
|
|
12
|
+
import { state } from "./state";
|
|
13
|
+
import { resizeCanvasForDpi } from "./helpers";
|
|
14
|
+
|
|
15
|
+
const canvas = document.createElement("canvas");
|
|
16
|
+
document.body.appendChild(canvas);
|
|
17
|
+
|
|
18
|
+
const ctx = canvas.getContext("2d", { alpha: false })!;
|
|
19
|
+
/* pixel_art_image_smoothing */
|
|
20
|
+
|
|
21
|
+
let lastFrameTime = 0;
|
|
22
|
+
let timeToProcessPhysics = 0;
|
|
23
|
+
|
|
24
|
+
function gameLoop(now: number) {
|
|
25
|
+
const dt = Math.min(now - lastFrameTime, 100); // clamp time delta to 100ms in case the user switched tabs
|
|
26
|
+
lastFrameTime = now;
|
|
27
|
+
|
|
28
|
+
resizeCanvasForDpi(ctx);
|
|
29
|
+
|
|
30
|
+
{
|
|
31
|
+
timeToProcessPhysics += dt;
|
|
32
|
+
const physicsTickMs = 1000 / 120; // process physics updates at a fixed 120hz time step
|
|
33
|
+
while (timeToProcessPhysics > physicsTickMs) {
|
|
34
|
+
if (!spud.isPaused) {
|
|
35
|
+
timeToProcessPhysics -= physicsTickMs;
|
|
36
|
+
update(state, physicsTickMs);
|
|
37
|
+
}
|
|
38
|
+
gamepads.clearInputs();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
draw(state, ctx);
|
|
43
|
+
requestAnimationFrame(gameLoop); // queue up the next tick
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
requestAnimationFrame(gameLoop);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
small sprites will be automatically inlined by Vite.
|
|
3
|
+
sprite files larger than the default 4kb assetsInlineLimit will be
|
|
4
|
+
optimized and fetched after the initial bundle has loaded.
|
|
5
|
+
read more at https://vite.dev/guide/assets#importing-asset-as-url
|
|
6
|
+
|
|
7
|
+
moon sprite credit: https://deep-fold.itch.io/pixel-planet-generator
|
|
8
|
+
*/
|
|
9
|
+
import sprite from "./assets/images/sprite.png";
|
|
10
|
+
|
|
11
|
+
type SpriteSheet = {
|
|
12
|
+
image: HTMLImageElement;
|
|
13
|
+
frameWidthPx: number;
|
|
14
|
+
frameHeightPx: number;
|
|
15
|
+
frameCount: number;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const moonSheet: SpriteSheet = {
|
|
19
|
+
image: new Image(),
|
|
20
|
+
frameWidthPx: 50,
|
|
21
|
+
frameHeightPx: 50,
|
|
22
|
+
frameCount: 5000 / 50,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
moonSheet.image.src = sprite;
|
|
26
|
+
|
|
27
|
+
export function drawSprite(
|
|
28
|
+
ctx: CanvasRenderingContext2D,
|
|
29
|
+
sheet: SpriteSheet,
|
|
30
|
+
frameIndex: number,
|
|
31
|
+
x: number,
|
|
32
|
+
y: number,
|
|
33
|
+
) {
|
|
34
|
+
const frame = frameIndex % sheet.frameCount;
|
|
35
|
+
const sourceX = frame * sheet.frameWidthPx;
|
|
36
|
+
const sourceY = 0;
|
|
37
|
+
const drawWidthPx = sheet.frameWidthPx;
|
|
38
|
+
const drawHeightPx = sheet.frameHeightPx;
|
|
39
|
+
|
|
40
|
+
// see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
|
|
41
|
+
ctx.drawImage(
|
|
42
|
+
sheet.image,
|
|
43
|
+
sourceX,
|
|
44
|
+
sourceY,
|
|
45
|
+
sheet.frameWidthPx,
|
|
46
|
+
sheet.frameHeightPx,
|
|
47
|
+
x,
|
|
48
|
+
y,
|
|
49
|
+
drawWidthPx,
|
|
50
|
+
drawHeightPx,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2024",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": [
|
|
6
|
+
"ESNext",
|
|
7
|
+
"DOM",
|
|
8
|
+
"DOM.Iterable"
|
|
9
|
+
],
|
|
10
|
+
"types": [
|
|
11
|
+
"vite/client"
|
|
12
|
+
],
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
/* Bundler mode */
|
|
15
|
+
"moduleResolution": "bundler",
|
|
16
|
+
"allowImportingTsExtensions": true,
|
|
17
|
+
"moduleDetection": "force",
|
|
18
|
+
"noEmit": true,
|
|
19
|
+
/* Linting */
|
|
20
|
+
"strict": true,
|
|
21
|
+
"noUncheckedIndexedAccess": true,
|
|
22
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
23
|
+
"noImplicitOverride": true,
|
|
24
|
+
"erasableSyntaxOnly": true,
|
|
25
|
+
"noFallthroughCasesInSwitch": true,
|
|
26
|
+
"noUncheckedSideEffectImports": true,
|
|
27
|
+
/* Aliases */
|
|
28
|
+
"paths": {
|
|
29
|
+
"~/*": [
|
|
30
|
+
"./src/*"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"include": [
|
|
35
|
+
"src"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { ViteImageOptimizer } from "vite-plugin-image-optimizer";
|
|
5
|
+
|
|
6
|
+
const dir = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
build: {
|
|
10
|
+
modulePreload: {
|
|
11
|
+
polyfill: false,
|
|
12
|
+
},
|
|
13
|
+
rolldownOptions: {
|
|
14
|
+
input: {
|
|
15
|
+
main: resolve(dir, "index.html"),
|
|
16
|
+
demo: resolve(dir, "demo.html"),
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
plugins: [ViteImageOptimizer()],
|
|
21
|
+
resolve: {
|
|
22
|
+
tsconfigPaths: true,
|
|
23
|
+
},
|
|
24
|
+
});
|
package/index.ts
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { mkdir, readdir } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { intro, outro, cancel, text, confirm, tasks, group, multiselect } from "@clack/prompts";
|
|
6
|
+
import kebabcase from "lodash.kebabcase";
|
|
7
|
+
|
|
8
|
+
intro("It's spud time.");
|
|
9
|
+
|
|
10
|
+
const Feature = { Audio: "Audio", PixelArt: "PixelArt" } as const;
|
|
11
|
+
type Feature = (typeof Feature)[keyof typeof Feature];
|
|
12
|
+
|
|
13
|
+
const { rawGameName, features, shouldContinue } = await group(
|
|
14
|
+
{
|
|
15
|
+
rawGameName: () =>
|
|
16
|
+
text({
|
|
17
|
+
message: "Game name",
|
|
18
|
+
placeholder: "eg. Space Invaders",
|
|
19
|
+
validate(value) {
|
|
20
|
+
if (!value?.trim()) return "Game name is required. Esc to cancel.";
|
|
21
|
+
},
|
|
22
|
+
}),
|
|
23
|
+
features: () =>
|
|
24
|
+
multiselect({
|
|
25
|
+
message: "Features",
|
|
26
|
+
initialValues: [Feature.Audio],
|
|
27
|
+
required: false,
|
|
28
|
+
options: [
|
|
29
|
+
{ label: "Audio", value: Feature.Audio },
|
|
30
|
+
{ label: "Pixel art", value: Feature.PixelArt },
|
|
31
|
+
],
|
|
32
|
+
}),
|
|
33
|
+
shouldContinue: ({ results }) =>
|
|
34
|
+
confirm({
|
|
35
|
+
message: `We'll create a folder for "${kebabcase((results.rawGameName ?? "").trim())}" in the current directory. Do you want to continue?`,
|
|
36
|
+
}),
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
onCancel() {
|
|
40
|
+
cancel("Cancelled.");
|
|
41
|
+
process.exit(0);
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
if (!shouldContinue) {
|
|
47
|
+
cancel("Operation cancelled.");
|
|
48
|
+
process.exit(0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const gameName = rawGameName.trim();
|
|
52
|
+
const slug = kebabcase(gameName);
|
|
53
|
+
const targetDir = path.resolve(process.cwd(), slug);
|
|
54
|
+
const templateDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "example");
|
|
55
|
+
|
|
56
|
+
await tasks([
|
|
57
|
+
{
|
|
58
|
+
title: `Scaffolding project in ./${slug}/`,
|
|
59
|
+
async task() {
|
|
60
|
+
await mkdir(targetDir, { recursive: true });
|
|
61
|
+
await copyDir(templateDir, targetDir, { gameName, slug, features });
|
|
62
|
+
return "Initialized project from spud starter template";
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
title: "Installing dependencies with Bun",
|
|
67
|
+
async task() {
|
|
68
|
+
const proc = Bun.spawn(["bun", "install"], {
|
|
69
|
+
cwd: targetDir,
|
|
70
|
+
});
|
|
71
|
+
await proc.exited;
|
|
72
|
+
return "Installed via bun";
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
outro(`You're all set! Now: cd ${slug} && bun dev`);
|
|
78
|
+
|
|
79
|
+
async function copyDir(
|
|
80
|
+
sourceDir: string,
|
|
81
|
+
destDir: string,
|
|
82
|
+
replacements: { gameName: string; slug: string; features: Feature[] },
|
|
83
|
+
) {
|
|
84
|
+
await mkdir(destDir, { recursive: true });
|
|
85
|
+
const entries = await readdir(sourceDir, { withFileTypes: true });
|
|
86
|
+
|
|
87
|
+
for (const entry of entries) {
|
|
88
|
+
const sourcePath = path.join(sourceDir, entry.name);
|
|
89
|
+
const destPath = path.join(destDir, entry.name);
|
|
90
|
+
|
|
91
|
+
if (entry.isDirectory()) {
|
|
92
|
+
if (entry.name === "node_modules" || entry.name === "dist") continue;
|
|
93
|
+
if (entry.name === "audio" && !replacements.features.includes(Feature.Audio)) continue;
|
|
94
|
+
await copyDir(sourcePath, destPath, replacements);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!entry.isFile()) continue;
|
|
99
|
+
if (entry.name === "audio.ts" && !replacements.features.includes(Feature.Audio)) continue;
|
|
100
|
+
if (entry.name === "sprite.ts" && !replacements.features.includes(Feature.PixelArt)) continue;
|
|
101
|
+
|
|
102
|
+
const ext = path.extname(entry.name);
|
|
103
|
+
const extensionsThatMayContainTemplateVariables = [".html", ".json", ".md", ".ts"];
|
|
104
|
+
|
|
105
|
+
if (!extensionsThatMayContainTemplateVariables.includes(ext)) {
|
|
106
|
+
const file = Bun.file(sourcePath);
|
|
107
|
+
await Bun.write(destPath, file);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const text = await Bun.file(sourcePath).text();
|
|
112
|
+
const replaced = text
|
|
113
|
+
.replaceAll("game_name", replacements.gameName)
|
|
114
|
+
.replaceAll("game_slug", replacements.slug)
|
|
115
|
+
.replaceAll(
|
|
116
|
+
" /* pixel_art_canvas_css */\n",
|
|
117
|
+
replacements.features.includes(Feature.PixelArt)
|
|
118
|
+
? " image-rendering: pixelated;\n"
|
|
119
|
+
: "",
|
|
120
|
+
)
|
|
121
|
+
.replaceAll(
|
|
122
|
+
"/* pixel_art_canvas_css */\n",
|
|
123
|
+
replacements.features.includes(Feature.PixelArt) ? "image-rendering: pixelated;\n" : "",
|
|
124
|
+
)
|
|
125
|
+
.replaceAll(
|
|
126
|
+
"/* pixel_art_image_smoothing */\n",
|
|
127
|
+
replacements.features.includes(Feature.PixelArt)
|
|
128
|
+
? "ctx.imageSmoothingEnabled = false;\n"
|
|
129
|
+
: "",
|
|
130
|
+
)
|
|
131
|
+
.replaceAll(
|
|
132
|
+
"/* moon_sprite_import */\n",
|
|
133
|
+
replacements.features.includes(Feature.PixelArt)
|
|
134
|
+
? 'import { drawSprite, moonSheet } from "./sprite";\n'
|
|
135
|
+
: "",
|
|
136
|
+
)
|
|
137
|
+
.replaceAll(
|
|
138
|
+
"/* audio_import */\n",
|
|
139
|
+
replacements.features.includes(Feature.Audio) ? 'import { sfx } from "./audio";\n' : "",
|
|
140
|
+
)
|
|
141
|
+
.replaceAll(
|
|
142
|
+
" /* moon_sprite_draw */\n",
|
|
143
|
+
replacements.features.includes(Feature.PixelArt)
|
|
144
|
+
? ` const moonFrameIndex = Math.floor(state.elapsedSeconds * 12);
|
|
145
|
+
drawSprite(ctx, moonSheet, moonFrameIndex, moon.x - moon.radius, moon.y - moon.radius);
|
|
146
|
+
`
|
|
147
|
+
: ` ctx.beginPath();
|
|
148
|
+
ctx.arc(moon.x, moon.y, moon.radius, 0, Math.PI * 2);
|
|
149
|
+
ctx.fill();
|
|
150
|
+
`,
|
|
151
|
+
)
|
|
152
|
+
.replaceAll(
|
|
153
|
+
" /* audio_shoot_sfx */\n",
|
|
154
|
+
replacements.features.includes(Feature.Audio)
|
|
155
|
+
? ` sfx("shoot").play({
|
|
156
|
+
detune: -1000 + Math.random() * 2000,
|
|
157
|
+
playbackRate: 0.5 + Math.random(),
|
|
158
|
+
});
|
|
159
|
+
`
|
|
160
|
+
: " /* handle inputs and update state */\n",
|
|
161
|
+
);
|
|
162
|
+
await Bun.write(destPath, replaced);
|
|
163
|
+
}
|
|
164
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-spud",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"bin": {
|
|
5
|
+
"create-spud": "./index.ts"
|
|
6
|
+
},
|
|
7
|
+
"files": [
|
|
8
|
+
"index.ts",
|
|
9
|
+
"example"
|
|
10
|
+
],
|
|
11
|
+
"type": "module",
|
|
12
|
+
"module": "index.ts",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@clack/prompts": "0.11.0",
|
|
15
|
+
"lodash.kebabcase": "4.1.1"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/bun": "latest",
|
|
19
|
+
"@types/lodash.kebabcase": "4.1.9"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"bun": ">=1.0.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# `create-spud`
|
|
2
|
+
|
|
3
|
+
The quickest way to set up and scaffold a [spud](https://spud.gg) game.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun create spud
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What gets created
|
|
12
|
+
|
|
13
|
+
- A new folder named after your game
|
|
14
|
+
- A ready-to-run spud game project based on the `example/` template
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
- [Bun](https://bun.com/) (runtime + package manager)
|
|
19
|
+
|
|
20
|
+
<details>
|
|
21
|
+
<summary><strong>Bun installation guide</strong></summary>
|
|
22
|
+
|
|
23
|
+
1. Install Bun ([docs](https://bun.com/docs/installation)):
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
curl -fsSL https://bun.sh/install | bash
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
2. Then restart your terminal so `bun` is on your `$PATH`.
|
|
30
|
+
|
|
31
|
+
</details>
|
|
32
|
+
|
|
33
|
+
## Notes
|
|
34
|
+
|
|
35
|
+
- This CLI is Bun-only. If you try to run it with Node (`npx create spud`, for example), that won't work.
|