Reference:FIFE:Minimal:Loading a map and scrolling it around

From Post-Apocalyptic RPG wiki

Jump to: navigation, search

Code reference.png This article covers outdated code reference information!

Code reference articles are stored at the wiki for legacy reasons. They are often outdated and duplicate Epydoc code documentation and department-specific tutorials. Code reference articles need to be reviewed by the programming department to see if they provide any useful information that is not available elsewhere at the wiki. After they have been reviewed and their unique information has been moved to more appropriate articles, the code reference articles should be deleted.


(Note: this article follows on from Minimal Fife engine: An introduction, and is highly recommended that you read that article first)

Now we need to add a map. There are two extra resources we need here, a map file and some graphic images. To keep things as simple as possible, my map uses only one ground texture, but we'll need to create some directory structure. Use whatever tool you want to create a directory structure like this:

fife/clients/pdemo/objects/ground/sands/01/

Thats a zero, not an O in the last name. Also, remember that pdemo was the name of the folder that we created in the previous article. Now copy all the two files in

fife/clients/rio_de_hola/objects/ground/sands/01/

to our folder (an object.xml file and a png containing the actual image). That handles all the graphics we need for this part. Next we need a map file. I created one using the map editor, or you can just use Media:map.tar (you'll obviously have to uncompress to the original XML as this wiki does not allow me to upload the original).

This map file looks as follow, first the map is defined, next the sand floor-tile is imported. Next the floor layer is defined which consists out of these sand tiles (each tile should have an instance, for each coordinate) and finally a camera is added. Note that the path to the sand tile needs to match the one on the file system.

<?xml version="1.0" encoding="ascii"?>
<map id="test-map" format="1.0">
	<import file="/objects/ground/sands/01/object.xml"></import>
	<layer grid_type="square" id="ground" x_scale="1.0" pathing="cell_edges_only" y_scale="1.0" rotation="0.0" x_offset="0.0" y_offset="0.0">
		<instances>
			<i r="0" z="0.0" x="2.0" o="sands:01" y="-2.0" ns="http://www.fifengine.de/xml/rio_de_hola"></i>
			<i x="1.0" o="sands:01" z="0.0" y="-1.0" r="0"></i>
			<i x="0.0" o="sands:01" z="0.0" y="0.0" r="0"></i>
                        <!-- several instances omitted -->
			<i x="3.0" o="sands:01" z="0.0" y="-1.0" r="0"></i>
			<i x="3.0" o="sands:01" z="0.0" y="0.0" r="0"></i>
			<i x="3.0" o="sands:01" z="0.0" y="1.0" r="0"></i>
			<i x="3.0" o="sands:01" z="0.0" y="2.0" r="0"></i>
		</instances>
	</layer>
	<camera tilt="-42.0" id="camera" ref_layer_id="ground" ref_cell_height="96" rotation="45.0" ref_cell_width="128" zoom="1.0">
	</camera>
</map>

Be aware that if you create your own, you check the resulting XML file to check all of the paths are correct and any extra files you may have used are in the pdemo folder. However you do it, put the map.xml file in the pdemo folder. Now we can turn to editing the code in run.py. Firstly, under line 15 - from basicapplication import ApplicationBase - add this code

from loaders import loadMapFile


The next piece of code we need to change is in the PDemo class, to load the map and make it viewable. Make the __init__() look like this:

	def __init__(self):
		super(PDemo,self).__init__()
		# load our map please
		self.map=loadMapFile("map.xml",self.engine)
		# and make sure we can see it
		self.view = self.engine.getView()
		self.view.resetRenderers()		
		self.listener=ApplicationListener(self.engine)


Save, and again execute run.py. You should see our map on the screen.

Now we would like to be able to move this map! Firstly though, a quick look at how fife views the co-ordinate system is in order, so we can understand a little easier what we need to do. The x and y co-ords in fife are like this:

Map grid.jpg

So when we scroll in the up/down, left/right directions we will need to adjust the values of both the x and the y co-ords. I hope that makes some sense. First we have to add a camera to our current level, so in the __init__ function of the PDemo class, add the following line:

self.camera_main = self.view.getCamera("camera")


The text "camera" refers to the name given in the XML file, so if you created your own map file you may need to change this. Next we need to add the keys we use to the EventManager. In the __init__() function for the ApplicationListener class change the NonConsumableKeys line so it now reads like this:

engine.getEventManager().setNonConsumableKeys(
    [fife.Key.ESCAPE,fife.Key.LEFT, fife.Key.RIGHT, fife.Key.UP, fife.Key.DOWN])


We need some extra variables to be stored in the same function:

		self.camera_x_velocity = 0
		self.camera_y_velocity = 0
		self.camera_speed = 0.01


Now we add some detail to the keyPressed() routine to check for the new keys (here you can that we have to change both the x and the y values). The whole thing now looks like:

	def keyPressed(self, evt):
		keyval = evt.getKey().getValue()
		if keyval == fife.Key.ESCAPE:
			self.quit = True
		elif keyval == fife.Key.UP:
			self.camera_y_velocity = -self.camera_speed
			self.camera_x_velocity = self.camera_speed
		elif keyval == fife.Key.DOWN:
			self.camera_y_velocity = self.camera_speed
			self.camera_x_velocity = -self.camera_speed
		elif keyval == fife.Key.LEFT:
			self.camera_x_velocity = -self.camera_speed
			self.camera_y_velocity = -self.camera_speed
		elif keyval == fife.Key.RIGHT:
			self.camera_x_velocity = self.camera_speed
			self.camera_y_velocity = self.camera_speed
		evt.consume()


We also need to reset the speed when the key is released, so add a whole new function:

	def keyReleased(self, evt):
		keyval = evt.getKey().getValue() 
		if((keyval == fife.Key.UP) or (keyval == fife.Key.DOWN) or
		   (keyval == fife.Key.LEFT) or (keyval == fife.Key.RIGHT)):
			self.camera_y_velocity = 0
			self.camera_x_velocity = 0
		evt.consume()


We are almost done! We need a function in the PDemo class to actually update the camera:

	def _moveMainCamera(self):
		coords = self.camera_main.getLocationRef().getMapCoordinates()
		delta_time = self.engine.getTimeManager().getTimeDelta()
		coords.x += self.listener.camera_x_velocity * delta_time
		coords.y += self.listener.camera_y_velocity * delta_time
		self.camera_main.getLocationRef().setMapCoordinates(coords)
		self.camera_main.refresh()


Notice the code about getTimeDelta() - this is to keep the speed consistent across different machines. Also worth noting is that the camera is set relative to the map co-ordinates. The very last thing to do is make sure this new routine is called, so at the end of the _pump() routine add the following line:

<souce lang="python"> self._moveMainCamera() </source>


So that we update the camera every time around the main loop. And that's it! Run the new program and we should be able to scroll around the map with the cursor keys.

Next: Adding a Character to the Map

Personal tools