How to access game object from scene class? - object

How
in the body of a function,
that is a member scene object class,
that is listed as a value in the game object config,
const config: Phaser.Types.Core.GameConfig = {
scene: MainScene,
...
would I get a reference to the game object,
if I wanted to do something like get values from pointer the like this:
export class MainScene extends Phaser.Scene {
private foo;
constructor() {
super({ key: "MainScene" });
this.foo = game.input.mousePointer;
}
assuming that the scene and game object are in different ts files
?

Try console.log(MainScene); and combing through that. I'm not really clear on what you're trying to accomplish?

You can access the game object in any scene using this.sys.game. This will not be available in a scene's constructor, though. You should move scene setup to the init function, which will be called automatically by the framework when the game object is available.
With this change your example would look like this:
export class MainScene extends Phaser.Scene {
private foo;
constructor() {
super({ key: "MainScene" });
}
init() {
this.foo = this.sys.game.input.mousePointer;
}
}

Related

Converting Key-Value Observation in AppKit/UIKit to Combine and SwiftUI

I'm having trouble wrapping my head around how to use Combine in SwiftUI. I'm accustomed to using key-value observation in AppKit an UIKit because view controllers don't need to know about each other and can just react to some global objects that help determine state.
For example, in an AppKit/UIKit app, I would create a global state object like this:
//Global State file
#objc class AppState: NSObject {
#objc dynamic var project: Project?
}
//Create an instance I can access anywhere in my app
let app = AppState()
Then in a view controller, I can get notified of any changes to my app-wide project instance and react accordingly:
//View Controller
class MyViewController: NSViewController{
var observerProject: NSKeyValueObservation?
override func viewDidLoad() {
observerProject = app.observe(\.project) { object, change in
self.refreshData()
}
}
func refreshData(){
//Query my persistent store and update my UI
}
}
What is the Combine/SwiftUI analog to this?
Do I need to create a Publisher and then listen to my global object changes? If so, how do I make my Core Data #FetchRequest (whose predicate includes my global Project object) respond in real-time?
I've done things the old way for so long that this transition to SwiftUI/Combine is rather confusing to me. 🙂
#FetchRequest doesn't work well with a dynamic predicate (There are some workarounds in SO) you will have to use the "old school" NSFetchedResultsController for that and put it into an ObservableObject. Here is a video with a sample. It is a lot of setup and code.
import SwiftUI
import Combine
class AppState: ObservableObject {
static let shared = AppState()
#Published var project: String?
//Just to mimic updates
var count = 0
private init() {
//Mimic getting updates to project
Timer.scheduledTimer(withTimeInterval: 2, repeats: true){ timer in
print("Timer")
self.project = self.count.description
self.count += 1
if self.count >= 15{
timer.invalidate()
}
}
}
}
class MyViewModel: ObservableObject{
#Published var refreshedData: String = "init"
let appState: AppState = AppState.shared
var projectCancellable: AnyCancellable?
init() {
projectCancellable = appState.$project.sink(receiveValue: {
value in
print(value ?? "nil")
self.refreshData()
})
}
func refreshData() {
refreshedData = Int.random(in: 0...100).description
}
}
struct MyView: View {
#StateObject var vm: MyViewModel = MyViewModel()
var body: some View {
VStack{
Text(vm.refreshedData)
}
}
}
struct MyView_Previews: PreviewProvider {
static var previews: some View {
MyView()
}
}

How to use class functions in another class?

How can i use class instance in another class like a pointer in C++ to class instance functions?
Example:
class A {
constructor()
{
this.block = [];
}
method()
{
return this.blocks.length;
}
}
another class:
class B {
constructor(instance)
{
this.instance = instance;
}
method()
{
this.instance.method(); // here i'm getting cannot get length of undefined
}
}
If i'm trying to to like that i'm getting problems to call it
You can try this. Here, when creating B class's instance I give into it an A class's instance as argument. Then inside B we can call A instance's methods, and access its properties.
Also, as #ViaTech posted you can use static methods to access them without needing to initialize an object of the class. That is what static methods is. Refer Static Methods
class B {
constructor(instance)
{
this.instance = instance;
}
method()
{
this.instance.method();
}
}
class A {
constructor()
{
}
method()
{
console.log("A's method");
}
}
var a = new A();
var b = new B(a);
b.method(); // A's method
You can easily do this in JS by calling a static method like so:
class A {
static write(){ //static method
console.log("Called write from A");
}
}
class B {
doIt(){
A.write();
}
}
let b = new B();
b.doIt();
Option 2, you instantiate the class in the constructor of the other like so:
class A {
write(){
console.log("Non-static write() called from class A");
}
}
class B {
constructor() {
this.a = new A();
}
doIt(){
this.a.write();
}
}
let b = new B();
b.doIt();
There are a few ways:
I accidentally switched between PHP and Javascript, but the principles are the same for both)
Use static functions:
Normally, you have a this in the class. Say you have this code:
class Car {
let color;
public function setColor(newColor){ this.color = newColor;}
}
let car = new Car();
car->setColor('green')`
The setColor function's this refers to that car. You can make let anotherCar = new Car(), then when you do anotherCar->setColor('red') you only change that car, not the first one. Simplistic: You can create multiple instances.
If you do not need that, but need the class once, you can make it static. A simple way to explain would be "you have a collection of seperate functions, just put into a wrapping class (which doesn't do a lot really)". For instance, you might have some sanatizing methods:
class Sanitize {
static function makeHtmlSave(input){
return doYourMagicHere(input);
}
static function removeXssCode(input){
return doMoreMagicHere(input);
}
}
This way, you can reuse it multiple times. If you want to use it, you do Sanitize::makeHtmlSave(someCode) where you need it. There isn't a Sanitize thing, it's just a wrapper to access the frunctions inside it.
Use extend:
You can extend a class. Say you have a generic class Vehicle, which has some properties (eg a motor, numberWeels, color) and you can extend that with more specific classes:
class Vehicle {
let color;
public function setColor(newColor){ this.color = newColor}
}
class Car extends Vehicle {
let hasAirco = false;
public function hasAirco(newValue){ this.hasAirco = newValue};
}
If you do let car = new Car(), you get a Car object, that extends/enlarges/complements the Vehicle class, so you can use both its (public) functions. Internally, Car can use the functions of Vehicle too.
Just pass it
class One {
// some stuff
}
class Two{
let otherObject;
construct(givenObject){
this.otherObject = givenObject;
}
}
You can now do this let a = new One(); let b = new Two(a);. You can not use the functions of One inside Two, but you can still use a->doSomething(). This solution feels like the easiest, but it almost never is. Classes/objects are tricky stuff, but I've rarely uses this solutions. There are use cases, but often it's a bad smell indicator.

Can I overload method in module.export in node.js?

I have an app.js with this code:
var addnote = (title,body) => { /* enter code here */ }
module.exports = {addnote};
Can I add another addnotes function with different parameters to that file?
Function overloading in JavaScript does not exist like in other programming languages such as C# and Java.
What you should be looking to do is pass an object as a parameter that has properties attached and filter them out there..
You could call different functions from your little 'mapping function' just implement the logic there if it isn't big (to keep the code clear).
function foo(parameters){
var title = parameters.title;
var body = parameters.body;
if(parameters.extraProperty){
// oh we have extraProperty passed in too, run a different function?
bar(title, body, parameters.extraProperty); // ??
}
}
foo({title: 'Title', body: 'Body', extraProperty: 'This is extra...'});
If this is your own custom module, you can use the concept of function overriding, where each child class can have its own way to handle something and also have a default way to do things.
class Parent {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello ${this.name}`);
}
}
class Child1 extends Parent {
constructor(name) {
super(name);
}
greet() {
console.log(`Hey there ${this.name}. This is Child 1`);
}
}
class Child2 extends Parent {
constructor(name) {
super(name);
}
greet() {
console.log(`Hi there ${this.name}. This is Child 2`);
}
}
const o1 = new Child1('Foo')
const o2 = new Child2('Foo')
o1.greet();
o2.greet();
But if you are trying to override a function in an external module(You do not have access to that code, like a library), my suggestion is to create a wrapper and add functionality there.

Haxe: Native Interface properties implementable?

I've got this compiletime errors when I make some class implement an interface with properties that have been fromerly defined in some native sub class, like openfl.display.Sprite. It occurs when I'm targeting flash, not js.
Field get_someValue needed by SomeInterface is missing
Field set_someValue needed by SomeInterface is missing
Field someValue has different property access than in SomeInterface (var should be (get,set))
In contrast, there's no problem with interface definitions of 'native' methods or 'non-native' properties. Those work.
Do I have to avoid that (not so typical) use of interfaces with haxe and rewrite my code? Or is there any way to bypass this problem?
Thanks in advance.
Example:
class NativePropertyInterfaceImplTest
{
public function new()
{
var spr:FooSprite = new FooSprite();
spr.visible = !spr.visible;
}
}
class FooSprite extends Sprite implements IFoo
{
public function new()
{
super();
}
}
interface IFoo
{
public var visible (get, set):Bool; // Cannot use this ):
}
TL;DR
You need to use a slightly different signature on the Flash target:
interface IFoo
{
#if flash
public var visible:Bool;
#else
public var visible (get, set):Bool;
#end
}
Additional Information
Haxe get and set imply that get_property():T and set_property(value:T):T both exist. OpenFL uses this syntax for many properties, including displayObject.visible.
Core ActionScript VM classes (such as Sprite) don't use Haxe get/set, but are native properties. This is why they look different.
Overriding Core Properties
If you ever need to override core properties like this, here is an example of how you would do so for both Flash and other targets on OpenFL:
class CustomSprite extends Sprite {
private var _visible:Bool = true;
public function new () {
super ();
}
#if flash
#:getter(visible) private function get_visible ():Bool { return _visible; }
#:setter(visible) private function set_visible (value:Bool):Void { _visible = value; }
#else
private override function get_visible ():Bool { return _visible; }
private override function set_visible (value:Bool):Bool { return _visible = value; }
#end
}
Overriding Custom Properties
This is not needed for custom properties, which are the same on all platforms:
class BaseClass {
public var name (default, set):String;
public function new () {
}
private function set_name (value:String) {
return this.name = value;
}
}
class SuperClass {
public function new () {
super ();
}
private override function set_name (value:String):String {
return this.name = value + " Q. Public";
}
}
Need to provide the method signatures in an Interface. Currently its just a property declaration.
The error message is saying it all.
Field get_someValue needed by SomeInterface is missing
Field set_someValue needed by SomeInterface is missing
Hopefully that helps.

OpenFL - How to use addChild in another class?

The answer should be simple but I can't find out how anywhere..
So I have a Main.hx class and a ObjectManager.hx class.
In the main class's constructor, it calls ObjectManager.addAllToScreen(); and my objectManager should then add the objects to the screen.
I thought this would be ok because in the constructor of Main you can just say addChild(Objects.platform); but apparently addChild isn't accessible?
The error is: Class<Main> has no field addChild so I'd guess that addChild is a method of Sprite or something?
package;
class Main extends Sprite {
public function new() {
super();
ObjectManager.addAllToScreen();
}
}
In ObjectManager:
package;
class ObjectManager {
public static function addAllToScreen():Void {
Main.addChild(Objects.platform);
Main.addChild(Objects.messageField);
}
}
UPDATE:
Ok so now the code is this... and it runs just fine apart from the objects never showing up on screen - however if the addChild code is put in main, they do show up.
Main:
class Main extends Sprite {
public function new() {
super();
var objectManager = new ObjectManager();
objectManager.addAllToScreen();
}
ObjectManager:
package;
import openfl.display.Sprite;
class ObjectManager extends Sprite {
public function new() {
super();
}
public function addAllToScreen() {
addChild(Objects.platform);
addChild(Objects.messageField);
}
}
addChild() is available in openfl.DisplayObjectContainer, which Sprite extends. So you would need to make your class extend Sprite, yes.
You just need to pass a reference to the stage to your ObjectManager class so you can add things to it later on.
Check this out.
Main.hx
package;
import openfl.display.Sprite;
class Main extends Sprite {
public function new () {
super();
ObjectManager.setup(stage);
ObjectManager.addAllToScreen();
}
}
ObjectManager.hx
package ;
import openfl.display.Sprite;
import openfl.display.Stage;
class ObjectManager {
// The reference to the applications stage
private static var stage:Stage;
// Do this first,
// we need to hold a reference to the Stage object so we can add to it later
public static function setup(stageref:Stage) {
stage = stageref;
}
public static function addAllToScreen() {
// An array of randomly generated sprite objects
var sprites:Array<Sprite> = [randomSprite(), randomSprite(), randomSprite()];
for(sprite in sprites) {
// Position the sprites randomly over the screen
sprite.x = Math.random() * stage.stageWidth;
sprite.y = Math.random() * stage.stageHeight;
// Add them to the stage
stage.addChild(sprite);
}
}
// Ignore this
// Makes a randomly sized circle in a random colour
private static function randomSprite():Sprite {
var spr = new Sprite();
spr.graphics.beginFill(Std.int(0xffffff * Math.random()), 1);
spr.graphics.drawCircle(0, 0, (Math.random() * 100) + 20);
spr.graphics.endFill();
return spr;
}
}

Resources