Haxe: Calling a function from and outside Class within Main Class - game-engine

I would like to call a function that is located outside the Main class of my Haxe game.
I am able to add bubbles to the game using: addChild(new Bubble(player.x, player.y));
I would like to update the game without using an EventListener in each added object.
The follow code: Bubble.tick();
Yields this error when run from main:
Bubble has no field tick
Bubble Class:
package;
import flash.Lib;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.MovieClip;
import openfl.Assets;
import flash.events.Event;
class Bubble extends Sprite
{
private var newBubble:Bitmap;
private static var gameBubble:Array<Sprite> = new Array<Sprite>();
public function new (xpos:Float,ypos:Float) {
super ();
this.x = xpos;
this.y = ypos;
newBubble = new Bitmap (Assets.getBitmapData ("img/sprite_bubble_16x16.png"));
newBubble.x = -12.5;
newBubble.y = -12.5;
addChild(newBubble);
gameBubble.push(this);
trace("Bubble");
}
private function tick2(e:Event) {
this.y -= 5;
checkPop();
}
public function tick() {
this.y -= 5;
checkPop();
}
private function checkPop() {
if(this.y < 0) {
this.parent.removeChild(this);
}
}
}

tick is a member method, not a static method.
Bubble.tick()
will look for static public function tick(), while
var b = new Bubble();
b.tick();
will look for public function tick().
Static functions are tied to the class, not a specific instance of the object. Member functions are tied to a specific instance of an object, and can use this to access that instance.
Hope that helps
EDIT (in response to your comment):
It's hard to tell exactly what you are trying to do, but it looks like you want each "Bubble" to slowly move towards the bottom of the screen, and to be removed when it does.
You have 2 options:
1) Every bubble instance creates it's own timer, and tick is a member function (public function tick) which does this.y -= 5 etc.
2) tick is a static function (static public function tick) which does a loop over every bubble (for (bubble in gameBubble) { bubble.y-=5; ...etc... })
The basic rule: anything static can't access this, because it doesn't know which bubble you are talking about, so you'll have to use your static array to go through each of them.

Related

I have an issue with casting Player to a MyPlayer

Hello I started learning to code minecraft bukkit plugins just few days a go, so please don't blame me if my issue is stiupid. I want to create a new MyPlayer class that will be Player subclass. I have already figured out that Player's root is org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer so I can make somethink like this: public class OticPlayer extends org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer. I want MyClass to contain all of his parent methods, but add some it's own. The problem is when i use: Bukkit.getPlayerExact(arg3[1]) it return the reference to a Player type object. I have a Lobby class with method addPlayer(MyPlayer arg0), so I need a reference to the MyPlayer type object, not Player. When I will try to cast a Player type reference to MyPlayer, it's throws an exception: java.lang.ClassCastException: org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer cannot be cast to me.gtddd.my.MyPlayer. I need to pass MyPlayer type reference to the addPlayer() method, because I want to make some kind of stats system (K/D/A), each of these stats must be a pool accesable, by MyPlayer type object. So how can I cast Player to MyPlayer? Example code that generates this problem:
package test;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_12_R1.CraftServer;
import org.bukkit.plugin.java.JavaPlugin;
import me.gtddd.otic.OticPlayer;
import net.minecraft.server.v1_12_R1.EntityPlayer;
public class MyPlayer extends org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer {
public MyPlayer(CraftServer server, EntityPlayer entity) {
super(server, entity);
}
int kills = 0;
int deaths = 0;
int assists = 0;
public int getKda() {
return kills/deaths/assists;
}
}
public class Lobby {
MyPlayer[] players = new MyPlayer[10];
public void addPlayer(MyPlayer arg0) {
players[players.length] = arg0;
}
public MyPlayer getPlayer(int slot) {
return players[slot-1];
}
}
public class Main extends JavaPlugin {
#Override
public void onEnable() {
Lobby lobby1 = new Lobby();
MyPlayer player = (MyPlayer) Bukkit.getPlayerExact("Notch");
lobby1.addPlayer(player);
System.out.println(lobby1.getPlayer(1).getKda());
}
}
I looked lot to find the answer, but I was not able to find anythink what would satisfy me. From top: Thanks for all answers! If somethink is unclear ask.
Instead of extending a Player, you should create a Wrapper around Bukkit's Player Object, more specifically wrapping the Player's Name or UUID (recommended) as it's not possible to edit Bukkit's Player instances without a lot of effort, it's implementation is very obscure, and you won't be able to include your MyPlayer in Bukkit's server.
So, for example, you could create a MyPlayer as following:
class MyPlayer {
private String playerName;
public MyPlayer(Player player) {
playerName = player.getDisplayName(); //Something like this to store the player
}
//More of your code, for example counting the kills
public Player recoverPlayerObject() {
return Bukkit.getPlayer(playerName);
}
And if you want to do things like adding a kill to the player, and then teleporting him, you could use your MyPlayer instance to modify your players' attributes, and using the recoverPlayerObject if you need to interact directly with Bukkit Player object.
For more information on Wrapper/Decorator, Iluwatar has a very nice Github repository about Design Patterns, including the Decorator.

Haxe+OpenFL->Neko, MouseEvent.xxxKey always false

I am making a game using Haxe+OpenFL. I had targeted js once ago, then I switched to neko and the following construction stopped working:
if(e.shiftKey)
do smth
Ofc I've not changed this block of code, nor context since changing the target. What has gone wrong?
P. S. Tracing shows, that holding alt, ctrl or shift keys do not change corresponding properties of MouseEvent object
Based on this link, it used to be a problem, but has been fixed two years ago. Strangely, my tests show it still doesn't work.
This class demonstrates that it will work correctly in js but not in neko.
class Main extends Sprite
{
public function new()
{
super();
var s:Sprite = new Sprite();
s.graphics.beginFill(0xff0000);
s.graphics.drawCircle(100, 100, 200);
s.graphics.endFill();
addChild(s);
//testing a simple click event
s.addEventListener(MouseEvent.CLICK, OnClick);
//testing wheel events, as I read somewhere it could a been a bug in earlier versions
s.addEventListener(MouseEvent.MOUSE_WHEEL, OnWheel);
//testing click events on the stage object, in case it acted differently
addEventListener(MouseEvent.CLICK, OnStageClick);
}
private function OnStageClick(e:MouseEvent):Void
{
trace(e.shiftKey);
}
private function OnWheel(e:MouseEvent):Void
{
trace(e.shiftKey);
}
private function OnClick(e:MouseEvent):Void
{
trace(e.shiftKey);
}
}
An alternative solution could be to use openfl.events.KeyboardEvent and note when the shift key is up or down as a boolean (note that shift's keycode is 16). This example works correctly in my tests.
class Main extends Sprite
{
var shiftIsPressed:Bool = false;
public function new()
{
super();
stage.addEventListener(KeyboardEvent.KEY_DOWN, OnDown);
stage.addEventListener(KeyboardEvent.KEY_UP, OnUp);
stage.addEventListener(MouseEvent.CLICK, OnClick);
}
private function OnUp(e:KeyboardEvent):Void
{
if (e.keyCode == 16)
{
shiftIsPressed = false;
}
}
private function OnDown(e:KeyboardEvent):Void
{
if (e.keyCode == 16)
{
shiftIsPressed = true;
}
}
private function OnClick(e:MouseEvent):Void
{
if (shiftIsPressed)
{
trace('Click!');
}
}
}
Update
Since I've always used the keyboard event trick I mentioned earlier, I missed the fact that it also does not work in C++. I suppose those two targets use some custom event system and someone forgot to register the modifier keys to the created event.
Update 2 (sept 22)
Someone fixed it

Why is this subclass' parent method call not polymorphic?

I've been dabbling in Dlang recently as C++ just wasn't quite sitting right with me after having used Python for so long. While dabbling, I came across what I thought would be a very simple exercise in polymorphism. I suppose how you would expect something to work and what it actually does are two entirely different things for reasons an end user probably can't comprehend. That being said, here is the source code of my "sandbox.D":
import std.stdio;
class Animal {
string voice = "--silence--";
void speak() {
writeln(this.voice);
}
}
class Dog : Animal {
string voice = "Whoof!";
}
int main() {
auto a = new Animal();
auto d = new Dog();
writeln(a.voice); // Prints "--silence--"
writeln(d.voice); // Prints "Whoof!"
a.speak(); // Prints "--silence--"
d.speak(); // Prints "--silence--" NOT "Whoof!"
return 0;
}
I guess my issue is why the "this" keyword just doesn't seem to be functioning how you would expect it to in the C++ successor language.
Methods are polymorphic, variables aren't. So instead of making the voice a variable, you want to override speak in the child.
Also, the auto return type doesn't work with polymorphism, you need to actually specify the types. (The reason is that auto return makes a function template in the compiler, which in theory could have multiple overridable slots in the function table, so it just doesn't try to put it in.)
So try this out:
import std.stdio;
class Animal {
void speak() { // changed to void instead of auto
writeln("--silence--");
}
}
class Dog : Animal {
override void speak() { // the override tells it to override the base method
writeln("woof");
}
}
int main() {
auto d = new Dog();
d.speak();
return 0;
}
If you have a lot of shared functionality and want to reuse one function with slight changes in child classes, you might make a method instead of a variable that just returns something.
Like string voice() { return "woof"; }, then it can be overridden in children.
Another way is to use template this parameter:
import std.stdio;
class Animal {
string voice;
void speak(this C)() {
writeln((cast(C)this).voice);
}
}
class Dog : Animal {
string voice = "Whoof!";
}
int main() {
auto a = new Animal();
auto d = new Dog();
a.speak(); // Prints ""
d.speak(); // Prints "Whoof!"
return 0;
}
Or when you do not need to have voice as a member:
import std.stdio;
class Animal {
static immutable voice = "";
void speak(this C)() {
writeln(C.voice);
}
}
class Dog : Animal {
static immutable voice = "Whoof!";
}
int main() {
auto a = new Animal();
auto d = new Dog();
a.speak(); // Prints ""
d.speak(); // Prints "Whoof!"
return 0;
}

Unity: Preserving static object/data between editor and play

I made offline Waypoints Network generator, which is able to construct waypoints network in editor so we can move or remove the waypoints during the editing process. However I need some way to reference the waypoints network from different objects in play mode and I really like the singleton approach. My idea is:
I have 3 scripts: WNNetwork, WNNetworkObject and WNNetworkData.
WNNetworkData is simple ScriptableObject, which holds the calculated data.
[System.Serializable]
public class WNNetworkData : ScriptableObject {
// Data of waypoints network
public List<WNWaypoint> waypoints = new List<WNWaypoint> ();
public WNKDTree tree = null;
}
WNNetworkObject is MonoBehaviour scripts that is attached to GameObject and it is use to update, re-generate or delete the waypoints network.
public class WNNetworkObject : MonoBehaviour {
#region Public Variables
// Properties of waypoints
public float size = 1f;
public Color color = Color.cyan;
public Color colorSelected = Color.white;
public Color colorLine = Color.white;
public float lineWidth = 0.5f;
public WNWaypoint.GizmosType type = WNWaypoint.GizmosType.CUBE;
// Parameters for network generation
public float maxClusterRadius = 2;
public float neighborsThreshold = 10f;
public bool doNeighborsSimplification = true;
// Others
// public GameObject queryTarget;
#endregion
#region Life-cycle
void Awake () {
DontDestroyOnLoad (this.gameObject);
}
void Start () {
Debug.Log (WNNetwork.data);
}
#endregion
...
}
This is how it's look in inspector editor:
WNNetwork Inspector editor
The last script is WNNetwork, which is basically a wrapper class holding static reference to WNNetworkData and WNNetworkObject, so I can easily access both.
public class WNNetwork {
public static WNNetworkObject root;
public static WNNetworkData data;
...
}
I also created an EditorScript, so I can create all objects from Menu, here is the creation part.
public class CreateWaypointsNetwork {
[MenuItem("GameObject/Create Other/Waypoints Network")]
public static void Create ()
{
WNNetworkData data = ScriptableObject.CreateInstance <WNNetworkData> ();
GameObject go = new GameObject ("WaypointsNetwork", new System.Type[]{typeof(WNNetworkObject)});
WNNetworkObject root = (WNNetworkObject) go.GetComponent<WNNetworkObject> ();
WNNetwork.data = data;
WNNetwork.root = root;
AssetDatabase.CreateAsset (data, "Assets/WaypointsNetworkData");
AssetDatabase.SaveAssets ();
EditorUtility.FocusProjectWindow ();
Selection.activeObject = go;
}
}
The thing is, when I create the Waypoints Network everything works in editor, every object seems to be successfully created and I can edit the waypoints. But as soon as I hit the play button, the WNNetwork is reset and all static variables are equal to null. The Network itself seems to be preserved, because every waypoint still have reference to all its neighbours, but I cannot access the data.
I know I am doing something terrible wrong, but I'm unable to determine what, I'm still not so familiar with Unity.
Thanks for any help.
Simply unity doesn't serialize static fields (even if they are of a serializable type).
When you switch from editor to play mode you are deserializing/serializing data, so you will end up losing everything stored into static fields.

How does Undo work?

How does undo work? Does it copy all the managed objects every time any of the values change? Or does it only copy the actual changes together with an information which objects were affected? Is that heavy or lightweight?
The 'undo' mechanism for pretty much any language that supports Object-Oriented constructs uses the Memento Design Pattern to make it happen.
Here's a rough implementation to get you thinking. This handles your stack of undoable operations. (It doesn't handle redo, but that's easy to support by replacing the stack with a list and keeping track of the current item.)
public class Undoable {
public static void Do(Action do, Action undo) {
do();
sUndoStack.Push(new Undoable(do, undo));
}
public static void Undo() {
sUndoStack.Pop().mUndoCallback();
}
private Undoable(Action doCallback, undoCallback) {
mDoCallback = doCallback;
mUndoCallback = undoCallback;
}
private Action mDoCallback, mUndoCallback;
// note: using a global stack here is lame, but works for demo purposes
private static readonly Stack<Undoable> sUndoStack = new Stack<Undoable>();
}
To use this, let's say the user can change a value in some object like this:
public class Foo {
public string Bar {
get { return mBar; }
set {
if (mBar != value) {
mBar = value;
}
}
}
private string mBar;
}
To make that operation undoable, we just change the setter to:
set {
if (mBar != value) {
string oldValue = mBar;
Undoable.Do(() => mBar = value,
() => mBar = oldValue);
}
}
Now, if you call Undoable.Undo() from anywhere in the application, your instance of Foo will restore the previous value of Bar. If Foo also raises an event when Bar changes (not shown here), the UI will also properly refresh on undo too.