The Dink Network

Windemere Stuff

December 22nd 2004, 11:03 PM
wizardb.gif
merlin
Peasant He/Him
 
No, not which fonts - I've already picked. I'd like to show you what I've been working on so far during my break. First, to show my progress, let me show you something that looks like the fonts you were looking at before (enlarged to 144px):

The word 'This'

The T and i look okay because they're mostly straight lines. But look at the curves on the h and s. Blocky. I have implemented a technology called Antialiasing for font text. Basically the alpha pixels on the border are manipulated to make it look smooth. So let's take a look at that with antialiasing:

The word 'This' with AA

Smooth. Not to mention millions of fonts and millions of sizes can all be loaded at once. So you, as a wmod developer, can customize your font. Yay.

EDIT: New Map info follows in another post.
December 23rd 2004, 01:24 AM
wizard.gif
Chrispy
Peasant He/Him Canada
I'm a man, but I can change, if I have to.I guess. 
Teh karma be with you.
December 23rd 2004, 03:07 AM
wizardb.gif
merlin
Peasant He/Him
 
Windemere Map Format: A Primer
==============================

HISTORY

When I sat down to begin coding the Windemere map format it quickly became apparent that I would need something to organize my thoughts, especially considering the greater complexity with freescrolling. There are an infinite ways to do this, but very few sane ways. With that in mind it would have been a mistake to build off of Seth's map format.

I write this article not to explain how the map format works to the reader, but how the format works to myself before actually coding it. I publish it with hope that something useful can be gained for the reader as well.

There were two approaches to the map format, as with any format, that were...

...to be considered: plain text or binary. I chose plain text because it is simpler. Binary formats are a mess to work with but are fairly compact; ASCII formats are exactly the opposite. I wanted both so I chose ASCII plain text that would later be compressed with my favorite compressor: Bzip2. While compression is beyond the scope of this document, its capabilities are amazing in comparison to its speed. There are better compression algorithms out there, yes, but the Burrow Wheelers algorithm is speedy for its yielding results.

There were still many ways to do this with ASCII but I chose one of the most widely-used methods of organization in existence: the tree method (as used by SGML, XML, HTML, etc.).

LIMITATIONS

Now, freescrolling relieves many limits of the previous tile-based implementation, but I had to further impose restrictions that I was not willing to code for, namely the map size. My plan was to allow an unlimited map size (up to 2^32 – 1 on 32-bit macines) and an unlimited number of maps. Since there were no longer tiles I made the terrain tiles sprites. Yes, tiles are now sprites! Which makes no difference whatsoever since there is no limit on the number of sprites that can be used.

I was not willing to code code that would draw only a portion of a sprite for the map. That would be not only cause more memory usage (new's, calls to glTexSubImage2D, and delete's every frame), but it would be slower and more work for me. Not something I want to do. So, the map size would have to be a multiple of the tile size. So, if the tile was 50 x 50 pixels, the map size would have to be divisible by 50.

The map would not have to be square either. A (bad) size could be 64 x 32. But then the tile size could not be 50 x 50 – it would have to be either 64 x 32, 32 x 16, 16 x 8, 8 x 4, 4 x 2, or 2 x 1. A better size would be 1000 x 500, meaning the width is twice as much as the height. This means that, at a tile size of 50 x 50, there would be 50 tiles across and 25 tiles up.

COORDINATES

But enough of the talk about tiles. That's just for reference for the OpenGL code in the engine. You, as a developer, only have to worry about one thing: pixels. I chose pixels not only because they were very simple but also so the engine could run at different resolutions without (too) adverse effects.

Here's the run-down:

We have a 2D plane on which to map. To plot a point, we need two things: the point and the point in relation (the point and origin). Like lattitude and longitute, we need some place to call 0. In Windemere, that place is the bottom-left corner of the map. Why the bottom left? Well, so the map can be added on to without it screwing up the rest of the coordinates. There are other ways to add onto a map, usually used for “indoor” areas, but those come later.

So, we know we need two things so far – the x and y pixel coordinates of our point, and the x and y pixel coordinates of the origin (0, 0), the bottom-left corner of the map. Bottom-left is the key here. Bottom-left everything. So, when you specify the coordinates for a sprite, you are specifying the point where the bottom-left of the sprite image will go.

In Seth's game we have areas called “indoor” areas. These areas are warped to and from using a warp. Areas like these are houses or shops or anything not connected to the outside world. Since I did not wish to force the author to put hardness around all areas that were indoor like one had to in Dink, I came up with a new idea: submaps. Instead of boxing off an area that would be warped to it would instead be created on an entirely separate map (in the same file, mind you). How do we know what part of the map is a submap? This is where a third coordinate comes in: the map number.

The number 0 is reserved for the overall main map, but the rest are yours to create and use.

1-1210,1350

That warps to the first submap, 1210 pixels over and 1350 pixels up.

0-0,0

That one warps to the main map at the very bottom-left corner. Probably not the most practical example but a proper one nonetheless.

Note that coordinates can get huge (ex: 196840,16783) which is another reason why I've created the submap system. If you're allergic to large numbers (like I'm allergic to Java) then you can create a hardness border around the map, force the user to use a path to change screens, and move him or her onto another submap. Very nice concept.

HARDNESS

Note that hardness methods can change as this is still under development.

Hardness is declared right inside of the map file using one of two methods: point hardness or rectangular hardness. Point hardness is where you want only a certain point to be hard (that didn't sound right) and rectangular hardness is used mainly for a box or line.

The first thing the engine does when the submap is loaded is create an array of all the hard coordinates for that plane. Each frame these will be referenced and dink will stop if he reaches one of them. This is why you must not warp inside one – you'll be stuck. You cheating fellow.

Point Hardness is defined like this:

[x, y]

And Rectangular Hardness is like this:

[x, y, w, h]

But that's pretty much useless unless it's in context. Let's look at the actual file.

THE MAP FILE

The first thing there will be are 4 characters: WMF\n. WMF means Windemere Map File and is checked to see if the file is really a map file (it's really used to see if the file is compressed or not).

Next:

<Map: 0>
{
Sprite(1, 340, 218);
Sprite(4, 4892, 3844);
Hard(5, 5);
Hard(27893, 1982, 280, 14);
}
<Map: 1>
...

Let's look at that line by line.

<Map: 0>
{

This designates the submap level. 0 is the main map. Everything after the { applies to that level.

Sprite(n, CoordX, CoordY);

This says display the bottom-left corner of sprite n at CoordX, CoordY. So, in this case, display sprite 1 at 340, 218.

The second sprite says display sprite 4 at 4892, 3844.

Hard(PointX, PointY);

This says create a point hardness at PointX, PointY. In this case, make sure the bottom part of the character cannot pass (5, 5).

The second Hard command says create a box of hardness from (27893, 1982) to (28173, 1996).

}

Close up Map 0.

<Map: 1>

Make everything apply to submap 1 now.

Overall it's a relatively simple map format. Simple enough to be written in a text editor, anyway.
December 23rd 2004, 04:31 AM
dragon.gif
The "Current Windemere Screenshot" and "Current Editor Screenshot" links on the Windemere website don't work. Why is this? And how do I download the editor? And where is a list of the codes?
December 23rd 2004, 04:46 AM
fairy.gif
Glennglenn
Peasant He/Him Norway
GlennGlenn doesn't want a custom title. 
You won`t get the list of the codesuntil windmere is finished 'couse he haven`t created the commands yet
December 23rd 2004, 08:15 AM
custom_fish.png
SabreTrout
Noble He/Him United Kingdom
Tigertigertiger. 
Sounds good. I'm certainly starting to look forward to the old Windy Mire.
December 23rd 2004, 08:23 AM
pq_frog.gif
Ric
Peasant They/Them Canada
 
The map format sounds perfect! Awesome.
But if the sprites are located based on thier lower-left corner, that may get tricky getting them to interact with touch(). For most things that are reletivly the same size it would work out with a distance or range property, but if one sprite was much larger, it would look like the smaller sprite need to touch that corner of the larger sprite. Or will such interactions be handled another way?
December 23rd 2004, 12:37 PM
goblinm.gif
Hardbox to hardbox would seem right... although you might not want to calculate it. Perhaps pic to pic?
December 23rd 2004, 12:48 PM
goblins.gif
igloo15
Peasant He/Him
 
any pictures and any word on when we can get our hands on this thing.
December 23rd 2004, 12:53 PM
dragon.gif
I'll second that!
December 23rd 2004, 01:04 PM
goblins.gif
igloo15
Peasant He/Him
 
I have a question actually in dink there was a vision thing which i thought was a great idea and i use it alot. Will windmere have something like this prolly not since its freescroll. I mainly use visions to do stuff like have a broken bridge in one vision and then in another vision have the bridge fixed. If we can't use visions how will go about doing this type of event.
December 23rd 2004, 01:14 PM
wizard.gif
Chrispy
Peasant He/Him Canada
I'm a man, but I can change, if I have to.I guess. 
Well, for the touch() procedure, one could figure out c in (x2-x1)^2+(y2-y1)^2=c^2... but for too many sprites on screen, that would really bog the system... There are probably ways to optimise the routine, aka, mid-routine outs, lower call times as a function of increasing distance, etc, etc. And also, there is the option of making touch() a purely main-character option, not letting the other characters get touch-based affects.
December 23rd 2004, 03:16 PM
wizardb.gif
merlin
Peasant He/Him
 
So many questions. Let's take Ric's question and Chrispy's response first (since it's the one at the bottom of my screen).

The active pixel will be cacluated using just that method unless it has been set in the windemere.ini (I have not yet decided on the format). It will be saved in memory at the beginning of the game for each sprite so it won't have to be calculated every frame. As far as optomizing the routine: assembly works well.

Now, DraconicDink's Draconic response:

The "Current Windemere Screenshot" and "Current Editor Screenshot" links on the Windemere website don't work. Why is this? And how do I download the editor? And where is a list of the codes?

I know it doesn't work. It doesn't work because I changed the directory structure around when I recoded it in PHP. You download the editor using SourceForge's site when I put it up. And I have no idea what codes you're talking about.

Next:

any pictures and any word on when we can get our hands on this thing.

Well I could take a picture but first, it would get out of date fast. And second, what would I take a picture of? The code? I haven't coded the map yet. The font pictures were partial screenshots (parts of the screen) of Windemere though.

As for when it's finished, the best I can offer is: when it's done. I will no longer be making dates. Last time I did that I had to extend them every time. Better that than getting your hopes up, right?

If you want it to get done faster, well, do you know anyone who can code an editor in FLTK? That would really help.

Next, the hard-to-read question:

I have a question actually in dink there was a vision thing which i thought was a great idea and i use it alot. Will windmere have something like this prolly not since its freescroll. I mainly use visions to do stuff like have a broken bridge in one vision and then in another vision have the bridge fixed. If we can't use visions how will go about doing this type of event.

Don't assume something. Visions will be very easy to implement. Watch (I don't expect you to - this serves more of as reminder to me):

My sprite rendering loop is this:

// Go through each sprite
for(std::list<SpriteRenderProps>::iterator it = RenderList.begin(); it != RenderList.end(); ++it)
{
glBindTexture(GL_TEXTURE_2D, dynamic_cast<WImageResource* WResources::Get()->GetResource(RES_IMG, it->iResLoc))->uiGLID); // Bind the texture

// Render it.
glBegin(GL_QUADS);
glTexCoord2f(0,0);
glVertex2f(it->iXPos, it->iYPos);

glTexCoord2f(1,0);
glVertex2f(it->iXPos + it->iWidth, it->iYPos);

glTexCoord2f(1,1);
glVertex2f(it->iXPos + it->iWidth, it->iYPos + it->iHeight);

glTexCoord2f(0,1);
glVertex2f(it->iXPos, it->iYPos + it->iHeight);
glEnd();

SDL_Delay(5);
}

All I do is stick something like this right inside the loop:

if(it->iActiveVision == WSprite::Get()->iCurrentVision)
{
// Render
}

Visions will definitely be included.
December 23rd 2004, 04:28 PM
burntree.gif
Striker
Noble She/Her United States
Daniel, there are clowns. 
Read over this a bit and I'm still not exactly clear why you would put the origin is centered at bottom left of the screen, instead of the the top left. Practically every graphics program in existence uses top left. I know when calculating the hardboxes of sprites, etc, I often use Paint Shop Pro to quickly grab the coordinates for sprites. It would be quite annoying for me to have to figure it out with a different origin.

December 23rd 2004, 08:19 PM
wizardb.gif
merlin
Peasant He/Him
 
The origin of what? The origin of the map will be at the bottom left whether you like it or not. The origin of the sprite I can change... I just need to remember to make the y coord negative.
December 23rd 2004, 08:51 PM
burntree.gif
Striker
Noble She/Her United States
Daniel, there are clowns. 
nm, redink1 explained the reason for the map. So OpenGL uses a bottom left origin, huh?

See, everything I've programmed with used the top left.
December 24th 2004, 01:38 AM
wizardb.gif
merlin
Peasant He/Him
 
Yep. That's why when you render say, a bitmap, into a glTexture it will appear upside down. Annoying but I've gotten used to it.

Now, for some map progress. Here is some engine output (all pulled from a std::vector<std::vector<WMapSprite> > 2D vector) (dots are for spaces since this forum hates me):

Number of submaps: 2
Submap 0
........Sprite 1 x: 5 y: 4
........Sprite 2 x: 19852 y: 3988775
........Sprite 32 x: 4 y: 32
Submap 4
........Sprite 3 x: 433 y: 680

This is what the map looks like:

<map>
........<submap number="0">
............<sprite number="1" x="5" y="4" />
............<sprite number="2" x="19852" y="3988775" />
............<sprite number="32" x="4" y="32" />
........</submap>

........<submap number="4">
............<sprite number="3" x="433" y="680" />
........</submap>
</map>

I haven't finished it completely but the main part (parsing) is complete. Just a bit of sibling manipulation and I can add hardmaps and even pictures of Tal's sister . I love this thing.