TerrainGraphics questions
Moderator: Forum Moderators
Forum rules
- Please use [code] BBCode tags in your posts for embedding WML snippets.
- To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
TerrainGraphics questions
I have a pet project I've been working on - rendering wesnoth .map files with javascript. An odd thing, but I'm having fun. I've run into a couple of oddities in the TerrainGraphics output from the wmlparser scripts, and was wondering if someone could help clarify.
1) When I use wmlparser3.py, I get a couple of image paths that don't exist. For example:
In data/core/images/terrain/mountains there is basic_range3_1.png, 3_2.png, 3_3.png, etc, but not basic_range31.png, 32, 33.
How does the game know to load 3_3, rather that 33, and why does wmlparser3.py (or wmlparser2.py) output names which don't exist?
2) set_no_flag base vs. base2 seems to cause overlapping rules. Here are another couple of rules I'm trying to figure out:
It looks to me like these should both match for the same terrain - their maps are the same, the tile.type's are the same, and the set_no_flag's are different. The mountains should match, setting the base2 flag, then the hills should match, setting the base flag, and both images get drawn. What am I missing, such that the hill graphic doesn't always overlay the mountain one?
1) When I use wmlparser3.py, I get a couple of image paths that don't exist. For example:
Code: Select all
"image": [
{
"name": "mountains/basic_range31.png",
"base": "88,107"
},
{
"name": "mountains/basic_range32.png",
"base": "144,107"
},
...etc...
How does the game know to load 3_3, rather that 33, and why does wmlparser3.py (or wmlparser2.py) output names which don't exist?
2) set_no_flag base vs. base2 seems to cause overlapping rules. Here are another couple of rules I'm trying to figure out:
Code: Select all
# Mountains
{
"image": [{
"variations": ";2;3;4;5;6",
"name": "mountains/basic@V.png",
"base": "90,107",
"center": "90,144"
}],
"map": "\n, *\n* , *\n, 1\n* , *\n, *",
"tile": [{
"pos": "1",
"set_no_flag": "base2",
"type": "Mm"
}],
"probability": "100"
}
# Hills
{
"image": [{
"name": "hills/regular@V.png",
"layer": "-1000",
"base": "90,144",
"center": "90,144"
}],
"map": "\n, *\n* , *\n, 1\n* , *\n, *",
"tile": [{
"pos": "1",
"set_no_flag": "base",
"type": "Mm"
}],
"probability": "100"
}
Re: TerrainGraphics questions
I'm not completely sure, but I'd suspect a bug in wmlparser; the actual WML does have the underscores in them, like here (the last macro argument):BlueWinds wrote:I have a pet project I've been working on - rendering wesnoth .map files with javascript. An odd thing, but I'm having fun. I've run into a couple of oddities in the TerrainGraphics output from the wmlparser scripts, and was wondering if someone could help clarify.
1) When I use wmlparser3.py, I get a couple of image paths that don't exist. For example:
In data/core/images/terrain/mountains there is basic_range3_1.png, 3_2.png, 3_3.png, etc, but not basic_range31.png, 32, 33.Code: Select all
"image": [ { "name": "mountains/basic_range31.png", "base": "88,107" }, { "name": "mountains/basic_range32.png", "base": "144,107" }, ...etc...
How does the game know to load 3_3, rather that 33, and why does wmlparser3.py (or wmlparser2.py) output names which don't exist?
Code: Select all
name={BUILD_IMAGE IMAGE_SINGLE {IMAGESTEM} _1}
It's the layers. The hills get layer=-1000, causing them to always be drawn under the mountain which has no layer and thus defaults to 0. The base coordinates only affect draw order between images that have the same layer; an image with a higher layer can never be drawn behind an image with a lower layer, no matter what their base coordinates are. Or at least that's my understanding.BlueWinds wrote:2) set_no_flag base vs. base2 seems to cause overlapping rules. Here are another couple of rules I'm trying to figure out:
It looks to me like these should both match for the same terrain - their maps are the same, the tile.type's are the same, and the set_no_flag's are different. The mountains should match, setting the base2 flag, then the hills should match, setting the base flag, and both images get drawn. What am I missing, such that the hill graphic doesn't always overlay the mountain one?Code: Select all
# Mountains { "image": [{ "variations": ";2;3;4;5;6", "name": "mountains/basic@V.png", "base": "90,107", "center": "90,144" }], "map": "\n, *\n* , *\n, 1\n* , *\n, *", "tile": [{ "pos": "1", "set_no_flag": "base2", "type": "Mm" }], "probability": "100" } # Hills { "image": [{ "name": "hills/regular@V.png", "layer": "-1000", "base": "90,144", "center": "90,144" }], "map": "\n, *\n* , *\n, 1\n* , *\n, *", "tile": [{ "pos": "1", "set_no_flag": "base", "type": "Mm" }], "probability": "100" }
P.S. There's also some other oddities with the mountain rules, such as hills transitions getting drawn in wrong and unnecessary places between mountain hexes, and a hills base being drawn under mountains which already cover the whole hex, but as it happens I'm right now working through some of that stuff to fix it.
Re: TerrainGraphics questions
"A bug" was my guess as well. For now I've been working around it by trying loadImg(name) || loadImg(name.replace(/(\d)(\d)/, '$1_$2').zookeeper wrote: I'm not completely sure, but I'd suspect a bug in wmlparser; the actual WML does have the underscores in them, like here (the last macro argument):
My guess would be that while the game itself parses that correctly and considers the whole "_1" as the argument, wmlparser interprets the underscore as a translation marker and loses it. That's the only explanation I can come up with.Code: Select all
name={BUILD_IMAGE IMAGE_SINGLE {IMAGESTEM} _1}
Doh, I was forgetting to assign the default layer of 0 to images if they didn't have one. Thanks for your quick reply!zookeeper wrote: It's the layers. The hills get layer=-1000, causing them to always be drawn under the mountain which has no layer and thus defaults to 0. The base coordinates only affect draw order between images that have the same layer; an image with a higher layer can never be drawn behind an image with a lower layer, no matter what their base coordinates are. Or at least that's my understanding.
P.S. There's also some other oddities with the mountain rules, such as hills transitions getting drawn in wrong and unnecessary places between mountain hexes, and a hills base being drawn under mountains which already cover the whole hex, but as it happens I'm right now working through some of that stuff to fix it.
Another question, if you don't mind, about 'base', which I've been mostly ignoring until now. I get that one purpose of base[1] (the y coord) is that it helps sort the order images are drawn, but does base do anything else? Does base[0] (the x coord) do anything at all?
Re: TerrainGraphics questions
If it looks like wmlparser can't easily be fixed to handle those cases right, then we can always simply disambiguate the WML by adding parentheses; mountains.cfg seems to be the only place where those kind of bare macro arguments starting with an underscore occur in mainline.BlueWinds wrote:"A bug" was my guess as well. For now I've been working around it by trying loadImg(name) || loadImg(name.replace(/(\d)(\d)/, '$1_$2').
No, as far as I can tell x is ignored, and the sorting happens exclusively according to the y value... which in a case of convenient coincidence I just stumbled upon yesterday, myself.BlueWinds wrote:Doh, I was forgetting to assign the default layer of 0 to images if they didn't have one. Thanks for your quick reply!
Another question, if you don't mind, about 'base', which I've been mostly ignoring until now. I get that one purpose of base[1] (the y coord) is that it helps sort the order images are drawn, but does base do anything else? Does base[0] (the x coord) do anything at all?
Re: TerrainGraphics questions
It looks like basex does show up in one more place - calculating the new basey when doing a rotation. I'll have to add that to my code, I wasn't adjusting the 'base' during rotations.
https://github.com/wesnoth/wesnoth/blob ... r.cpp#L565
builder.cpp is the file I wish I'd known about when I started! By sheer convergent evolution a lot of my function names match the ones in there, but being able to read the actual source would have (and still will) save me a bunch of trial and error. I'll probably get the map renderer working this weekend - getting close now, just need to track down some bugs in the rules matching - and will post some pictures and the code.
https://github.com/wesnoth/wesnoth/blob ... r.cpp#L565
builder.cpp is the file I wish I'd known about when I started! By sheer convergent evolution a lot of my function names match the ones in there, but being able to read the actual source would have (and still will) save me a bunch of trial and error. I'll probably get the map renderer working this weekend - getting close now, just need to track down some bugs in the rules matching - and will post some pictures and the code.
Re: TerrainGraphics questions
Right, yeah of course. I forgot about that.BlueWinds wrote:It looks like basex does show up in one more place - calculating the new basey when doing a rotation. I'll have to add that to my code, I wasn't adjusting the 'base' during rotations.
https://github.com/wesnoth/wesnoth/blob ... r.cpp#L565
Re: TerrainGraphics questions
Adding parens to mountains.cfg doesn't fig the issue. It still outputs mountains/basic_range23.png, etc even when using
Easy bug to workaround on my end, so not going to spend time looking for the root cause / fixing wml parser right now. Maybe someday.
-------
What does ~CS(a, b, c) in an image name mean? It seems to do a color shift somehow, but AFIKT is undocumented. I'd be happy to document it for the wiki, or add link to it from the TerrainGraphicsWML page if it already exists somewhere and I just can't find it.
-------
Other funny thing I noticed - turns out when you draw a single mountain on top of grass, the transitions, which look decent, are actually the hill transitions, because it draws the hill (including transitions) then puts the mountain over the top. There are no rules that use the mountain transitions anywhere!
https://github.com/wesnoth/wesnoth/blob ... mall-n.png
^ totally unused. Wesnoth uses this instead:
https://github.com/wesnoth/wesnoth/blob ... ular-n.png
The mountain ones look a bit better, IMO, since they're designed to go with the mountain tiles.
Thanks again for all your help.
Code: Select all
{BUILD_IMAGE IMAGE_SINGLE {IMAGESTEM} (_1)}
-------
What does ~CS(a, b, c) in an image name mean? It seems to do a color shift somehow, but AFIKT is undocumented. I'd be happy to document it for the wiki, or add link to it from the TerrainGraphicsWML page if it already exists somewhere and I just can't find it.
-------
Other funny thing I noticed - turns out when you draw a single mountain on top of grass, the transitions, which look decent, are actually the hill transitions, because it draws the hill (including transitions) then puts the mountain over the top. There are no rules that use the mountain transitions anywhere!
https://github.com/wesnoth/wesnoth/blob ... mall-n.png
^ totally unused. Wesnoth uses this instead:
https://github.com/wesnoth/wesnoth/blob ... ular-n.png
The mountain ones look a bit better, IMO, since they're designed to go with the mountain tiles.
Thanks again for all your help.
- James_The_Invisible
- Posts: 534
- Joined: October 28th, 2012, 1:58 pm
- Location: Somewhere in the Northlands, fighting dark forces
- Contact:
Re: TerrainGraphics questions
It is a function that shifts colors of an image. It is documented here.What does ~CS(a, b, c) in an image name mean?
My content: For Power series
Ports: Danse Macabre Story of the Wose
Guides: How to translate your UMC
Ports: Danse Macabre Story of the Wose
Guides: How to translate your UMC
Re: TerrainGraphics questions
Thanks! I'm not registered to edit the wiki yet (just sent in a request), but once I have access I'll add a link to that from https://wiki.wesnoth.org/TerrainGraphicsWML. I'll also update the description on the RefernceWML page to mention that it's used for more than just faction colors.James_The_Invisible wrote:It is a function that shifts colors of an image. It is documented here.What does ~CS(a, b, c) in an image name mean?
Re: TerrainGraphics questions
ImagePathFunctions are usable as part of any image path anywhere, so while the page can of course be linked to from TerrainGraphicsWML, there's nothing special about them being supported in that context.
Anyway, if you intend to make the renderer accurate, you'll have to also handle the ~BLIT, ~MASK and ~O functions. And almost any other function could end up being used sooner or later.
Anyway, if you intend to make the renderer accurate, you'll have to also handle the ~BLIT, ~MASK and ~O functions. And almost any other function could end up being used sooner or later.
Right, I guess that actually makes sense. Parentheses only delimit the argument, but don't affect how the content gets interpreted. Adding quotes instead might work.BlueWinds wrote:Adding parens to mountains.cfg doesn't fig the issue. It still outputs mountains/basic_range23.png, etc even when usingEasy bug to workaround on my end, so not going to spend time looking for the root cause / fixing wml parser right now. Maybe someday.Code: Select all
{BUILD_IMAGE IMAGE_SINGLE {IMAGESTEM} (_1)}
Re: TerrainGraphics questions
Turns out that the flu sucks, so not going to finish this weekend. Still more bugs to work through. Here's a WIP screenshot, though: http://imgur.com/a/ZFuut. All the borders are currently offset one hex south of where they should be, but it draws simple terrain pretty well.
High level languages (coffeescript, in this case) are nice.
Now that I've added a redraw step to rule compilation to support CS, adding more image manipulation functions is pretty easy. Here's the opacity one:zookeeper wrote:ImagePathFunctions are usable as part of any image path anywhere, so while the page can of course be linked to from TerrainGraphicsWML, there's nothing special about them being supported in that context.
Anyway, if you intend to make the renderer accurate, you'll have to also handle the ~BLIT, ~MASK and ~O functions. And almost any other function could end up being used sooner or later.
Code: Select all
shiftOpacity = (srcCanvas, opacity)->
imageData = srcCanvas.getImageData(0, 0, src.width, src.height)
data = imageData.data
for i in [0...data.length] by 4
data[i + 3] *= opacity
srcCanvas.putImageData(imageData, 0, 0)
Quotes work, good call. Created pull request, we'll see if I did it right. https://github.com/wesnoth/wesnoth/pull/907zookeeper wrote:Right, I guess that actually makes sense. Parentheses only delimit the argument, but don't affect how the content gets interpreted. Adding quotes instead might work.
Re: TerrainGraphics questions
Let's say I have these two rules:
I'm dealing with this section of a map, with the first water at (1,1):
Here are some diagrams of how the rules match onto the map:
So here's the top-left corner of each rule that matched:
Notice how the water and sand are offset horizontally but on the same row. Once the sand is moved due to the image's "center", I end up actually drawing this:
What am I missing? It seems odd that the rules match at different locations, but I'm not sure how it should be working. Why are some one-tile rules surrounded by *s and offset with "center", but others just use a single "tile" rule with no center?
Code: Select all
{
"tile": [
{
"set_no_flag": "base",
"x": "0",
"y": "0",
"image": [
{
"name": "water/coast-tropical-A[01~15].png~CS(40,0,-30):110",
"layer": "-1000"
}
],
"type": "Ww,Wwr,Wwf"
}
]
},
{
"map": "\n, *\n* , *\n, 1\n* , *\n, *",
"probability": "100",
"tile": [
{
"type": "Ds",
"set_no_flag": "base",
"pos": "1"
}
],
"image": [
{
"base": "90,144",
"variations": ";2;3;4;5;6;7;8;9;10;11",
"center": "90,144",
"layer": "-1000",
"name": "sand/beach@V.png"
}
]
}
Code: Select all
. .
. Wwt
Wwt .
. Ds
Ds .
. .
. .
Code: Select all
Water at 1,1 and 2,1
. .
. Wwt
Wwt .
. .
. .
. .
. .
Sand at 0,1
. .
. .
* .
* *
Ds .
* *
* .
and at 1,1
. .
. *
* *
. Ds
* *
. *
. .
Code: Select all
. .
s w
sw .
. .
. .
. .
. .
Code: Select all
. .
. w
w .
. .
s .
. s
. .
Re: TerrainGraphics questions
I can't interpret all your diagrams, but:
There's no particular reason why the beach and water base tile rules are different like that. The beach sands simply use TERRAIN_BASE_RANDOM which eventually resolves to GENERIC_SINGLE_PLFB which uses a map-based rule which can accommodate bigger-than-hex images, whereas water uses ANIMATED_WATER_15 which doesn't.
However, one detail regarding map= and centering you should note (and which might be part of your current problem), is that if you have a map= like this...
Then one might think that to center an image onto that you'd need center=90,108, but the game doesn't actually know how to deal with a map= that doesn't have a full hex at the top left corner. So, internally that ends up getting an extra top row and thus treated as this, meaning that you'd need center=90,144 instead:
Finally, if the rule has rotations then you end up with every other rotation getting that treatment, which is why half of for example castle and wall tiles have a different vertical size than the other half (usually 144 and 180).
There's no particular reason why the beach and water base tile rules are different like that. The beach sands simply use TERRAIN_BASE_RANDOM which eventually resolves to GENERIC_SINGLE_PLFB which uses a map-based rule which can accommodate bigger-than-hex images, whereas water uses ANIMATED_WATER_15 which doesn't.
However, one detail regarding map= and centering you should note (and which might be part of your current problem), is that if you have a map= like this...
Code: Select all
map="
, *
* , *
, 1
* , *
, *"
Code: Select all
map="
. , .
, *
* , *
, 1
* , *
, *"
Re: TerrainGraphics questions
Turns out I was parsing the "map" key wrong in a pretty fundamental way. ^^;; With that fixed, I'm getting to the point where full fledged maps look decent. Here's a couple of examples. http://imgur.com/a/Kbibz
I'm still having problems with Keeps and a few types of terrain with similar borders, as you can probably see. The trouble is that all the walls are rendering in the same place. Given this map:
and this rule:
I end up with six rotations matching on the single keep hex, as expected - but the trouble is, the top left corner of every image is in the same location. They end up overlayed on each other, all in one spot (http://imgur.com/a/5jKQY), rather than spread out around the cobbles.
As I read the wiki, "base" is only used for determining layering - it doesn't influence image position. What part of this rule should be causing the borders of the keep to be placed as expected (forming a wall it) rather than in a big heap?
I'm still having problems with Keeps and a few types of terrain with similar borders, as you can probably see. The trouble is that all the walls are rendering in the same place. Given this map:
Code: Select all
Gg, Khs, Gg
Gg, Gg, Gg
Code: Select all
[terrain_graphics]
map="
2
, 3
1"
probability=100
rotations="tr,r,br,bl,l,tl"
[tile]
pos=1
set_no_flag="wall-@R0"
type="Kh,Kd*,Ko,Kv"
[/tile]
[tile]
pos=2
set_no_flag="wall-@R2"
type="!,K*"
[/tile]
[tile]
pos=3
set_no_flag="wall-@R4"
type="!,K*"
[/tile]
[image]
base="54,72"
layer=0
name="castle/keep@V-convex-@R0.png"
variations=";2;3;4;5;6"
[/image]
[/terrain_graphics]
As I read the wiki, "base" is only used for determining layering - it doesn't influence image position. What part of this rule should be causing the borders of the keep to be placed as expected (forming a wall it) rather than in a big heap?
Re: TerrainGraphics questions
Without an [image] center=, the images are by default aligned to the top left corner of the map=. But when you're dealing with multihex images with rotations, the stuff in my previous post becomes relevant.
So, if you have this:
Then the subsequent rotations will internally end up being like this:
In your example, the unrotated (tr) base rule places castle/keep@V-convex-tr.png and aligns it to the top left corner of the hex north of the castle hex.
The next rotation (r) places castle/keep@V-convex-r.png and aligns it to the top left corner of the hex north of the castle hex (because of that internally-created dummy padding hex).
The next rotation (br) places castle/keep@V-convex-br.png and aligns it to the top left corner of the castle hex.
If the rule does use [image] center= then, as you'd expect, that causes the image to be centered on those coordinates on the map= (again, calculated from the top left corner). However, I think the engine does automatically adjust the coordinates when rotating, so if you have a rotated map= like this with [image] center=90,144 then the image does actually stay in the center of hex 1 without bouncing up and down on every rotation:
So, if you have this:
Code: Select all
map="
2
, 3
1"
Code: Select all
#rotation r
map="
.
, 2
1
, 3"
#rotation br
map="
1
, 2
3"
#rotation bl
map="
.
, 1
3
, 2"
etc
The next rotation (r) places castle/keep@V-convex-r.png and aligns it to the top left corner of the hex north of the castle hex (because of that internally-created dummy padding hex).
The next rotation (br) places castle/keep@V-convex-br.png and aligns it to the top left corner of the castle hex.
If the rule does use [image] center= then, as you'd expect, that causes the image to be centered on those coordinates on the map= (again, calculated from the top left corner). However, I think the engine does automatically adjust the coordinates when rotating, so if you have a rotated map= like this with [image] center=90,144 then the image does actually stay in the center of hex 1 without bouncing up and down on every rotation:
Code: Select all
map="
, 2
* , *
, 1
* , *
, *"