Getting text to display when next to door [Solved]


(Lozza JP) #1

Hi all,

Just trying to get my head around how some things are working.

I have in a class at the top a protected var doorText:Text; // from flashpunks.graphics Another door class calls a method which includes the statements

doorText = new Text(doorName, x, y);

addGraphic(doorText);

So basically if I walk past a door its name is displayed. But if I have two doors in the same world, both get their names displayed. So I am wondering how the doorText variable is working, is the same variable displaying both text/graphics somehow?

How can I target a certain doors text to remove or change?


(Jacob Albano) #2

How many static variables are you relying on?


(MartĂ­ Angelats i Ribera) #3

It’s hard to say with no code but you should have that variable stored in the “Door” class. Then you should be sure that you change the stored one in that class. I recomend you to have a function that changes if you can see the text of the door.

public class Door extends Entity
{
	public var text:Text;
	public Door()
	{
		//whatever you want to do before set the text


		doorText = new Text(doorName, x, y);
		doorText.visible = false;
		world.addGraphic(doorText);
	}
}

Then you can modify the parameters of that text using the Door variable:

var door:Door = new Door(); //Or your constructor

door.text.visible = true;
door.text.visible = false;

Do not use static variables.

Another way of doing that is using a Graphiclist with the door graphic itself and the text graphic.


(Lozza JP) #4

No static variables.


(Lozza JP) #5

Sorry if my codes not explained well, it begins in door class and is passed into world as a parameter in a function to be created.

I think I got enough from your help to continue, thank you.


(Jacob Albano) #6

If there are no static vars in play, this is definitely a different problem than I had guessed. Can you show the code where you detect the player walking in front of the door?


(Lozza JP) #7

I will post it up a bit later, from what I recall the DoorWay class has an index variable that is passed as a parameter in the constructor. I then just use a switch statement that detects the index variable and sets text string to a variable.

Checks for collision then asks GameWorld (I think the current instance of it? not sure), to run one of its functions that is the door text add graphic code I put above.

So I think maybe my logic is straying a bit.


(MartĂ­ Angelats i Ribera) #8

You can use the colision to handle this. Here an example that goes in the player update() function:

//get the Entities that collides with it
var collisionedEntities:Array = new Array;
colide("door", x, y, collisionedEntities);

//get all the Door class entities
var doorsList:Array = new Array;
world.getClass(Door, doorsList);

var d:Door;
for each (d in doorsList)
{
	//checks if the door is colliding
	if (collisionedEntities.indexOf(d) < 0)
	{
		//d does not collide with the player
		d.text.visibility = false;
	}
	else
	{
		//d does collide with it
		d.text.visibility = true;
	}
}

PD: Haven’t test it becouse i’m too lazzy to make the entire code.


(Lozza JP) #9

That’s cool, given me a new insight into it. Thanks :slight_smile:


(Lozza JP) #10

When you use world.addGraphic

Do you have to declare world as a variable somewhere or does world always point to current world?


(Lozza JP) #11

Here is my code trying to factor in your suggestions (beforehand used a call to my GameWorld class). We are using OGMO to create levels and have the doors working well as entities we place in ogmo and give an index number. It’s just trying to get some tooltip text to display.

This currently throws a 1009 error that it cannot access a propery or method of a null object reference, but I can’t figure out why. My understanding is it thinks no new Text has been instantiatied?

Also it is in the update method, I had it working previously using a call to my gameworld class and it was adding entities really fast, I am guessing 1 per frame. So can I put it just in the main method somehow?

import net.flashpunk.Entity;
import net.flashpunk.utils.*;
import net.flashpunk.FP;
import net.flashpunk.World;
import net.flashpunk.graphics.Text;
import entities.Player;
import GameWorld;

public class DoorWay extends Entity 
{
	private var targetX:Number;
	private var targetY:Number;
	private var targetLevel:Class;
	private var level:GameWorld;
	private var index:int;
	private var doorText:Text = new Text("", 0, 0);
	private var gameWorld:GameWorld = world as GameWorld;
	
	/**
	 * 
	 * @param	level - the current level, this is necessary becuase this calls functions my game world that do not exist in the base flashpunk world.
	 * @param	x - the x position to place the doorway.
	 * @param	y - the y position to place the doorway.
	 * @param	targetX - the x position where the player character will start in the level this door leads to.
	 * @param	targetY - the y position where the player character will start in the level this door leads to.
	 * @param	index - used to determine the level that this door leads to.
	 */
	
	public function DoorWay(level:GameWorld, x:Number, y:Number, targetX:Number, targetY:Number, index:int, doorName:String="") 
	{			
		this.level = level;
		this.x = x;
		this.y = y;
		this.targetX = targetX;
		this.targetY = targetY;
		this.index = index;
		
		setHitbox(24, 24);
					
		
		
		
		
		
		
		// Assign index in ogmo or level oel/xml doorway.index, put the reference here in case # to the level to go to.
		switch (index)
		{
			case 0:
				targetLevel = Assets.TESTLEVEL;
				break;
				
			case 1:
				targetLevel = Assets.STREETLEVEL;
				break;
				
			case 11:
				targetLevel = Assets.SEWERLEVEL;
				break;
				
			case 12:
				targetLevel = Assets.SKYLEVEL;
				break;
				
			case 2:
				targetLevel = Assets.HOMELEVEL;
				break;
				
			case 21:
				targetLevel = Assets.BEDROOMLEVEL;
				break;
			
			case 3:
				targetLevel = Assets.PARKLEVEL;
				break;
				
			case 4:
				targetLevel = Assets.MALLLEVEL;
				break;
				
			case 5:
				targetLevel = Assets.MOXENLEVEL;
				break;
				
			case 6:
				 targetLevel = Assets.FACTORYLEVEL;
				break;
				
			case 7:
				targetLevel = Assets.LABLEVEL;
				break;
				
			case 8:
				targetLevel = Assets.TOWERLEVEL;
				break;
		}
	}
	
	
	override public function update():void 
	{				
		
		if (collide("player", x, y))
		{
			doorText = new Text("test", 400, 400);
			gameWorld.addGraphic(doorText);
			// Goes in the doorway.
			if (Input.pressed(Key.C))
			{ 
				// Creates new world with targetLevel, and puts player at targetX and Y
				// I am assuming the old world is lost in memory/deleted.
				// I don't think it is -laurence.
				FP.world = new GameWorld(targetLevel, targetX, targetY);
			}
		}
		
		// Creates a reference to eddy, so we can do player.x for his location.
		var player:Player = world.getInstance("eddy") as Player;
		
		// Checks if eddy is close to the door ~2 blocks. When we get remove text working remember to
		// reverse the <.
		if (FP.distance(player.x, player.y, x, y) > 48) // (FP.distance(player.x, player.y, x, y) > 5)
		{
				trace("You are not close to the door.");
		}
		
	} // end update function
}

My logic is that doorName in the constructor gets a string we put in ogmo editor. Then I want to get the Text object working by (doorName, player.x, player.y).


(MartĂ­ Angelats i Ribera) #12

world is a parameter of the Entity. It returns the world in wich that Entity is.


(Lozza JP) #13

Oh that makes it more clearer, thanks again copying :slight_smile:


(MartĂ­ Angelats i Ribera) #14
private var gameWorld:GameWorld = world as GameWorld;

It might be this line of code becouse you haven’t added the entity to a world, calling this should return a 1009 error.

Edit: that’s not it. It worn’t return any error until you try to use that variable.


(Jacob Albano) #15

Nope, you’re on the right track. Instantiating that variable in that way will set it when the class is constructed, while world is still null, so next time you access it you’ll get an error. Putting gameworld = world as GameWorld in added() should fix that error.


(MartĂ­ Angelats i Ribera) #16

Acually it’s better if they use a Graphiclist for waht they do. Here you have modified version of your class:

import net.flashpunk.Entity;
import net.flashpunk.graphics.Graphiclist;
import net.flashpunk.graphics.Image;
import net.flashpunk.utils.*;
import net.flashpunk.FP;
import net.flashpunk.World;
import net.flashpunk.graphics.Text;
import entities.Player;
import GameWorld;

public class DoorWay extends Entity 
{
	
	//Embed
	private static const doorImage:Class;
	
	private var targetX:Number;
	private var targetY:Number;
	private var targetLevel:Class;
	private var level:GameWorld;
	private var index:int;
	private var doorText:Text;

	/**
	 * 
	 * @param	level - the current level, this is necessary becuase this calls functions my game world that do not exist in the base flashpunk world.
	 * @param	x - the x position to place the doorway.
	 * @param	y - the y position to place the doorway.
	 * @param	targetX - the x position where the player character will start in the level this door leads to.
	 * @param	targetY - the y position where the player character will start in the level this door leads to.
	 * @param	index - used to determine the level that this door leads to.
	 */

	public function DoorWay(level:GameWorld, x:Number, y:Number, targetX:Number, targetY:Number, index:int, doorName:String="") 
	{			
		this.level = level;
		this.x = x;
		this.y = y;
		this.targetX = targetX;
		this.targetY = targetY;
		this.index = index;

		setHitbox(24, 24);
		
		doorText  = new Text("test", 0, 0);
		doorText.visible = false;
		
		graphic = new Graphiclist(new Image(doorImage), doorText);


		// Assign index in ogmo or level oel/xml doorway.index, put the reference here in case # to the level to go to.
		switch (index)
		{
			case 0:
				targetLevel = Assets.TESTLEVEL;
				break;

			case 1:
				targetLevel = Assets.STREETLEVEL;
				break;

			case 11:
				targetLevel = Assets.SEWERLEVEL;
				break;

			case 12:
				targetLevel = Assets.SKYLEVEL;
				break;

			case 2:
				targetLevel = Assets.HOMELEVEL;
				break;

			case 21:
				targetLevel = Assets.BEDROOMLEVEL;
				break;

			case 3:
				targetLevel = Assets.PARKLEVEL;
				break;

			case 4:
				targetLevel = Assets.MALLLEVEL;
				break;

			case 5:
				targetLevel = Assets.MOXENLEVEL;
				break;

			case 6:
				 targetLevel = Assets.FACTORYLEVEL;
				break;

			case 7:
				targetLevel = Assets.LABLEVEL;
				break;

			case 8:
				targetLevel = Assets.TOWERLEVEL;
				break;
		}
	}


	override public function update():void 
	{				

		if (collide("player", x, y))
		{
			doorText.visibile = true;
			// Goes in the doorway.
			if (Input.pressed(Key.C))
			{ 
				// Creates new world with targetLevel, and puts player at targetX and Y
				// I am assuming the old world is lost in memory/deleted.
				// I don't think it is -laurence.
				FP.world = new GameWorld(targetLevel, targetX, targetY);
			}
		}
		else
		{
			doorText.visibile = false;
		}

		// Creates a reference to eddy, so we can do player.x for his location.
		var player:Player = world.getInstance("eddy") as Player;

		// Checks if eddy is close to the door ~2 blocks. When we get remove text working remember to
		// reverse the <.
		if (FP.distance(player.x, player.y, x, y) > 48) // (FP.distance(player.x, player.y, x, y) > 5)
		{
				trace("You are not close to the door.");
		}

	} // end update function
}

(Lozza JP) #17

Thanks again copying! Adapted this to work perfectly for my needs.

Just one thing, graphiclist is only taking in the doorText variable, there are no door images.

It doesn’t sound right to use just one item in a list, but is it still ok to do?


(MartĂ­ Angelats i Ribera) #18

I’m glad it helped ^^

If you have no Door image just change that line for:

graphic = doorText;

BTW, don’t use a second Entity to set the image of a door (if you have it). Not even use teh addGraphic function. That function creates an Entity with that graphic in it. In this cases the best option is always use Graphiclist (and it’s more intuitive becouse you have both graphics of the same thing together in the same Entity).


(MartĂ­ Angelats i Ribera) #19

Now the second question:

Remember that AS3 is an object oriented lenguage. It means that if you save a variable and pass it to another class you will be able to control the saved object (if you want to prevent this you have to save a clone, not the object itself).

In this case the Graphiclist class is literally only this: a list. Only updates all the graphics together and render them. It’s basically a way of having multiple graphics at once. It works this way: it have a list with all the Graphics and when you call the update function, it calls the update function in all the listed graphics. The same with all the other the other functions (like render, added, removed, etc.). It does this and make the graphic position relative to the Graphiclist.

Any modifications to any graphic listed won’t effect this class. It’s a trick that can be applied a lot of times and allow you to work with the variables that you pass as parameters (some time is the only way).

TL;DR: There is no problem if you modify a Graphic wich is in a Graphiclist.