I'm new to dev and i'm trying to learn JS doing game on canvas.
This is a Tile Map Editor project
I'm looking to create a multidimensional array with the ID's of the tiles i drew in the canvas. So when i go to export the JSON i can handle the colissions easily on my game.
But I'm stuck, I can detect the mouse position and put my tile id in the right place, but I don't know how to save the information in my array. Every time i try the array does not save the tile id and replaces with the new one.
//////////////////////////////
//// TO RESOLVE !!!!! ///////
////////////////////////////
let array = [];
function saveIdexedTiledMap() {
for (let l = 0; l < canvas.height / 32; l++) {
array[l] = [];
for (let c = 0; c < canvas.width / 32; c++) {
array[l][c] = 0;
}
}
array[mouseCanvasGrids.y / 32][mouseCanvasGrids.x / 32] =
selectedTile[0].index;
console.log(array);
}
Thanks :D
////////////////////////////////////////////////////////////
/////////// GET INPUT VALUES AND BUTTONS //////////////////
//////////////////////////////////////////////////////////
const clearCanvas = document.querySelector("#btn-clearCanvas");
const exportImage = document.querySelector("#btn-exportImage");
const form = document.querySelector("#form");
const submit = document.querySelector("#submit");
const elems = Array.from(form.elements);
submit.addEventListener("click", (e) => {
e.preventDefault();
elems.forEach((el) => localStorage.setItem(`${el.id}`, `${el.value}`));
});
/////////////////////////////////////////////////////////////
/////////// GET BOTH CANVAS AND VARIABLES //////////////////
///////////////////////////////////////////////////////////
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const canvasImg = document.querySelector("#canvasImg");
const ctxImg = canvasImg.getContext("2d");
let gridsPosX;
let gridsPosY;
let tileSizeW = 32;
let tileSizeH = 32;
let gridsColor = "#bad1f5";
//////////////////////////////////////////////////////////
/////////// DRAW ON CANVAS TILE GRIDS //////////////////
////////////////////////////////////////////////////////
class DrawGrids {
constructor(x, y, canvasW, canvasH, tileW, tileH, color) {
this.x = x;
this.y = y;
this.canvasW = canvasW;
this.canvasH = canvasH;
this.tileSizeW = tileW;
this.tileSizeH = tileH;
this.color = color;
}
draw() {
let tileGridsX;
let tileGridsY;
for (let l = 0; l < this.canvasH / this.tileSizeH; l++) {
for (let c = 0; c < this.canvasW / this.tileSizeW; c++) {
tileGridsX = c * this.tileSizeW;
tileGridsY = l * this.tileSizeH;
const variables = [ctx, ctxImg];
variables.forEach((el) => {
el.strokeStyle = this.color;
el.rect(tileGridsX, tileGridsY, this.tileSizeH, this.tileSizeW);
el.stroke();
});
}
}
}
}
const canvasImgGrids = new DrawGrids(
gridsPosX,
gridsPosY,
canvasImg.width,
canvasImg.height,
tileSizeW,
tileSizeH,
gridsColor
);
const canvasMapGrids = new DrawGrids(
gridsPosX,
gridsPosY,
canvas.width,
canvas.height,
tileSizeW,
tileSizeH,
gridsColor
);
/////////////////////////////////////////////////////////////////////
/////////// GET/SHOW FILE AND CUT IMAGE INTO ARRAY//////////////////
///////////////////////////////////////////////////////////////////
const tileImage = new Image();
tileImage.src = "./images/tileset_32x32(new).png";
tileImage.onload = cutImage;
let imageTileParts = [];
function cutImage() {
let index = 1;
for (let l = 0; l < tileImage.height / 32; l++) {
for (let c = 0; c < tileImage.width / 32; c++) {
imageTileParts.push({
index,
tileImage,
x: c * tileSizeW,
y: l * tileSizeH,
w: tileSizeW,
h: tileSizeH,
x_draw: c * tileSizeW,
y_draw: l * tileSizeH,
});
index++;
}
}
showSpreadSheetImg();
}
function showSpreadSheetImg() {
imageTileParts.forEach((el) => {
ctxImg.drawImage(
el.tileImage,
el.x,
el.y,
el.w,
el.h,
el.x_draw,
el.y_draw,
el.w,
el.h
);
});
canvasImgGrids.draw();
canvasMapGrids.draw();
getMouseCanvasImgPos();
getMouseCanvasPos();
}
//////////////////////////////////////////////////////////////////
/////////// GET MOUSE POSITION AND EVENT CLICK //////////////////
////////////////////////////////////////////////////////////////
let mouseCanvasImg = {};
let mouseCanvasGrids = {};
function getMouseCanvasImgPos() {
const canvasImgPos = canvasImg.getBoundingClientRect();
canvasImg.addEventListener("click", (e) => {
mouseCanvasImg = {
x: Math.floor((e.clientX - canvasImgPos.left) / tileSizeW) * tileSizeW,
y: Math.floor((e.clientY - canvasImgPos.top) / tileSizeH) * tileSizeH,
};
compareMouseIdWithTiles();
});
}
function getMouseCanvasPos() {
const canvasGridsPos = canvas.getBoundingClientRect();
canvas.addEventListener("mousedown", (e) => {
mouseCanvasGrids = {
x: Math.floor((e.clientX - canvasGridsPos.left) / tileSizeW) * tileSizeW,
y: Math.floor((e.clientY - canvasGridsPos.top) / tileSizeH) * tileSizeH,
};
if (e.button == 0) {
drawSelectedTileInGrids();
} else if (e.button == 2) {
deleteSelectedTile();
}
saveIdexedTiledMap();
});
}
/////////////////////////////////////////////////////////////////
/////////// COMPARE MOUSE WITH TILES POSITION //////////////////
///////////////////////////////////////////////////////////////
let selectedTile = [];
function compareMouseIdWithTiles() {
for (let i = 0; i < imageTileParts.length; i++) {
if (
mouseCanvasImg.x == imageTileParts[i].x &&
mouseCanvasImg.y == imageTileParts[i].y
) {
// Delete last tile clicked in the array
if (selectedTile.length >= 1) {
selectedTile.shift();
}
selectedTile.push(imageTileParts[i]);
}
}
}
///////////////////////////////////////////////////////////
/////////// DRAW/DELETE SELECTED TILE IN GRIDS ///////////
/////////////////////////////////////////////////////////
// :: DRAW :: //
function drawSelectedTileInGrids() {
if (selectedTile <= 0) {
console.log("Veuillez choisir une Tile !!!");
} else {
ctx.drawImage(
selectedTile[0].tileImage,
selectedTile[0].x,
selectedTile[0].y,
selectedTile[0].w,
selectedTile[0].h,
mouseCanvasGrids.x,
mouseCanvasGrids.y,
tileSizeW,
tileSizeH
);
}
}
///////////////////////////////
//////////////////////////////
//// TO RESOLVE ON !!!!! ////
////////////////////////////
let array = [];
function saveIdexedTiledMap() {
for (let l = 0; l < canvas.height / 32; l++) {
array[l] = [];
for (let c = 0; c < canvas.width / 32; c++) {
array[l][c] = 0;
}
}
array[mouseCanvasGrids.y / 32][mouseCanvasGrids.x / 32] =
selectedTile[0].index;
console.log(array);
}
// :: DELETE :: //
function deleteSelectedTile() {
ctx.clearRect(mouseCanvasGrids.x, mouseCanvasGrids.y, tileSizeW, tileSizeH);
}
////////////////////////////////////////////////
/////////// CLEAR/SAVE CANVAS IMAGE ///////////
//////////////////////////////////////////////
clearCanvas.addEventListener("click", () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
canvasMapGrids.draw();
});
////////////////////////////////////////////
/////////// EXPORT CANVAS IMAGE ///////////
//////////////////////////////////////////
* {
box-sizing: border-box;
}
body {
margin: 0;
margin-bottom: 50px;
padding: 0;
}
.body {
width: 900px;
margin-bottom: 50px;
background-color: #ccdaf0;
margin: 20px auto;
border-radius: 8px;
background: linear-gradient(145deg, #dae9ff, #b8c4d8);
box-shadow: 7px 7px 12px #818997, -7px -7px 12px #ffffff;
}
header {
margin: 0 30px;
display: flex;
justify-content: space-between;
align-items: baseline;
}
.content {
display: flex;
}
aside {
flex-grow: 1;
}
.canvas-content {
margin: 0 30px;
border-radius: 8px;
background: #ccdaf0;
box-shadow: inset 7px 7px 12px #818997, inset -7px -7px 12px #ffffff;
}
.img-container {
padding: 10px;
height: 200px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tile Map Editor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div class="body">
<header>
<h1>Tile Map Editor</h1>
<div>
<button id="btn-clearCanvas">clear canvas</button>
<button id="btn-exportImage">Export Map</button>
</div>
</header>
<div class="content">
<aside>
<form id="form">
<label>Config : </label>
<div class="config-container">
<div class="mapSize">
<label>Map Size : </label>
<label>width</label>
<input type="number" id="mapSizeW" />
<label>height</label>
<input type="number" id="mapSizeH" />
</div>
<div class="tileSize">
<label>Tile Size</label>
<input type="number" id="tileSize" />
</div>
<input id="submit" type="submit" value="Valider" />
</div>
</form>
</aside>
<div class="canvas-content">
<canvas
oncontextmenu="return false;"
width="608"
height="416"
></canvas>
</div>
</div>
<div id="img-container">
<canvas
oncontextmenu="return false;"
id="canvasImg"
width="600"
height="200"
></canvas>
</div>
</div>
<script src="./index.js"></script>
</body>
</html>
This mistake is in this function, you are clearing the array on every save:
let array = [];
function saveIdexedTiledMap() {
for (let l = 0; l < canvas.height / 32; l++) {
array[l] = [];
for (let c = 0; c < canvas.width / 32; c++) {
array[l][c] = 0;
}
}
array[mouseCanvasGrids.y / 32][mouseCanvasGrids.x / 32] =
selectedTile[0].index;
console.log(array);
}
So you need to move the clearing outside like this:
let array = [];
for (let l = 0; l < canvas.height / 32; l++) {
array[l] = [];
for (let c = 0; c < canvas.width / 32; c++) {
array[l][c] = 0;
}
}
function saveIdexedTiledMap() {
array[mouseCanvasGrids.y / 32][mouseCanvasGrids.x / 32] =
selectedTile[0].index;
console.log(array);
}