In my game I am trying to use one of my variables I have initiated in my create function outside of that scope and to be used in the update function. Ideally my code would look like this:
create()
{
const map = this.make.tilemap({ key: 'mainmap' })
const tileset = map.addTilesetImage('Serene_Village_16x16', 'tiles', 16, 16, 1, 2)
const Next1 = map.createLayer('Next', tileset)
update(t: number, dt: number){
this.physics.world.collide(this.faune, Next1, ()=>{
console.log("testing")
this.scene.stop(),
this.scene.start('secondmap');
});
The problem with this however is that I can not access next1 to collide with my player character "faune" since the error given is that I "Cannot find name 'Next1'.". If anyone has any idea how to use this across functions with Phaser that would be extremely helpful.
Thanks, arthur
The problem is that you are defining the function Next1 in the create function and trying to access it in the update function.
you could, simply define a property in the create function, like this:
this.next1 = map.createLayer('Next', tileset)
and in the update function, use it like this:
this.physics.world.collide(this.faune, this.next1, () => {
// ...
});
for this not to through a compiler error, when using typescript you would have to add the property to the class definition.
class myScene extends Phaser.Scene {
// you can use the exact datatype if you know it
public next1:any;
...
}
Or simply put the this.physics ... code into the create function.
Related
I have a class I reuse, often, to the tune of possibly tens of thousands of instances in a given session. It occurred to me that creating all these properties within the constructor may be replication, that is each function is unique in memory and not a pointer, so I created a little test setup:
const testTree = function (){
console.log(this, this.konnichiwa);
}
const testFjord = function (aloha){
return function() {
console.log(this, aloha, this.konnichiwa);
}
}
class Clown extends Object{
constructor(props){
super(props);
const aloha = "Hello!"; //<- Private party
this.konnichiwa = "Also hello I think"; //<- Everyone's invited
this.testWan = () => {
console.log(this, aloha, this.konnichiwa);
}
this.testTree = testTree;
this.testFjord = testFjord(aloha);
}
testToo = () => {
console.log(this, this.konnichiwa);
}
}
//export default Clown; //this is an export in my application, used lots
const test = new Clown();
const otherTest = new Clown();
console.log(test.testWan === otherTest.testWan);
console.log(test.testToo === otherTest.testToo);
console.log(test.testTree === otherTest.testTree);
console.log(test.testFjord === otherTest.testFjord);
test.testWan();
test.testToo();
test.testTree();
test.testFjord();
Part 1
As you can test above, testWan, testToo, and testFjord are all unique per instance, but testTree is not. Is there any way to declare a "pointer"/"reusable function" but inside class constructor?
The issue here with testToo and testTree is that they can't access private vars within the constructor like testWan can. testFjord is a factory and can be passed these, but then the returned function is unique and won't be able to interact well with vars passed into it.
It's very likely not possible - I think it's a catch 22 scope thing - but you may know better. The only recourse I can think of is to add a property to this for each thing I need to use in testTree, but that exposes things I may not want exposed outside of the class.
Part 2
This part only applies if this is a generally consistent behavior, and not something completely unique per-browser. Does the engine hold onto references to things like conditionals (which I suspect are sorta anonymous-function-like behind the scenes) once the constructor has run?
I have a fairly knarly conditional setup I'm not going to shove in the code here. This is entirely within the constructor right now. I suspect that, although not a function declaration itself, it is also not a pointer, but an entirely fresh instance per the 'new' in new Clown. It needs to manipulate some private vars and so per Part 1 I haven't figured out a good way to extract this.
Example, there are references to private vars inside the constructor for exposed functions: aloha above is private but used by public testWan function, and so needs to be held after constructor has executed. Is the entire constructor held for the life of test & otherTest or is the constructor going to be dropped after use and just the reference to aloha held in memory?
In Angular 2 testing utility I do something like this:
fixture = TestBed.createComponent(EditableValueComponent);
where EditableValueComponent is a normal component class.
I wonder how it works:
static createComponent<T>(component: Type<T>): ComponentFixture<T>;
Beceause I wanna do something similar (I want to simplify some testing stuff):
export class SuperFixture<T>
{
fixture: ComponentFixture<T>;
component: T;
constructor()
{
this.fixture = TestBed.createComponent(T); // <--- problem here!
this.component = this.fixture.componentInstance;
}
}
The problem is:
'T' only refers to a type, but is being used as a value here.'
EDIT #1
I solved the problem this way:
constructor(component)
{
this.fixture = TestBed.createComponent<T>(component);
But I still don't know how it works..
You still need to pass actual class (constructor function that creates instances of a class) into constructor function of SuperFixture. Under the hood TestBed.createComponent calls provided constructor function with new to create instance of provided class. So SuperClass signature might look like this:
class SuperFixture<T>
{
fixture: ComponentFixture<T>;
component: T;
// passing in the constructor for instances of T
constructor(componentConstructor: new () => T)
{
this.fixture = TestBed.createComponent<T>(componentConstructor);
this.component = this.fixture.componentInstance;
}
}
Was working on that answer, but had to step out for coffee. ¯_(ツ)_/¯
The language feature you are using is called a Generic in TypeScript. It allows defining types at runtime with "type variables" (like <T>), which are separate from function arguments.
Before, the type variable was being passed as a function argument, when the function expected an instance of type T. That's what the error means.
The change you made works because you are passing the type variable and the instance in their correct positions in the call.
The SuperFixture object gets the value of T when you create it, and then it will pass that type variable to createComponent in the constructor, along with the value of component.
I'm trying to explore using ES6 classes instead of how we do it currently, using the Function.prototype means. Currently our API looks like:
var myclass = createClass('MyClass', {
test : function() {}
});
We iterate through the object and apply those properties onto the Function that we return, basically a prettier way than to do so that it's more inline with other programming languages of sorts:
function MyClass() {}
MyClass.prototype.test = function() {};
We also cache the class onto an object where name is the key and the function is the value for use throughout our application. The class name can be namespaced so you can have My.Cls and it will split by the period and then cache it onto the manager but it also can be retrieved via window.My.Cls.
Looking into ES6 classes, I don't see how I can keep the createClass function. Would love something like:
function createClass(name, config) {
return class name config;
}
I didn't expect it to work and it doesn't.
Two issues I have here:
How can I create a class using a variable as the class name?
How can I create a class and assign the properties via the config object argument?
Not sure this would be possible. We don't plan on keeping the createClass, we hope to keep it for now and upgrade our legacy "classes". I'd like to start using ES6 classes but not break the whole app for however long it'll take us to fully upgrade.
The only good upgrade route is to refactor the property hashes into proper classes. You can start that work and keep using your hash-based classes in the meantime, which will lighten the requirement to do it all at once.
If you have a limited number of "class" name:config pairs -- which you should for maintainability reasons -- then you can replace createClass with an implementation that does:
class Foo { ... }
class Bar { ... }
let classes = {'Foo': Foo, 'Bar': Bar};
function createClass(name, config) {
if (classes[name]) {
return classes[name];
}
// old impl
}
This will ignore the config if a "real" implementation exists, but keep using the legacy behavior if you haven't replaced the class. If it is, you can implement createClass more like:
function createClass(name, config) {
if (classes[name]) {
return new classes[name](config);
}
// old impl
}
and pass the config arguments into the class ctor. In this case, you may want to filter out function properties (methods) first, as the class probably implements them already. Something like:
function createClass(name, config) {
if (classes[name]) {
let fields = Object.keys(config).filter(key => {
return typeof config[key] !== 'function';
}).map(key => config[key]);
return new classes[name](fields);
}
// old impl
}
I have Small application in Famo.us Framewok.
I want to declare array variable that can be use in calling js.
I have 2 .js file: (1) PageView.js (2) GetContent.js
(1) PageView.js
function AddContent() {
View.apply(this, arguments);
var getContent = new GetContent();
getContent.AddPages();
(2)GetContent.js
function GetContent() {
View.apply(this, arguments);
}
GetContent.prototype = Object.create(View.prototype);
GetContent.prototype.constructor = GetContent;
GetContent.DEFAULT_OPTIONS = {};
GetContent.prototype.AddPages = function () {
GetData();
}
I want to declare array variable in GetContent.js file that can be accessible in PageView.js using the object of GetContent defiened in PageView.js in above code.
so that i can use like getContent.variablename[1]
how to achieve it?
Your GetContent class would need to have an array assigned to it's instance like so:
this.variablename[1, 2, 3];
Adding this allows your array to be attached to the class's specific instance. Otherwise, your array will only exist for the lifetime of the function scope you create it in.
You may also find that you can't access the getContent object after it's been created in your PageView for the same reason. Instead try this.getContent = new GetContent();
Lastly, try to avoid directly accessing other class's variables directly. Instead, use getter/setter methods which allow the class to share and modify their data securely.
The solution to this question suggested the use of John Resig's class implementation. This solution covers all my needs except:
How to declare a public global variable inside this class that can be accessed from outside?
I would like to establish something like the following:
var MyClass = Class.extend({
EVENT_NAME : 'event-name',
init : function() {
// ...
}
});
// Now another file can directly read this value without creating the class object
console.log( MyClass.EVENT_NAME );
The "only" way to do what you want to do is to use a function as the "class". This way you are declaring a "class" whose public "static" members can be accessed. Something like this:
function MyObject() {
// constructor stuff here
}
MyObject.EVENT_NAME = "event_name";
console.log(MyObject.EVENT_NAME); // No need to instantiate MyObject
However, seems to me like you are mixing concepts from statically typed languages with Javascript's more dynamic stuff. Why would you want to access a member of an object that has not been created?
Declare it in the window context or don't use the 'var' keyword:
window.globalVar = somevalue
globalVar = somevalue
var MyClass = Class.extend({
EVENT_NAME : 'event-name',
init : function() {
// ...
}
return {
event_name: function() { return EVENT_NAME; }
}
});
console.log( MyClass.event_name );
Actually, to be honest, I'm not sure how the above is going to work with .extend() as I've not actually used extend() before.
However, the return { name:value } technique is a pretty common way of exposing public instance methods in objects. It shouldn't take long to test it properly, sorry I didn't have a chance to do it myself.