[PC C++] DirectX Help

Got questions? Got answers? Go here for both.

Moderator: MaxCoderz Staff

User avatar
thegamefreak0134
Extreme Poster
Posts: 455
Joined: Mon 23 Jan, 2006 10:09 pm
Location: In front of a Computer, coding
Contact:

[PC C++] DirectX Help

Post by thegamefreak0134 »

I want to create a game for windows. As such, I have no real knowledge of DirectX. I want the engine to be entirely 2D based, so I want to use DirectDraw7. I have found some very nice tutorials for C++ Direct Draw handling using visual studio 6.0. I would like to know of two tutorials, if such things exist:

(1) How do you do menus, file opening and closing, and the common open and close file dialogs in C++? (I know how to do this in VB.NET, just not in this older language.)

(2) Are there good directDraw tutorials that will walk me through the basics of doing windowed graphics simply and effectively?

Thanks for any help. For the record, I am creating a GB emullator.

-thegamefreak

PS: Is there any reason the error messgaes in the forum (the no title one, for instance) are completely black?
I'm not mad, just a little crazy.

DarkNova - a little side project I run.
User avatar
kv83
Maxcoderz Staff
Posts: 2735
Joined: Wed 15 Dec, 2004 7:26 pm
Location: The Hague, Netherlands
Contact:

Post by kv83 »

Is there any reason the error messgaes in the forum (the no title one, for instance) are completely black?
Yes. A wrong css-file. We're to lazy to fix it.
Image
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

DirectDraw is long dead. These days, it's Direct3D that's used (yes, for 2D work as well).

If you're creating a GB emulator, I can't see that you'd want any 2D graphics library at all though - just the ability to get/set pixels. You can do this trivially and quickly in VB.NET by locking a Bitmap, creating an Int() array containing the RGB values, then using Marshal.Copy() to dump the data back over.

If you're convinced that DirectX is the way to go, Managed DirectX has the Sprite class and so on for 2D graphics (part of Direct3D).

Likewise, if you're hooked on using C++, you can use C++/CLI which will give you access to the familiar System.Windows.Forms for your interface.

For the love of God, just don't use Visual C++ 6.
User avatar
thegamefreak0134
Extreme Poster
Posts: 455
Joined: Mon 23 Jan, 2006 10:09 pm
Location: In front of a Computer, coding
Contact:

Post by thegamefreak0134 »

I absolutely love the idea of re-drawing every single pixel every simgle frame using the bitmap control. However, I've found that this generally tends to be a little bit slow. Course, this comes from writing an emulator that I had update the screen every instruction for lack of a better way, but we'll get to that later.

I'm concerned with speed here, and figured DirectX would be much speedier than using windows controlls, which tend to bog themselves down in system stuff and message handling and other whatnot. I also wanted an easier way to do sprites, but I've since noted that it's possible to change the location of a sprite every scanline, so this woudn't work too well. Alas, windows it is.

Question then: I have Visual C++.NET. Is there a way to make a forms application with that program that will have some power behind it? I am really worried about speed issues, as they have troubled me many times with visual studio products. The only reason I was using 6.0 was because thats what I could get directX running under.

-thegamefreak
I'm not mad, just a little crazy.

DarkNova - a little side project I run.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

.NET applications are just-in-time compiled and as a result run just as fast as native code (theoretically, they could in fact run faster as the binaries that the CPU executes are optimised for your particular hardware). The output .exe files are compiled MSIL bytecode, but the first time they are run they are compiled to regular binaries and stored in the global assembly cache (GAC). You can even get your installer to perform this precompilation (via ngen.exe).

When you say redrawing every single pixel every single frame - it sounds like you were using the SetPixel/GetPixel functions. These are incredibly slow for a good reason - the application has to lock the bitmap, perform the calculations to place the pixel, write the pixel data, then unlock it again. This is terrible for performance.

The best way to do it is to lock the bitmap at the start of a frame (Bitmap.LockBits()). This returns BitmapData containing a pointer to the first pixel (Scan0). You can then use an unsafe { } block (this works in C#, not in VB) and write to it manually, (int* pointer = (int*)BitmapData.Scan0.ToPointer()) or write an array of pixel data to it using Marshal.Copy (works merrily in VB, no need for unsafe code). If you want me to write you a simple VB app to demonstrate that pixel access is fast in .NET, I can ;)

If you're still scared that .NET applications run more slowly than native applications, you could always write the core of the application in native C, compile it to a DLL then use P/Invoke to communicate with it from your .NET app.
User avatar
thegamefreak0134
Extreme Poster
Posts: 455
Joined: Mon 23 Jan, 2006 10:09 pm
Location: In front of a Computer, coding
Contact:

Post by thegamefreak0134 »

Well that might have something to do with it. I never figured on the actual pixel operations being slow, but I see your point. This applies of course even if the bitmp is in memory, no doubt?

I was using VB for the project I talked about, and would like to know the code for that, as it would help a bunch. Is this also fairly possible in C++? I don't know any C# at all. It looks similar, but I would still mess stuf up. (Or are the two interchangeable, from a backwards compatability point of view like C and C++ are?)

This will help a bunch. Thank you sooo much!

-thegamefreak
I'm not mad, just a little crazy.

DarkNova - a little side project I run.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

If you mean C++/CLI when you say C++ (which is the "C++ and .NET"), it is indeed possible. Thing is, C++/CLI is pretty much there for compatibility with legacy code and isn't as clean or easy to use as the languages designed purely for dealing with .NET (see also J#, the Java-esque language intended for Java users).

C# is not backwards compatible with C++ in the way that C++ is with C. It's a completely different language. It does, however, have the C-style 'look' (curly braces and whatnot).

There are not many advantages in using C# over VB, so it's really a case of picking which you're comfortable with. The two essentially compile down to the same MSIL. I find C# a bit cleaner and easier to read, but miss the ease of breaking out of nested control blocks in VB (see Exit Do/Exit For type things). VB is also more widely used, which is why Microsoft focus on it more (so it's easier to find things for).

The only real advantage I can think of in C# is the ability to use unsafe code, which is only really useful if you're using P/Invoke (for example, talking to C libraries or the Win32 API).

I'll rustle up a basic VB demo showing how to do efficient pixel access and post it tomorrow.
User avatar
Dwedit
Maxcoderz Staff
Posts: 579
Joined: Wed 15 Dec, 2004 6:06 am
Location: Chicago!
Contact:

Post by Dwedit »

One word: Allegro.

The allegro graphics library makes it easy to do stuff in Win32. Just create the window and menus and stuff using the win32 api, then attach allegro to the main window so it can draw there.
You know your hexadecimal output routine is broken when it displays the character 'G'.
User avatar
thegamefreak0134
Extreme Poster
Posts: 455
Joined: Mon 23 Jan, 2006 10:09 pm
Location: In front of a Computer, coding
Contact:

Post by thegamefreak0134 »

If it is possible to code something like this in VB and get the speed I need, by all means I'm up for it. I'm much more comfortable in VB anyway. I like C++ because it lets you do all the memory stuff a little better, but VB is so much easier to use.

While I'm on the subject, how do you get VB to ignore overflow errors? I'll need to work with values of the Byte Size, but when I subtract from a byte and it goes below -126, it gives me hell about overflow. I've been combatting this by using an integer type and then doing a couple of "if" checks to see if the value needs to rollover, but this is obviously slower. I really need to be able to use an unsigned byte type as well, but apparently when I try, it says all sorts of junk to the effect of it can't do anything. (like compare or add.) This is kinda why I like C++.

-thegamefreak0134
I'm not mad, just a little crazy.

DarkNova - a little side project I run.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Go into the project settings (Project->[project name] properties) and disable overflow checking.

Seriously, I haven't used VB in a while and going back to write this demo for you I can see why I switched to C# - it's a lot less fussy. ;) No harm in giving it (C#) a try - it took about half an hour from my VB background to feel comfortable in it, and the more languages you know, the better. Adding bytes and ignoring overflow isn't a 'feature' of C++, adding bytes and complaining bitterly about overflow is an annoyance of VB :P

Little VB demo for writing pixels quickly.

Allegro is probably overkill if you just want to get/set pixels; SDL is much more primitive and doesn't require the ugly END_OF_MAIN macro hackery.
User avatar
thegamefreak0134
Extreme Poster
Posts: 455
Joined: Mon 23 Jan, 2006 10:09 pm
Location: In front of a Computer, coding
Contact:

Post by thegamefreak0134 »

Once again, you are awesome. Thanks! I should have lots of fun with this project now. I'll come back and post a link if I get anything to work in it. (it will be titles, at most. I've done no coding yet, cause I've been having these issues and things.)

-thegamefreak0134
I'm not mad, just a little crazy.

DarkNova - a little side project I run.
User avatar
thegamefreak0134
Extreme Poster
Posts: 455
Joined: Mon 23 Jan, 2006 10:09 pm
Location: In front of a Computer, coding
Contact:

Post by thegamefreak0134 »

Wow. I'm sure this is a cool project, but it's from a newer version. I can see the source though. I see that you had to go off and be fancy with a ripple effect. Nice.

One question. I noticed you are using an integer type for the pixels (which I assume represents 32-bit pixels or something similar?). If I have the integer value for a pixel, how do I get R,G,B from that? Likewise, if I have R,G,B, how do I go back to integer? (This problem has plagued me for a while and prevented me from making my own paint-like apps.

Also, if I have any standard image, (yes, I know this is more than one question) will it open as an array with integer types for the values? If so, I can expand on a lot of other programs I have by using this.

Once again, you are wonderful. For once, I feel like I know what I'm doing now. Thanks!

-gamefreak
I'm not mad, just a little crazy.

DarkNova - a little side project I run.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Newer version? This is a VB8 project (Visual Studio 2005, .NET 2.0). If you want a VB7 (Visual Studio 2003, .NET1.x) project, I can do that, but it seems you got it to run anyway :)

Converting pixel colours (R,G,B) to an integer depends entirely on the pixel format you're using.

As you can see, I'm using the pixel format 32bppRGB, which is 32 bits (an integer) with R, G, B values in there.

Really, we only use 24 bits of that 32 bits - each colour component (R, G or B) is a byte, 8 bits.

If you've ever had experience with HTML colour codes, you'd know they are in hex - #RRGGBB style. This is the same as these values - for example, the integer &HFFFFFF in VB is white, just like #FFFFFF in HTML.

To stick all the different components next to eachother, we need to shift them along - 8 to the left for green, 16 to the left for red. You can do this through multiplication in VB, so:

Code: Select all

Dim R As Integer = 127
Dim G As Integer = 255
Dim B As Integer = 32

Dim RGB As Integer = B + G * 256 + R * 65536
Doing it the other way requires masking off the 8 bits we want to read, like this:

Code: Select all

Dim RGB As Integer = &HCC9933

Dim R As Integer = RGB \ 65536 ' Note use of integer divide \ rather than /
Dim G As Integer = (RGB \ 256) And &HFF
Dim B As Integer = RGB And &HFF
As for opening images as arrays - well, no, you can't do this directly.
You can, however, lock a Bitmap and read the pixel values into an array using Marshal.Copy - look at the Form_Load code in the demo, where it loads the "Beard" image. (It loads it from the project resources, you could also just use Dim MyImage As Bitmap = New Bitmap("myfile.jpg")).

One other thing to note - the arrays are not 2D arrays (so you can't use x,y coordinates directly), they are 1D. This means that to access an (x,y) element you need to go by x+y*width.
User avatar
thegamefreak0134
Extreme Poster
Posts: 455
Joined: Mon 23 Jan, 2006 10:09 pm
Location: In front of a Computer, coding
Contact:

Post by thegamefreak0134 »

Newer version? This is a VB8 project (Visual Studio 2005, .NET 2.0). If you want a VB7 (Visual Studio 2003, .NET1.x) project, I can do that, but it seems you got it to run anyway
Yup, I am indeed using the 2003 version. I'm on a school laptop (which I have to give back... :cry: ) so I don't have much option of upgrading. I can however open the .exe file cause the .NET framework is free to update, and I can view your source code, since it's basically a text file. I'll try to get our director to get the newer version for next years competition.


Really, we only use 24 bits of that 32 bits - each colour component (R, G or B) is a byte, 8 bits.
Just out of curiosity, are the un-used 8 bits there for an alpha channel?
You can, however, lock a Bitmap and read the pixel values into an array using Marshal.Copy - look at the Form_Load code in the demo, where it loads the "Beard" image. (It loads it from the project resources, you could also just use Dim MyImage As Bitmap = New Bitmap("myfile.jpg")).
Nice thinking. Of course, my primitive brain wouldn't assume it could go both ways... I'm assuming that opening a paletted image with the bitmap type simply converts it to a bitmap in memory? If so, say if I wanted to open a PCX file and see the palette, would I have to do that with file system commands and figure it out myself? (not necessary for this project, but rather as a side thing I'm working on)
One other thing to note - the arrays are not 2D arrays (so you can't use x,y coordinates directly), they are 1D. This means that to access an (x,y) element you need to go by x+y*width.
I do this frequently. In my other emulator, I have all of the pixels in a array so I can simply run through a loop to copy them to the screen. (or rather the buffer, but you know what I mean.) I figured this bit out actually with a program I worked on for the calc that could read the entire screen out to a list. Unfortunately, I soon discovered that (1) this made it huge, and (2) lists have limits. Still worked however. I even at one point had a system going that could recognize lines and such, thus reducing the file size dramatically. The downside? It took a good couple of hours to run, being written in pure BASIC. Ahh... good times. </ranting>

For the record, you have pretty much gained my personal respect forever. Thanks again.

-thegamefreak
I'm not mad, just a little crazy.

DarkNova - a little side project I run.
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

thegamefreak0134 wrote:Yup, I am indeed using the 2003 version. I'm on a school laptop (which I have to give back... :cry: ) so I don't have much option of upgrading. I can however open the .exe file cause the .NET framework is free to update, and I can view your source code, since it's basically a text file. I'll try to get our director to get the newer version for next years competition.
I'm using the freebie version of VB 2005, so if it's cost that worries you - http://msdn.microsoft.com/vstudio/express/ (if it's a rule 'no software may be installed', though, I fully understand). I strongly recommend using Visual Studio 2005 thanks to access to .NET 2.0, which offers many useful features (especially, IMO, generics).
Just out of curiosity, are the un-used 8 bits there for an alpha channel?
Not in my code, because the pixel format I'm using is 32-bit per pixel RGB (look at the Lock statements). The upper 8 bits aren't used at all. If I locked as 32 bit ARGB, on the other hand, the upper 8 bits would be for alpha. Seeing as I never write to alpha, you wouldn't actually see anything in the demo as every pixel would have an alpha of 0, fully transparent. ;)
I'm assuming that opening a paletted image with the bitmap type simply converts it to a bitmap in memory? If so, say if I wanted to open a PCX file and see the palette, would I have to do that with file system commands and figure it out myself? (not necessary for this project, but rather as a side thing I'm working on)
It depends entirely on how you lock the Bitmap for which values you read/write - as I lock using 32 bpp RGB, every time I read/write I'm getting 32 bpp RGB values, regardless of the image format (I daresay if you created the Bitmap as, say, a 16bpp Bitmap, you'd lose performance as it converted back and forth between pixel formats - make sure you create Bitmaps to match that format).

If using palettised images (GIF, PNG, PCX, some BMP &c) you can get access to the palette through Bitmap.Palette. Be warned, however, that if you want to change the palette on the fly you need to copy the palette, edit it, then write it back - editing it directly doesn't work. So:

Code: Select all

Dim B As Bitmap = New Bitmap("myfile.pcx")

Dim Palette As ColorPalette = B.Palette
Palette.Entries[0] = Color.Red ' Try to set colour 0 to red - won't work
B.Palette = Palette ' You need to copy it back like this after setting!
I do this frequently.
Just making sure ;)

Good luck!
Post Reply