Ascii3d


Vorporeal

Yes, no, I, this is.
Joined
Sep 13, 2007
Messages
1,614
Age
34
Website
Visit site
I'm currently working on an engine (or game, not sure which yet) that realizes Squidi's "Mechanic #83 - ASCII 3D".

I currently have it so that it simply displays the 3D, top-down perspective. It doesn't do any parallax scrolling for camera movement and the like (that's coming soon).

My question is - does anyone know of a good way to overlay different layers in SDL? I'm trying to find a way to overlay all of the different versions of the walls that looks good, but I'm having trouble coming up with anything.

Here's a picture of everything so far: [img=img14.imageshack.us/img14/3662/ascii3d.png]

EDIT: The updates will be posted on the blog, but I'll also make posts here mentioning the updates for the larger ones. The link to the blog's in my signature. For those of you suffering from the forum bugs:
CODE
http://saucepansoftware.wordpress.com
 
Last edited by a moderator:
You'll lose a lot of speed blitting mostly-transparent layers every frame.

Especially when above floor level only a small chunk of the level or room is actually populated by ASCII symbols.

Best bet is to loop from floor to roof, blitting everything.
 
Last edited by a moderator:
Use OpenGL to first render the non-extruding parts of the world (the floor for example) with one texture and then the extruding parts of the world on another texture, on which you apply an "echo" shader that draws the texture multiple times and scales it every time. Or you can use OpenGL and do the same in non-graphics-memory :p (a loop + glScalef + draw)

lulzfish your idea would work if it wasn't for the fact that the ASCII characters have to be scaled on every level closer to the camera (to look realistic), or do I understand your suggestion correctly? To use a glyphmap (a big surface with all characters) to dynamically assemble a final surface by reading in a 2D array containing allt he chars, and outputting some of the chars mutiple times fromt he glyphmap?
 
Last edited by a moderator:
YAAAAAY i love squidis site! Awesome. i lap up the trail of beauty that trails you
 
Right now, what I'm doing is reading in the map from a text file, creating one bitmap that contains all of the map (the floor), and also creating one that only has the walls. Then I use rotozoom (more specifically zoomSurface) to create the zoomed-in wall layers and blit them on top. It's terribly inefficient, I know. It also doesn't look great, as the zooming with the mostly black background and little bit of white space doesn't end up pretty (the transparency comes from setting black as the transparent color key). I was looking through SDL_gfx and saw it had a whole host of overlay/addition/subtraction/etc. filters, and thought one of those might do a better job of combining the layers.

@dflemstr: I was thinking of using OpenGL, but I don't actually know it yet. I've been planning on learning it for some time now. Do you think it would make a significant difference (in both speed and graphical quality) if I used that for the display stuff over SDL? If so, I might just learn it now (at least, the parts I need to know to do this) and go that route.

@PoisonedV: So do I! After I finish this (which could take a long ass time), there are some other ideas on there that I'm contemplating trying to code. :D
 
Last edited by a moderator:
Vorporeal said:
@dflemstr: I was thinking of using OpenGL, but I don't actually know it yet. I've been planning on learning it for some time now. Do you think it would make a significant difference (in both speed and graphical quality) if I used that for the display stuff over SDL? If so, I might just learn it now (at least, the parts I need to know to do this) and go that route.
If I draw a simple white-filled surface on one of my low-end machines with SDL, I get 200 FPS.

If I draw a quad in OpenGL with the same white-filled texture, I get 3000 FPS. So, you should get about 15x the performance (depends on alot of other things too of course), especially if you want to 'rotozoom' or scale and rotate a texture, which the hardware can do for you in OpenGL (not sure if SDL does that, maybe SpriG does).

And, I mean seriously, there's not that big of a learning curve compared to SDL, you can pretty much just reuse most of your old coding styles anyways; look, for example, at the OpenGL tuts on the wiki:

http://pandorawiki.org/OpenGL_ES_1.1_Tutorial
 
Last edited by a moderator:
Looks good. I've done a bit of OpenGL stuff, but a lot of the more 3D aspects (the way you do rotations and the like) made me queasy. Doing purely 2D using OpenGL shouldn't be too bad, as you said.
 
Last edited by a moderator:
Alright. Here's the issue I'm having. It draws the perspective correctly (!), but only when the center of the viewport is below and/or right of the original center. If I try to move the center of the viewport either to the left of the initial center or above it, the clipping for the walls doesn't get updated, and they just draw in the wrong place. Here's my draw function:
CODE
void A3D_Level::drawLevel(SDL_Surface *screen, SDL_Rect &center)
{
SDL_Rect layerClip, baseClip;
baseClip.x = center.x - SCREEN_WIDTH/2;
baseClip.y = center.y - SCREEN_HEIGHT/2;
SDL_BlitSurface(background, NULL, screen, &baseClip);
for(int i=0; i<NUM_LAYERS; i++)
{
layerClip.x = (int) ((wall_cx - base_cx) - (baseClip.x * multiplier));
layerClip.y = (int) ((wall_cy - base_cy) - (baseClip.y * multiplier));
SDL_BlitSurface(wallLayers, &layerClip, screen, NULL);
}
}

I'm sure it's not the best draw function you've ever seen (and it's definitely not as efficient as it could be - I'm focusing on getting it working before making optimizations), but it does mostly work. center is the center of the viewport, where (0,0) is the top-right hand corner of the map (from a bitmap perspective, not a map data perspective). base_cx/base_cy are the centers of the floor bitmap; wall_cx[]/wall_cy[] are the centers of the walls. (wall_cx[0] is the wall level closest to the floor, wall_cx[NUM_LAYERS-1] is the wall closest to the viewer.) My problem is that if baseClip.x or baseClip.y is less than 0, the walls don't get updated and get drawn in the wrong place. The floor still draws correctly though.

Any ideas?

(tl;dr: If baseClip.x or baseClip.y is less than 0, layerClip.x or layerClip.y (paired appropriately) will be calculated as though baseClip.? is not less than zero, but equal to zero. No clue why that's happening.)
 
Last edited by a moderator:
A bit of advice, if I may. Do not use SDL if you have partially transparent layers blitting to other partially transparent layers. SDL's policy on this is to use the alpha channel of the destination layer, not to do an alpha combine. The result is predictably terrible.

You can't get any sort of hardware acceleration using alpha combine. You will have to write a software blitter to combine the alpha channels correctly (but slowly).

Use OpenGL/ES or some other graphics library, or be prepared to completely avoid alpha channel blitting to surfaces with an alpha channel.
 
I'm going to be switching it over to OpenGL in the future - I'm just using SDL for the time being to "prototype" it, as I don't know OpenGL yet and I don't really want to leave this hanging for a while to figure it out.

(Also, the way it's working right now blits a partially transparent layer to an opaque layer, then blits another partially transparent layer to the same opaque layer, etc. Is that still affected by the alpha combining issues you mentioned?)
 
Last edited by a moderator:
You could probably acheve that effect much more effecently by just drawing textured plains for the walls and using OpenGL's perspective to transform it.

Edit:

Quick test using the multiple scaled image technique in Quad-Ren.
textroom_screen.png


And the source code and image.
CODE

#include <quad-ren/quad-ren.h>

int main()
{
qr_renderer *renderer = new qr_renderer(vector2d_i(16, 9),
10.0 ,false ,vector2d_i(0, 0));

qr_resource_manager *res_man = renderer ->
get_resource_manager();

/* Background */
qr_sprite *background = new qr_sprite(res_man, 1);
background -> create_solid_frame(0, 0, 0, 255, 1);
background -> convert_data();
renderer -> set_bg_sprite(background);

/* Add some extra layers */
renderer -> set_total_layers(20);

/* Load room image */
qr_sprite *roomtex = new qr_sprite(res_man, 1);

roomtex -> load_png_frame(
"./textroom.png", 1);

roomtex -> convert_data();

/* Create quads */
qr_scene_node *roomlayers[10];
float size = 5;

for(int lay = 1; lay < 11; lay ++)
{
roomlayers[lay-1] = new qr_quad(res_man);
roomlayers[lay-1] -> set_sprite(roomtex);
roomlayers[lay-1] -> set_layer(lay);

size += 0.1;
roomlayers[lay-1] -> set_size(vector2d_f(size,size));
}

/*main loop*/
while(renderer -> run())
{
}

/* clean up */
renderer -> drop();
}


textroom.png
 
Last edited by a moderator:
That's more or less what I'm doing. The reason why my draw method is more complex is because it's shifting the various layers around so that the center of the window is the camera, and it looks straight down on the scene.

Well, I found out the source of my problems.
CODE
SDL_BlitSurface(background, NULL, screen, &baseClip);

When I do this, if baseClip.x or baseClip.y is negative, after this, it will be set to 0. It's a bit of a pain, but I solved it easily by just copying baseClip before the blit, using the copy, then using the original to calculate the positions of the wall layers.
 
Last edited by a moderator:
Alright, really annoying problem here. I'm trying to compile a non-debug (release) version of the binary so that I can distribute it to a few people. Whenever I switch from the Debug configuration to the Release configuration, the binary doesn't work correctly. I've narrowed it down to the fact that the Debug configuration has the /RTCs flag (Runtime checking for Stack frames), and the Release configuration doesn't. If I take the Release configuration and turn on that flag (and turn off all sorts of other optimization and whatnot flags), the problems that the Release binary was having disappear. Any ideas? You would think that simple runtime checks wouldn't make the difference between it working properly or not...

EDIT: I'm using Visual C++ 2008 Express Edition, in case that makes any difference.
 
Last edited by a moderator:
Alright, here's real news. I sorted out all the various (REALLY ANNOYING) problems I was having, and got the camera movement all sorted out. It looks decent, and the walls are actually starting to take some three-dimensional shape. I put together a small zip file with the files in there if anyone wants to try it out.

Everything's up on my blog - I'll be using that to document my progress in more detail, but I'll keep posting here as I hit roadblocks or make noteworthy progress. You can find my blog at:
CODE
http://saucepansoftware.wordpress.com
 
Last edited by a moderator:
Good progress! I was really keen to see it in action, but it won't run. XP error message:

"The application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem."
 
Back
Top