NDS Framework (in C)

Earlier I was planning a release 2 weeks ago on Sunday… But I really needed much more time, yesterday I finally got it working: my NDS Framework.

Since the whole blog is to give people more info about NDS programming and making it easier to program, I could just make a game like everyone does, but I’ve chosen to create something useful for almost everything you want to create on your NDS: A framework.

My framework works using a parent child concept (just like HTML) in order to position elements quickly to there positions. This way you can easily create a button on the right bottom side of your screen without calculating with pixels, it’s all done by the program!

Taken the above example: “You want to create a button on the right bottom side of the screen”, you will first have to create a screen to render on:

// Create a screen (width, height, backgroundimage (can be NULL))
struct CElement *screen1 = CElementCreateScreen(256, 192, backgroundimage);

// Since I don't have a button element yet, we will draw a squire
// It has the properties (RenderOn, leftOffset, topOffset, width, height)
CElementCreateSquire(screen, -1,-1,100,50);

If the leftOffset will be lower than 0, it will render it on the other side of the screen (the right side), the same counts for the topOffset. The width and height are 100px by 50px.

Another example can be found over here: https://iepro.wordpress.com/2010/01/14/create-an-easy-interface/ where you can see it can also automatically scale (like: width = 100%) all sorts of elements by giving it a width of 0 or a height of 0. A negative width or height will create a rightOffset, so if you want to position something with a border of 5 px, you can do this:

CElementCreateRectangle(screen, 5,5,-5,-5);

I’ve created a screen, what’s next? Well now the program has to calculate the real width, height, offsetLeft and offsetRight of the element. It’s done using the same meganism that DOM is using, by looking to the parent of the element. This is because all elements are positioned relatively to their parents, for example, you’ve created a container (= a special element that can hold multiple elements) on the bottom right of the screen. If you will draw a Squire, it will be drawn on the bottom right section (so relatively to the container where it’s in). To calculate all this, you only have to call the next line:

CElementSetProperties(screen1);

Ok, so now you’ve got a screen holding elements, but you want to render it on one of the two screens of the NDS, this is what you will do to get that working:

CElementDraw(screen1, video_buffer1);
CElementDraw(screen1, video_buffer4);

It will now render my virtual screen to both screens of the NDS. This way you can make multiple screens and load them in memory, and when you need them, you only have to execute CElementDraw(screen_settings, video_buffer4); to get it working!

Is there more?

Well since a framework is never done, and I am limited to time, I included the following things in this framework:

  • The auto calculation of elements (biggest part of the code)
  • A lookup element to see on what element is pushed using CElementAt(screen1, x, y)
  • An element to draw a triangle
  • An element to draw a rectangle
  • An element to draw a line
  • An element to draw a circle
  • A List “class” to create dynamic arrays
  • A function to remove a bunch of elements (so if you want to delete screen1, you can just: CElementRemove(screen1) and it will remove all other elements with it! And release there pointers šŸ˜‰ )
  • A draw function to create a AntiAliassed line using the Xiaolin Wu algorithm (echter deze kijkt ook echt naar de achtergrond om de anti aliassing kleur te genereren)
  • A draw function to create a Circle (not anti aliassed, since it costs 1000 lines of code to get that working)
  • An element that can contain multiple elements
  • An element that lets you devide a screen in to multiple sections (sortof a table)

Things like text elements aren’t implemented, but you can easy implement a Element by looking to my code. The only thing you really have to create is a function to draw it on your screen.

Example

	prep();
	
	// Create a virtual screen
	struct CElement *screen1 = CElementCreateScreen(256, 192);
	// Create a container fill it to the whole screen (width: 0, height: 0)
	struct CElement *container = CElementCreateContainer(screen1, 0, 0, 0, 0);
	// Split the screen in two sections vertically (and add it to the container)
	struct CElement *splitterY = CElementCreateSplitterY(container, 0, 0, 0, 0, 2);
	// Split the screen in three sections horizontally (and add them to the above splitter)
	struct CElement *splitterX1 = CElementCreateSplitterX(splitterY, 0, 0, 0, 0, 3);
	struct CElement *splitterX2 = CElementCreateSplitterX(splitterY, 0, 0, 0, 0, 3);
	// Add some elements to it:
	CElementCreateRectangle(splitterX1, 0,0,0,0);
	CElementCreateTriangle(splitterX1, 0,0,0,0);
	CElementCreateRectangle(splitterX1, 0,0,0,0);
	CElementCreateRectangle(splitterX2, 0,0,0,0);
	CElementCreateCircle(splitterX2, 0,0,0,0);
	struct CElement *rect= CElementCreateRectangle(splitterX2, 0,0,0,0);
	
	// Set properties & draw
	CElementSetProperties(screen1);
	CElementDraw(screen1, video_buffer1);
	CElementDraw(screen1, video_buffer4);
	

	wait(1000);
	
	CElementRemove(splitterX2);
	splashImage(video_buffer4, (u32 *)iepro_fun_img_bin);
	CElementDraw(screen1, video_buffer4);

Changelog

  • Updated CDraw.h/.c + CDrawElement.h/.c; renamed Squire to Rectangle (since it is a rectangle, and squire isn’t spelled correctly
  • Added negative left / top to become the right offset like posted above

Download

The download package will have 2 folders, C and C_NDS, the C is to easily debug (without using NDS related code), if compiled you can see exactly what it is doing. The C_NDS is the same package + NDS related code to create a NDS rom.

[ Download ]

Advertisements

One Response to NDS Framework (in C)

  1. contrechoc says:

    Pretty impressive!
    Good to choose a subject you apparently like: making frameworks. Investigating ordering principles. You evidently mastered the pointer arithmetic without any problems.

    Also your “plain c-mirror” is exactly why i introduced the parallel way (either using notepad or devcpp). Much easier to debug!

    My compliments for immediately thinking of garbage collection, freeing your splitter pointers.

    Just a few remarks anyway:
    I imagine “squire” must be “square”, this for our English friends :-)… to make it more comprehensible.

    Not only frameworks are never finished and can always be improved, frameworks need a terrible follow up: writing the *** manuals (nobody will ever read)…

    about the name (of the variable): video_buffer4 in
    CElementDraw(screen1, video_buffer4);
    this can be made more clear with a #define BUFFER(n) and likewise #define SCREEN(n)

    At the moment the prep() and the main() seem to be cluttered with concepts which are of the same kind.

    The first thing I did was putting

    struct CElement *screen1 ;
    struct CElement *container;
    struct CElement *splitterY;
    struct CElement *splitterX1;
    struct CElement *splitterX2;

    in the header prep.h, then all the prepstuff in the main in a method “void prepFrameWorks();” in the prep.c.

    Now all is available for the run.c

    In the while loop in run.c i made things like removing and adding elements on touch positions. Then (at this moment of the framework) you have to dive into the code, what does “CElementRemove” really means, does it throw away the pointer? Or does it just remove the elements?

    Removing splitter2, (like the example provided) two times also removes splitter1, (linked list?).

    No problem though, working like this with your elements all things in your framework will be changed around many times to get a “good look and feel”. At this point feedback of user experience is becoming important.

    In general: a very good exercize!

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: