GUI library for D

Adam D. Ruppe destructionator at gmail.com
Tue Apr 5 20:07:33 PDT 2011


Note: I just updated my simpledisplay.d. My color constructor
said b = c when I meant this.b = c... hence everything was yellow!
You can download again from the same place.

Nick Sabalausky wrote:
> I haven't benchmarked or even tested this, and heck, maybe I'm just
> a dinosaur, but for better speed and flexibility I'd recommend
> something more like what I've attached.

Yea, that does sound better. Though I have a few comments...

> The width is statically-known, so the compiler can optimize the
> index calculation from multiplication to shifts when appropriate.

One concern I have here is will it be an incompatible type with
dynamic widths? i.e. an image loaded from a file? (I'll be hopefully
cleaning up my png and bmp loaders in the near future to use with
this.)

Maybe it could use an interface to smooth that over.

I actually had a similar fight with myself over Indexed vs TrueColor
when writing the original thing. They really don't have compatible
interfaces. Sure, you could do some kind of putpixel(uint data)
for each of them, but it's not really the same.

So I think they should be separate types, with functions to convert
back and forth. (both conversions being lossy in their own way..
just because two palette entries have the same rgb values doesn't
mean the two colors are semantically the same.)


But, I'm getting off the point. Indexed images can be played with
later.

> The alpha channel opens the door for, well, mixing images using alpha.

Definitely.



> A major improvement, of course, would be to replace the GDI
> stuff with Direct3D 7 or 8 (there's no real need to require
> anything beyond those versions).

Now, I don't want to get too fancy.. especially since I've never
used directx, not even for hello world, and I don't think
performance will be too big of a deal.

But, I did do something similar with my D1 game lib. It uses
SDL for most its stuff, but I found that to be dreadfully slow
with anything beyond the simple, so I changed the output to
use OpenGL, set up to do 2d output. Only difference client code
wise was I had was I had to stop using putPixel - it was even
slower! But sprite rotation and blitting, lines, shapes, all that
stuff was sped up by huge, huge amounts.

And I got free alpha blending and gradients! It was a huge
benefit, ultimately very worth it.


So yeah, I think I would like to do something similar here too,
but since I have no experience with D3D it'll have to be low
on my own priority list. But I like the idea!



Now, the next thing I want to write up in here is some kind of
event handling. The idea is:

image.display(); // does what it does now - just make it work, and
                 // wait for the user to close the window.

This keeps it dead simple for a reporting use case. But, let's
think about some interactivity too.

In DOS, the pattern I used was something like this:

// initialize the program and the screen

while(still_going) {
    if(kbhit()) {
       char c = getch();
       // handle c
    }

    // draw your frame

    wait_for_next_frame();
}

// clean up



My D1 game code did something similar, but the loop was replaced
by a virtual class method and the wait was done by a system timer.
(And something too cool: instead of
checking the keyboard, it checked a joystick or keyboard, pretending
it always had a Playstation controller.

if(buttonWasPressed(triangle, 1)) // the 1 is player #1
   // react
if(buttonIsDown(square))
   // react

Then, if you had a controller plugged into the computer, it'd
just work, or you could be boring and use the keyboard, with
the keys mapped to the playstation names.

One of the IMO best parts was that the controller interface was
also network transparent, so any game that stuck to it could
be played online too. The way that'd work is the server sends
out state to everyone, random number seeds, etc. Then, all
controls were lagged a frame or two. If you pressed a button, it'd
transmit your action to the other players along with a timestamp.

Frame 20, you hit circle. It sends down the network "on frame 22,
send the event that player #2 pressed circle". Then, since everyone
has the same program and the same initial state, everyone sees
the same thing, without the game itself needing to know anything
about the network.

Of course, the lag could be slightly annoying, but meh, didn't
bother me. Besides, I can't complain too much about free networking!


Man, I wish I had more time to make games.

Of course, there were also keyIsDown, etc, too if you couldn't
use the controller interface, but it didn't get the automatic
networking or different players.



Wow, I'm off topic again. Anyway, for the event loop here, I'm
thinking something similar to how std.concurrency does it might
be a good approach: a bunch of delegates, matched to events by
their signature. Simple signatures could be accepted as well
as fancier ones.

// need to make a simple window separately here so it is persistent
auto win = new DrawableWindow(width, height);

// still use an image the same way. Alternatively, DrawableWindow
// could implement the same interface as Image, probably double
// buffering internally anyway, so pretty much same implementation.
auto image = new Image(width, height);

window.eventLoop(
   50, // first parameter is the timeout. can be 0 to only react
       // to events, but putting one in gives you an easy to use
       // frame pulse for drawing
   (int keyPressed) { // might be a struct KeyEvent rather than int
        // react to the key
   },
   (int x, int y, int mouseButton) {
        // react to a mouse click
   },
   () { // no params means your timeout happened, time to draw
        // draw your frame...

        image.display(win); // this overload uses the existing
                            // window and returns immediately
                            // rather than making and waiting
   }
   // might also offer a platform specific msg, wParam, lParam
   // so you could in theory do all of Win32 based on this same
   // framework
);



This way, you could whip something up right there and have a
simple little game all inside a couple dozen lines of main()
without needing any monster libraries in your project.

Wow, I think I really like this...


More information about the Digitalmars-d mailing list