I have a problem where canvas only draws one of the images i make him draw. I have have seen though the code and checked eveything and everything is fine but not the drawImage or image.onload function. idk why its doing that cause it should draw image everytime its called but it doesnt. it just draws it 1 time and then done. Maybe i am doing something wrong but after what i have seen it should work;
const canvas = document.getElementById("myCanvas")
const ctx = canvas.getContext("2d")
class Cell {
constructor(x, y, w) {
this.x = x
this.y = y
this.w = w
this.bomb = false
this.revealed = false
}
show() {
const cell = new Path2D();
cell.rect(this.x, this.y, this.w, this.w);
ctx.stroke(cell);
this.cell = cell;
}
}
const w = canvas.width
const h = canvas.height
const ColumnRow = w / 15
const cells = []
const bombs = 5
const bombPosition = []
let checked = true
const arr = [
[-1, 1],
[0, 1],
[1, 1],
[1, 0],
[1, -1],
[0, -1],
[-1, -1],
[-1, 0]
]
function setup() {
for (let x = 0; x < w - 1; x = ColumnRow) {
for (let y = 0; y < h - 1; y = ColumnRow) {
cells.push(new Cell(x, y, ColumnRow))
}
}
}
function drawCells() {
for (let c of cells) {
c.show()
}
}
function numOfBombs() {
for (let i = 0; i < bombs; i ) {
if (bombPosition.length < bombs) {
let randomX = Math.floor(Math.random() * w / ColumnRow) * ColumnRow
let randomY = Math.floor(Math.random() * h / ColumnRow) * ColumnRow
for (let j = 0; j < bombPosition.length; j ) {
if (bombPosition[j].x == randomX && bombPosition[j].y == randomY) {
numOfBombs()
}
}
bombPosition.push({ x: randomX, y: randomY });
} else {
break;
}
}
}
function drawBomb() {
let img = new Image();
img.onload = function () {
for (let i = 0; i < bombPosition.length; i ) {
ctx.drawImage(img, bombPosition[i].x, bombPosition[i].y, ColumnRow, ColumnRow)
}
};
img.src = "https://raw.githubusercontent.com/americosp/Minesweeper/master/Minesweeper/images/mine.png";
//set cell bomb to true
for (let i = 0; i < cells.length; i ) {
for (let j = 0; j < bombPosition.length; j ) {
if (cells[i].x == bombPosition[j].x && cells[i].y == bombPosition[j].y)
cells[i].bomb = true
}
}
}
function drawNumbers() {
for (let i = 0; i < cells.length; i ) {
let totalBombs = 0;
if (!cells[i].bomb) {
for (let j = 0; j < arr.length; j ) {
tmpx = cells[i].x arr[j][0] * ColumnRow // 0 x
tmpy = cells[i].y arr[j][1] * ColumnRow // 1 y
// console.log(tmpx);
for (let k = 0; k < cells.length; k ) {
if (cells[k].x == tmpx && cells[k].y == tmpy) {
if (cells[k].bomb) {
totalBombs ;
}
break;
}
}
}
}
if (totalBombs > 0) {
test(totalBombs, cells[i].x, cells[i].y)
}
}
}
let images = []
for (let i = 1; i < 9; i ) {
let img = new Image()
images.push(img)
}
function test(totalBombs, x, y) {
images[totalBombs].onload = function () {
ctx.drawImage(images[totalBombs], x, y, ColumnRow, ColumnRow)
}
images[totalBombs].src = `https://raw.githubusercontent.com/americosp/Minesweeper/master/Minesweeper/images/number_${totalBombs}.png`
}
function draw() {
drawCells()
if (checked) {
drawBomb()
drawNumbers()
// coverCell()
checked = false
}
requestAnimationFrame(draw)
}
function update() {
setup()
numOfBombs()
}
update()
draw()
// bombTest()
<canvas id="myCanvas" width="600" height="600"></canvas>
CodePudding user response:
The problem is that you are trying load images and draw them at the same time. So, while the image is still loading you are replacing onload
function with for each number. This is where Promise
comes in:
const canvas = document.getElementById("myCanvas")
const ctx = canvas.getContext("2d")
class Cell {
constructor(x, y, w) {
this.x = x
this.y = y
this.w = w
this.bomb = false
this.revealed = false
}
show() {
const cell = new Path2D();
cell.rect(this.x, this.y, this.w, this.w);
ctx.stroke(cell);
this.cell = cell;
}
}
const w = canvas.width
const h = canvas.height
const ColumnRow = w / 15
const cells = []
const bombs = 5
const bombPosition = []
let checked = true
const arr = [
[-1, 1],
[0, 1],
[1, 1],
[1, 0],
[1, -1],
[0, -1],
[-1, -1],
[-1, 0]
]
function setup() {
for (let x = 0; x < w - 1; x = ColumnRow) {
for (let y = 0; y < h - 1; y = ColumnRow) {
cells.push(new Cell(x, y, ColumnRow))
}
}
}
function drawCells() {
for (let c of cells) {
c.show()
}
}
function numOfBombs() {
for (let i = 0; i < bombs; i ) {
if (bombPosition.length < bombs) {
let randomX = Math.floor(Math.random() * w / ColumnRow) * ColumnRow
let randomY = Math.floor(Math.random() * h / ColumnRow) * ColumnRow
for (let j = 0; j < bombPosition.length; j ) {
if (bombPosition[j].x == randomX && bombPosition[j].y == randomY) {
numOfBombs()
}
}
bombPosition.push({ x: randomX, y: randomY });
} else {
break;
}
}
}
function drawBomb() {
let img = new Image();
img.onload = function () {
for (let i = 0; i < bombPosition.length; i ) {
ctx.drawImage(img, bombPosition[i].x, bombPosition[i].y, ColumnRow, ColumnRow)
}
};
img.src = "https://raw.githubusercontent.com/americosp/Minesweeper/master/Minesweeper/images/mine.png";
//set cell bomb to true
for (let i = 0; i < cells.length; i ) {
for (let j = 0; j < bombPosition.length; j ) {
if (cells[i].x == bombPosition[j].x && cells[i].y == bombPosition[j].y)
cells[i].bomb = true
}
}
}
function drawNumbers() {
for (let i = 0; i < cells.length; i ) {
let totalBombs = 0;
if (!cells[i].bomb) {
for (let j = 0; j < arr.length; j ) {
tmpx = cells[i].x arr[j][0] * ColumnRow // 0 x
tmpy = cells[i].y arr[j][1] * ColumnRow // 1 y
// console.log(tmpx);
for (let k = 0; k < cells.length; k ) {
if (cells[k].x == tmpx && cells[k].y == tmpy) {
if (cells[k].bomb) {
totalBombs ;
}
break;
}
}
}
}
if (totalBombs > 0) {
test(totalBombs, cells[i].x, cells[i].y)
}
}
}
let images = []
for (let i = 1; i < 9; i ) {
images.push(new Promise((resolve, reject) =>
{
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject(img);
img.src = `https://raw.githubusercontent.com/americosp/Minesweeper/master/Minesweeper/images/number_${i}.png`;
}))
}
function test(totalBombs, x, y) {
images[totalBombs-1].then(function (img) {
ctx.drawImage(img, x, y, ColumnRow, ColumnRow)
});
}
function draw() {
drawCells()
if (checked) {
drawBomb()
drawNumbers()
// coverCell()
checked = false
}
requestAnimationFrame(draw)
}
function update() {
setup()
numOfBombs()
}
update()
draw()
// bombTest()
<canvas id="myCanvas" width="600" height="600"></canvas>