I am trying to load data (including images) via a JSONP feed into Phaser 3.60.0. I know how to load image asset normally as per my GameScene.js code below:
class GameScene extends Phaser.Scene {
constructor() {
super({ key: 'GameScene' });
}
preload() {
this.load.image('oranges', './assets/Ambersweet_oranges.jpg');
}
create() {
this.add.image(240, 320, 'oranges')
}
}
The JSONP feed is located on a different server and is structured like this:
/**/ typeof handleItems === 'function' && handleItems([
{"offerWeek":"kw17","id":"1028377","name":"Bananen","price":"1.79","url":"https://www.rewe.de/angebote/nationale-angebote/#1028377","image":"https://upload.wikimedia.org/wikipedia/commons/5/5d/Pl%C3%A1tanos_de_Canarias.JPG"},
{"offerWeek":"kw17","id":"2670547","name":"Big City Pizza","price":"1.99","url":"https://www.rewe.de/angebote/nationale-angebote/#2670547","image":"https://upload.wikimedia.org/wikipedia/commons/a/a5/Pizza_20.jpg"},
{"offerWeek":"kw17","id":"3663221","name":"Die Thüringer Bratwurst","price":"4.59","url":"https://www.rewe.de/angebote/nationale-angebote/#3663221","image":"https://upload.wikimedia.org/wikipedia/commons/9/91/Bratwurst_on_the_grill.jpg"},
{"offerWeek":"kw17","id":"3919250","name":"Orangen","price":"2.99","url":"https://www.rewe.de/angebote/nationale-angebote/#3919250","image":"https://upload.wikimedia.org/wikipedia/commons/4/43/Ambersweet_oranges.jpg"}]
);
How do I access the product names and images and display them in Phaser? Also how do I wait for the request to finish before create() is called? All advice appreciated!
There is probably a better solution, but my first idea would be:
create a global variabel, like this
var globalItemsStore = { isLoaded: false, inGame: false, items: []};
create the jsonp callback function, like this
function handleItems(loadedItems){
globalItemsStore = {
isLoaded: true,
inGame: false,
items: loadedItems
};
}
Now in your game in the update
method of the scene, you can check for the finished load, like this
(Or alternative just use the global variable)
...
update(){
...
if(!globalItemsStore.inGame && globalItemsStore.isLoaded){
// Do your thing ...
globalItemsStore.inGame = true;
}
}
...
OR if you want to use events and emitters in phaser, here is a small example:
document.body.style = 'margin:10px;';
var button = document.querySelector('#button');
const DEMO_ITEMS = [1,2,3,4,5,6];
button.addEventListener('click', () => handleItems(DEMO_ITEMS));
function handleItems (items){
game.scene.scenes[0].events.emit('DATA-LOADED', items);
}
var config = {
type: Phaser.AUTO,
width: 536,
height: 143,
scene: {
create
},
banner: false
};
function create () {
this.add.text(10,10, 'Click the HTML Button to simulate,\nloading Data.')
.setScale(1.5)
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
// you can use any string for the event Name
this.events.on('DATA-LOADED', args => {
console.info(args);
this.add.text(10, 80, `Data loaded!\nItemCount: ${args.length}`)
.setScale(1.5)
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial', color: 'green'});
});
}
var game = new Phaser.Game(config);
<button id="button" style="margin-bottom:5px;"> Simulate Load Data </button> <br>
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>
Just:
create
method, with this.events.on(...);
(link to the documentation)scene.events.emit(...)
function. (link to the documentation)You just have to select the correct scene. If you only have one it is easy
If you only want to start the game after loading the data, the easy solution would be to create the game in the handleItems
function. Something like this
function handleItems(loadedItems){
var game = new Phaser.Game(config)
game._myLoadedItems = loadedItems;
}
and in the create function you could get the data like this:
create(){
console.info(this.game._myLoadedItems);
...
}