JavaScript - Creating a basic 15x10 grid using a 400-item array

Recently I made the switch from Map Tiler to Tiled for my map creation. With Map Tiler, I got multiple arrays (one for each level of the X axis), but with Tiled, I'm dealing with one long array.

Initially, when working with Map Tiler, I would do:

      for (var y = 0; y <= 15; y++) {
        for (var x = 0; x <= 0; x++) {
// draw map board[0][13] for example
// then tileX *32 and tileY *32 being the spritesheet being cut
context.drawImage(imageObj, tileX * 32, tileY * 32, 32, 32, x*32, y*32, 32, 32)
}
}

Now, however, I am facing difficulties in drawing a simple map using the single long array format.

The tileset I'm working with can be viewed here: https://i.sstatic.net/OkU1c.png, and this is what it looks like: https://i.sstatic.net/drh5Z.png

The main question at hand is, how can you extract the current 15x10 required arrays from that larger 400-element array so they can be displayed on the canvas?

// Canvas viewport size is 15 tiles wide, 10 tiles tall
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d')

var imageObj = new Image()
imageObj.src = 'https://i.sstatic.net/OkU1c.png'

var client = {
    'vWidth': 15,
        'vHeight': 10,
        'imageWidth': 159,
        'imageHeight': 32
}

var tilesX = client.ImageWidth / 32
var tilesY = client.ImageHeight / 32

// Extracting the correct 15x10 canvas from a single 400-element array
// Desired map view should resemble this: https://i.sstatic.net/drh5Z.png

imageObj.onload = function () {
    context.drawImage(imageObj, 0, 0)

    var getTile = 0

    for (var y = 0; y <= client.vHeight; y++) {
        for (var x = 0; x <= client.vWidth; x++) {

            // Need to find a way during each loop through the canvas (of the size 15x10) to locate the right tile from the larger array
            // starting from 0,0... after every 15 loops [client.vWidth] (for painting the map), within the BOARD...
            // skip 20 array elements before continuing from where you left off earlier

            // Find the correct tile
            var tile = (board()[getTile])

            // Positioning on canvas
            var theX = x * 32
            var theY = y * 32

            var tileY = Math.floor(tile / tilesX)
            var tileX = Math.floor(tile % tilesX)

            console.log('Tile: ' + tile + ', TileY: ' + tileY + ', TileX: ' + tileX)

            context.drawImage(imageObj, tileX * 32, tileY * 32, 32, 32, theX, theY, 32, 32)

            getTile++
        }
    }
}

function board() {
    return [*(Large 400 element array)*]
}

//console.log(board);
#canvas {
    background: grey;
}
<canvas id="canvas" height="352" width="512"></canvas>

Take a look at this reference image which demonstrates the desired output from the lengthy board() array:

https://i.sstatic.net/8Z0nF.jpg

You can see what I have accomplished so far here: https://jsfiddle.net/3fx58ock/

Answer №1

Just like @J4G pointed out in the comments, you can calculate the row's offset in a 1D array by multiplying y with the width and then add x to determine the column's offset:

function drawViewport(leftBound, topBound) {
  var rightBound = leftBound + width;
  var bottomBound = topBound + height;

  for (var x = leftBound; x < rightBound; x++) {
    for (var y = topBound; y < bottomBound; y++) {
      map[x][y] = tiles[y*height + x]; // Insert your actual code here
    }
  }
}

drawViewport(0,0) would display the top left of the map. drawViewPort(2,2) would showcase the area of size 15x10 that is shifted 2 units down and 2 units right from the top left corner of the map.

To illustrate this, consider a 2D array:

[ [a, b, c],
  [d, e, f] ]

In a 1D array form, it would be:

[a, b, c, d, e, f]

Let's take e, which resides at index 4. The width of the 2D array is 3.

var x = index%width;
// x = 4%3
// x = 1

After obtaining x, we can compute y by dividing by the width:

var y = (index-x)/width;
// y = 3/3;
// y = 1;

Therefore, 1dArray[4] === 2dArray[1][1].

We can reverse this process for 2dArray to figure out the element's position in the 1D array:

var x = 1, y = 1;
var index = y*width + x;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on using Jquery to animate an element to a specific pixel measurement

My expertise lies in executing the following code: $("#nurseView").animate({"left": "+=100px"}, "slow"); However, I am facing a dilemma. How can I animate an object to exactly 1576px on the X-axis regardless of its current position? The code snippet abov ...

JSON representing an array of strings in JavaScript

Encountering difficulties when trying to pass two arrays of strings as arguments in JSON format to call an ASMX Web Service method using jQuery's "POST". The Web Method looks like this: [ScriptMethod(ResponseFormat=ResponseFormat.Json)] publ ...

Embed a Style-sheet into an Iframe (Facebook Like Box)

I'm facing the challenge of customizing a Facebook like box with predefined image sizes and borders that don't align with our design. I want to override some styles to make it more suitable for our website. The Likebox is currently embedded via ...

Unable to eliminate the default styling of Material UI table using an external CSS file

Currently, I am incorporating a Material Ui table into my project. My goal is to eliminate the border and adjust the padding of the table. Upon investigation, I came across a default className for material ui table known as MuiTableCell-root-40. Below is t ...

How to write to a file in PHP without adding an extra newline character

I have successfully figured out how to read a CSV data file, load it into an array, make edits, and then write it back to a file. I found great examples on Stackoverflow that helped me achieve this in one go! Thank you for the assistance. However, I am fa ...

Making an AJAX POST request using jQuery to send the current date and time to an ASP

I am working with an ASP.NET Web API endpoint where I need to send POST data. Suppose I want to post the following information: var myObject = { name: "Alice Johnson", age: "29", accountCreated: "CURRENT DATE TIME" }; What is the JavaScript equivalent o ...

If any modifications are made to the database, the script will re-execute

Is there a way to make my script only automatically execute again if the database undergoes changes? Currently, it runs continuously based on the variable timer and setInterval, updating the output of the textboxes whenever I alter the database value witho ...

Reading Data from a Text File into an Array Using the FileStream Class in C#

Currently, I am working on using StreamReader to extract data from text files and store it in an array. However, I have encountered a problem that has me puzzled. Instead of retrieving just the single line of data with the search name and its accompanyin ...

Updating the index page with AJAX in Rails 4: Step-by-step guide

It's surprising that I haven't found answers to my specific questions despite searching extensively. I have an Expenses page where I want to display all expenses for a given month in a table. Currently, I achieve this by adding month and year par ...

How to capture a change event in a dynamically loaded element using JQuery

I am facing an issue with dynamically added rows in my table. Each row contains a select option, and I need to trigger an action when the select is changed. However, since the rows are loaded after the page load, my function does not work as expected. < ...

Guide to switching a button using JavaScript

I am trying to create a button that will toggle the font size between 16px and 14px when clicked. The button text should also change from "Increase Font" to "Decrease Font" accordingly. UPDATE: I managed to get it working, but it only toggles twice and th ...

The header cannot be adjusted once it has been sent to the client

Encountering an issue where I receive the error message "Can't set the header after they are sent to client" when the incoming request lacks basic authentication and jwt token. This error occurs because I am unable to prevent node.js from executing t ...

I am looking to halt the AJAX requests within an asynchronous function after reaching a limit of 10 requests

I've been working on an async function that sends AJAX requests based on the previous response. The function is functioning properly, but it's sending multiple requests in quick succession. I need to implement a 5-second interval between each req ...

Transform JSON arrays into JSON structure

I'm currently facing an issue with converting JSON arrays to JSON format data. The output I am currently getting looks like this: https://i.stack.imgur.com/SW2NW.png However, I would like my output to be in the following format: https://i.stack.img ...

Developing an assortment of markers to generate various types of information windows on a map

Currently, I am utilizing a MapView with 30 pin locations placed and everything is running smoothly. I have recently added a button in the callout using a rightCalloutAccessoryView. Below is the code for the button: UIButton *rightButton = [UIButton butto ...

What is the best way to arrange an array of objects by their ID in a React application?

I am currently in the process of developing my own social media application. At this point, I have a feature that allows users to post content or text on the platform. I have also set up temporary data in the form of an array of objects, which is currently ...

Ways to activate a button action with jQuery even when it is disabled and clicked

Thank you for the responses. To clarify my goal, I want the form button to submit all select field responses for processing through php on the next page. If a user clicks the submit button before selecting an option in each field, it should display "whoa d ...

Is it possible to replicate this JavaScript syntax in C++?

As someone who frequently writes JavaScript, I find myself particularly drawn to the syntax of this feature. While I'm uncertain about its nomenclature, here's an illustrative example: object.function1().function2().function3() I understand tha ...

Separate the Array elements and organize them into an object

Check out this code snippet that demonstrates how to divide an array into chunks. If you have a more efficient solution, please share it with me. var numbers = []; for (var i = 0; i < 4500; i++) { numbers.push(i); } var chunks = {}; var start = 0 ...

An error was encountered: Unable to assign value to the property "once" of [object Object] because it only has a

`Encountering an Uncaught TypeError: Cannot set property 'once' of [object Object] which has only a getter at HTMLDivElement.addEventListener (polyfills.js:1:146664). This issue is being faced during the process of upgrading the Angular version. ...