Problem with Iterating on Different Platforms

I’m working on a text game project, but I’m stuck. I’ve got two big problems going on. One can wait, I need to test if it’s actually not working or if it just looks like it’s not working. The other has got me totally stumped.

Basically I’ve got this code:

                    // List the contents of the room, if any
		playerView += "<b>Contents:</b>\n\n";
		if (cast(playerFocus, GameRoom).getContents().length > 0) {
			for (i in cast(playerFocus, GameRoom).getContents()) {
				playerView += "<a href=\"event:" + i.getName + "\">" + i.getName + "</a>  ";
			}
		}
		playerView += "\n\n";

And it’s not working. It’s not throwing an error but the code that comes after it, starting with the last line of what I copied, doesn’t get processed in Flash. It sort of works on Windows and HTML5 but it’s wrong in different ways on those.

Basically what I’m trying to do is display the contents (mobs) in a room. The room I’m looking at doesn’t have any, so the length of the list I get from cast(playerFocus, GameRoom).getContents().length should be zero, skipping over that whole code block. But instead the program breaks down there in three different ways on three different targets. For Flash it just stops processing and nothing gets printed after the if statement. For Windows/C++ it gives me the output “#function0” where the list of contents should go, then continues and does the list of exits (A very similar code block) properly, giving the exit “East”.

In the HTML5 target, I get "> instead of the function. Apparently a concatenation issue.

So I’ve got this one code block failing three different ways and none of them make sense to me. :confused:

Anyone out there have a clue?

first: is it casting unavoidable?
second: it is quite hard to get a problem without knowing all the code.
third: that use of “i” is quite ugly. “i” is an index, there you have an element. please call it object, or element, or whatever else. it seems not important to follow good programming rules but in fact it really matters.

so: set up a very simple project with inside just a textField and one array like the “Contents” one.
after try to set up the variables as they should be.
in the end execute the loop.
you will se if the problem is in the loop.

anyway I was thinking, if, and only if, the playerView is a textField, shouldn’t you set the “htmlText” property?

PS: if you have a flash debugger (open the swf with just the flash player and compile with lime test flash -debug should be enough) use it, sometimes error on flash are hard to see and don’t appear on compile time.

PPS: before trying to make it work on EVERY target, focus on making it work on one, the rest will come easier.

Yeah I don’t see any way to do what I’m doing without casting. It recieves a GameObject but it has to determine which subclass of GameObject it is so that it can use the right functions, GameRoom or GameMob or GameScene, so that it knows how to handle them.

There’s a lot of code to link it all… I tried to keep the most essential

I can change the name of i if you think it’s that bad. I was taught to use i, j, etc as iterators back in school. I suppose this isn’t the iterator though… I’ll change it.

I do have a flash debugger, but it isn’t picking up any bugs. It’s really irritating, because it’s clear that procesing stops at this point, but it doesn’t say anything is wrong.

I’m also not really trying to make it work on every target, I just compiled it to the other targets to see if it would give me any insight into why my code wasn’t working.

Thanks for your help. I’ll try your suggestion of making a small project just to test this.

let me know how it is going.


I think anyway that instead of casting you could use an interface.

interface GameObject {
public function getContents():Array;
public function get_name():String;
//…
}

and implements on every “GameObject” you have
and then instead of casting use it as playerFocus value


otherwise you can extend all the “GameObject” classes from a REAL GameObject class, so they will share the basic function (that you need gamewise) and you can declare playerFocus as a GameObject

It turned out I needed brackets on i.getName, because it was a function and I was referencing the function rather than calling it with i.getName()

The GameObject class I use has only a few properties and functions that are similar amongst my three subclasses. I suppose I could cram everything in there and only use it if it’s the appropriate time, and get rid of the casting, but now that I’ve got the brackets in there the casting works fine. Would you just say it’s bad programming? None of the schools I went to taught good programming, it’s really something you’re expected to learn in the workplace.

If you structure your code right, you should be able to use the same methods for every object. In your first post, you were making a string that describes the contents of the room. But you were doing this from somewhere outside GameRoom.hx.

A better way would be to make a toString() function on the GameObject class, and have every subclass override it.

In GameObject.hx:

public function toString():String {
    return getName();
}

In GameRoom.hx:

public override function toString():String {
    var string:String = "<b>Contents</b>\n\n";
    
    //No need for an "if" statement here. If getContents()
    //is empty, the for loop will do nothing.
    for(item in getContents()) {
        string += "<a href=\"event:" + item.toString() + "\">" + item.toString() + "</a> ";
    }
    
    string += "\n\n";
    return string;
}

Now you can call playerView += playerFocus.toString() without casting anything.


Another example: if you want to respond to a mouse click, don’t have the event listener do this:

if(Std.is(playerFocus, GameRoom)) {
    //Handle it one way.
} else if(Std.is(playerFocus, GameSprite)) {
    //Handle it a different way.
} else if(Std.is(playerFocus, SomethingElse)) {
    //Handle it a third way.
} else {
    //Don't do anything.
}

Instead, define an onClick() function, and have your MouseEvent.CLICK listener call that.

If playerFocus is currently a GameRoom, then GameRoom's version of the function will be called, and that function can respond accordingly. If playerFocus is a different subclass, than that other class will get to handle it.

As long as you leave GameObject's copy of the function blank, it will default to doing nothing.

1 Like