Parsing JSON data from Tiled map editor and rendering it onto a canvas

I am currently following a tutorial on how to load JSON map files created by the Tiled Map Editor in my JavaScript/Canvas game. So far, I have implemented my own version without any errors showing up in Firebug or the console.

Upon closer inspection with console.logs and alerts, it seems that the script is running perfectly fine. However, the canvas remains blank when it should display a tilemap.

Below is my implementation of the tutorial in my game:


function Level() {
var c;
var data;
var layers = [];

this.get_map = function(name, ctx) {
c = ctx;
$.getJSON('maps/' + name + '.json', function(json) {
get_tileset(json);
});
};

function get_tileset(json) {
data = json;
this.tileset = $("<img />", { src: json.tilesets[0].image })[0];
this.tileset.onload = renderLayers(this);
}

function renderLayers(layers) {
layers = $.isArray(layers) ? layers : data.layers;
layers.forEach(renderLayer);
}

function renderLayer(layer) {
if (layer.type !== "tilelayer" || !layer.opacity) {
alert("Not a tileLayer");
}
var s = c.canvas.cloneNode(),
size = data.tileWidth;
s = s.getContext("2d");

if (layers.length < data.layers.length) {
layer.data.forEach(function(tile_idx, i) {
if (!tile_idx) { return; }
var img_x, img_y, s_x, s_y,
tile = data.tilesets[0];
tile_idx--;
img_x = (tile_idx % (tile.imagewidth / size)) * size;
img_y = ~~(tile_idx / (tile.imagewidth / size)) * size;
s_x = (i % layer.width) * size;
s_y = ~~(i / layer.width) * size;
s.drawImage(this.tileset, img_x, img_y, size, size,
s_x, s_y, size, size);
});

layers.push(s.canvas.toDataURL());
c.drawImage(s.canvas, 0, 0);
} else {
layers.forEach(function(src) {
var i = $("<img />", { src: src })[0];
c.drawImage(i, 0, 0);
});
}

}

}

The above code is called from my main JavaScript file as shown below:


$(document).ready(function() {

var canvas = document.getElementById("TBG");
var ctx = canvas.getContext("2d");

var ui = new Gui();
var level = new Level();

// ... (Additional JavaScript code)

});

Despite everything seeming correct in the code, the tile-map still fails to show up on my canvas. Any suggestions or assistance would be greatly appreciated. Thank you for your help!

Sincerely, Tom

Answer №1

Utilizing Tiled and Canvas Together

I recently came across a fascinating blog post on using Tiled and Canvas to render game screens by Shane Riley, which can be found at this link.

The good news is that I was able to successfully run the code from his demo on my local development machine.

After going through the process and analyzing your code, I believe there are two key issues that need addressing in order to make your code work smoothly:

1) There seems to be a minor bug in your get_tileset function.

2) You must ensure that all files from Shane's demo are pointed towards locations on your own computer. I simply placed all these files in a single folder (which worked for me). Here's a list of the files you need to update:

  • mountain.html
  • mountain.json
  • mountain.tmx
  • mountain_landscape_23.png
  • render_scene.js

I have listed the necessary changes below, which should help resolve any issues. However, if you face any difficulties, feel free to reach out and I can provide you with my complete code.

A Bug -- The tileset.onload function in your get_tileset() method requires a named or inline function, not a function call.

// Instead of this.tileset.onload=renderLayers(this)
this.tileset.onload=renderLayers;    

// Change the signature of renderLayers 
// (you have “layers” in scope for visibility in this function so this should be okay)
// So: instead of function renderLayers(layers)
function renderLayers()    

Please make sure to include an error handler in your $.getJSON to receive notifications about failed requests!

$.getJSON('maps/'+ name + '.json', function(json){
        get_tileset(json);
}).fail( alert(“I think you should know that something has gone horribly wrong!”);  );

Below are the modifications required to localize your files.

In mountain.html:

    <script src="render_scene.js" type="text/javascript"></script>

In render_scene.js (if you downloaded from the Gist)

load: function(name) {
  return $.ajax({
    url: "mountain.json",
    dataType: "text json"
  }).done($.proxy(this.loadTileset, this));
}

In mountain.json:

"image":"mountain_landscape_23.png",

In mountain.tmx:

<image source="mountain_landscape_23.png" width="512" height="512"/>

Mountain_landscape_23.png

Important! Depending on your development environment setup, you may encounter cross-domain security errors leading to the browser refusing to draw your tiles. If this happens, consider opening the png file in an editor like Photoshop and saving it back out to your dev domain to bypass the CORS error.

Answer №2

Well, better late than never! If you simply update

        size = data.tileWidth;

to

        size = data.tilewidth;

the issue should be resolved without any further complications.

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

Is it possible to retrieve the index of a particular element within an array during an update operation in MongoDB?

After executing the following update statement const result = await Post.updateOne({_id: postId},{ $pull: {reacts: {publisher: req.query.publisher}}, $inc: {postPoints: - reactsEnum[ReactType]} }); I am interested in obtaining the ...

retrieve information from an array of objects that include promises

Within my react application, I am faced with the task of retrieving email and name data for various user IDs from separate API endpoints. To achieve this, I follow these steps: const promises = ids.map( id => ( {email: axios.get(`blabla/${id}/email ...

The error message "Vue.JS computed from VueX Store is not recognized" is displaying

Within my Vuex store, I am able to see it in the Vue Devtools tool. However, when attempting to load data into a computed property, an error message stating that it is not defined is displayed. computed: { userData(){ return this.$store.state.use ...

jquery animation does not reset after event occurs

My script is functioning well to animate my elements, but I am facing an issue where when the function is called again after a timer, the elements move to their correct positions but do not initiate a new animation. The goal of the function updateFlights( ...

Utilizing express.js alongside the native MongoDB driver: A comprehensive guide

I'm facing difficulties when attempting a simple mongoDB query from my express app: app.js var express = require('express'); var routes = require('./routes'); var user = require('./routes/user'); var http = re ...

Tips for accessing the HTML content enclosed within a specific HTML tag using Python with Selenium

I am trying to extract the source code of an HTML document that is embedded within an <iframe> tag generated by JavaScript. The HTML contents within this <iframe> tag appears as #document, which expands to reveal a full HTML document starting w ...

Establish characteristics for the temporary print document

Struggling to configure the properties of a temporary file created for later printing by the user. Here's a breakdown of the process: User clicks on "Print Map Area" button on the website. A menu appears asking for preferred dimensions (e.g. A4 ...

Gulp- Ensuring the latest versions of your javascript files

I have implemented bundling and minification for my JavaScript files using gulp. What I am aiming to achieve is that whenever I make a change in any of my files and run gulp, a new bundled and minified file with a version number is generated. For example: ...

software tool for managing state transitions

Can anyone recommend a superior javascript library for workflows? Right now, I'm utilizing Joint JS, but I require something with a more visually appealing interface (users tend to prefer that). ...

The error message "TypeError: undefined is not an object (evaluating '_reactNative.Stylesheet.create')" occurred in a React Native environment

I've been working on a project in React Native and have successfully installed all the necessary dependencies. However, upon running the code, I encounter the following error message: TypeError: undefined is not an object (evaluating '_reactNativ ...

Discovering which chip has wrapped to the next line in Material UI Autocomplete can be found by closely inspect

Currently, I am working with a Material UI autocomplete feature that functions as follows: https://i.sstatic.net/4LrwI.png My goal is to determine when the fourth chip wraps to the next line within the autocomplete so that I can proceed with additional c ...

Troubleshooting overload errors within ReactJS: tips and tricks

import React from 'react' import { Link } from 'react-scroll' import "./Protocol.css" import { ANALYTICS, TRADE, USERS, TRADERS, VOTES, ZEROES } from "../../Constants" const Protocol = () => { return ( ...

Transferring a single dataset from a table to a pop-up modal using Angular

I am working on a table to display entries for a contest, extracted from a database using PHP and converted into a .json object for AngularJS and JavaScript. I want to add a modal feature so that when a "judge" clicks on an entry, they can view its details ...

Tips for incorporating JavaScript into your Selenium WebDriver workflow using Java

Looking to integrate JavaScript with WebDriver (Selenium 2) using Java. After following a guide listed on the Getting Started page, I found an initial instruction to run: $ ./go webdriverjs Curious about the specific folder/location where the above ...

Obtain the node identifier within the Angular UI Tree component [angular-ui-tree]

Utilizing Angular UI tree to create a relationship between items and categories has been successful in the default setup. However, a new requirement has emerged to incorporate node/section numbering within the tree for managing hierarchy. I attempted to i ...

JavaScript scripts are unable to function within an Angular directive's template due to compatibility issues

I'm facing an issue with a directive (function (angular) { 'use strict'; function digest(factory) { var directive = { restrict: 'E', templateUrl: '/js/app/digest/templates/digest.tem ...

Transferring data from a form to a function in JavaScript

Hey there! I've been working on a form that sends a value to a new window, but for some reason, the value val2 is showing up as null in the new window instead of being passed. Here's my code: function sendValue(value) { ViewImg = window.ope ...

Determining when the clear button is clicked in a v-select (vue-select) detection strategy

While working on creating a drop-down using v-select, I encountered an issue. After selecting an option, I needed to clear the drop-down and revert the option array back to its initial stage upon clicking the clear button. I attempted various methods such ...

Create a form in a PHP file containing a pair of buttons for selecting a specific action

Consider the following HTML code snippet: <body onload="showcontent()"> <!-- onload attribute is optional --> <div id="content"><img src="loading.gif"></div> <!-- exclude img tag if not using onload --> < ...

Ensuring grid columns are equal for varying text sizes

I am looking to achieve equal width and spacing for columns without using the width, min-width, max-width properties. Can anyone help me accomplish this using flex or any other method? https://i.sstatic.net/xo56M.png .d-flex { display: flex; } .d-fl ...