Accessing variables across classes returns incorrect value


(Nate ) #1

Hey guys, so I thought I had this down but I am still having small issues… And I am talking about accessing the value of a variable in one class from a another. For what I am working on, I am trying to access the boolean value (true/false) of a variable in my enemy class from a conditional statement in my player class.

Everything runs, but when I run a trace from my player class, it never changes from false, when I trace from my enemy class it changes true/false like it is supposed to.

In my player class I basically have

if(enemy.isHit == false) { do something } if(enemy.isHit == true) { do something else }

In the player class I created enemy as a new theEnemy and I have the isHit boolean variable in theEnemy class as public. I was just wondering if there was something that I was missing fundamentally which would explain why my instance of theEnemy class in my player class is not getting anything other than false, even though the value in theEnemy class is most definitely changing.

Here is the Enemy.as in case it is needed to formulate speculation:

package entities {


import net.flashpunk.Entity;
import net.flashpunk.graphics.Image;
import net.flashpunk.FP;
import net.flashpunk.graphics.Spritemap;
import worlds.theWorld
import net.flashpunk.World;


public class theEnemy extends Entity
{
	private var power:Number = 2;
	
	public var isHit:Boolean = false;

	private var sprEnemy:Spritemap = new Spritemap(ENEMY, 40, 40);
	
	[Embed(source = '../assets/enemy.png')]
	
	public static const ENEMY:Class;

	
	public function theEnemy(posX:int, posY:int)
	{
		graphic = sprEnemy;
		sprEnemy.add("chomp", [0, 1, 2], 5, true);
		setHitbox(40,40);
		type="enemy"; 
		x = posX * 40;
		y = posY * 40;
		
		sprEnemy.play("chomp");
			
	}
	
	override public function update():void
	{
			
			
			if (!isHit)//if false move left
			{
				x -= power;
			}
			
			
			if (isHit)//if true move right
			{
				x += power;
			}
			
			
			
			 if (collide("wall", x - 5,  y) && isHit == false)
			{
				isHit = true;

			}

			if (collide("wall", x + 5,  y) && isHit == true)
			{
				isHit = false;

			}
		
			
			trace("isHit from the enemy class: " + isHit);
			
			
			
		
			
			super.update();
			
	}
}

}

Thanks guys!


(Alex Larioza) #2

Can you post the code where you are creating the new enemy/tracing the isHit value?

If the code appears to be working in the enemy class, I suspect there is something wrong in your player class.


(Nate ) #3

Okay this is all the related enemy code from the player class:

	import entities.theEnemy;

	private var enemy:theEnemy;

    enemy = new theEnemy(0, 0); 

    if (collide("enemy", x, y) && !collide("wall",x - 50 ,y))
		{
			if (enemy.isHit == false)//enemy moving left
			{
				x -= 50;
				y -= 15;
				health --;
			
				
			}
			if (enemy.isHit == true)//enemy moving right
			{
				x += 50;
				y -= 15;
				health --;
			}
		}
		
		trace("enemy.isHit: " + enemy.isHit);

(David Williams) #4

Is this enemy ever being added to the world? It’s checking for this enemy specifically. What I would suggest is:

var enemy:theEnemy = collide("enemy", x, y);

That goes in your update function. Then, you can go:

if (enemy && !collide("wall",x - 50 ,y))
    {
        if (enemy.isHit == false)//enemy moving left
        {
            x -= 50;
            y -= 15;
            health --;


        }
        if (enemy.isHit == true)//enemy moving right
        {
            x += 50;
            y -= 15;
            health --;
        }
    }

    trace("enemy.isHit: " + enemy.isHit);

What this does is see if the player is currently colliding with any enemies, and if they are, then it returns that specific enemy.


(Nate ) #5

I added the first line to my update function in the player class and it did not like that one bit…

col: 29 Error: Implicit coercion of a value with static type net.flashpunk:Entity to a possibly unrelated type entities:theEnemy. var enemy:theEnemy = collide(“enemy”, x, y);


(David Williams) #6

Try: var enemy:theEnemy = collide(“enemy”, x, y) as theEnemy;


(Nate ) #7

Okay that ran, when I traced enemy it now says null. Can I set enemy = enemy.isHit?


(Nate ) #8

Okay I have been messing around for quite some time now, and decided to break it down to the three basic classes that I am working with and to re-phrase my question. Since I am new to FP and am only really just getting my bearings (Or think I am)

I have three classes that need to be interconnected to an extent. I have three for the sake of organization and clean code (or as clean as I can make it)

The classes are, theWorld, thePlayer, theEnemy.

As of right now, this is how I have them all set up:

theWorld: Responsible for spawning the player, enemy, walls etc etc.

thePlayer: Contains collision data, including collision with the enemy; as well as the basic input data, gravity, friction etc.

theEnemy: Contains path movement for the enemy, that is it really.

Where should I be handling player collision with the enemy? As of now I am trying to handle it within the player class as I believe that will provide the cleanest most legible solution, however I cannot seem to make it work properly.

Thank you in advance for your input you guys!


(David Williams) #10

Say in your world, you add 10 enemies:

add(new theEnemy());
add(new theEnemy());
...

There are no references to those saved anywhere, but they are in the world. How will thePlayer class know which one of them to access (for the isHit() function)?
Well, doing this, you get the specific instance returned that your are colliding with, stored in a temporary variable so that you can access the public function:

var enemy:theEnemy = collide("enemy", x, y) as theEnemy;
if(enemy)
{
    //There is collision happening!
    trace(enemy.isHit);
}
else
{
    //No collision has happened, so "enemy" is null.
}

Does that make slightly more sense?


(Nate ) #11

This does make more sense now! I will try to implement this code! Thank you for your assistance! :smile:


(Nate ) #12

Hey Deamonr I just wanted to get back to you! First of all I wanted to thank you for the help! Second of all I wanted to mention that I don’t think you knew what isHit was supposed to be, basically it is a boolean from my enemy class that when it is false my enemy is moving left, and when it is true the enemy is moving right. So my main fundamental question was, how do I properly access the isHit value from the player class.

Long story short, I used your code snippets in my own implementation from my world class and got it functioning just how I want it to for now! This works with as many enemies that I was to throw onto the map!

Here is what I came up with!

	var collisionEnemy:theEnemy = theEnemy(hero.collideTypes("enemy", hero.x, hero.y));
		
		if (collisionEnemy != null)//if a collision is happening with the enemy
		{
		
			if (!collisionEnemy.isHit)// if the enemy is moving left
			{
				if (!hero.collideTypes("wall", hero.x - 50, hero.y))
				{
					hero.x -= 50;
					hero.y -= 15;
					hero.health --;
				}
			}
			
			if (collisionEnemy.isHit)//if the enemy is moving right
			{
				if (!hero.collideTypes("wall", hero.x + 50, hero.y))
				{
				hero.x += 50;
				hero.y -= 15;
				hero.health --;
				}
			}
			
			
		}

My question still stands however, how would one normally access a value from one class to another without the world class being one of those two classes? It is this fundamental issue that has been limiting my development (well mainly) problems for a few days now. It seems like as soon as I want to access another classes variables the only way I can fully do it is from the world class… maybe that is the only class that is able to access values? Or most likely not and I am a noob. But what do you guys think?

Thanks! :blush:


(Alex Larioza) #13

I feel that you may be misunderstanding a concept from object oriented programming, here’s a small crash course:

Object instances and classes are two different things.

Classes are basically a blue print which are used to create instances. There will only ever be one class, but there can be many instances of that class.

New instances of a class are created when you call the “new” operator, for example:

new Enemy() // a new instances of the class Enemy is returned

In order to access a public variable from instance of an object, you need to have the reference of the instance stored in a variable. For example:

var enemy1:Enemy = new Enemy()
enemy1.health = 100 // change the health variable of enemy instance 1

var enemy2:Enemy = new Enemy()
enemy2.health = 10 // change the health variable of enemy instance 2

In your case, since you only want to check an enemy’s variable when it collides when the player, you get the reference to the instance from the collide function. The collide function loops through all the instances in your game of the specified type, checking to see if two masks intersect. If they do, the first colliding instance is returned.


How to access functions of a world from an entity?
[SOLVED] Interesting Problem
[SOLVED] getInstance(String) question
(Nate ) #14

Oh this makes much more sense! Thank you SHiLLy! :dancer:

But my question still is, for example, I have two classes… One class contains a public variable called, test it is of type integer and holds a 0. In the class containing test, within its update method I say, test++, which increments it by one every tick.

I have another class that I would like to simply trace the value of test from theTest class.

I do the following:

		var otherClass:theTest = new theTest()
	
	trace("otherClass.test: " + otherClass.test);

When I trace the value of test from the update function within theOther class, it only gives me 0. When I trace it from the test variable within the update function from theTest class it increments.

What am I missing for accessing the current value of a variable from another class?


(Alex Larioza) #15
var otherClass:theTest = new theTest()
trace("otherClass.test: " + otherClass.test);

Are you executing this code every frame? If so, its always going to return the default value (which is zero in your case) because you’re creating a new instance of theTest each frame.

Instead you need to store the reference to the instance in a member variable:

public var otherClass:Test
...
override public function added():void 
{
    // code is only executed when the entity is added to the world
    otherClass = new theTest()
    world.add(otherClass) // add the other class to the world
}
...
override public function update():void 
{
    trace(otherClass.test) // prints the incremented value each frame
}

(Nate ) #16

Okay thank you so much SHiLLy! That was exactly what I was trying to figure out! That damn evasive added function and adding my reference to the world is what I was missing, which now explains everything to me! lol I now know the meaning of life! Not literally but you get my point!

Thank you again SHiLLy!!! :smiley: :sunny: :smile: