简体   繁体   中英

Canvas drawImage() not working - Javascript game

I have been working on a snake game in Javascript using HTML 5 Canvas. The game works with no errors and the image is being loaded by the webpage, however the image is not drawn.

<script>
    $(document).ready(function(){
        // get canvas context
        var cvs = $("canvas").get(0);
        var ctx = cvs.getContext("2d");
        // declare variables
        var food;
        var snake;
        var grid = 20;
        var h = cvs.height;
        var w = cvs.width;
        var apple = new Image();

        //Makes the canvas look sharp
        cvs.width *= 2;
        cvs.height *= 2;
        cvs.style.width = cvs.width / 2;
        cvs.style.height = cvs.height / 2;
        ctx.scale(2, 2);

        function init(){

            apple.src = "food.png";

            keyPress();     

            reset();

            setInterval(draw, 1000 / 10);
        }

        function reset(){
            snake = {
                direction: "right",
                x: 0,               
                y: 0,
                length: 5,
                pieces: [],
                score: 0
            };

            food = [];

            addFood();
        }

        function draw() {
            // calls functions and clears squares
            updateSnake();
            moveSnake();
            ctx.clearRect(0, 0, w, h);
            drawFood();
            drawSnake();

            // stores score as a string
            var snakeText = snake.score.toString();
            // add 0's to counter
            while (snakeText.length < 3) {
                snakeText = "0" + snakeText;
            }
            // displays score counter
            ctx.fillStyle = "red";
            ctx.textBaseline= "top";
            ctx.font = "20px monospace";
            ctx.fillText("Score: " + snakeText, 5, 0);
        }

        // draw visible snake
        function drawSnake(){
            ctx.fillStyle = "green";
            ctx.strokeStyle = "black";
            ctx.lineWidth = 1;
            // draw square on snakes head
            ctx.beginPath();
            ctx.rect(snake.x, snake.y, grid, grid);                 
            ctx.stroke();
            ctx.fill();
            // draws a square on all of the snakes body piecees
            for (var i = 0; i < snake.pieces.length; i++) {
                ctx.beginPath();
                ctx.rect(snake.pieces[i].x, snake.pieces[i].y, grid, grid);
                ctx.stroke();
                ctx.fill();
            }

        }

        function updateSnake(){
            // detects collision with snakes head and body
            for (var i = 0; i < snake.pieces.length; i++) {
                if(snake.x == snake.pieces[i].x && snake.y == snake.pieces[i].y){
                    reset();
                }
            }               

            // get the last element of the food array
            var foodIndex = food.length - 1;

            // go through food array 
            while (foodIndex >= 0) {
                // detects snake collision with food, increase snake length, remove food, increase score
                if(snake.x == food[foodIndex].x && snake.y == food[foodIndex].y){
                    snake.length +=1;
                    food.splice(foodIndex, 1); 
                    snake.score+=1;
                    //add new food
                    addFood();
                }

                // go to the next piece of food
                foodIndex--;
            }

            // clamps down array to length of snake
            snake.pieces.length = Math.min(snake.pieces.length, snake.length - 1);

            // adds the snake pieces to beeginning of array, at the snakes head location
            snake.pieces.unshift({
                x: snake.x,
                y: snake.y
            });
        }

        // generates food in random locations
        function addFood(){

            var valid;
            // generates food if allowed
            while (true) {
                valid = true;

                var newFood = {
                    x: Math.floor(Math.random()*(w / grid)) * grid,
                    y: Math.floor(Math.random()*(h / grid)) * grid
                };
                // stops food being put on the snakes head
                if (snake.x == newFood.x && snake.y == newFood.y) {
                    console.log("head");
                    valid = false;
                }
                // stops food from being put on the sankes body 
                for (var i = 0; i < snake.pieces.length; i++) {
                    if(newFood.x == snake.pieces[i].x && newFood.y == snake.pieces[i].y){
                        console.log("body");
                        valid = false;
                    }
                }
                // stops food from being out on top of each other
                for (var i = 0; i < food.length; i++) {
                    if(newFood.x == food[i].x && newFood.y == food[i].y){
                        valid = false;
                    }
                }
                // add new food to array
                if (valid) {
                    food.push(newFood);
                    break;
                }
            }
        }

        window.addFood = addFood;

        // draws the visible food
        function drawFood(){
            ctx.fillStyle = "salmon";
            ctx.strokeStyle = "black";
            //Draws at the foods location
            for (var i = 0; i < food.length; i++) {
                ctx.drawImage(apple, food.x, food.y, grid, grid);
            }
        }

        function moveSnake(){

            if(snake.direction == "right"){
                snake.x+= grid;
            }
            if(snake.direction == "left"){
                snake.x-= grid;
            }
            if(snake.direction == "up"){
                snake.y-= grid;
            }
            if(snake.direction == "down"){
                snake.y+= grid;
            }

            if(snake.x < 0){
                reset();
            }
            if(snake.x > w-20){
                reset();
            }
            if(snake.y > h-20){
                reset();
            }   
            if(snake.y < 0){
                reset();
            }           
        }
        // detects keys pressed
        function keyPress(){

            $(document).keydown(function(e){

                if(e.keyCode == 37 && snake.direction != "right"){
                    snake.direction = "left";
                }
                if(e.keyCode == 39 && snake.direction != "left"){
                    snake.direction = "right";
                }
                if(e.keyCode == 38 && snake.direction != "down"){
                    snake.direction = "up";
                }
                if(e.keyCode == 40 && snake.direction != "up"){
                    snake.direction = "down";
                }

            })
        }

        init();
    });

</script>

<canvas width="400" height="400" style="border: solid black 1px">
    Sorry, no canvas support!
</canvas>

The image is created in the variablees and given a source in my init() function:

        var cvs = $("canvas").get(0);
        var ctx = cvs.getContext("2d");
        // declare variables
        var food;
        var snake;
        var grid = 20;
        var h = cvs.height;
        var w = cvs.width;
        var apple = new Image();

        //Makes the canvas look sharp
        cvs.width *= 2;
        cvs.height *= 2;
        cvs.style.width = cvs.width / 2;
        cvs.style.height = cvs.height / 2;
        ctx.scale(2, 2);

        function init(){

            apple.src = "food.png";

            keyPress();     

            reset();

            setInterval(draw, 1000 / 10);
        }

drawImage() is called here in the drawFood() function:

function drawFood(){
            ctx.fillStyle = "salmon";
            ctx.strokeStyle = "black";
            //Draws at the foods location
            for (var i = 0; i < food.length; i++) {
                ctx.drawImage(apple, food.x, food.y, grid, grid);
            }
        }

I have tried using an onLoad function / EventListeners but cannot get it to work.

Thanks.

The problem is in the draw food function

    function drawFood(){
        ctx.fillStyle = "salmon";
        ctx.strokeStyle = "black";
        //Draws at the foods location
        for (var i = 0; i < food.length; i++) {
            // you had ctx.drawImage(apple, food.x, food.y, grid, grid);
            // should be
            ctx.drawImage(apple, food[i].x, food[i].y, grid, grid);
        }
    }

But you should still check images have loaded before you try to draw them. There are plenty of examples of how to load images here on stackoverflow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM