FIFE forums

General Category => Game creators corner => Topic started by: Kresp on December 10, 2012, 07:27:04 am

Title: Basics of instance and object manipulation
Post by: Kresp on December 10, 2012, 07:27:04 am
Hi.
I've just recently started to use FIFE and, to familiarize myself with it, i'm writing a simple app for solving sudoku puzzles.
What i can not figure out myself is the best way to transform values inside cells.
I've decided not to use runtime text output, but to create an atlas of 10 squares, with numbers alredy drawn on them (from 1 to 9 and and empty one). So the tileset has 10 objects with ids from 'tile:1' to 'tile:9', and 'tile:0' for the empty square.
My first intention was to use Object.setId method to transform a tile, but it does not seem to make any visible alterations. The id gets changed(getId() now returns different value for this object), but engine renders same image on top of the object.
So now i'm trying to delete current object, and create a new one in old one's place. I use Layer.deleteInstance method, and it works fine. But when i try to create a new one, the app breaks somewhere inside engine's pump() method, and my Python debugger doesn't catch any exceptions to trace.
That's how i try to create a new object and add it to current layer:
Code: [Select]
object = instance.getObject()
coordinates = instance.getLocation().getMapCoordinates()
self._scene.kill_object(instance)
new_object = Object('tile:0', 'http://192.168.1.1')
self._cell_layer.createInstance(new_object, coordinates)
Can you give me a hint to what i'm doing wrong? Sorry for my english grammar, it's probably horrible.
Title: Re: Basics of instance and object manipulation
Post by: helios on December 10, 2012, 07:36:52 pm
Hey Kresp,
You have different options. If you have already 10 objects and each holds one static image then you have to code something like this:

Code: [Select]
def changeTile(instance, id="tile:1")
    # save old location
    layer = instance.getLocation().getLayer()
    emc = instance.getLocation().getExactLayerCoordinates()
    # delete old instance
    layer.deleteInstance(instance)
    # get object
    object = self.model.getObject(id, "yourNamespace")
    # create new instance
    newInstance = layer.createInstance(object, emc)
    fife.InstanceVisual.create(newInstance)


The other option is that you create only one object which holds all the images but use different directions. Lets say tile0 have direction 0, tile1 a direction of 10, tile2 of 20 and so on.
Then you can call instance.setRotation(0) to get the empty square displayed or setRotation(10) to get the square with 1. It's a bit hacky but so you have not to delete and create new instances on the fly.
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 10, 2012, 10:00:52 pm
Thanks, the first option works perfectly.
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 14, 2012, 09:03:33 am
I need to draw borders around some sides of some objects, with different width and different colors. What's a cleanest way to do it?
http://www.fifengine.net/doxygen/class_f_i_f_e_1_1_render_backend.html#a854a5f3811269b680c59b90d97bc5343 (http://www.fifengine.net/doxygen/class_f_i_f_e_1_1_render_backend.html#a854a5f3811269b680c59b90d97bc5343)
I can't locate drawLine method inside python documentation.
Title: Re: Basics of instance and object manipulation
Post by: ChrisOelmueller on December 14, 2012, 01:42:33 pm
Heya,

you might be interested in the GenericRenderer: http://www.fifengine.net/epydoc/fife.fife.GenericRenderer-class.html#addLine
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 14, 2012, 09:53:55 pm
Thanks, Chris.
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 16, 2012, 01:41:32 am
How can i make precise outline?
If i fit coordinates for the lines so there is no gaps between them, it all breaks when i change zoom.
Attached picture - zoom 0.6 instead of 1.0. White is outline color, all different colored pixels are part of tile sprite.

And is there a way to may thick lines except to draw a few lines close to each other?
Title: Re: Basics of instance and object manipulation
Post by: flutschfinger on December 16, 2012, 05:20:34 am
Maybe your are looking for the Instance renderer, there you can add a outline http://wiki.fifengine.net/Instance_Renderer
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 16, 2012, 05:51:48 am
Maybe your are looking for the Instance renderer, there you can add a outline http://wiki.fifengine.net/Instance_Renderer
I'm unsure about how it works. Left and right sides remains untouched for any Threshold values i've tried.
And anyway it can't outline only one particular side.
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 16, 2012, 11:49:17 am
Code: [Select]
clickpoint = fife.ScreenPoint(event.getX(), event.getY())
if event.getButton() == fife.MouseEvent.LEFT:
instances = self.get_instances_at(clickpoint, self._layers['ground_layer'])
instance = instances[0]
points_A = []
points_B = []
def add_point(points, x, y):
zoom = self._cameras['main'].getZoom()
points.append(fife.Point(int(round(x * zoom)), int(round(y * zoom))))
add_point(points_A, 0, -70)
add_point(points_A, 0, -69)
add_point(points_A, -1, -69)
add_point(points_B, 60, -34)
add_point(points_B, 59, -34)
add_point(points_B, 60, -33)
for point_A in points_A:
for point_B in points_B:
i1 = fife.RendererNode(instance, point_A)
i2 = fife.RendererNode(instance, point_B)
self._generic_renderer.addLine('123', i1, i2, 255, 255, 255)
Something like this works as intended, but only for 1.0 zoom (attached picture zoom 0.5). Code looks bad, but i can not figure out a better way to do the same thing. Will have to "whitelist" available zoom values and calibrate each of them manually later on.

And one more thing. ref_cell_height in map file is ignored if ref_cell_width was set before. Hard to make hexagonal tiles to be placed tight, when each tile must lay inside a box with 1:2*3^-0.5 ratio sides. Thinking about using square hexagons Imperialism-style.
Title: Re: Basics of instance and object manipulation
Post by: helios on December 16, 2012, 01:06:23 pm
I'm not sure what is your goal but if you want to outline the cells on the grid then you can try something like this. It should work as long as your tile size match the cell grid size.

Code: [Select]
clickpoint = fife.ScreenPoint(event.getX(), event.getY())
if event.getButton() == fife.MouseEvent.LEFT:
instances = self.get_instances_at(clickpoint, self._layers['ground_layer'])
instance = instances[0]
loc = instance.getLocationRef()
grid = loc.getLayer().getCellGrid()

vertices = grid.getVertices(loc.getLayerCoordinates())
for i in vertices:
firstpt = self._cameras['main'].toScreenCoordinates(grid.toMapCoordinates(i))
...

But zooming is always a problem because in some situations the pixel position can not be determined clearly. thanks for the pointer to ref_cell_height, I'll take a look at it.
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 16, 2012, 09:56:23 pm
I'm not sure what is your goal
Basically i want to draw borders, while border color should indicate which player owns the outlined tiles.
Attached - screenshot from civ5.
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 17, 2012, 12:04:23 am
Code: [Select]
vertices = grid.getVertices(loc.getLayerCoordinates())
Code: [Select]
TypeError: CellGrid_getVertices() takes exactly 3 arguments (2 given)
http://www.fifengine.net/epydoc/fife.fife.CellGrid-class.html#getVertices (http://www.fifengine.net/epydoc/fife.fife.CellGrid-class.html#getVertices)
What exactly this method should receive?
Title: Re: Basics of instance and object manipulation
Post by: helios on December 17, 2012, 06:38:15 am
Sorry seems that there was a bug  :-\
The output parameter was missing, is now fixed in trunk.
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 17, 2012, 08:09:29 am
Code: [Select]
C:\Program Files\SlikSvn\bin>svn.exe co http://fife.svn.cvsdude.com/engine/trunk
...
Checked out revision 4075.
Code: [Select]
C:\Program Files\SlikSvn\bin\trunk>c:\Python27\python.exe setup.py install
running install
running build
running build_py
running install_lib
running install_data
running install_egg_info
Removing c:\Python27\Lib\site-packages\fife-0.3.3r3-py2.7.egg-info
Writing c:\Python27\Lib\site-packages\fife-0.3.3r3-py2.7.egg-info
Still get the same error.
Have i used wrong repository?
Title: Re: Basics of instance and object manipulation
Post by: helios on December 17, 2012, 09:41:00 am
The repository is right. But seems you mixed the last official release (0.3.3r3) and trunk.
Here is the win compile guide: http://wiki.fifengine.net/Building:Win32:SCons (http://wiki.fifengine.net/Building:Win32:SCons)
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 17, 2012, 10:44:18 am
Tried fresh install, same error.
engine_build_log.txt: http://pastebin.com/Y05au54E (http://pastebin.com/Y05au54E)
engine_install_log.txt: http://pastebin.com/abuwgvUt (http://pastebin.com/abuwgvUt)
_fife.pyd hashes:
Code: [Select]
CRC-32: ae340d34
   MD4: 74b7a7b51e7a59f37f9f827a396c0bbd
   MD5: f754d26e48c1745400a855fe854be46f
 SHA-1: 65ee7551dbe06a688a1a85a7c1afd828ffae3cac
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 17, 2012, 11:04:08 am
Oh, sorry, my mistake.
Error is different this time:
Code: [Select]
TypeError: in method 'CellGrid_getVertices', argument 3 of type 'FIFE::ModelCoordinate const &'
Title: Re: Basics of instance and object manipulation
Post by: helios on December 17, 2012, 11:41:26 am
Sorry no idea. Here it works, I tested it with rio and here is my code snippet:
Code: [Select]
loc = self.hero.agent.getLocationRef()
grid = loc.getLayer().getCellGrid()
vertices = grid.getVertices(loc.getLayerCoordinates())
for i in vertices:
print i
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 17, 2012, 11:46:14 am
Changed getExactLayerCoordinates to
Code: [Select]
getLayerCoordinates()
Doesn't break anymore.
Will try and see if it does what i want.
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 17, 2012, 12:08:55 pm
getVertices returns absolute coordinates (like 1036:441), and if i want to attach lines/points/whatever to a tile, not to a camera, i need them to be relative to instance's center. How can i get an instance's coordinates relative to camera's coordinate system?
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 17, 2012, 05:41:04 pm
Code: [Select]
        clickpoint = fife.ScreenPoint(event.getX(), event.getY())
        if event.getButton() == fife.MouseEvent.LEFT:
            instances = self.get_instances_at(clickpoint, self._layers['ground_layer'])
            instance = instances[0]
            loc = instance.getLocationRef()
            grid = loc.getLayer().getCellGrid()

            vertices = grid.getVertices(loc.getLayerCoordinates())
            anchor = self._cameras['main'].toScreenCoordinates(grid.toMapCoordinates(instance.getLocation().getLayerCoordinates()))
            points = []
            for i in vertices:
                firstpt = self._cameras['main'].toScreenCoordinates(grid.toMapCoordinates(i))
                p = fife.Point(firstpt.x - anchor.x, firstpt.y - anchor.y)
                points.append(p)
            for i in range(0, 6):
                i1 = fife.RendererNode(instance, points[i])
                i2 = fife.RendererNode(instance, points[i - 1])
                self._generic_renderer.addLine('123', i1, i2, 0, 0, 0)
This works. Not perfect, though. And will have to finetune manually anyway.
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 18, 2012, 12:17:48 am
I have an idea how to make perfect borders. I just have to create 2^6 sprites with borders prerendered on them with a single color. And when a map is loading, app will generate sprites with whatever colors i may need from the original ones. May take a while to process 64*[number of players] images though, but it don't have to redraw everything every time a new game is started. Just once a new color is involved and then store them for later usage.
Pluses: if border tiles and ground tiles are of the same size, zoom should work like a clock; probably a bit better performance, as engine won't have to make all this coordinates calculations.
Minus: speed hit when sprites are drawn for the first time.
Title: Re: Basics of instance and object manipulation
Post by: Niektory on December 18, 2012, 03:36:30 am
I don't think you'd need to generate separate sprites for different colors, the renderer can color them for you (InstanceRenderer::addColored()).
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 20, 2012, 04:14:04 am
InstanceRenderer::addColored()
Thanks, i'll look into it.

Can i get a full list of available pychan styling attributes somewhere?
Also, is it possible to change SDL_app caption of the main application window and relocate it, before it has been properly initialized and loaded?
Title: Re: Basics of instance and object manipulation
Post by: helios on December 21, 2012, 08:18:32 am
We have settings to set the window title and icon. Rio de hola stores it in the settings.xml file.
Code: [Select]
    <Setting name="WindowTitle" type="str"> FIFE - Rio de hola </Setting>
    <Setting name="WindowIcon" type="str"> gui/icons/boy.png </Setting>
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 21, 2012, 09:31:57 pm
Code: [Select]
<Setting name="WindowTitle" type="str"> FIFE - Rio de hola </Setting>
"SDL_app" title is visible for a second or two, then changes according to the setting.
Title: Re: Basics of instance and object manipulation
Post by: helios on December 22, 2012, 09:25:52 am
I had not realized but it's fixed now.
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 23, 2012, 09:31:01 am
Pychan buttons keep focus after being clicked, and thus stop fife.IKeyListener from intercepting keystrokes. Is it possible to make a button unfocusable, to unfocus a button programmatically or to make FIFE use global keyboard hooks?
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 23, 2012, 08:34:18 pm
When i use addColored method, resulting objects are either too dark, or too bright (depenging on what base color was used for template image). How do i instruct engine not to recolour existing colour, but replace it, saving only alpha-channel from original pixels?
Title: Re: Basics of instance and object manipulation
Post by: Niektory on December 24, 2012, 01:18:45 am
The last argument determines how much of the original color remains. It's in the 0~255 range, use 0 to replace the original color completely:
Code: [Select]
addColored(instance, 255, 210, 0, 0)
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 24, 2012, 02:00:32 am
Thanks.
Title: Re: Basics of instance and object manipulation
Post by: Kresp on December 26, 2012, 01:37:01 am
Code: [Select]
cellgrid = self._model.getCellGrid('hexagonal')
cellgrid.thisown = 0
cellgrid.setRotation(0)
cellgrid.setXScale(1)
cellgrid.setYScale(1)
cellgrid.setXShift(0)
cellgrid.setYShift(0)
layer = self._map.createLayer('ground_layer', cellgrid)
layer.setPathingStrategy(fife.CELL_EDGES_AND_DIAGONALS)
layer.setLayerTransparency(1)
Resulting layer doesn't render any objects than i add later. What do i miss?

UPD: figured out. Had to use addActiveLayer for a new layer.