Skip to content
Advertisement

Tile drawing is not displaying

I’m working on this code where if you put in certain characters for the map array, the canvas will display the image corresponding to that character.

I have an array for all the ground blocks, at the top.

Here’s my code so far:

const blockSize = 160;
let ground = [];

function setup() {

  createCanvas(400, 400);

  ground = new Ground(x*blockSize,y*blockSize)
}

function preload() {
  groundImg = loadImage('https://mars.stcollier.repl.co/images/ground.png');
}

let map = [
    [
    "################",
    "################",
    "################",
    "################",
    "################",
    "################",
    "################",
    "################",
    "################",
    "################"
    ]
];

for (var i = 0; i < map.length; i++) {
  ground.push([]);
  
  for (var y = 0; y < map[i].length; y++) {
    for (var x = 0; x < map[i][y].length; x++) {
      switch (map[i][y][x]) {
        case "#":
          ground[i].push(ground);
          break;
      }
    }
  }
}

function draw() {
  for (var i = 0; i < ground.length; i++) {
    ground[i].draw();
  }
}

class Ground {
  constructor(x, y) {
    this.pos = createVector(x, y)
  } draw() {
    drawImage(groundImg, this.pos.x, this.pos.y, blockSize, blockSize)
  }
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>repl.it</title>
    <link href="style.css" rel="stylesheet" type="text/css" />
    <script src="https://cdn.jsdelivr.net/npm/p5@1.3.1/lib/p5.js"></script>
  </head>
  <body>
    <script src="script.js"></script>
  </body>
</html>

However, nothing seems to be drawing to the screen. I believe this might be a problem with my loops. Does anyone have a fix for this?

Thanks for any help.

Advertisement

Answer

There are a bunch of defects in your code:

  1. You are replacing the ground array with a single instance of Ground in your setup() function
  2. You are pushing a reference to ground into itself ion your for loop that initializes it
  3. drawImage() is not a function, perhaps you mean image() in Ground.draw
  4. In your main draw() function you are treating ground like an array of objects with a .draw() function, but ground is either a single instance of Ground and not an array, or it is an array of arrays of Ground objects.

Here’s a working example:

const blockSize = 16;
let ground = [];

function setup() {
  createCanvas(400, 400);
}

function preload() {
  groundImg = loadImage('https://mars.stcollier.repl.co/images/ground.png');
}

let map = [
    [
    "################",
    "#####000000#####",
    "####0######0####",
    "###0##0##0##0###",
    "###0########0###",
    "###0##0##0##0###",
    "###0###00###0###",
    "####0######0####",
    "#####000000#####",
    "################"
    ]
];

// This code could be moved to the setup() function, but in any case it cannot be run until the Ground class is actually declared
function init() {
  for (var i = 0; i < map.length; i++) {
    ground.push([]);

    for (var y = 0; y < map[i].length; y++) {
      for (var x = 0; x < map[i][y].length; x++) {
        switch (map[i][y][x]) {
          case "#":
            // I'm assuming that this is what you actually intended to do
            // Instead of pushing a reference to the ground array into itself
            ground[i].push(new Ground(x*blockSize,y*blockSize));
            break;
        }
      }
    }
  }
}

function draw() {
  for (var i = 0; i < ground.length; i++) {
    // ground contains arrays of Ground objects, not sure why
    for (var j = 0; j < ground[i].length; j++) {
      ground[i][j].draw();
    }
  }
}

class Ground {
  constructor(x, y) {
    this.pos = new p5.Vector(x, y)
  }
  draw() {
    image(groundImg, this.pos.x, this.pos.y, blockSize, blockSize)
  }
}

// Don't call init() until the Ground class is actually declared
init();
<script src="https://cdn.jsdelivr.net/npm/p5@1.3.1/lib/p5.js"></script>

Some honest feedback: you need to work on your basic debugging. When you run your code and it doesn’t work check the JavaScript console. Look at the error message in detail. Look for the line in your code where the error is being thrown and make an effort to deduce why it might be happening. When your code doesn’t do what you expect but doesn’t show errors, add console.log() statements to see if your expectations are valid. Think about what each line of code is doing (i.e. do things like ground[i].push(ground) make any kind of sense whatsoever).

How I Debugged Your Code

  1. Run the code, nothing happened, no errors ๐Ÿ˜•
  2. Add console.log('drawing: ' + ground.length) to the draw() function (and add noLoop() to prevent the log getting spammed).
  • Result: drawing: undefined
  • That is odd, I thought ground was an array ๐Ÿคจ
  1. Scan the code for assignments to ground, discover that ground is initialized twice, once as an array, and once as new Ground().
  2. Since the latter (new Ground()) makes no sense, comment it out.
  3. Hit the run button, TypeError: ground[i].draw is not a function coming from line 48 (inside the main draw() function)
  4. Look at the code that initializes ground in more detail, realize that it is an array of arrays, correct the code in draw() to have a nested loop.
  5. Run the code: TypeError: ground[i][j].draw is not a function
  6. Look at the ground initialization code more more depth, notice ground[i].push(ground) ๐Ÿคฏ
  7. At a guess this should be ground[i].push(new Ground(...)), give that a try
  8. Run the code: ReferenceError: Cannot access 'Ground' before initialization
  • This is a facet of JavaScript, you cannot use Classes in running code before they are declared (although you can reference them in the body of a function so long as that function is not called until the Class is declared).
  • At this point we can either move the ground initialization code into setup() or a special init function that we invoke ourselves after declaring the Ground class.
  • I opted for the custom init function
  1. Run the code: ReferenceError: createVector is not defined
  • Oops, I forgot that p5.js functions like createVector are not available globally until setup() is called ๐Ÿคฆโ€โ™‚๏ธ. I would have avoided this if I had moved the ground initialization code to setup(), but fortunately we can use new p5.Vector() any time.
  1. Run the code: ReferenceError: drawImage is not defined
  • easy fix, should be image()

Success ๐ŸŽŠ

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement