How to access functions of a world from an entity?


(Finn Brightwell) #1

Hi everyone, I’ve been messing around with Flashpunk for a couple of weeks now. I’m trying to make a platform game where the player can press a key to switch between the two main forms of the main character. The two forms act very differently, so they are represented by two different entities. I have a method in the level world two add one form and remove the other, but I cannot figure out how to access this method from the entities.

This is what I have tried:

            //switch forms
		if (Input.pressed(Key.S))
		{ Level.SwitchForm(); }

. . .but I get the error:

Call to a possibly undefined method SwitchForm through a reference with a static type Class.

Any help would be appreciated :smile:


(David Williams) #2

The ‘SwitchForm()’ function needs to be static. Where you declare the function, it should be:

public static function SwitchForm():whatever
{
   ...
}

(Finn Brightwell) #3

Thanks, now I can access the function, but every line inside it is throwing up errors:

Call to possibly undefined function add()

Call to possibly undefined function remove() , etc


(JP Mortiboys) #4

SwitchForm() should not be static, as it should belong to the instance of the level and not the class definition itself - read this link for more information (this should be a sticky somewhere).

What you need to do is ensure SwitchForm is public, and then access it through the world property, casting it to the Level class, like so:

if (Input.pressed(Key.S)) {
  Level(world).SwitchForm();
}

or, in a slightly different format

if (Input.pressed(Key.S)) {
  (world as Level).SwitchForm();
}

The only difference between these two forms is what happens when world is not an instance of Level - since you should ensure that never happens, the difference is academic.

If you are going to be accessing the typed world more often, it might be worth thinking about making it a permanent member of the entity class:

class Player extends Entity {
  /// ...
  private var level:Level = null;

  override public function added():void {
    level = world as Level;
  }

  override public function removed():void {
    level = null;
  }

  override public function update():void {
    // ...
    if (Input.pressed(Key.S)) {
      level.SwitchForm();
    }
  }
}

(Jacob Albano) #5

Good form all around.


(Finn Brightwell) #6

Thanks, that helped heaps!, All working how I want it to now.

OOP is hard . . .

NotARaptor, how does the “world as Level” bit work? Does it take the instance of the world that I have already declared in my Engine, and then create a pointer to it from inside the Player Entity? Or do I skip declaring the world in my engine, and create the entity first?


(Jonathan Stoler) #7

I’m not 100% sure on the technical details of how it works, but basically it takes the world object (of type World) and casts it to type Level. This is a feature of the language itself. Here is an article about typecasting.

(Note that this article uses basic types, but you can do it between any two objects, although often objects will be incompatible.)


(JP Mortiboys) #8

No, you can’t skip declaring the world in the engine, this is merely giving the player entity a permanent reference to the world, cast as a Level object.

I’m not much with analogies, but I’ll give it a go.

Imagine that three people, Aaron, Beatrix and Cuthbert, are participating in an active survey about their pets. They each get a form to fill in. The form starts with basic questions about the pets - their names, their ages and stuff like that. That’s all fine, they fill them out - because all pets have names (analogy: the World class has methods like add, remove and collide that any class extending World will also have).

Now the problems start - A has a dog, B has a goldfish and C has a pet rock. The next part of the form says “Give your pet twice as much water to drink for two days, and report any changes.”. Well, A is fine - but B can’t do anything, because the instructions don’t make sense for a goldfish.

The next part - “walk your pet in the morning for a week, then in the evening for the next week”, again doesn’t make sense for B or C.

The next part - “are your pet’s gills larger in the morning than the evening” doesn’t make any sense for A or C, because only fish have gills.

The point here is that each pet owner needs a different form and list of instructions, specific to their pet. The pet-specific form is the typed (cast) pointer - Level in your case, the generic form is the World pointer.

I hope that made sense, it’s (relatively) early and I haven’t had my coffee yet.


Changing var values in World from an Entity