feat(#3): simplify code
4
.gitignore
vendored
|
@ -1,5 +1 @@
|
||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
|
||||||
.DS_Store
|
|
||||||
*.log
|
|
||||||
deploy
|
|
|
@ -4,13 +4,14 @@ A WIP game for learning purpouses
|
||||||
|
|
||||||
## Libraries Used
|
## Libraries Used
|
||||||
|
|
||||||
- None at the moment, just rollup
|
- None at the moment, just serve
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
- Created by Juan Sebastián Montoya
|
- Created by Juan Sebastián Montoya
|
||||||
- Assets by:
|
- Assets by:
|
||||||
- [ArMM1998](https://opengameart.org/content/zelda-like-tilesets-and-sprites)
|
- [ArMM1998](https://opengameart.org/content/zelda-like-tilesets-and-sprites)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
|
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
|
||||||
|
|
BIN
assets/cave.png
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 11 KiB |
BIN
assets/font.png
Before Width: | Height: | Size: 2.4 KiB |
BIN
assets/inner.png
Before Width: | Height: | Size: 18 KiB |
BIN
assets/log.png
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 24 KiB |
21
index.css
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#game {
|
||||||
|
border: 1px solid black;
|
||||||
|
image-rendering: crisp-edges;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
}
|
||||||
|
#resources {
|
||||||
|
display: none;
|
||||||
|
}
|
60
index.html
|
@ -1,48 +1,24 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>Evolver</title>
|
|
||||||
<style>
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#game {
|
<head>
|
||||||
display: flex;
|
<meta charset="UTF-8">
|
||||||
flex-direction: column;
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
justify-content: center;
|
<title>Baena</title>
|
||||||
align-items: center;
|
<link rel="stylesheet" href="index.css">
|
||||||
height: 100%;
|
</head>
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas {
|
<body>
|
||||||
background-color: #fbf7f3;
|
<div id="resources">
|
||||||
border: 1px solid black;
|
<img id="overworld" src="resources/overworld.png">
|
||||||
image-rendering: pixelated;
|
</div>
|
||||||
image-rendering: crisp-edges;
|
<div id="container">
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin: 5px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="game">
|
|
||||||
<div id="controls">
|
|
||||||
<button id="debug">Debug</button>
|
<button id="debug">Debug</button>
|
||||||
|
<button id="level1">Level 1</button>
|
||||||
|
<button id="level2">Level 2</button>
|
||||||
|
<canvas id="game"></canvas>
|
||||||
</div>
|
</div>
|
||||||
<canvas></canvas>
|
<script type="module" src="index.js"></script>
|
||||||
</div>
|
</body>
|
||||||
<script
|
|
||||||
type="module"
|
|
||||||
src="src/index.js"
|
|
||||||
></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
71
index.js
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import { CanvasResizer } from "./modules/canvas-resizer.js";
|
||||||
|
import { getLevel } from "./modules/utils.js";
|
||||||
|
|
||||||
|
const TILE_SIZE = 16;
|
||||||
|
const canvasResizer = new CanvasResizer({
|
||||||
|
canvas: document.getElementById("game"),
|
||||||
|
width: 320,
|
||||||
|
height: 240,
|
||||||
|
percentage: 0.9
|
||||||
|
});
|
||||||
|
|
||||||
|
const cols = canvasResizer.width / TILE_SIZE;
|
||||||
|
const rows = canvasResizer.height / TILE_SIZE;
|
||||||
|
const ctx = canvasResizer.canvas.getContext("2d");
|
||||||
|
let debug = false;
|
||||||
|
|
||||||
|
async function drawLevel({ levelName, imageName }) {
|
||||||
|
const levelImage = document.getElementById(imageName);
|
||||||
|
const level = await getLevel(levelName);
|
||||||
|
const layer = level.layers[0];
|
||||||
|
const data = layer.data;
|
||||||
|
|
||||||
|
for (let row = 0; row < rows; row++) {
|
||||||
|
for (let col = 0; col < cols; col++) {
|
||||||
|
if (debug) {
|
||||||
|
ctx.strokeRect(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE)
|
||||||
|
}
|
||||||
|
|
||||||
|
const tile = data[row * cols + col]
|
||||||
|
ctx.drawImage(
|
||||||
|
levelImage,
|
||||||
|
((tile - 1) * TILE_SIZE) % levelImage.width,
|
||||||
|
Math.floor((tile - 1) * TILE_SIZE / levelImage.width) * TILE_SIZE,
|
||||||
|
TILE_SIZE,
|
||||||
|
TILE_SIZE,
|
||||||
|
col * TILE_SIZE,
|
||||||
|
row * TILE_SIZE,
|
||||||
|
TILE_SIZE,
|
||||||
|
TILE_SIZE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
await canvasResizer.load()
|
||||||
|
|
||||||
|
let selectedLevel = { levelName: "overworld", imageName: "overworld" };
|
||||||
|
|
||||||
|
const debugButton = document.getElementById("debug");
|
||||||
|
debugButton.addEventListener("click", async () => {
|
||||||
|
debug = !debug;
|
||||||
|
await drawLevel(selectedLevel);
|
||||||
|
});
|
||||||
|
|
||||||
|
const level1Button = document.getElementById("level1");
|
||||||
|
level1Button.addEventListener("click", async () => {
|
||||||
|
selectedLevel = { levelName: "overworld", imageName: "overworld" }
|
||||||
|
await drawLevel(selectedLevel);
|
||||||
|
});
|
||||||
|
|
||||||
|
const level2Button = document.getElementById("level2");
|
||||||
|
level2Button.addEventListener("click", async () => {
|
||||||
|
selectedLevel = { levelName: "ocean", imageName: "overworld" }
|
||||||
|
await drawLevel(selectedLevel);
|
||||||
|
});
|
||||||
|
|
||||||
|
await drawLevel(selectedLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
41
modules/canvas-resizer.js
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
export class CanvasResizer {
|
||||||
|
/**
|
||||||
|
* Creates a new instance of `CanvasResizer` class.
|
||||||
|
* @param {Object} config - The configuration options for the class.
|
||||||
|
* @param {HTMLCanvasElement} config.canvas - The canvas element to resize.
|
||||||
|
* @param {number} config.width - The native width.
|
||||||
|
* @param {number} config.height - The native height.
|
||||||
|
* @param {number} config.percentage - The percentage of the screen size to use for the canvas.
|
||||||
|
*/
|
||||||
|
constructor({ canvas, width, height, percentage }) {
|
||||||
|
this.canvas = canvas;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.percentage = percentage;
|
||||||
|
|
||||||
|
this.canvas.width = this.width;
|
||||||
|
this.canvas.height = this.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
load() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
["load", "resize"].map(item => window.addEventListener(item, () => {
|
||||||
|
this._resize();
|
||||||
|
if (item === "load") {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_resize() {
|
||||||
|
let canvasWidth = Math.floor(window.innerWidth * this.percentage);
|
||||||
|
let canvasHeight = Math.floor(canvasWidth / (this.width / this.height));
|
||||||
|
if (canvasHeight >= window.innerHeight * this.percentage) {
|
||||||
|
canvasHeight = Math.floor(window.innerHeight * this.percentage);
|
||||||
|
canvasWidth = Math.floor(canvasHeight / (this.height / this.width))
|
||||||
|
}
|
||||||
|
this.canvas.style.width = canvasWidth + 'px';
|
||||||
|
this.canvas.style.height = canvasHeight + 'px';
|
||||||
|
}
|
||||||
|
}
|
4
modules/utils.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export async function getLevel(name) {
|
||||||
|
const level = await fetch("/resources/" + name + ".json")
|
||||||
|
return await level.json()
|
||||||
|
}
|
16
package.json
|
@ -3,25 +3,13 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "del-cli dist",
|
"serve": "serve ."
|
||||||
"build": "yarn clean && rollup -c",
|
|
||||||
"serve": "yarn clean && rollup -c --watch"
|
|
||||||
},
|
},
|
||||||
"repository": "git@git.jusemon.com:jusemon/evolver.git",
|
"repository": "git@git.jusemon.com:jusemon/evolver.git",
|
||||||
"author": "Jusemon <juansmm@outlook.com>",
|
"author": "Jusemon <juansmm@outlook.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "^26.0.1",
|
"serve": "^14.2.3"
|
||||||
"@rollup/plugin-json": "^6.1.0",
|
|
||||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
||||||
"@rollup/plugin-terser": "^0.4.4",
|
|
||||||
"@web/rollup-plugin-html": "^2.3.0",
|
|
||||||
"chalk": "^5.2.0",
|
|
||||||
"del-cli": "^5.1.0",
|
|
||||||
"rollup": "^4.18.0",
|
|
||||||
"rollup-plugin-copy2": "^0.4.0",
|
|
||||||
"rollup-plugin-serve": "^1.1.1",
|
|
||||||
"rollup-plugin-zip": "^1.0.3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
345
resources/ocean.json
Normal file
|
@ -0,0 +1,345 @@
|
||||||
|
{
|
||||||
|
"compressionlevel": -1,
|
||||||
|
"height": 15,
|
||||||
|
"infinite": false,
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
259,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
299,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
339,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
124,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
165,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
166,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
125,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284
|
||||||
|
],
|
||||||
|
"height": 15,
|
||||||
|
"id": 1,
|
||||||
|
"name": "Tile Layer 1",
|
||||||
|
"opacity": 1,
|
||||||
|
"type": "tilelayer",
|
||||||
|
"visible": true,
|
||||||
|
"width": 20,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nextlayerid": 2,
|
||||||
|
"nextobjectid": 1,
|
||||||
|
"orientation": "orthogonal",
|
||||||
|
"renderorder": "right-down",
|
||||||
|
"tiledversion": "1.11.0",
|
||||||
|
"tileheight": 16,
|
||||||
|
"tilesets": [
|
||||||
|
{
|
||||||
|
"columns": 40,
|
||||||
|
"firstgid": 1,
|
||||||
|
"image": "overworld.png",
|
||||||
|
"imageheight": 576,
|
||||||
|
"imagewidth": 640,
|
||||||
|
"margin": 0,
|
||||||
|
"name": "overworld",
|
||||||
|
"spacing": 0,
|
||||||
|
"tilecount": 1440,
|
||||||
|
"tileheight": 16,
|
||||||
|
"tilewidth": 16
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tilewidth": 16,
|
||||||
|
"type": "map",
|
||||||
|
"version": "1.10",
|
||||||
|
"width": 20
|
||||||
|
}
|
345
resources/overworld.json
Normal file
|
@ -0,0 +1,345 @@
|
||||||
|
{
|
||||||
|
"compressionlevel": -1,
|
||||||
|
"height": 15,
|
||||||
|
"infinite": false,
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
1,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
1,
|
||||||
|
1179,
|
||||||
|
445,
|
||||||
|
446,
|
||||||
|
446,
|
||||||
|
446,
|
||||||
|
690,
|
||||||
|
259,
|
||||||
|
260,
|
||||||
|
261,
|
||||||
|
1,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
1,
|
||||||
|
1179,
|
||||||
|
485,
|
||||||
|
486,
|
||||||
|
486,
|
||||||
|
486,
|
||||||
|
730,
|
||||||
|
299,
|
||||||
|
300,
|
||||||
|
301,
|
||||||
|
121,
|
||||||
|
122,
|
||||||
|
122,
|
||||||
|
122,
|
||||||
|
122,
|
||||||
|
122,
|
||||||
|
122,
|
||||||
|
122,
|
||||||
|
123,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1179,
|
||||||
|
525,
|
||||||
|
526,
|
||||||
|
526,
|
||||||
|
526,
|
||||||
|
770,
|
||||||
|
339,
|
||||||
|
340,
|
||||||
|
341,
|
||||||
|
161,
|
||||||
|
162,
|
||||||
|
162,
|
||||||
|
162,
|
||||||
|
162,
|
||||||
|
162,
|
||||||
|
162,
|
||||||
|
162,
|
||||||
|
163,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1219,
|
||||||
|
565,
|
||||||
|
566,
|
||||||
|
567,
|
||||||
|
567,
|
||||||
|
810,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
379,
|
||||||
|
201,
|
||||||
|
202,
|
||||||
|
202,
|
||||||
|
202,
|
||||||
|
202,
|
||||||
|
202,
|
||||||
|
202,
|
||||||
|
202,
|
||||||
|
203,
|
||||||
|
243,
|
||||||
|
244,
|
||||||
|
245,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
850,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
243,
|
||||||
|
244,
|
||||||
|
244,
|
||||||
|
244,
|
||||||
|
244,
|
||||||
|
244,
|
||||||
|
244,
|
||||||
|
244,
|
||||||
|
245,
|
||||||
|
283,
|
||||||
|
284,
|
||||||
|
285,
|
||||||
|
406,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
324,
|
||||||
|
324,
|
||||||
|
324,
|
||||||
|
283,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
285,
|
||||||
|
323,
|
||||||
|
324,
|
||||||
|
325,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
283,
|
||||||
|
363,
|
||||||
|
364,
|
||||||
|
363,
|
||||||
|
364,
|
||||||
|
363,
|
||||||
|
364,
|
||||||
|
284,
|
||||||
|
285,
|
||||||
|
366,
|
||||||
|
1175,
|
||||||
|
1176,
|
||||||
|
1177,
|
||||||
|
366,
|
||||||
|
1175,
|
||||||
|
1176,
|
||||||
|
1177,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
283,
|
||||||
|
403,
|
||||||
|
404,
|
||||||
|
403,
|
||||||
|
404,
|
||||||
|
403,
|
||||||
|
404,
|
||||||
|
284,
|
||||||
|
285,
|
||||||
|
406,
|
||||||
|
1215,
|
||||||
|
1216,
|
||||||
|
1217,
|
||||||
|
366,
|
||||||
|
1215,
|
||||||
|
1216,
|
||||||
|
1217,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
283,
|
||||||
|
363,
|
||||||
|
364,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
363,
|
||||||
|
364,
|
||||||
|
284,
|
||||||
|
285,
|
||||||
|
366,
|
||||||
|
1255,
|
||||||
|
1256,
|
||||||
|
1257,
|
||||||
|
366,
|
||||||
|
1255,
|
||||||
|
1256,
|
||||||
|
1257,
|
||||||
|
366,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
283,
|
||||||
|
403,
|
||||||
|
404,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
403,
|
||||||
|
404,
|
||||||
|
284,
|
||||||
|
285,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
283,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
363,
|
||||||
|
364,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
285,
|
||||||
|
366,
|
||||||
|
1175,
|
||||||
|
1176,
|
||||||
|
1177,
|
||||||
|
406,
|
||||||
|
1175,
|
||||||
|
1176,
|
||||||
|
1177,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
283,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
403,
|
||||||
|
404,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
285,
|
||||||
|
406,
|
||||||
|
1215,
|
||||||
|
1216,
|
||||||
|
1217,
|
||||||
|
366,
|
||||||
|
1215,
|
||||||
|
1216,
|
||||||
|
1217,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
283,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
284,
|
||||||
|
285,
|
||||||
|
366,
|
||||||
|
1255,
|
||||||
|
1256,
|
||||||
|
1257,
|
||||||
|
366,
|
||||||
|
1255,
|
||||||
|
1256,
|
||||||
|
1257,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
366,
|
||||||
|
323,
|
||||||
|
324,
|
||||||
|
324,
|
||||||
|
324,
|
||||||
|
324,
|
||||||
|
324,
|
||||||
|
324,
|
||||||
|
324,
|
||||||
|
325,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406,
|
||||||
|
406
|
||||||
|
],
|
||||||
|
"height": 15,
|
||||||
|
"id": 1,
|
||||||
|
"name": "Tile Layer 1",
|
||||||
|
"opacity": 1,
|
||||||
|
"type": "tilelayer",
|
||||||
|
"visible": true,
|
||||||
|
"width": 20,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nextlayerid": 2,
|
||||||
|
"nextobjectid": 1,
|
||||||
|
"orientation": "orthogonal",
|
||||||
|
"renderorder": "right-down",
|
||||||
|
"tiledversion": "1.11.0",
|
||||||
|
"tileheight": 16,
|
||||||
|
"tilesets": [
|
||||||
|
{
|
||||||
|
"columns": 40,
|
||||||
|
"firstgid": 1,
|
||||||
|
"image": "overworld.png",
|
||||||
|
"imageheight": 576,
|
||||||
|
"imagewidth": 640,
|
||||||
|
"margin": 0,
|
||||||
|
"name": "overworld",
|
||||||
|
"spacing": 0,
|
||||||
|
"tilecount": 1440,
|
||||||
|
"tileheight": 16,
|
||||||
|
"tilewidth": 16
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tilewidth": 16,
|
||||||
|
"type": "map",
|
||||||
|
"version": "1.10",
|
||||||
|
"width": 20
|
||||||
|
}
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
28
resources/overworld.tmx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="20" height="15" tilewidth="16" tileheight="16" infinite="0" nextlayerid="2" nextobjectid="1">
|
||||||
|
<editorsettings>
|
||||||
|
<export target="ocean.tmj" format="json"/>
|
||||||
|
</editorsettings>
|
||||||
|
<tileset firstgid="1" name="overworld" tilewidth="16" tileheight="16" tilecount="1440" columns="40">
|
||||||
|
<image source="overworld.png" width="640" height="576"/>
|
||||||
|
</tileset>
|
||||||
|
<layer id="1" name="Tile Layer 1" width="20" height="15">
|
||||||
|
<data encoding="csv">
|
||||||
|
259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,
|
||||||
|
299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,
|
||||||
|
339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
|
||||||
|
379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,
|
||||||
|
284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,
|
||||||
|
284,284,284,284,284,284,284,284,284,284,125,284,284,284,284,284,284,284,284,284,
|
||||||
|
284,125,284,284,284,284,284,125,284,284,284,284,284,284,284,125,284,284,284,284,
|
||||||
|
284,284,284,284,284,124,284,284,284,165,284,284,284,284,284,284,284,284,284,284,
|
||||||
|
284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,166,284,284,
|
||||||
|
284,284,125,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,
|
||||||
|
284,284,284,284,284,284,284,284,284,284,125,284,284,284,284,284,284,284,284,284,
|
||||||
|
284,284,284,125,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,
|
||||||
|
284,284,284,284,284,284,125,284,284,284,284,284,284,284,125,284,284,284,284,284,
|
||||||
|
284,284,284,284,284,284,284,284,284,284,284,125,284,284,284,284,284,284,125,284,
|
||||||
|
284,284,284,284,284,125,284,284,284,284,284,284,284,284,284,284,284,284,284,284
|
||||||
|
</data>
|
||||||
|
</layer>
|
||||||
|
</map>
|
|
@ -1,62 +0,0 @@
|
||||||
import path from "path";
|
|
||||||
import fs from "fs";
|
|
||||||
import chalk from "chalk";
|
|
||||||
|
|
||||||
export default function bundleSize({ file, maxSize = 13 }) {
|
|
||||||
return {
|
|
||||||
name: "rollup-plugin-bundle-size",
|
|
||||||
writeBundle: {
|
|
||||||
secuential: true,
|
|
||||||
order: "post",
|
|
||||||
async handler(options, bundle) {
|
|
||||||
let uncompressedSize = 0;
|
|
||||||
console.log(
|
|
||||||
chalk.green("Filename".padEnd(30, " ") + "\t Size (bytes).")
|
|
||||||
);
|
|
||||||
for (const file in bundle) {
|
|
||||||
const { modules } = bundle[file];
|
|
||||||
if (bundle[file].type === 'chunk') {
|
|
||||||
for (const moduleName in modules) {
|
|
||||||
const module = modules[moduleName];
|
|
||||||
const name = path.basename(moduleName);
|
|
||||||
uncompressedSize += module.renderedLength;
|
|
||||||
console.log(
|
|
||||||
`${chalk.cyan(name.padEnd(30, " "))}\t ${chalk.cyan(
|
|
||||||
module.renderedLength
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (bundle[file].type === 'asset') {
|
|
||||||
const { size } = fs.statSync(file);
|
|
||||||
uncompressedSize += size;
|
|
||||||
console.log(
|
|
||||||
`${chalk.cyan(file.padEnd(30, " "))}\t ${chalk.cyan(
|
|
||||||
size
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
chalk.green(
|
|
||||||
"Total before compression " +
|
|
||||||
chalk.bold(chalk.green(uncompressedSize))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const asset = path.join(options.dir, file);
|
|
||||||
const { size } = fs.statSync(asset);
|
|
||||||
const percent = parseInt((size / (maxSize * 1024)) * 100, 10);
|
|
||||||
const color =
|
|
||||||
percent < 50 ? chalk.green : percent < 80 ? chalk.yellow : chalk.red;
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Created bundle ${chalk.cyan(asset)}: ${chalk.bold(
|
|
||||||
chalk.cyan(size)
|
|
||||||
)} bytes, ${color(percent + "%")} of total game size used.`
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,41 +0,0 @@
|
||||||
import json from "@rollup/plugin-json";
|
|
||||||
import terser from "@rollup/plugin-terser";
|
|
||||||
import { rollupPluginHTML as html } from "@web/rollup-plugin-html";
|
|
||||||
import zip from "rollup-plugin-zip";
|
|
||||||
import serve from "rollup-plugin-serve";
|
|
||||||
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
|
||||||
import commonjs from "@rollup/plugin-commonjs";
|
|
||||||
import copy from "rollup-plugin-copy2";
|
|
||||||
import bundleSize from "./rollup-plugins/bundle-size.mjs";
|
|
||||||
|
|
||||||
const zipPlug = zip({ file: "game.zip" });
|
|
||||||
zipPlug.writeBundle.sequential = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {import('rollup').RollupOptions}
|
|
||||||
*/
|
|
||||||
export default {
|
|
||||||
input: "index.html",
|
|
||||||
output: [
|
|
||||||
{
|
|
||||||
inlineDynamicImports: true,
|
|
||||||
dir: "dist",
|
|
||||||
format: "iife",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
inlineDynamicImports: true,
|
|
||||||
dir: "dist/min",
|
|
||||||
format: "iife",
|
|
||||||
name: "version",
|
|
||||||
plugins: [terser(), zipPlug, bundleSize({ file: "game.zip", maxSize: 13 })],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
html({ minify: true }),
|
|
||||||
json(),
|
|
||||||
nodeResolve(),
|
|
||||||
commonjs(),
|
|
||||||
copy({ assets: ["assets/*"] }),
|
|
||||||
serve({ contentBase: "dist", port: 9000, verbose: true }),
|
|
||||||
],
|
|
||||||
};
|
|
|
@ -1,113 +0,0 @@
|
||||||
/**
|
|
||||||
* Represents a canvas window that resizes to fit the screen while maintaining a native aspect ratio.
|
|
||||||
*/
|
|
||||||
export default class CanvasWindow {
|
|
||||||
/**
|
|
||||||
* Creates a new instance of the `CanvasWindow` class.
|
|
||||||
* @param {Object} config - The configuration options for the canvas window.
|
|
||||||
* @param {number} config.nativeWidth - The width of the native game size.
|
|
||||||
* @param {number} config.nativeHeight - The height of the native game size.
|
|
||||||
* @param {number} config.maxMultiplier - The maximum allowed size multiplier for the canvas window.
|
|
||||||
* @param {number} config.windowPercentage - The percentage of the screen size to use for the canvas window.
|
|
||||||
* @param {HTMLCanvasElement} config.canvas - The canvas element to resize.
|
|
||||||
*/
|
|
||||||
constructor(config) {
|
|
||||||
/**
|
|
||||||
* The width of the native game size.
|
|
||||||
*
|
|
||||||
* @member {number}
|
|
||||||
*/
|
|
||||||
this.nativeWidth = config.nativeWidth ?? 320;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The height of the native game size.
|
|
||||||
*
|
|
||||||
* @member {number}
|
|
||||||
*/
|
|
||||||
this.nativeHeight = config.nativeHeight ?? 240;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The max multiplier.
|
|
||||||
*
|
|
||||||
* @member {number}
|
|
||||||
*/
|
|
||||||
this.maxMultiplier = config.maxMultiplier ?? 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The percentage of the window size to use for the canvas size.
|
|
||||||
*
|
|
||||||
* @member {number}
|
|
||||||
*/
|
|
||||||
this.windowPercentage = config.windowPercentage ?? 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The canvas element to resize.
|
|
||||||
*
|
|
||||||
* @member {HTMLCanvasElement}
|
|
||||||
*/
|
|
||||||
this.canvas = config.canvas;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum width of the canvas.
|
|
||||||
*
|
|
||||||
* @member {number}
|
|
||||||
*/
|
|
||||||
this.maxWidth = this.nativeWidth * this.maxMultiplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum width of the canvas.
|
|
||||||
*
|
|
||||||
* @member {number}
|
|
||||||
*/
|
|
||||||
this.maxHeight = this.nativeHeight * this.maxMultiplier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum width of the canvas.
|
|
||||||
*
|
|
||||||
* @member {number}
|
|
||||||
*/
|
|
||||||
this.canvasWidth = this.nativeWidth;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum width of the canvas.
|
|
||||||
*
|
|
||||||
* @member {number}
|
|
||||||
*/
|
|
||||||
this.canvasHeight = this.nativeHeight;
|
|
||||||
|
|
||||||
window.addEventListener("resize", () => this.resize());
|
|
||||||
}
|
|
||||||
|
|
||||||
async load() {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
window.addEventListener("load", () => {
|
|
||||||
this.canvas.width = this.canvasWidth;
|
|
||||||
this.canvas.height = this.canvasHeight;
|
|
||||||
this.resize();
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resizes the canvas window to fit the screen while maintaining the native aspect ratio.
|
|
||||||
*/
|
|
||||||
resize() {
|
|
||||||
this.canvasWidth = window.innerWidth;
|
|
||||||
this.canvasHeight = window.innerHeight;
|
|
||||||
const nativeRatio = this.nativeWidth / this.nativeHeight;
|
|
||||||
const browserWindowRatio = this.canvasWidth / this.canvasHeight;
|
|
||||||
if (browserWindowRatio > nativeRatio) {
|
|
||||||
this.canvasHeight = Math.floor(this.canvasHeight * this.windowPercentage);
|
|
||||||
if (this.canvasHeight > this.maxHeight)
|
|
||||||
this.canvasHeight = this.maxHeight;
|
|
||||||
this.canvasWidth = Math.floor(this.canvasHeight * nativeRatio);
|
|
||||||
} else {
|
|
||||||
this.canvasWidth = Math.floor(this.canvasWidth * this.windowPercentage);
|
|
||||||
if (this.canvasWidth > this.maxWidth) this.canvasWidth = this.maxWidth;
|
|
||||||
this.canvasHeight = Math.floor(this.canvasWidth / nativeRatio);
|
|
||||||
}
|
|
||||||
this.canvas.style.width = `${this.canvasWidth}px`;
|
|
||||||
this.canvas.style.height = `${this.canvasHeight}px`;
|
|
||||||
}
|
|
||||||
}
|
|
53
src/index.js
|
@ -1,53 +0,0 @@
|
||||||
import CanvasWindow from "./canvas-windows";
|
|
||||||
import LevelLoader from "./level-loader";
|
|
||||||
import overworldLevel from "./levels/overworld.json";
|
|
||||||
|
|
||||||
const canvasWindow = new CanvasWindow({
|
|
||||||
canvas: document.querySelector("canvas"),
|
|
||||||
maxMultiplier: 5,
|
|
||||||
windowPercentage: 0.9,
|
|
||||||
});
|
|
||||||
|
|
||||||
let debug = true;
|
|
||||||
const GAME_TILE = 16;
|
|
||||||
const ROWS = canvasWindow.nativeHeight / GAME_TILE;
|
|
||||||
const COLUMNS = canvasWindow.nativeWidth / GAME_TILE;
|
|
||||||
|
|
||||||
function drawLevel(ctx, level) {
|
|
||||||
const levelCols = level.image.width / GAME_TILE;
|
|
||||||
for (let row = 0; row < ROWS; row++) {
|
|
||||||
for (let col = 0; col < COLUMNS; col++) {
|
|
||||||
const tile = level.layer[row * COLUMNS + col];
|
|
||||||
if (tile !== 0) {
|
|
||||||
ctx.drawImage(
|
|
||||||
level.image,
|
|
||||||
((tile - 1) * GAME_TILE) % level.image.width,
|
|
||||||
Math.floor((tile - 1) / levelCols) * GAME_TILE,
|
|
||||||
GAME_TILE,
|
|
||||||
GAME_TILE,
|
|
||||||
col * GAME_TILE,
|
|
||||||
row * GAME_TILE,
|
|
||||||
GAME_TILE,
|
|
||||||
GAME_TILE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug &&
|
|
||||||
ctx.strokeRect(col * GAME_TILE, row * GAME_TILE, GAME_TILE, GAME_TILE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
await canvasWindow.load();
|
|
||||||
const { canvas } = canvasWindow;
|
|
||||||
const ctx = canvas.getContext("2d");
|
|
||||||
|
|
||||||
const [overworld] = await Promise.all([overworldLevel].map(LevelLoader.load));
|
|
||||||
drawLevel(ctx, overworld);
|
|
||||||
|
|
||||||
document.getElementById("debug").addEventListener("click", () => {
|
|
||||||
debug = !debug;
|
|
||||||
drawLevel(ctx, overworld);
|
|
||||||
});
|
|
||||||
})();
|
|
|
@ -1,22 +0,0 @@
|
||||||
class Level {
|
|
||||||
constructor({ image, layer }) {
|
|
||||||
this.image = image;
|
|
||||||
this.layer = layer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class LevelLoader {
|
|
||||||
/**
|
|
||||||
* Loads a level on memory from the specified source and layer.
|
|
||||||
*
|
|
||||||
* @return {Promise<Level>} A Promise that resolves with the loaded level.
|
|
||||||
*/
|
|
||||||
static load({ source, layer }) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const image = new Image();
|
|
||||||
image.src = source;
|
|
||||||
image.onload = () => resolve(new Level({ image, layer }));
|
|
||||||
image.onerror = reject;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"source": "assets/overworld.png",
|
|
||||||
"layer": [
|
|
||||||
243, 244, 244, 244, 245, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 283, 283,
|
|
||||||
284, 284, 284, 285, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 283, 283, 284,
|
|
||||||
284, 284, 285, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 283, 323, 324, 324,
|
|
||||||
324, 325, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 283, 1, 1, 1, 1, 1, 1,
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 283, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 283, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
||||||
1, 1, 1, 283, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 283,
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 283, 1, 1, 1, 1, 1,
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 283, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 283, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ,
|
|
||||||
1, 1, 1, 1, 283, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
||||||
283, 245, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 283, 403,
|
|
||||||
244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244,
|
|
||||||
244, 244, 244, 404
|
|
||||||
]
|
|
||||||
}
|
|