Home > Software engineering >  Why doesn't canvas draw multiple images
Why doesn't canvas draw multiple images

Time:04-20

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>

  • Related