Editor: Level prefetching!

Messages are moved here (should anyone ever want to see them again) once they are no longer applicable to the current version (e.g. suggestions that have been implemented or bugs that have been fixed).

Moderator: George Gilbert

Forum rules
Please read the Forum rules and policies before posting.
Post Reply
Paradak
Novice
Posts: 19
Joined: Thu Sep 21, 2006 5:16 pm
Location: Montréal, Québec, Canada

Editor: Level prefetching!

Post by Paradak »

In the editor, it seems that every time I change levels, the editor "loads the level".

Just how much memory space is needed to save the entire dungon anyway? The whole dungeon should fit in memory. So:

a) When I go to another level, then come back, the level should not be reloaded, but simply kept in memory, because it already is there.

b) When I don't do anything in the editor, it could start loading the other dungeon levels "in the background" (unobstrusively -- without freezing up for a few seconds when I will hit a key to do something else), so that when I go to a level I don't have to wait.
---
L'imagination, c'est la mémoire du possible.
User avatar
George Gilbert
Dungeon Master
Posts: 3022
Joined: Mon Sep 25, 2000 11:04 am
Location: London, England
Contact:

Post by George Gilbert »

The editor (or in fact the actual game) isn't doing anything related to the file when you swap levels - it's already all loaded into memory.

What's taking the time is the *drawing* of the level - specifically blitting out tens of thousands of bitmaps to screen. For a large level (e.g. DM-IIs thicket), or on a slow machine, that can take a few seconds.

If it's a problem for you, then you can turn off the representation of items in the dungeon as bitmaps (it's one of the options on the view menu IIRC), or of course you can reduce the zoom size so there's less to draw in the first place!
Paradak
Novice
Posts: 19
Joined: Thu Sep 21, 2006 5:16 pm
Location: Montréal, Québec, Canada

Post by Paradak »

I don't have a "slow" machine. I don't have the latest "bomb" either.

But I'm convinced of one thing: displaying 2-D data on today's machines should be near-instantaneous.

There are a lot of ways to speed this part.

First, whats the deal with 'tens of thousands" of bitmaps?

A typical dungeon has about 1000 squares. You mean you have to manipulate apprx 10 bitmaps per DUNGEON SQUARE? Are you telling me that you are actually computing from scratch everything from the BASE bitmaps? No wonder its so slow!

Ask yourself this: Just how many DIFFERENT bitmaps are displayed? Ask yourself how you could do the computing you're doing on your bitmaps ONCE PER DIFFERENT bitmap instead of "everytime". Divide and conquer! Separate the computing steps. Do you really need to do all the work from the unzoomed images? OFr could you first reduce each image you need, and only if they that wasn't already done before during this instanciation of the program, and THEN copy those "new source" images in the destination array?

Once you've computed ONE bitmap, just keep it's already-iconized-image around for all other instead of that bitmap will speed things up greatly. Then copying from a 4 times smaller image means not only 16 times less data to move around, but also less operations on the data, too (because it is ALREADY iconized and thus you don't need to recompute the zooming every time). A computer has only a VERY limited amount of regstry in CPU where it can put data, so the more you chew up the work out for it, the easier (i.e. faster) it runs.

Anyway, blitting zoomed bitmaps like this should be lightning fast. I did this programming optimization step once at work at it provided 100+ times faster ROTATIONS of objects. Now, with static, non-rotated bitmaps, this should really be a laugh.

Use the following method:

Determine current zoom factor for the various lements (for example, the floor bitmaps aren't necesseraly zoomed at the same factor as objects).

Now, determine the pixel skip value vector for each possible zoom levels. Since everything is square, this vector is the same for both horizontal and vertical.

PRECOMPUTE which columns/rows will be displayed for the maximum size bitmap. for example, for a zoom factor such that 32 pixels of bitmap will be displayed on screen using 6 pixels, then the zoom factor is 5.4, and my vector would look something like:
0,5,11,16,22,27,32,etc.
(i.e. 2nd position = 2 * 5.4 = 10.8 rounded to 11) in short, precomputing where each "closest pîxel" will fall in advance.

Then accessing each destination-color pixel is only a matter of finding the offset in the index vector to get the needed position in the bitmap.

I call a reduced bitmap its icon. But don't create separate images for all icons. This is because allocating a memnory, even a tny one, takes, relatively speaking a HUGE amount of time, CPU wise. Heck, creating your own heap is WAY faster than using the default rutines. And for "fixed size" elements like sets of bitmaps all of the same size, its definitely the way to go.

Instead draw directly all icons directly inside one HUGE IMAGE of standardized "multiple-of-two" width, keeping for each image its total byte offset in the big image. I call this big image (several in fact, one for each icon size) my "workbench". Such images can be pre-computed with a timestamp and saved in a file so that it doesn't have to be produced every time the editor is started.

Image operations should not be of the type:

For X=0 to Width
For Y = 0 to Height
Destination (X)(Y) = Source (X)(Y)
Next Y
Next X

This is very simple to code, easy to "rad and debug", but... it is a common programing technique mistake made by many programmers!

Use this instead:
(remember to put Y before X in vectoring matrix operations!)

Blitting a Width by Height rectangle from Source to Destination:
(Check cases if Width or Height are zero)
Pointer to First Source Pixel = S
Pointer to First Destination Pixel = D
SW = SourceTotalWidth
DW = DestinationTotalWidth
EndPointer = S + ( Height * SourceTotalWidth )
SourceSKip = SourceTotalWidth - Width
DestSKip = DestinationTotalWidth - Width
While S different than EndPointer
EndLinePointer = S + Width
While S different than EndLinePointer
Content of D++ = Content of S++
EndWhile
S += SourceSKip
D+= DestSkip
EndWhile

Note that even though the pointers seem to be able to attain values that ccould, if dereferenced, mean invalid memory access voilations, the while conditions means that the pointers are deferenced only when within valid image area.

This idea of minimizing the actual number of variables used, using extremely simple while logic conditions, precalcultating values OUTSIDE of loops, and working directly with pointers INSIDE the array rather than the array variable and dereferencing the X and Y corrdinates at each loop iteration is a common and very useful tool in programming and makes for INCREDIBLY fast code.

Ask yourself this: what is faster:

A) For X Y with Pixel = Image(Y)(X)

"Bob, go find where the house's entrance is. Then go to the first corridor, Then go to the first room in that corridor. Copy the paper there."
then
"Bob, go find where the house's entrance is. Then go to the first corridor, Then go to the second room in that corridor. Copy the paper there."
then
"Bob, go find where the house's entrance is. Then go to the first corridor, Then go to the third room in that corridor. Copy the paper there."
etc.
repeat until corridor Y / room X.

or

B) While P not at End loop with Pixel = Content of Pointer P++

"Bob, go find where the house's entrance is. Find the first corridor, find the first room."
"Go into the room in front of you. Copy The paper there. Move on to the next room"
then
"Go into the room in front of you. Copy The paper there. Move on to the next room"
then
"Go into the room in front of you. Copy The paper there. Move on to the next room"
etc.
repeat until you find the room number you're in front of is End.

A computer may work fast, but each operation takes time, even if a tiny bit. By giving the computer EFFICIENT sets of instructions, a program can go much faster, because it needs less commands to do the same job.


Now, its clear to have your image not in a window portable format but directly an array-in-memory is much faster. You'd be surprised how much FASTER direct memory manipulation is. Then, as a LAST step, bitblip your final image to screen.

Of course, drawing lines is similarly much faster if you use the Bresenham Line Algorithm directly into a memory buffer rsather than using the so-extremely-inefficient conventional drawing routines.

http://www.cs.helsinki.fi/group/goa/mal ... esenh.html

Tricks of the trade.

I can do it for you igf you like. In what language did you code?

patrick.rannou@sympatico.ca
---
L'imagination, c'est la mémoire du possible.
User avatar
George Gilbert
Dungeon Master
Posts: 3022
Joined: Mon Sep 25, 2000 11:04 am
Location: London, England
Contact:

Post by George Gilbert »

<Lots of tips>
Trust me - I am aware of such things; I do do this sort of thing for a living as well as in my spare time :wink:

The issue is that in the editor, it just uses the Windows BltBlt functions because it was quick to write and easy to do. What you've suggested is all very well and good for a 32bpp screen resolution - it's a whole lot more work to get it working for all possible screen depths. More importantly, it means that it "Just Works" for all variants of Windows without having to mess about through various layers in my code.

The game itself however doesn't run in a Window, uses direct manipulation of the screen and source bitmaps and so does use all of the things that you mention above (and many, many more!) which is why it's so much faster than the editor.

BTW - It does already pre-scale/zoom each bitmap as well!
Paradak
Novice
Posts: 19
Joined: Thu Sep 21, 2006 5:16 pm
Location: Montréal, Québec, Canada

Post by Paradak »

Heh, sorry... I should have guessed that I was talking to a pro...

;-)

Pax
---
L'imagination, c'est la mémoire du possible.
User avatar
Sophia
Concise and Honest
Posts: 4240
Joined: Thu Sep 12, 2002 9:50 pm
Location: Nowhere in particular
Contact:

Post by Sophia »

Doing the whole thing with GDI is just George's way of encouraging everyone to poke around in the text files instead. :P
User avatar
Des
Um Master
Posts: 461
Joined: Wed Jun 11, 2003 11:58 pm
Location: Southampton, UK

Post by Des »

No problems on my 3GHz dual-core PC. It's a mere 1000 times faster than my first computer (a Spectrum with a 4MHz processor). Moore's law is our friend :D
Paradak
Novice
Posts: 19
Joined: Thu Sep 21, 2006 5:16 pm
Location: Montréal, Québec, Canada

Post by Paradak »

Its our friend only until it catches up with our brain, Des. After that, it'll be our enemy...

(Terminator flashbacks...) ;-)


Pax.
---
L'imagination, c'est la mémoire du possible.
Post Reply