Polygonal platformer
OICW

Since we're getting closer to christmas hack and there are many requests for platformers I was thinking about some way how to do platformer without tilemap. The good way is to use polygons, because then you can make terrain as you wish and it will be quite simple to check collisions and make moving - also I know at least one game which uses polygons for this type - SOLDAT. So I was thinking further. The main idea is that map will contain non-convex polygons - theese will represent not passable terrain. Each will be described by number of vertexes and of course the texture - and this is a tricky bit.
One way how to handle this is to have entire level as one bitmap described by polygons. So polygons are there only for collision detection. But because I want to spare disk space I prefer the other way. You'll have all textures in datafile, each will be say 64x64 px. in size. Then in the program you want to fill the polygon with this texture. And now comes the question: what is the best way how to do it?

I've only come up with idea that while loadingg the level I generate a bitmap for each polygon. Then draw this polygon using primitives onto this bitmap filled with texture. Then I'll use floodfill to make parts which I don't want to see transparent (using magic pink). But personally I don't like this way because it will dumb memory with bitmaps and I think there should be some more honorable way.

Inphernic

Forget the bitmap, move over to OpenGL, use the polygons for drawing as well (just map a texture on them), maybe add a foliage "layer" by calculating extra quads from the surface, etc.

Take a look at "Hippy's Trip" by James Lohr (SH'04 entry) to see what I'm talking about.

OICW

The thing is that I don't want to use OpenGl. I'm a bit "oldschool" in this, so I want to do something like that using 2d functions to map a texture onto a polygon.

Inphernic
Quote:

The thing is that I don't want to use OpenGl. I'm a bit "oldschool" in this, so I want to do something like that using 2d functions to map a texture onto a polygon.

By using OpenGL, you will not only get hardware acceleration, but also a number of useful features. If you're worried that you can't get an oldschool feeling/graphical style into the game, don't worry - moving over to OpenGL does not automatically mean 3D FPS games with lots of shader effects, you're still free to do pretty much what you want.

Ignoring the power of OpenGL just for the sake of being "oldschool" is not exactly a good reason. Just give it a chance. I'm pretty sure you'll like it. ;)

Paul Pridham

OpenGL calls aren't as portable as the Allegro software drawing functions. And for once, would people just lay off of a guy when he want to use Allegro's own drawing primitives instead of OpenGL? Jeez! :P Allegro's stuff is already there, easy to use, and it works.

Inphernic
Quote:

OpenGL calls aren't as portable as the Allegro software drawing functions.

Allegro's software drawing isn't nearly as fast/flexible as hardware acceleration (OpenGL). And aside from features like shaders (which would probably not be used here) etc, what makes you think that OpenGL calls aren't at least as portable as Allegro? What platforms are out if he'd go for OpenGL?

Quote:

And for once, would people just lay off of a guy when he want to use Allegro's own drawing primitives instead of OpenGL? Jeez! :P

No! NEVAR!!1 ;D

Quote:

Allegro's stuff is already there, easy to use, and it works.

AllegroGL is just one library to compile, it's (arguably) even easier to use and yet more powerful, and it works even better. ;)

OICW

There's no doubt that OpenGl is powerful (and I know that I can do even tilemap with it), I want to learn it but as Paul said - Allegro is here and ready to use. The second reason is: how would you make it few years ago when OpenGl didn't existed? And even OpenGl must do it somehow inside some MapTetxtureToPolygon function.
EDIT: There must be way how to do it only with Allegro or Window GDI.

Fladimir da Gorf

You don't have to learn OpenGL to be able to use OpenGL ;) There's always OpenLayer, which has polygon rendering, line strip functions and BlitDistorted. And the interface should look familiar for those who have used Allegro. OL2.0 will even test for polygon collisions and textured line strips. Have you seen the screenshots of Beary's Bash 2? That's a polygonal platformer made with OL :)

james_lohr

OpenGL is perfectly suited to what you are are trying to do, while Allegro is ill-suited. If you want something that is uglier, slower and just generally nastier, then go with plain Allegro ...and you're welcome to call it 'old school' if that make you feel better.

Quote:

I want to do something like that using 2d functions to map a texture onto a polygon.

It's called texture mapping and it's what OpenGl excels at. :P

Murat AYIK

I believe the solution is having an OpenGL driver for Allegro's primitives. Actually OpenLayer tries to do it in a more proffessional way, as far as I understand(I didn't use it) But letting Allegro primitives decay is not nice either. Maybe AL,AGL and OL should all merge together.

OICW

Flad: from morning I was asking myself: "If I ask, how long will it take till someone mention OpenLayer?" - don't take it personal, I don't have anything against it (I'm just too lazy to use it :-[). Yeah I must say that I saw those screenies - really nice. But anyway, can we now forget about OpenGl, DirectX, any other platforms and Allegro addons and make a discussion about ways how to make it in plain Allegro? Or some theory about that? Note: OpenLayer must achieve it somehow too.

EDIT: That way I posted above was the first thing that came up to my mind. Make a screen sized temp bitmap -> throw there texture -> draw polygon (using line and magic pink) -> floodfill the are outside the poly with magic pink -> clip the result to size of polygon -> save it to memory.

Fladimir da Gorf
Quote:

Note: OpenLayer must achieve it somehow too.

Actually that's your graphics card which does it.

But Allegro has textured polygons as well, so why not to use them? You don't get anti-aliasing, blending and others, but you wanted old school after all?

PS. I guessed from your earlier threads that you're not going to learn a new library anytime soon ;)

Quote:

Actually OpenLayer tries to do it in a more proffessional way, as far as I understand(I didn't use it)

In 1.93 the primitives are quite like in Allegro. But in 2.0 the system is totally renewed.

Thomas Harte

Right, Firefox 1.5 has once again thrown away one of my posts and I'm exceedingly angry about it. So I'm going to be very short.

For the Allegro Demo Game, I used a full polygon level. Polygon drawing was achieved with the "polygon" function and a drawing_mode of DRAW_MODE_COPY_PATTERN, with the "texture" passed as a pattern and an offset equal to the amount by which the level is scrolled. This is almost certainly the fastest way to produce a 2d polygon based level with software Allegro.

Fladimir da Gorf

And it's also a fine way if you consider just making a quick little game...

OICW
Quote:

I guessed from your earlier threads that you're not going to learn a new library anytime soon

That's not true.
Ok seems like good idea to use allegro polygon functions ;D
Now I'm just curious how that texturing works.

Fladimir da Gorf
Quote:

Now I'm just curious how that texturing works.

My guess would be scanline by scanline. First you need to detect where a scanline starts and where it ends and then copy the pixels over to the destination along that line.

OICW

I suppose that when I try to do it myself like I did with vectors (now I found that vector namespace in STD is not vector related :o) it will be pretty slow, not because I'm dumb but because putpixel would slow it. Note that my vector class is fast.

Thomas Harte

Here, for your enjoyment, is a tiny filled triangle filler:

1void mypolygon(BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int colour)
2{
3 /* sort */
4 if(y3 < y2)
5 {
6 y3 ^= y2; y2 ^= y3; y3 ^= y2;
7 x3 ^= x2; x2 ^= x3; x3 ^= x2;
8 }
9 if(y2 < y1)
10 {
11 y1 ^= y2; y2 ^= y1; y1 ^= y2;
12 x1 ^= x2; x2 ^= x1; x1 ^= x2;
13 }
14 if(y3 < y2)
15 {
16 y3 ^= y2; y2 ^= y3; y3 ^= y2;
17 x3 ^= x2; x2 ^= x3; x3 ^= x2;
18 }
19 
20 fixed AddX1, AddX2;
21 fixed X1, X2;
22 X1 = X2 = itofix(x1);
23 
24 AddX2 = itofix(x3 - x1) / (y3 - y1);
25 
26 acquire_bitmap(bmp);
27 if(y2 != y1)
28 {
29 AddX1 = (itofix(x2) - x1) / (y2 - y1);
30 
31 while(y1 != y2)
32 {
33 hline(bmp, fixtoi(X1), y1, fixtoi(X2), colour);
34 X1 += AddX1;
35 X2 += AddX2;
36 y1++;
37 }
38 }
39 else
40 X1 = itofix(x2);
41 if(y3 != y1)
42 {
43 AddX1 = (itofix(x3) - X1) / (y3 - y1);
44 
45 while(y1 != y3)
46 {
47 hline(bmp, fixtoi(X1), y1, fixtoi(X2), colour);
48 X1 += AddX1;
49 X2 += AddX2;
50 y1++;
51 }
52 }
53 release_bitmap(bmp);
54}

Note that there is no subpixel accuracy as all parameters are ints. What you'd normally do is advance to the nearest scanline at the top, then allow for an AddX1 switch "part way through" a scanline between the two while loop bits. This is the sort of thing that makes graphics people be so precied about where abouts the centre of the pixel is.

Obviously replace the hlines with little calls to blit to replicate the innards of polygon when presented with a patterned fill.

If you wanted to do a Gouroud or texture or whatever fill, you'd iterate more than just X1 and X2 along the edges. You'd iterate in 1/z space if you wanted to be perspective correct and then interate along scanlines too.

In the olden days a rival school of thought just maintained a separate set of basis vectors for their texture space and used a couple of dot products and a divide to calculate the texel per pixel without any bothersome iterating, but this doesn't integrate well with modelling software and was generally rejected by the industry.

OICW

Thanks for the code. I think that I'd be able to write my own code for polygon filling.

Thomas Harte
Quote:

Thanks for the code. I think that I'd be able to write my own code for polygon filling.

I'm sure you could, I was just responding to Fladimir's comment "My guess would be..." (emphasis added) - although I'm also sure he could write his own at least as quickly as I did. The purpose of posting the code was to further the discussion of polygon fills by making one method explicit. I'm sure if you wanted or needed code you would have asked explicitly.

Fladimir da Gorf

TH, that's quite what I expected, thanks for the clear example. By the way:

y3 ^= y2; y2 ^= y3; y3 ^= y2;
// Is usually slower than using a temp variable:
int temp = y3;
y3 = y2;
y2 = temp;

because the compiler will optimize out the temporary variable.

vpenquerch

And how will the compiler optimize out the temp variable ?
I assume you mean totally optimize it out, not merely use
a register (because otherwise it could also do the xors in
registers).
And frankly, compared to the rest of the code, it won't make
much of a difference. Now, for readability, that's another
story.

zer0

I tried something like that late last year that I picked up again sometime this spring (flad may remember). I dropped it because of memory issues with the pathfinding.

It rendered the polygons by using a mask. First, I filled a buffer with the texture. Then, I filled a mask-buffer with an arbitrary place-holder color. Then, I used allegro's polygon drawing routines to draw my polygon onto the mask using the whatever magic invisible color (pink/black/whateva'). Then, I drew the mask over the texture buffer. This left the polygon, surrounded by the place holder color. Fill all the placeholder color in with the magic invisible color and wa-la! A rendered polygon. I thought it was clever at least 8-).

If you're interested, check it out! Complete with editor and everything.
~clickity~
and a readme
~docClickity~
(i'm particularly proud of the scripting engine :))

If you have any questions I'd be happy to answer them.

Just a note, theres a small memory leak from the pathfinder.

oh, and credit goes to jim sinha for the view-shrowding. turn it on and off with F1

edit: and yea, this is an abandoned project, I know the code is kinda hard to follow. And I know its not totally optimized, or the best way to do this.
edit2: and i may get a delayed start on the xmas hack, was up pretty late working on this post

OICW

That sounds good Craig. I also think that I can prepare the masks at the loading of the level, store them in memory and then just draw rectangle filled with texture to buffer and then draw a mask over there. One question follows - how much memory consumes one bitmap? Let's say one with proportions of 640x480x16. I guess that it's an integer field.

zer0

Someone else may say different, but I wouldn't worry too much about the size of the bitmaps.

The only thing I would recommend is that when designing your levels, keep the bitmaps smaller than the size of the screen. When you play my example, you'll notice it kinda drags. Thats because it uses huge bitmaps, even though much of the bitmap isn't on the screen. My example doesn't draw bitmaps that are completely off the screen, but if theres a massive bitmap and even only a pixel of it is to be drawn, it'll attempt to draw the whole thing. And if you're worried about size you could store your level in pieces, instead of one big chunk, then load only the part that is immediately needed. I'm not sure as to the specifics of speed and blitting large/small bitmaps though, maybe someone else can fill in the details.

You can also just render all of your polygons, and store the rendered image. Then, just blit the polygon. Unless its dynamic (like rotating, or the texture scrolls), then you have to render it ever tick. You may be able to store all possible forms of a polygon. Out of experiences from my attempt at this I'd recommend keeping the shape of your polygons static, as it makes pathfinding and collision detection..umm..tricky when they're changing.

And thank you, thats the first kind word I've had from a regular:D

OICW

Ok thanks for the advices Craig. I'm not planning to use something like changing polygons, but I can say I'd be able to handle collisions with them. For the time being I can handle point vs polygon and polygon vs polygon tests even when the polygon is rotating so I don't see big deal there. Also your method is far better than my involving drawing primitives.

Flecko

As an aside, you should seriously check out Out of this World for the SNES. It was the first game I ever played that used polygons for 2d. Amazing game...sorry I can't find a link for a review or anything, but look it up.

And dare I say it, download the ROM and try it out.

Best of luck,
-Flecko

Corelian
Quote:

As an aside, you should seriously check out Out of this World for the SNES. It was the first game I ever played that used polygons for 2d. Amazing game...sorry I can't find a link for a review or anything, but look it up.

Aka Another World. I've never played it on SNES, but I'll doubt that its better than the PC or Amiga versions. Linkage. The game used polygon objects (characters, moving stuff), but IIRC the backgrounds were bitmaps.

OICW

I've heard about this one. Pretty cool stuff.

Tobias Dammers

Hey, why code your own polygon fillers when allegro comes with a full set of them? Optimized and all? All you need to do is use the correct polygon mode (for 2, affine mapping is perfect), specify texture coordinates (you can start off by just copying the un-scrolled x and y coords) and pass a BITMAP* as the texture. To be on the safe side, you should also set all the z coords to the same (non-zero) value.

Quote:

What platforms are out if he'd go for OpenGL?

Pretty much all platforms without (proper) opengl drivers. "Serious" gamers laugh at this, but the casual gamer expects games to run on an out-of-the-box system without further hassle. And for windows, out-of-the-box often means that opengl is MS-only, which is a lot slower than allegro's 3d routines. Also, without 3d hardware (some older laptops and very old desktop pc's), opengl is virtually useless for anything real-time.
I have to admit, though, that opengl is a lot easier to use once you get used to it. Allegro 3D is pretty nasty and error-prone; where opengl returns a well-documented error code and does nothing further, allegro produces rendering artifacts, SIGSEGVs and mysterious crashes when not used properly.

Thread #552757. Printed from Allegro.cc