Simply put, I have two classes that do all the work in my game that inherit the Flixel Sprite class, as well as the Flixel state class. Their respective names are GameObject and GameRoom. I have a child of GameRoom: PlayState, and it has two variables that GameRoom doesn't; those being oPlayer and oWalls. oWalls is the problem at hand. It's a Flixel group. What I'm trying to do is from oPlayer, use oWalls in FlxG.collide, but the compiler says it's not a variable of GameRoom. Here is the code:
This is the player's frame event/update code, inherited from the GameObject class.
override public function frameEvent(backEnd:GameRoom)
{
// Set the velocity -- not the coordinates. We do that at the end.
hsp = (-boolToInt(FlxG.keys.pressed.LEFT) + boolToInt(FlxG.keys.pressed.RIGHT)) * moveSpeed;
vsp = (-boolToInt(FlxG.keys.pressed.UP) + boolToInt(FlxG.keys.pressed.DOWN)) * moveSpeed;
x += hsp;
y += vsp;
FlxG.collide(this, backEnd.oWalls);
}
The base class's function doesn't have any code, it's all done by the child.
This is where the GameRoom class loops through all game objects to do their frame event.
override public function update():Void
{
// Do all the frame events in the game objects
for (i in gameObjects)
{
i.frameEvent(this);
}
super.update();
}
The actual PlayState doesn't override it, because it doesn't need to. The whole reason for this is that it's portable across all levels, so no matter the state/level, as long as the room inherits GameRoom, it will have the same structure.
So I get this error
source/ObjPlayer.hx:36: characters 21-35 : GameRoom has no field oWalls
I know it's because I use backEnd:GameRoom as a parameter, so it will only consult GameRoom, but it is being passed the child object, not GameRoom. Even when I put the for loop
inside PlayState, guaranteeing that it is being passed the child, PlayState, and not GameRoom, I got the same error. So then, the question is how do I pass the child object to it instead of the base class?
Any help is greatly appreciated.
--This is the end of the post, but if you need all the code for everything, here it is. I know it's unformatted, I don't know what happened--
PlayState.hx
import flixel.group.FlxGroup;
class PlayState extends GameRoom
{
// Game objects
public var oPlayer:ObjPlayer;
// The walls in the room
public var oWalls:FlxGroup;
//Function that is called up when to state is created to set it up.
override public function create():Void
{
super.create();
// Populate the load map
addLoadClass("#", ObjWall, oWalls);
oPlayer = new ObjPlayer(32, 32, this);
// Load the game room
loadFile(16, 16, "assets\\Level.txt", 0, 0);
}
}
ObjPlayer.hx
import flixel.FlxG;
class ObjPlayer extends GameObject
{
// The player's movement speed in pixels
var moveSpeed:Float;
// The velocity in pixels for collision checking
var hsp:Float;
var vsp:Float;
override public function create(newX:Int, newY:Int, backEnd:GameRoom)
{
// Just load the player's graphic
loadGraphic(AssetPaths.player__png);
moveSpeed = 3;
}
override public function frameEvent(backEnd:GameRoom)
{
// Set the velocity -- not the coordinates. We do that at the end.
hsp = (-boolToInt(FlxG.keys.pressed.LEFT) + boolToInt(FlxG.keys.pressed.RIGHT)) * moveSpeed;
vsp = (-boolToInt(FlxG.keys.pressed.UP) + boolToInt(FlxG.keys.pressed.DOWN)) * moveSpeed;
x += hsp;
y += vsp;
FlxG.collide(this, backEnd.oWalls);
}
// Convert a boolean value to an int (1 or 0)
private function boolToInt(bool:Bool)
{
if (bool) return 1; else return 0;
}
}
GameRoom.hx
import flixel.FlxState;
import flixel.group.FlxGroup;
import sys.io.File;
class GameRoom extends FlxState
{
// The list of all the events to do
public var gameObjects:Array<GameObject>;
// The child class must fill this map to use the room loader
var loadMap:Map<String, Class<GameObject>>;
var loadMapGroup:Map<String, FlxGroup>;
override public function create():Void
{
super.create();
// Create the empty array for game objects
gameObjects = [];
// Create an empty map for loadMap
loadMap = new Map<String, Class<GameObject>>();
loadMapGroup = new Map<String, FlxGroup>();
}
// Function that is called when the game is over
override public function destroy():Void
{
// Do all the destroy events in the game objects
for (i in gameObjects)
{
i.destroyEvent(this);
}
super.destroy();
}
// Really obvious frame events
override public function update():Void
{
// Do all the frame events in the game objects
for (i in gameObjects)
{
i.frameEvent(this);
}
super.update();
}
// Add a class to the load map
function addLoadClass(char:String, loadClass:Class<GameObject>, useGroup:FlxGroup):Void
{
loadMap[char] = loadClass;
loadMapGroup[char] = useGroup;
}
// Loads a file into a room
function loadFile(tileWidth:Float, tileHeight:Float, fname:String, xOffset:Int, yOffset:Int):Void
{
// First we load the file into a string
var workingFile:String = File.getContent(fname);
// These are the x/y inside the loop
var workingX:Int = 0;
var workingY:Int = 0;
// Now we loop through each character
for (i in 0...workingFile.length)
{
// Put an object here is it wasn't a space
if (workingFile.charAt(i) != " " && loadMap.exists(workingFile.charAt(i)))
{
var tempClass = Type.createInstance(loadMap[workingFile.charAt(i)], [xOffset + workingX * tileWidth, yOffset + workingY * tileHeight, this]);
// Add the object to a group if applicable
if (loadMapGroup[workingFile.charAt(i)] != null)
{
loadMapGroup[workingFile.charAt(i)].add(tempClass);
}
}
// Check if we are at the end of a line
workingX++;
if (workingFile.charAt(i) == "\n")
{
workingX = 0;
workingY++;
}
}
}
}
And last, GameObject.hx
import flixel.FlxSprite;
class GameObject extends FlxSprite
{
// This class basically just has stubs for a frame, and create
public function new(newX:Int, newY:Int, backEnd:GameRoom)
{
super(newX, newY);
create(newX, newY, backEnd);
// Add this object to the backEnd
backEnd.gameObjects.insert(backEnd.gameObjects.length, this);
backEnd.add(this);
}
// This is for the child class
public function create(newX:Int, newY:Int, backEnd:GameRoom)
{
// All for the child class...
}
public function frameEvent(backEnd:GameRoom)
{
// Nothing...
}
public function destroyEvent(backEnd:GameRoom)
{
// Nothing...
}
}
Sorry about the code dump, but I know on Stack Overflow, people go nuts if you don't post all the code.