How to do this properly? (physics and encapsulation etc) - Tiles from XML


(John Andersson) #1

Hi. I have a gameworld class, and this is the code:

package { import net.flashpunk.Entity; import net.flashpunk.; import net.flashpunk.graphics.; import net.flashpunk.masks.; import net.flashpunk.utils.;

public class GameWorld extends World 
{
	
	protected var hero:Hero;
	protected var map:Entity;
	protected var background:Backdrop;
	
	protected var _mapGrid:Grid;
	protected var _mapImage:Image;
	protected var _didLose:Boolean;
	protected var _mapData:Class;
	
	public function GameWorld(mapData:Class = null) 
	{
		super();
		
		//Save our data
		_mapData = mapData;
		
		//Set initial conditions
		_didLose = false;
		
		if (mapData != null)
		{
			//Load the provided map file
			loadMap(_mapData);
		}
		else
		{
			//Create a debug map
			_mapGrid = new Grid(1920, 1080, 120, 120, 0, 0);
			_mapGrid.usePositions = true;
			_mapGrid.setRect(0, 0, 1920, 1080, true),
			_mapGrid.setRect(120, 120, 1900, 1070, false);
			hero = new Hero(5, 5);
		}
		
		//Create an image based on the map's data and scale it accordingly			
		_mapImage = new Image(_mapGrid.data),
		_mapImage.scale = 120;
		
		//Create a map entity to render and check collisions with
		map = new Entity(0, 0, _mapImage, _mapGrid);
	}	
	
	/* Called when World is switched and set to the currently active world */
	override public function begin():void
	{
		super.begin();
		
		//Add the game entities to GameWorld
		add(hero);
		
		//No need to reference these entities again
		add(map);
	}
	
	override public function update():void
	{
		super.update();
		
		if (_didLose)
		{
			//The player hast lost
			
				/* Add something here, like a game over text screen */
			
			//When space is pressed, create a new GameWorld with the current map
			if (Input.pressed(Key.SPACE))
			{
				FP.world = new GameWorld(_mapData);
			}
		}
		else
		{
			//The player has not lost.... yet >:)
			
			/* //Update the camera and screen to match the player
			camera.x = hero.x - FP.screen.width * 0.5;
			camera.y = hero.y - FP.screen.height * 0.5;
			//Check the keyboard for updates and pass them to the player
			handleInput(); */
			
			//If the player collides with the map, trace
			if (map.collideWith(hero, 0, 0))
			{
				trace("Hit");
				hero.isOnGround();
			}
			if (!map.collideWith(hero, 0, 0))
			{
				hero.isNotOnGround();
			}
		}
	}
	
	/*
	
	protected function handleInput():void
	{
		//Check left and right input and save the sum to n, so both left and right simultaneously will equal no movement
		
		var n:int = 0;
		
		if (Input.pressed(Key.LEFT)) n--;
		if (Input.pressed(Key.RIGHT)) n++;
		
		//Based on n, determine if the player should spin
		if ( n != 0)
		{
			if (n < 0) player.goLeft();
			else player.goRight();
		}
	} */
	
	
	protected function loadMap(mapData:Class):void
	{
		var mapXML:XML = FP.getXML(mapData);
		
		//Create the map grid
		_mapGrid = new Grid(uint(mapXML.@width), uint(mapXML.@height), 120, 120, 0, 0)
		_mapGrid.loadFromString(String(mapXML.Grid), "", "\n");
		
		//Spawn hero
		hero = new Hero(int(mapXML.Entities.Spawn.@x), int(mapXML.Entities.Spawn.@y));
	}
	
	
	//End
}

}

As you can see, when the player touches the map, it runs a function from the hero class, which looks like this:

	public function isOnGround():void
	{
		onTheGround = true;
	}

And in the hero class, the update function checks if the hero is on the ground like so:

if (onTheGround) { ySpeed = 0;

			if (Input.check(Key.UP))
			{
				ySpeed -= jumpPower;
			}

		} else {
			
			ySpeed = gravity;
		}

Now, this is very unconvenient. How do I make it so that the hero class itself can detect if it collides with the map? And more importantly, how to make it so that the hero collisions with ONLY A SPECIFIC TYPE OF TILE triggers the physics handling? So it doesn’t happen if the hero touches ANYTHING.

Here is my level file

< level width=“1920” height=“1080”> < Grid exportMode=“Bitstring”>0000000000000000 1000000000000000 1001111000000000 1100110000000000 1110000000000000 0000000000010000 0000000000110000 0000000001110000 1111111111110011< /Grid> < Entities> < Spawn id=“0” x=“120” y=“720” /> < /Entities> < /level>

The number 1 = the ground tiles, which I only want to trigger the physics handling on the hero.

Thanks


(Jacob Albano) #2

You probably want to take a look at the Grid class, and its loadFromString() method.