Black screen when changing scene Phaser 3 - javascript

I'm having a problem changing scenes when I reach the area that should trigger the second level in the game I'm developing. For some reasons instead of showing the second level the game shows a black screen and no errors on the console. I think that the answer to my question is here (http://www.html5gamedevs.com/topic/37617-trouble-changing-scenes-in-phaser-3/) as the guy who asked the question had my problem and managed to resolve it, but I don't understand his last post.
the way I call the second scene in my first scene is the function:
PassaggioLivello() {
if(this.player.sprite.x > 15400){
this.scene.start(MainScene2);
}
}
And both scenes are included in the config file:
import {MainScene} from "./main-scene.js";
import {MainScene2} from "./main-scene.js";
let config = {
type: Phaser.AUTO,
width: 1280,
height: 720,
backgroundColor: "#000c1f",
parent: "game-container",
scene: [MainScene, MainScene2],
pixelArt: true,
physics: { default: "matter" },
plugins: {
scene: [
{
plugin: PhaserMatterCollisionPlugin, // The plugin class
key: "matterCollision", // Where to store in Scene.Systems, e.g.
scene.sys.matterCollision
mapping: "matterCollision" // Where to store in the Scene, e.g. scene.matterCollision
}
]
}
};
let game = new Phaser.Game(config);
Can you please help me? I don't understand my error.

The this.scene.start() method requires the identifying key of the scene you want to start--not the scene object itself.
Each scene being imported should have a key declared in the constructor method, like this:
constructor() {
super({ key: 'game' });
}
Then, you should be able to start the scene you want by calling this.scene.start('game');

Related

Phaser 3 (Typescript) Property 'start' does not exist on type 'Scene'

I'm unable to switch scenes in Phaser 3 (I've tried scene.switch and scene.start), but none of these appear to be methods on Phaser.Scene in Phaser 3. How do you change scenes in Phaser 3? Any help would be greatly appreciated, as I cannot find any alternative methods. Thank you!
// My Game entry point
HomePage.ngZone.runOutsideAngular(() => {
this.config = {
type: Phaser.AUTO,
scale: {
mode: Phaser.Scale.FIT,
},
parent: 'game',
scene: [MazeScene, MainScene],
physics: {
default: 'matter',
matter: {
debug: false,
gravity: {
y: 0.0,
x: 0.0,
},
},
},
};
this.phaserGame = new Phaser.Game(this.config);
});
I have tried both scene.start('main'),and scene.swap('main'), but both of these methods do not seem to appear in the Phaser.Scene class in Phaser 3.
As it turn out you need to reference the scene from sys.game.scene. This is what ultimately worked for me.
this.scene.sys.game.scene.switch('mazeScene', 'mainScene')

Invalid Tilemap Layer ID

I was doing my game in phaser 3 when I went to add a tilemap created in tiled, I followed several tutorials, I did and redid the code several times and even then it always gives me the same invalid ID error.
unsuccessful attempts:
Tried to manually make the tilemap;
Tried using JSON files;
I tried to use a single layer;
I tried to use the names according to the tiled layers;
I tried using different names;
here follows the code:
import './phaser'
const config = {
type: Phaser.AUTO,
parent: "phaser-example",
width: 1824,
height: 960,
physics: {
default: 'arcade'
},
scene: {
preload: preload,
create: create
}
};
export const game = new Phaser.Game(config)
function preload()
{
this.load.image('terrain', './complementos/tilemaps/terrainBasic.png')
this.load.tilemapTiledJSON('map', './complementos/tilemaps/basicLand.json')
}
function create()
{
const teste = [[0,1,2],[0,1,2],[0,1,2]]
const map = this.make.tilemap(teste)
map.addTilesetImage('terrainBasic','terrain', 32, 32)
const layer = map.createLayer(0,'land', 0, 0)
}
I don't know if it changes much but I was using react together with phaser 3, but my react code only had styling.
The problem is, that your are not providig the correct parameters for the tilemap function. You have to pass a Phaser.Tilemaps.MapData checkout the documentation, here https://photonstorm.github.io/phaser3-docs/Phaser.Tilemaps.Tilemap.html or you could checkout the examples on the phaser.io website.
Checkout especially, some Demos on the official website, they show many different ways how to use tiles(maps) (with working examples): https://phaser.io/examples/v3/category/tilemap
Here is a snippet, showing how to use a array, for the tiles:
var config = {
type: Phaser.AUTO,
width: 5*16,
height: 3*16,
zoom:2,
scene: {
preload: preload,
create: create
}
};
var game = new Phaser.Game(config);
function preload ()
{
this.load.image('tiles', 'https://labs.phaser.io/assets/tilemaps/tiles/super-mario.png');
}
function create ()
{
// Load a map from a 2D array of tile indices
var level = [ [ 0, 0, 0, 0, 0],[ 0, 14, 13, 14, 0],[ 0, 0, 0, 0, 0]];
var map = this.make.tilemap({ data: level, tileWidth: 16, tileHeight: 16 });
var tiles = map.addTilesetImage('tiles');
var layer = map.createLayer(0, tiles, 0, 0);
}
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>

chartjs in react useEffect keeps on creating new charts?

I have this extremely odd issue.. every single time I try and use a chartjs object, it keeps on creating itself on a new object (new id). The initial load never works, and I have to refresh. Everytime I switch from unmounting this component to mounting, when I console.log the chart instance it's always incrementing in id. I'm confused as what's going wrong here.
here is a basic snipped of my code:
useEffect(() => {
if (chartContainer && chartContainer.current) {
const newChartInstance = new Chartjs(chartContainer.current!, chartConfig);
removeData(newChartInstance);
if (newChartInstance) {
setIsClear(true);
setChartInstance(newChartInstance);
return () => {
removeData(newChartInstance);
newChartInstance.destroy();
if (chartInstance) chartInstance.destroy();
}
}
};
}, [chartContainer]);
useEffect(() => {
if (chartInstance && delay) {
const intervalUpdate = setInterval(() => {
console.log("updating");
console.log(chartInstance);
chartInstance.update();
}, delay);
return () => clearInterval(intervalUpdate);
}
}, [chartInstance, delay])
return (
<div className={styles.chartContainer}>
<canvas ref={chartContainer} height={"140"}/>
</div>
);
On the initial load a chart is created, and I'm adding data to it. But I believe 2nd one gets created and that's holding no data & is what is being display on the canvas. I know there's two somehow because because when I log I get an id of 1, instead of 0.
When I console.log() chart instance, on the very first initial load is always:
Chart {id: 1, ctx: CanvasRenderingContext2D, canvas: canvas.chartjs-render-monitor, config: {…}, width: 1024, …}
Which I believe is why my chart is empty. When I refresh it goes back to:
Chart {id: 0, ctx: CanvasRenderingContext2D, canvas: canvas.chartjs-render-monitor, config: {…}, width: 1024, …}
which properly displays the data.

Map layers do not render again past initial load

I am using VueMapbox (0.4.1) to utilize Mapbox GL in a Vue project.
<template>
<MglMap
:accessToken="accessToken"
:mapStyle.sync="mapStyle"
:repaint="true"
#load="onMapLoaded">
<MglMarker
:coordinates="someCoordinates"
class="map-marker-wrapper">
<div
slot="marker"
class="map-marker">
</div>
</MglMarker>
</MglMap>
</template>
<script>
import Mapbox from 'mapbox-gl'
import { MglMap, MglMarker } from 'vue-mapbox'
import * as MAP from '#/constants/map'
// Vue-Mapbox documentation: https://soal.github.io/vue-mapbox/guide/basemap.html#adding-map-component
export default {
name: 'Map',
components: {
MglMap,
MglMarker
},
props: {
someCoordinates: {
type: Array,
required: true
},
darkMode: {
type: Boolean,
required: true
}
},
data () {
return {
accessToken: MAP.ACCESS_TOKEN,
mapbox: null,
map: null,
actionsDispatcher: null
}
},
computed: {
mapStyle () {
return this.darkMode ? MAP.COLOR_PROFILES.DARK : MAP.COLOR_PROFILES.LIGHT
}
},
created () {
this.mapbox = Mapbox
},
methods: {
async onMapLoaded (event) {
this.map = event.map
this.actionsDispatcher = event.component.actions
await this.actionsDispatcher.flyTo({
center: this.someCoordinates
})
}
}
}
</script>
On the first load, everything works as expected:
But if I move to a different pseudo-route (say from /#/Map to /#/Profile and back), some of the map layers specified by my mapStyle (roads, city names,..) are not rendered anymore (default layers instead). The map also stops honoring any change of the mapStyle url, even when I specify mapStyle.sync in my template.
If I hit the browser's reload button it loads the layers as expected as the entire app is reloaded from scratch, but I unfortunately cannot afford to do this by default.
Any ideas are greatly appreciated.
I found a solution, in the example of vue-mapbox, the variable map (this.map) is set by "event.map" which causes an error because the card is not refreshed afterwards.
In my case i just remove that (this.map = event.map) in my onMapLoaded function and this is great.
Have a good day.
Despite I don’t know the syntax of Vue.js, the problem you are facing is that you are creating your layers in map.on('load', ... which is an event that happens only once, so when the style change happens, all the layers of the map style (including the ones created by custom code) are removed.
If you want to recreate your layers on style change, you have to do it in the event map.on('style.load', ..., but as said, I don’t see in your vue.js code where that is being done. If you share the part of the code where vue.js is invoking the methods it’ll be easier to help you

How to i correctly attatch an instance of a registered component to a scene in Aframe?

I want to create a new Component in Aframe and attach it to my scene. But i don't quite get how it is supposed to be used.
For example i have this component line:
How do i create an instance of the component and attatch it to my scene?
Also how do i correctly set the parameters upon creation?
I have taken a look at the Aframe docs which sais to do as follows:
AFRAME.registerComponent('hello-world', {
init: function () {
console.log('Hello, World!');
}
});
document.querySelector('a-scene').setAttribute('hello-world', '');
but that Example isn't enough for me to know how to use it.
I want to create multiple instances of this component:
I hope you can help me.
AFRAME.registerComponent('line', {
schema: {
color: {type: 'string', default: '#8b4513'},
points: {type: 'array', default: []},
},
init: function () {
console.log(this.data.color);
}
});
Attaching a component called hello-world can be achieved in multiple ways:
// no properties / default
setAttribute('hello-world', '')
// assuming there are properties in the schema
setAttribute('hello-world', 'property', 'value')
setAttribute('hello-world', {
'propertyOne': 'valueOne',
'propertyTwo': 'valueTwo'
})
// another instance - if multiple enabled
setAttribute('hello-world__one', 'property', 'value')
You can have multiple instances of your component attached, if you define its multiple property:
AFRAME.registerComponent('foo',
multiple: true
// .....
})
You can attach multiple components like this:
<a-entity foo="" foo__one="" foo__two=""></a-entity>
fiddle here. It's also quite well documented here.
Taking lines as an example, you can simply have a 'manager' entity, with the lines attached.
<script>
AFRAME.registerComponent('line-manager', {
init: function() {
this.el.setAttribute("line__one", {
"start": '0 0 0",
"end": '1 2 3'
})
this.el.setAttribute("line__two", {
"start": '0 0 0",
"end": '3 2 1'
})
}
})
</script>
<a-scene>
<a-entity line-manager></e-entity>
Maybe this fiddle could help.

Categories

Resources