Phaser 3 ScaleManager exception - phaser-framework

I am trying to enable fullscreen in my game written in Phaser 3.
I am doing it from Scene class via
this.game.scale.startFullScreen();
but getting error in f12 browser console
Uncaught TypeError: this.game.scale.startFullScreen is not a function
at TitleScene.<anonymous> (TitleScene.js:23)
at InputPlugin.emit (phaser.js:2025)
at InputPlugin.processDownEvents (phaser.js:167273)
...
In docs ScaleManager class has startFullScreen method.
Why console tells me it doesn't?
This is the full code of TitleScene.js:
export class TitleScene extends Phaser.Scene {
constructor ()
{
const config =
{
key: 'TitleScene'
}
super(config);
}
preload ()
{
this.load.image('Title', 'assets/Title.png');
}
create ()
{
this.background = this.add.image(960, 540, 'Title');
this.input.manager.enabled = true;
this.input.once('pointerdown', function () {
this.scene.start('MainScene');
this.game.scale.startFullScreen(); // here is the error
}, this);
}
}

There are two problems prevented me from resolving this problem:
I followed examples from here
https://www.phaser.io/examples/v2
But I am using the third version Phaser. And everyone who uses the same must follow examples from here
https://www.phaser.io/examples/v3
You must pay attention to url while using their site with examples. Both pages are the same from the first look. But urls are different. Also there are warning after each example using the second (old) version of engine.
And finally this function name is not startFullScreen but startFullscreen :)

Related

NodeJS + TypeScript Error TS2339: Property 'timeOrigin' does not exist on type 'Performance'

I have a NodeJS/TypeScript app that uses Selenium WebDriver, which has approximately this snippet:
import { WebDriver } from "selenium-webdriver";
export class MyClass {
public async getTimeOrigin(driver: WebDriver): Promise<number> {
return await driver.executeScript(function () {
// This should be the DOM's timeOrigin (same as if a person types "performance.timeOrigin"
// into the Chrome DevTools console)
return performance.timeOrigin;
});
}
}
When I attempt to build the above, I get the following error message:
error TS2339: Property 'timeOrigin' does not exist on type 'Performance'
But it does certainly exist, since I can looks up the references on the Performance object and see timeOrigin inside. Can anyone please advise on how to fix this and correctly access the timeOrigin property?
performance is a global variable which is only available to the web browser you test. While you're working in NodeJS environment, it doesn't have any global performance, that's why Typescript cannot detect it and throw the error when compiling.
To fix this, you only need a simple global variable declaration:
declare var performance: any;
If you're using a lot of web interfaces in your Node environment, I recommend you import the lib lib.dom to typescript to avoid these types of errors:
{
"compilerOptions": {
"lib": [
"dom"
]
}
}
As mentioned by mcernak, another way is to use string as input to executeScript function.
To avoid the compilation issues, you can provide the script that you want to execute in context of the browser as a string(instead of a function):
public async getTimeOrigin(driver: WebDriver): Promise<number> {
return await driver.executeScript("return performance.timeOrigin;");
}
From the documentation of WebDriver.executeScript:
Executes a snippet of JavaScript in the context of the currently
selected frame or window. The script fragment will be executed as the
body of an anonymous function. If the script is provided as a function
object, that function will be converted to a string for injection into
the target window.
Maybe you can try to cast it as Performance.
import { WebDriver } from "selenium-webdriver";
export class MyClass {
public async getTimeOrigin(driver: WebDriver): Promise<number> {
return await driver.executeScript(function () {
// This should be the DOM's timeOrigin (same as if a person types "performance.timeOrigin"
// into the Chrome DevTools console)
const perf = <Performance>performance; // or "performance as Performance"
return perf.timeOrigin;
});
}
}

Testing A Library That Uses The Web Audio API With Mocha & Chai

I am building a library which uses the web audio api(ToneJS to be more specific).
I have tried using jsdom, mocha-jsdom with no success.
I get this error -
node_modules/tone/build/Tone.js:3869
this.input = this.output = this._gainNode = this.context.createGain();
Which makes sense and tells me that i need to use an environment with a context.
I'm not even sure how i should setup the tests for my project.
How should i setup a test environment correctly for my project?
I would suggest to not use Tone.js at all in your unit tests. Tone.js only works in the browser as it requires the Web Audio API. Instead you could use a spy/mock/stub of Tone.js which just makes sure that you use Tone as intended.
If you for example want to write a test for the AudioManager you could create a stripped down mock of Tone.js which just provides what you need.
const FakeTone = {
Players: function () { },
context: { resume () { } }
};
Next I would recommend to rewrite the AudioManager in a way that it accepts Tone as a constructor argument instead of importing it. This will make testing a lot easier. Instead of ...
import Tone from 'tone';
export class AudioManager {
// ...
generatePlayers () {
return new Tone.Players()
}
// ...
}
... it would then be ...
export class AudioManager {
constructor (Tone) {
this.Tone = Tone;
}
// ...
generatePlayers () {
return new this.Tone.Players();
}
// ...
}
... which looks a bit ugly at first, but you hopefully get used to it after a while. :-)
This will allow you to test the AudioManager with the FakeTone object.
const audioManager = new AudioManager(FakeTone);
expect(audioManager.generatePlayers()).to.be.an.instanceOf(FakeTone.Players);
You could also use something like Sinon.JS to write more advanced tests.

Parent/Child class hierachy in nodejs

child.js
class Child {
constructor(){
this.helloWorld = "Hello World";
}
run() {
}
}
export default new Child();
parent.js
import child from './child.js';
class Parent {
constructor() {
this.child = child;
}
}
export default new Parent();
index.js
import parent from './parent.js'
console.log(parent.child.helloWorld); <-- does not throws an error, displays "Hello World"
console.log(parent.child.run); <-- throws an error (Cannot read property run from undefined)
console.log(parent.child.run()); <-- throws an error (Cannot read property run from undefined)
If I do console.log(parent.child) in index.js, run does not show up, however the property helloWorld does..
How can I have the functions exposed as well? I was hoping to be able to do this to help keep my code a bit more organized, so was going to separate it out into separate classes to help minimize the amount of code in each file.
To make one thing clear from the start: The error you seem to get has nothing to do with run not appearing in the console.log output.
If your code really throws that error then that means that the value of parent.child is undefined. Hence when you call console.log(parent.child), you should see undefined, not an object. However, I don't see why you'd get that error.
Anyways, run is defined on the prototype of parent.child, not on itself. console.log most likely shows an object's own properties (the console API is not standardized, so results can vary between environments). That's normal.
Simple example to reproduce:
var foo = {
x: 42
};
var bar = Object.create(foo);
bar.y = 21;
console.log(bar, bar.x, bar.y);
// Open the browser console to see output
bar.x is accessible even though console.log doesn't show it (in Chrome at least).
Well I'm not sure if helps you to solve the problem, but whenever I want to add inheritance, I use extends and super here is an example:
Base Class:
class BaseDataModel {
constructor() {
}
getModel() {
return 'model';
}
module.exports.BaseDataModel = BaseDataModel;
Class extending Base Class:
"use strict"
// Imports
const BaseDataModel = require('../baseDataModel').BaseDataModel; // use the proper location
class UserMembershipModel extends BaseDataModel {
constructor() {
super(); // this is optional, I use this to inherit the constructors
}
getChildModel() {
return super.getModel(); // This is how you access the function from your extended class
}
module.exports.UserMembershipModel = UserMembershipModel;
Again, not sure if it solves your problem, since your actually adding a property with a Child class. My example is actually extending (or UserMembershipModel inherits from BaseDataModel).
Hope this helps you a bit.

Can't figure out where to put require.config when using TypeScript, RequireJs, and Jasmine

I've been following the pattern for setting up TypeScript, RequireJS, and Jasmine that Steve Fenton describes here:
https://www.stevefenton.co.uk/Content/Blog/Date/201407/Blog/Combining-TypeScript-Jasmine-And-AMD-With-RequireJS/
That pattern as really worked well and truly unblocked me (yay!), but I'm now at the point where I need to customize some settings for RequireJS but I can't seem to figure out where to put my require.config call. Everywhere I've tried has caused breaks and regressions. Here are the two approaches that seem most logical/promising
In SpecRunner.cshtml
<script data-main="/Scripts/TypeScript/RequireJsConfig" src="/Scripts/require.js"></script>
In RequireJsConfig.ts
require.config({
baseUrl: "../Scripts",
paths: {
jquery: "../jquery-2.1.3"
}
});
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Attempt 1: When I try it this way I immediately get this error
//
// JavaScript runtime error: Object doesn't support property or method 'config'
//
import TestLoader = require("Tests/TestLoader");
TestLoader.Run();
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Attempt 2: When I try it this way, everything builds and runs without errors, but
// Jasmine doesn't find any of the tests. All I get is "No specs found" even
// though I see the breakpoints on my "it" statements getting hit.
//
require(["Tests/TestLoader"], (testLoader) => {
testLoader.Run();
});
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
jasmine.getEnv().execute();
In TestLoader.ts
import GuidHelperTests = require("Tests/T3/Helpers/GuidHelperTests");
import ObjectHelperTests = require("Tests/T3/Helpers/ObjectHelperTests");
class TestLoader {
public static Run: () => void = () => {
GuidHelperTests.Run();
ObjectHelperTests.Run();
}
}
export var Run = () => TestLoader.Run();
In GuidHelperTests.ts
import T3 = require("T3/T3Lib");
export var Run = () => {
describe("GuidHelper tests", () => {
it("GUID validator validates good GUID", () => {
// etc. ...
My guess is that Attempt 2 doesn't work because of some kind of sequencing issue where the test discovery process is happening before modules are loaded, or something like that. I'm just not versed enough in RequireJS to know what my options are here.
I prefer to keep my configuration away from my application - you can pre-register the configuration like this, and it will be picked up by RequireJS when it loads. No need to add it to your first file.
<script>
var require = {
baseUrl: "../Scripts",
paths: {
jquery: "../jquery-2.1.3"
}
};
</script>
<script data-main="/Scripts/TypeScript/RequireJsConfig" src="/Scripts/require.js"></script>

Using EasyRTC in dart: Class 'Proxy' has no instance getter 'iterator'

As an experiment, I'm trying some stuff out with dart and easyrtc. I started at porting this (it is normally served through a nodejs server, found here) to a dart version and this is what I made from it
EDIT: I found out which part of the code is causing the error. It is the data object proxy which the for loop is unable to run through. Normally, the setRoomOccupantListener function gives as parameters the name of the room and an object with all the peers connected to the room. I have made a screenshot of the object layout in normal javascript as how it looks when I debug in chrome, found here.
function connect() {
easyrtc.setRoomOccupantListener(convertListToButtons);
}
function convertListToButtons (roomName, data, isPrimary) {
clearConnectList();
var otherClientDiv = document.getElementById("otherClients");
for(var easyrtcid in data) {
var button = document.createElement("button");
button.onclick = function(easyrtcid) {
return function() {
performCall(easyrtcid);
};
}(easyrtcid);
var label = document.createTextNode(easyrtc.idToName(easyrtcid));
button.appendChild(label);
otherClientDiv.appendChild(button);
}
}
And here is the screenshot when i debug the dart code in chromium
void connect() {
easyrtc.setRoomOccupantListener(convertListToButtons);
}
void convertListToButtons(roomName, data, isPrimary) {
clearConnectList();
var otherClientDiv = querySelector("#otherClients");
for (var easyrtcid in data) {
var button = document.createElement("button");
button.onClick.listen((event) {
performCall(easyrtcid);
});
button.appendText(easyrtc.idToName(easyrtcid));
otherClientDiv.append(button);
}
}
This is the error I get:
Class 'Proxy' has no instance getter 'iterator'.
NoSuchMethodError: method not found: 'iterator' Receiver: Instance of 'Proxy' Arguments: []
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:45)
#1 P...<omitted>...7)
Am I missing something simple here or is this some kind of incompatibility? Thank you.
I see you can use import package:js/js.dart'; too. I don't know how to use it
You could try
import 'dart:js' as js;
https://www.dartlang.org/articles/js-dart-interop/
This looks weird too
easyrtc = js.context.easyrtc; // <== here you have context 'easyrtc'
easyrtc.easyApp('easyrtc.audioVideo', 'selfVideo', new js.JsObject.jsify(['callerVideo']), loginSuccess, loginFailure);
// and here again 'easyrtc.audioVideo', I guess this is one to much
try
easyrtc.easyApp.callMethod('audioVideo', ['selfVideo', js.JsObject.jsify(['callerVideo']), loginSuccess, loginFailure]);
where 'audioVideo' is the called method and the rest are arguments
easyrtc.callMethod('easyApp', ['audioVideo', 'selfVideo', js.JsObject.jsify(['callerVideo']), loginSuccess, loginFailure]);
where 'easyApp' is the called method and the rest are arguments.
If you can add how the code would look in JavaScript I could create better examples.
Like dart:js package:js doesn't handle directly Dart List. So the following line :
easyrtc.easyApp('easyrtc.audioVideo', 'selfVideo',
['callerVideo'], loginSuccess, loginFailure);
should be :
easyrtc.easyApp('easyrtc.audioVideo', 'selfVideo',
js.array(['callerVideo']), loginSuccess, loginFailure);
See also What is a difference between dart:js and js package?

Resources