0
\$\begingroup\$

I would like to create a basic 2d graphics program to do very simple editing of in game assets.

My question, starting out how could I represent the canvas?

Let's say I know i'll need a canvas 512x512 pixels in siz, each pixel can be up to 256 colors. I can design a pixel as a struct with x,y,z coordinate and the canvas will be a 2d array or something that will hold each of those pixels.

That's a very basic way to model the drawing area, next how do I actually make that view so if I say put red at position 100x100 on my array it'll show up on screen?

Thanks in advance.

\$\endgroup\$
  • 1
    \$\begingroup\$ Why would the struct have the x,y,z coordinates? First of all, isn't this a 2d game? Secondly, can't you just use the array index as the coordinates? ie. canvas[20][30] = COLOR_RED; would be setting the pixel at (20, 30) to red. \$\endgroup\$ – lewisjb Jun 2 '15 at 23:20
  • \$\begingroup\$ I suppose you could use Z as part of a depth buffer type system...but as for displaying it to the screen, you need to look into how windows work in C++, etc. or use a library (which would likely already have graphics support). \$\endgroup\$ – CodeNMore Jun 3 '15 at 0:01
1
\$\begingroup\$

I would understand a level/map editor but use one of the many available image/photo editing software to create/modify your assets is better (IMHO). Also it will save you time, as image editors are full and complex projects in themselves and develop one, with serious and useful features, will take as many effort and time as the game itself. My advice is not to impose yourself such a workload.

GIMP is a good and free tool for that.

You have also paint.net

To support the loading of the assets in the game, BMP and GIF formats are not a challenge. BMP specs from Wikipedia are enough to support the most common, if not all, the variations of the BMP headers that the tools you decide to use will generate. There are libraries to save development time if you prefer. You probably don't need GIF.

PNG, and you probably want it, are a bit more complex. I recommend a library.

JPEG, maybe you don't need it but it will be nice to support, will surely be a challenge so use a library.

This library support all those formats: http://freeimage.sourceforge.net/


You can model a Canvas interface to encapsulate a pixel buffer in RAM or a DirectDraw Surface. Here an idea:

// Declare functions as virtual or abstract if
// you want only an interface to derive various implementations
class Canvas
{
    public:
    void moveTo (int x, int y);
    void lineTo (int x, int y);
    void draw (int x, int x, Image* src);
    void draw (int src_x, int src_y, int dst_x, int dst_y, Canvas* src);
    void draw (int src_x, int src_y, int dst_x, int dst_y, Image* src);
    void* lock (); // Give direct access to pixels
    void unlock ();
    PixelFormat* getPixelFormat (); // you need this info if you use lock()
};

Even if you decide to follow my advice on not to use time in developing an own image editor, you may still find value in a Canvas API, you can use it in your game engine, for example, not only in an image editor.


How can you represent the Canvas pixels?

If using a DirectDraw Surface, or its equivalent in other APIs, you will use the DirectDraw functions to create the surface, and to present them to visible portion of the screen. You will have to pin some tabs in your web browsers containing the DirectDraw documentation.

You can create the surface in the Canvas constructor or pass a pointer to a surface in one of the Canvas constructors.

Some functionality, like drawing lines, you will have to implement yourself. Usually, this involves to lock on the surface, then access the pixels to apply your line drawing algorithm of choice, then unlock the surface.

If using a pixel buffer in RAM, for a software renderer, just create a char array in the canvas constructor or pass a pointer to an already created one.

Tip: as many APIs out there do, do not use multidimensional arrays, it is better to use a single dimensional array where all pixels are contiguous in memory, maybe with padding at the end of each scanline. If you want the commodity of a multidimensional array, you can add, to your Canvas interface, a function like this:

// will return a multidimensional array
// of pointers to the first pixel of each scanline
void** getScanLines ();

By using the same pixel representation that the potential APIs with those your game engine will have to interact you save having to do expensive format conversions later.


To create and present surfaces using old DirectDraw API: http://www.codeproject.com/Articles/2370/Introduction-to-DirectDraw-and-Surface-Blitting

Note: old DirectDraw code tend to fail in modern platforms due to headers change. Don't panic, just search each error and you will probably find a solution, usually involving changing an #include or add a define in your project compiler parameters.

Alternatively, on modern Windows OSes, you can use Direct2D: https://msdn.microsoft.com/en-us/library/windows/desktop/dd370990%28v=vs.85%29.aspx

To draw a bitmap in memory using old OpenGL fixed pipeline (everything else, like drawing lines, you will do by software using your Canvas interface): http://www.glprogramming.com/red/chapter08.html

2D Sprites with OpenGL, better than previous approach, hardware accelerated: http://www.gamedev.net/page/resources/_/technical/opengl/rendering-efficient-2d-sprites-in-opengl-using-r2429

To create a drawable area in a window using GDI and draw a bitmap into it: http://www.winprog.org/tutorial/bitmaps.html

Line drawing algorithm: http://en.wikipedia.org/wiki/Line_drawing_algorithm

Blit/Draw algorithm: just copy the pixels to the correct place, doing format conversion if needed. Tip: avoid format conversion by converting your assets to your current screen pixel format when loading them, this is specially needed if you develop a software renderer to improve performance of the game.

Blit/Draw algorithm with scaling: if using OpenGL or Direct3D this is very easy to do. Take as an example the link on 2D Sprites with OpenGL. You will have the GPU doing everything for you. If done by software, it will be probably very slow, offer "nearest-neighbor" as an option to allow the game to run in slower hardware.


Why 256 (probably indexed) colors?

The GIMP can create and edit (and convert to other formats) such images.

You may decide to store sprites like 256 colors, 1 Byte per pixel, bitmaps to save storage, but that does not mean you need to work with them during game execution. Just get a library that understand the format and load them and apply any required pixel format conversion to get the same format as the current screen configuration. Having the assets in that format does not imply that you are forced to leave them as they are once loaded.

\$\endgroup\$
  • \$\begingroup\$ Thank you this was a very detailed answer. Although I am not trying to make an image editor like photoshop or gimp, I want to create a simple 2d animation tool something akin to dragonbones but w/o needing to use flash. Just a way to take in images and edit their position, rotation, scale, alpha, etc. The drawing API is there to make simple geometry or selection of certain parts of the image. \$\endgroup\$ – steffan Jun 3 '15 at 7:18
  • \$\begingroup\$ Then I didn't understood part of your question. I took "do very simple editing of in game assets" as do some image editing. Sorry, I'm not a natural English speaker. \$\endgroup\$ – Hatoru Hansou Jun 3 '15 at 14:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.