Day 2 - C Learning ← Previous

Day 3 - Input/Output

The only Output system we’ll talk about for now is the basic text system... Next, we’ll see the different input methods : Pad, Stylus, and Keyboard etc....

Output : Text

Text is important for virtually EVERY single DS game. Imagine a game without speech or instructions. Creating your own text functions would be difficult, but that is what PAlib is for. PAlib ships with many handy text functions.

In order to initialize text, use PA_InitText (bool screen, u8 bg_select)

The first argument is the screen (1 = top, 0 = bottom), and the second is the background (0-3). Now, for every single text function using the same screen, it uses the same background.

Simple Text

Creating simple text is easy, or it wouldn’t be called simple text. Use PA_OutputSimpleText(bool screen, u16 x, u16 y, const char *text). The argument screen is the screen to use. x is the x-coordinate, in tiles(0-31). y is the y-coordinate, in tiles(0-23). text is, well, the text.

Here is some sample code...

void printText()
{
    PA_InitText(1,0);
    PA_SetTextCol(1,31,31,31);
 
    PA_OutputSimpleText(1,0,0,"This is an example");
}

If you want to erase some text, just overwrite it with spaces, like PA_OutputSimpleText(0, 0, 0, " “);

Box Text

Simple text may be useful, but often, it just doesn’t cut it. Sometimes, you need wrapping text, confined to a rectangular portion of the screen. That’s what PA_BoxText() is for. Its arguments are as follows:

 
    PA_BoxText(screen,basex,basey,maxx,maxy,"text",limit);
 
  • screen - the screen to use (0 or 1)
  • basex - the top left corner x of the box, in tiles.
  • basey - the top left corner y of the box, in tiles.
  • maxx - the bottom right corner x of the box, in tiles.
  • maxy - the bottom right corner y of the box, in tiles.
  • text - text to output
  • limit - the maximum letters to show at this time.

Basic usage of this function displays the specified text immediately.

To have slow-typing text use a loop to display the text, increasing the limit by one each time, so that it seems as if it is being displayed character by character. The following example code also recognises when to cease the loop... When the number returned does not change, it has stopped (either because there is no more text, or because the limit has been reached). At this point, it stops increasing the limit and exits the loop.

[NOTE: The following example has been copied from the Italian translation, as it seemed to be missing/deleted from here. Descriptive text and further examples need translating and pasting here also!]

#include <PA9.h>       // Include for PA_Lib
 
// Function: main()
int main(int argc, char ** argv)
{
	PA_Init();    // Initializes PA_Lib
	PA_InitVBL(); // Initializes a standard VBL
 
	PA_InitText(1, 0);  // Initialise the text system on the top screen
 
        u16 x=2;
        u16 y=2;
        u16 width=29;
        u16 height=15;
        u32 countletters=0;
        u32 limit=0;
        
        while (countletters==limit)
        {
          limit++;
          countletters=PA_BoxText(1, x, y, width, height, "So you see the text looks like it is being typed character by character...\n\n Oh, and line-break works too...", limit);
           PA_WaitForVBL();  
        }
 
	// Infinite loop to keep the program running
	while (1)
       {
        	PA_WaitForVBL();  
	}
	
	return 0;
} // End of main()
 

If you have a long speech, you need to know the maximum number of characters that can be outputed. In that case, use this formula...

u8 maxChar = (maxx - basex+1)*(maxy - basey+1);

It should work:-).

Advanced Text

Now that you have seen how to output some basic text on the screen, we’ll see what could be considered as the most important text function : PA_OutputText(bool screen, u16 x, u16 y, const char *text, arguments...). As you see, it’s not that different from the first simple text function, except for the arguments list, which is very important. It allows you to display the contents of variables or strings directly on the screen, which is really great for debugging !

You can take a look at the Text/Text example for some applications...

Displaying Integers

Here is some sample code displaying the Stylus’s position... (you’ll see how to use the stylus very soon...)

PA_OutputText(1,0,0,"Stylus X : %d   Stylus Y : %d", Stylus.X, Stylus.Y);

First thing you see, is the %d... it is used to display integers (s32...). If you put %d somewhere in the text, it’ll search for an argument in the arguments you gave (Stylus.X and Stylus.Y, here). If you have %d several times, it’ll take the arguments in the order of appearance... so the first ‘%d’ is for Stylus.X, the second for Stylus.Y, etc....

Displaying Floats

Displaying floats isn’t much different than displaying integers... There are just 2 things that differ :

  • Use %f instead of %d
  • Add how many numbers you want to be displayed after the period...

So you get something like this :

float test = 4.678;
PA_OutputText(1,0,0,"Float value : %f3", test);

See, not much harder ! This will display Float value : 4.678

Displaying Strings

The last thing to know is how to display strings... This is pretty useful, because you can for example integrate the player’s name in your text, and thus have a personnalized message ! Just use %s, for string !

So you get something like this :

char name[10] = "Mollusk";
PA_OutputText(1,0,0,"Hi %s", name);

See, not much harder ! This will display Hi Mollusk. One important thing : your string, which is basically an array of chars, MUST have as last character value a 0... if not, the text output will continue until it falls on a 0, which could take some time... So if you add letters one by one in a string, with like ‘a’, then ‘b’, etc... always add 0 at the end.

Text Color

There are 3 different ways to choose a text’s color :

PA_SetTextCol

You can, at any point, change the font’s color by using a simple function : PA_SetTextCol(screen, r, g, b). This can set the color as you want on 1 screen... ALL the text on that screen will have the same color, even if you wrote it before changing the color. What values are r, g, and b ??

  • r stands for red... It’s the red quantity in the color, from 0 (no red) to 31 (maximum red).
  • g is the same thing for green...
  • b is for blue...

Here are a few examples :

  • Blue : PA_SetTextCol(screen, 0, 0, 31)
  • Red : PA_SetTextCol(screen, 31, 0, 0)
  • White : PA_SetTextCol(screen, 31, 31, 31)
  • Black : PA_SetTextCol(screen, 0, 0, 0)
  • Grey : PA_SetTextCol(screen, 22, 22, 22)
  • Magenta : PA_SetTextCol(screen, 31, 0, 31)

You can check the Text/Text example, it uses it :-)

PA_SetTextTileCol

PA_SetTextTileCol is slightly different to PA_SetTextCol, because it does not change the existing text’s color... But it allows you to have different colors on the same screen (which is pretty nice :-P). The PAlib example is Text/TextColors

PA_SetTextTileCol(1, i); // Change the color on the top screen, values 0 to 9
PA_OutputSimpleText(1, 2, i, "Color test...");  // Screen 1 has different colors

PA_SetTextTileCol(1, n); sets the text color for the new texts to n... nothing less, nothing more. n can take values from 0 to 9 ( 0 = white, 1 = red, 2 = green, 3 = blue, 4 = purple, 5 = cyan, 6 = yellow, 7 = light grey, 8 = dark grey, 9 = black).

09/04/2006: I believe Mollusk has just added color defines to the lib:

  • Blue can now be accessed using TEXT_BLUE
  • Red can now be accessed using TEXT_RED
  • The same pattern follows

An example using PA_SetTextTileCol:

PA_SetTextTileCol(screen,TEXT_RED); //This will turn the text red

%cX

The last way to change a text’s color is to use the %cX input in your string, X being the color number (0-9, like right before). The nice part about this is that you can have multiple colors in the same string ! The examples comes from TextColors, once again :

PA_OutputText(0, 0, 0, "Color test...%c1another one, %c2again, %c3again...");

As you can see, just putting %cX changes the color (test on emulator if you don’t believe me :-P). It’s simple, easy, and simple, lol.

Custom font & text border

PA_lib allows you to customize the text font and the text border easily. You will need to import graphics to your project, and that’s where it becomes tricky, because it will involve some graphics conversion and if you are reading the wiki in the order, you should be a bit disappointed as you read this.

In fact, graphical data (like jpg images, gif, png...) are not directly compatible with the DS hardware. You have to convert those data into a raw format which can be understood by the DS.

Everything about converting data is well explained in the Sprites and Backgrounds tutorials. So, before you proceed, I suggest you to skip the Custom font & text border tutorial till you learned about Converting with PAGfx (day 4) and tiled backgrounds (day 5).

Custom font

Basically, a custom font is a tiled background, each tile representing a specific character. Here is a basic custom font layout:

The layout is very important, each character has its very own coordinate in this layout, so don’t mix them up (unless it’s voluntary). A character has the same size as a tile (8×8 pixels). You can edit this layout to make your own custom font.

For a more accurate editing, I suggest you to display a grid (8×8 pixels) in your favourite graphics editor, like this (zoomed):

One more thing to know about this layout, is how to differentiate capital from normal letters. In this example, capital and normal letters are the same. In fact, the first letter line is for capital letters and the second line is for normal letters.

you can use also PAFont to get you font ready to use without spend time and fatigue!

From now, you need to convert it into a tiled background. Here is the PAGfx settings:

#TranspColor Magenta
 
#Sprites :
 
#Backgrounds :
newfont.gif TileBg
 
#Textures :
 

Here we go for the code (assuming you have put your gfx in a directory named font):

// Includes
#include <PA9.h>       // Include for PA_Lib
 
#include "font/all_gfx.h"
#include "font/all_gfx.c"
 
 
 
// Function: main()
int main(int argc, char ** argv)
{
	PA_Init();    // Initializes PA_Lib
	PA_InitVBL(); // Initializes a standard VBL
	
	PA_InitText(0, 0);  // Initialise the normal text on the bottom screen
 
	// Load a custom text font on the top screen
	PA_InitCustomText(1,        //screen
	                  0,        //background number
	                  newfont); //font name
 
	// PA_OutputSimpleText is the fastest text function, and displays 'static' text
	PA_OutputSimpleText(1,                 // screen
	                    2,                 // X postion
	                    2,                 // Y position
	                    "Hello World !!"); // display a custom text on the top screen
 
        PA_OutputSimpleText(0, 2, 2, "Hi there :p"); // and a normal one on the bottom screen
	
        // Infinite loop to keep the program running
	while (1)
	{	
		PA_WaitForVBL();
	}
	
	return 0;
} // End of main()

As you can see, it’s very simple to use a custom font. You just have to initiate the text of a screen with PA_InitCustomText instead of PA_InitText. That’s all.

Tip: How to print out custom fonts by character.

Each slot on the font has an ascii id which is why there are a bunch of blanks before the default symbols and letters come in, well starting at 0 and working your way up you can reference each one by its ID like so:

PA_OutputText(screen, x, y, (char[]){65, 66, 67});

That will output ABC to the screen, and using this method you can call out any character from the possible 288 characters the PAlib font size allows

One thing that should be noted, however is that there are a lot of reserved special characters between 0-31 (the first row) so you should probably create your special characters 128 and so on.

-ObsidianX

Custom text border

Input : Pad, Stylus, Keyboard

There are basically 3 ways to input on the DS : using the pad (all the keys...), the stylus, or PAlib’s keyboard... A last method would be using the microphone, I guess, but we’ll talk about that later on, in the Sound tutorial...

Pad

Using the pad could hardly be easier ! It is automatically updated every frame, and a simple structure allows you to access it. The structure is named ‘Pad’, and it contains multiple structures, depending on the press type : Held, Released, and Newpress.

  • Newpress is when you just pressed the keys, stays at 1 for only 1 frame.
  • Held is by default to 0, passes to 1 when the key is held down
  • Released passes to one when the key gets released (was pressed and is no longer pressed...), stays at 1 for only 1 frame.

Each press structure then contains a list of all the keys :

  • Left, Right, Up, Down for the arrow presses...
  • A, B, X, Y for the ABXY keys
  • L, R for the left and right triggers
  • Start, Select for... start and select...

So, in the end, to check a key, you have Pad.Checktype.Keyyoucheck Checking if the A button is held down would mean looking at Pad.Held.A ! Pad.Released.A is when it gets released, and Pad.Newpress.A for a new press...

As you can see, this is easy. Here is a quick and sample code that doesn’t work but just to show how to use the keys :

if(Pad.Held.Up)
{
    MoveUp();
}
if(Pad.Held.Down)
{
    MoveDown();
}

Simple, isn’t it ?

Check out the Input/Pad example if you want...

Mollusk 29/11/2005 22:44

Stylus

The stylus works pretty much the same as the pad... It is automatically updated every frame, and uses a structure named Stylus (simple...) The different stylus variables are :

  • Held, Released, and Newpress, just like the pad ones...
  • X and Y, used for the stylus’s position

So here’s a basic code example :

if (Stylus.Held)
{
  PA_SetSpriteXY(screen, sprite, Stylus.X, Stylus.Y);
}

As you may guess, this simple code checks for the stylus press. If the stylus is held on the screen, it will position the top left corner of the sprite at the stylus’s position... Nothing much more to say :-)

Check out the Input/Stylusexample if you want...

Note by Phaezon: If you’re using PA_OutputSimpleText() (or any other related function), make sure you put a few spaces after %d, like so:

PA_OutputText(screen, tileX, tileY, "Stylus X: %d   ", Stylus.X);

Not doing this could lead to bugs which make you think that the stylus is COMPLETELY off (it said something like 964 pixels on mine) when it gets to double-digit and single-digit numbers. If I had 135 once and then I tapped where 34 is, I’d get 345, since the last number in the three-digit coordinate (the 135) is not overwritten (34 is, obviously, a two-digit number, so the third digit (5) has nothing to be overwritten by. The spaces will overwrite it and make it much more precise.

Keyboard

Using PAlib’s keyboard is really easy and simple, as you can see in the Input/Keyboard example...

To work, the keyboard must be loaded on a given background (numbers 0 to 3), different from the text background and any other one...

PA_Init();    // Initializes PA_Lib
PA_InitVBL(); // Initializes a standard VBL
	
PA_InitText(1, 0);  // Initialise the text system
	
PA_InitKeyboard(2); // Load the keyboard on background 2...
	
PA_KeyboardIn(20, 100); // This scrolls the keyboard from the bottom, until it's at the right position
	
PA_OutputSimpleText(1, 7, 10, "Text : "); 
	
s32 nletter = 0; // Next letter to right. 0 since no letters are there yet
char letter = 0; // New letter to write.
char text[200];  // This will be our text.
	
// Infinite loop to keep the program running
while (1)
{
	// We'll check first for color changes, with A, B, and X
	if (Pad.Newpress.A) PA_SetKeyboardColor(0, 1); // Blue and Red
	if (Pad.Newpress.B) PA_SetKeyboardColor(1, 0); // Red and Blue
	if (Pad.Newpress.X) PA_SetKeyboardColor(2, 1); // Green and Red
	if (Pad.Newpress.Y) PA_SetKeyboardColor(0, 2); // Blue and Green
		
	letter = PA_CheckKeyboard();
		
	if (letter > 31) { // there is a new letter
		text[nletter] = letter;
		nletter++;
	}
	else if ((letter == PA_BACKSPACE)&&nletter) { // Backspace pressed
		nletter--;
		text[nletter] = ' '; // Erase the last letter
	}
	else if (letter == '\n'){ // Enter pressed
		text[nletter] = letter;
		nletter++;
	}
		
	PA_OutputSimpleText(1, 8, 11, text); // Write the text
	PA_WaitForVBL();
}

I guess it’s a pretty complexe example (compared to the other ones...), so we’ll see that step by step.

It starts by a text init, because... we’ll need to display some text !

Then comes

PA_InitKeyboard(2); // Load the keyboard on background 2...
PA_KeyboardIn(20, 100); // This scrolls the keyboard from the bottom, until it's at the right position
  • The first function loads the keyboard on the bottom screen, on background 2... you can use any background from 0-3 that doesn’t have anything on it yet... The second one scrolls the keyboard in, just because it looks nice that way :-P It scrolls it in to position (20, 100), but you can set any position you want...
  • PA_SetBgPalCol(Screen, BG, PA_RGB(31,31,31)); is a function to change the background color. Screen should be 0 or 1 (0 for bottom), BG is for Background number (of the keyboard) (0-3) and PA_RGB is the color (0-31). This isnt used for the keyboard persé, but its the quickest way to change the background color.
  • PA_SetKeyboardColor(0, 1); is a function to change the keyboard’s color... just check the different values and use the one you like most...
  • letter = PA_CheckKeyboard(); is the most important function ! CheckKeyboard tests to see if you pressed a key with the stylus, and returns the keyboard key pressed in the form of a character, or 0 if not pressed...
if (letter > 31) { // there is a new letter
	text[nletter] = letter;
	nletter++;
}
  • Another important block... If the key was a letter, we’ll add it to the current text... and that’s one more letter in it, so nletter++ !
  • PA_OutputSimpleText(1, 8, 11, text); is the function to display the text we are outputting...

I skipped a few lines of code (the backspace and line return (\n is line return) because even though it’s in this code example, you’ll have to figure it out by yourself :-P

Compile and test the demo, even works on DualiS ! Enjoy !!

Shape Recognition

This last feature is pretty interesting... You can use it in 2 ways :

  • Using PAlib’s Graffiti-like recognition
  • Using your own custom shapes, to do something like Lost Magic or Pac-Pix

In general this method of text input is useless and just results in a headache the idea behind this hand writing input is rubbish and rarely works correctly who knows why some idiot wrote the code behind this as its of no use at all,and just demonstrates how rubbish the touch input can be,and as any users of the DS touch screens will know they are never 100% reliable as often many touch inputs are failed to get recognised and causes annoying problems when this is the only way available to play a game or application on the DS!

PA Graffiti

This code will allow you to collect letters using the Graffiti-like system... It will be improved over time. The code is based heavily on the keyboard example’s one, so it shouldn’t be too hard to figure it out. There are some obscure 8bit stuff you’ll see later on in backgrounds :-)

The code comes from Input/RecoGraffiti.

PA_InitText(1, 0);  // Initialise the text system on the top screen
PA_Init8bitBg(0, 0); // We'll draw the characters on the screen...
	
u16 *pal = (u16*)PAL_BG0;
pal[1] = PA_RGB(31, 31, 31); // colors...
	
PA_WaitForVBL();
 
u8 nletter = 0;
char text[200];  // This will be our text.
	
// Infinite loop to keep the program running
while (1)
{
	   
	if(Stylus.Newpress) PA_Clear8bitBg(0); // Reset the screen when we start a new character
	   
	PA_8bitDraw(0, 1);
	   	   
	char letter = PA_CheckLetter(); // Returns the letter !!!
		
	if (letter > 31) { // there is a new letter
		text[nletter] = letter;
		nletter++;
	}
	else if ((letter == PA_BACKSPACE)&&nletter) { // Backspace pressed
		nletter--;
		text[nletter] = ' '; // Erase the last letter
	}
	else if (letter == '\n'){ // Enter pressed
		text[nletter] = letter;
		nletter++;
	}
		
	PA_OutputText(1, 2, 2, text); // Write the text
		
	PA_OutputSimpleText(1, 0, 10, "Draw a PAGraffiti letter to have it recognized by the system...");
		
	PA_WaitForVBL();
}
 

Now, let’s it part by part...

PA_InitText(1, 0);  // Initialise the text system on the top screen
PA_Init8bitBg(0, 0); // We'll draw the characters on the screen...
	
u16 *pal = (u16*)PAL_BG0;
pal[1] = PA_RGB(31, 31, 31); // colors...
	
PA_WaitForVBL();
 
u8 nletter = 0;
char text[200];  // This will be our text.

This part just initialises the text and a drawable background, you’ll learn more about that later on...

  • nletter = 0; Will be used to count the number of letters
if(Stylus.Newpress) PA_Clear8bitBg(0); // Reset the screen when we start a new character   
PA_8bitDraw(0, 1);

This is some code used to draw on the screen and erase it if you press the stylus again... Later on, later on...

char letter = PA_CheckLetter(); // Returns the letter !!!

Now we’re getting to it ! This code checks the letter !!! Must be called every frame in order to work (like the keyboard, like the keyboard...) Returns 0 if the letter isn’t finished yet...

And the rest of the code is IDENTICAL to the keyboard example, I will not talk about it again.

.

Custom Shapes

What’s really nice with this system is that you can have custom shapes ! It’s just a matter of seconds to add them, and this example is there to show you...

The code comes from Input/RecoAddShape

PA_UsePAGraffiti(0); // Do not use the provided Graffiti shapes...
	
PA_RecoAddShape('a', "AAAAAAAAAAAAAAA"); // Straight right-going line
PA_RecoAddShape('b', "111111111111111"); // Straight left-going line	
PA_RecoAddShape('c', "IIIIIIIIIIIIIII"); // Straight up-going line	
PA_RecoAddShape('d', "999999999999999"); // Straight down-going line			
		
PA_WaitForVBL();
 
	
// Infinite loop to keep the program running
while (1)
{
	   
	if(Stylus.Newpress) PA_Clear8bitBg(0); // Reset the screen when we start a new character
	   
	PA_8bitDraw(0, 1);
	   	  
			   
	char letter[2]; letter[1] = 0;
	letter[0] = PA_CheckLetter(); // Returns the letter !!!
		
	if (Stylus.Released){ // only show if released
		PA_OutputText(1, 2, 7, "Shape Recognized : %s", letter); // Letter recognized
		PA_OutputText(1, 0, 1, "A for right, B for left, C for up, D for down");
	}		
		
	PA_OutputText(1, 4, 22, "Shape : %s", PA_RecoShape); // Write the shape string
		
	PA_OutputSimpleText(1, 0, 10, "Draw a PAGraffiti letter to have it recognized by the system...");
		
	PA_WaitForVBL();
}

Now the comments :

//PA_UsePAGraffiti(0);// Removes the graffiti recognition, so only our shapes will be taken...
PA_RecoAddShape('a', "AAAAAAAAAAAAAAA"); // Straight right-going line
PA_RecoAddShape('b', "111111111111111"); // Straight left-going line	
PA_RecoAddShape('c', "IIIIIIIIIIIIIII"); // Straight up-going line	
PA_RecoAddShape('d', "999999999999999"); // Straight down-going line	

This is where we give PAlib the new shapes to recognize... It might not seem very intuitive, given... How did I obtain them ? By running this rom, lol. You’ll see a little bit further. All you need to understand is that a shape is defined by 2 parameters :

  • The letter (or number 1-255) which will be returned when it is called
  • Its string, given by this rom... When drawing a shape using this code, the string is shown, allowing you to copy and use it ! :-P Nice !!

The rest of the code is actually very similar to the previous example, so I won’t comment it more. Only 1 line remains important :

PA_OutputText(1, 4, 22, "Shape : %s", PA_RecoShape); // Write the shape string

PA_RecoShape is the string in which the shape was stored... That’s how I got the 4 shapes we put right before !

And that’s it, the program will recognize the shapes we asked :-P

Shape Infos

I lately added a third example to go with the latest version of the lib... It adds informations to shape recognition. This information is basic but can be usefull in certain contexts. The information is stored on Stylus.Released in a structure called PA_RecoInfo. It contains :

  • Length, the total length of the drawing in pixels
  • startX and startY, the position of the first point. This can be used in a game to determine if a given object/sprite is activated, for instance.
  • endX and endY, the position of the last point.
  • minX, minY, maxX, and maxY which delimit the shape. This can be used to know how big the shape is, and find it’s center.
  • Angle, the global angle between the first point and the last one... Not always usefull.

Here’s the code using it, which is just a copy/paste of the Custom Shape one, so I’ll just post the modified stuff... All this is in the infinite loop...

if (Stylus.Released){ // only show if released
	PA_OutputText(1, 2, 7, "Shape Recognized : %s", letter); // Letter recognized
	PA_OutputText(1, 0, 1, "A for right, B for left, C for up, D for down");
			
	// Use all the info to draw the shape outline, start and end...
	// Rectangle around the drawing zone
	PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.minY, PA_RecoInfo.maxX, PA_RecoInfo.minY, 2);
	PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.maxY, PA_RecoInfo.maxX, PA_RecoInfo.maxY, 2);		
	PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.minY, PA_RecoInfo.minX, PA_RecoInfo.maxY, 2);		
	PA_Draw8bitLine(0, PA_RecoInfo.maxX, PA_RecoInfo.minY, PA_RecoInfo.maxX, PA_RecoInfo.maxY, 2);
			
	// Plot points on the start and end :
	PA_Put8bitPixel(0, PA_RecoInfo.startX, PA_RecoInfo.startY, 2);
	PA_Put8bitPixel(0, PA_RecoInfo.endX, PA_RecoInfo.endY, 2);			
}		
		
PA_OutputText(1, 4, 22, "Shape : %s", PA_RecoShape); // Write the shape string
PA_OutputText(1, 4, 23, "Length : %d pixels  ", PA_RecoInfo.Length); // Length in pixels		

I won’t re-explain what I just said :-P I just don’t like repeating myself, lol. Basicaly, the code which can be used to draw a box around the shape :

PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.minY, PA_RecoInfo.maxX, PA_RecoInfo.minY, 2);
PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.maxY, PA_RecoInfo.maxX, PA_RecoInfo.maxY, 2);		
PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.minY, PA_RecoInfo.minX, PA_RecoInfo.maxY, 2);		
PA_Draw8bitLine(0, PA_RecoInfo.maxX, PA_RecoInfo.minY, PA_RecoInfo.maxX, PA_RecoInfo.maxY, 2);

It just draws 4 lines using the min/max X/Y positions, pretty standard...

Then, 2 pixels are plotted at the start and end position :

PA_Put8bitPixel(0, PA_RecoInfo.startX, PA_RecoInfo.startY, 2);
PA_Put8bitPixel(0, PA_RecoInfo.endX, PA_RecoInfo.endY, 2);

...

And the length is displayed with PA_OutputText(1, 4, 23, “Length : %d pixels “, PA_RecoInfo.Length);

Nothing more, nothing less... If you see anything missing, some info I forgot which seems vital, please send me a mail (Mollusk) or drop on the forum...

Oh, and I didn’t put Angle in that example because it wasn’t that usefull...

Output : 8bit and 16c modes

This section is for advanced users... If you are just starting, I highly recommend skipping this part and going on with Sprites for now, coming back later on... These text modes require a bit more knowledge to master (though it still is pretty easy ^^), and are generally not needed when starting coding games. If you plan on coding applications, though, this could be usefull...

Understanding the basics

The first part of this tutorial talked about simple text output, as well as displaying variable values on the screen and all... So you’re probably asking yourself why on earth 2 other different text systems are there too, as the first one allowed you to do pretty much anything you needed...

The default text system uses the DS’s hardware tile system, just like backgrounds, to display text. This means it uses 8×8 pixels tiles, and it is impossible to change that... 8bit and 16c text modes, however, use backgrounds you can draw on, plotting pixel per pixel... Starting to see the difference ?

Advantages of the 16c/8bit

Plotting pixel per pixel (or actually 2, 4, or 8 by 8 for speed reasons) has a huge advantage over the tiled text system : you can have different font sizes, and especially letters of different sizes inside a same font ! Yes, you heard it right, this means variable width fonts !

Font Sizes

By default, PAlib offers 5 different font sizes, numbered 0 to 4... The smallest font is like 4 or 5 pixels wide and tall, which means you can put nearly twice as much text per line ! And as you can display more lines of text than the normal output system, this means even more than twice as much text on the same screen ! Nice :p

Ok, that’s a cool thing, but it’s not all. And actually that size can be a bit of a pain to read. Using sizes 1 or 2 feels better for the user (something like 7 and 9 pixels high fonts), and you still get another advantage from the system... read on :p

Variable Width

In this text system, different letters can have different sizes... Ever wondered why on earth both ‘i’ and ‘w’ would take the same space on the screen ???? Yeah, kind of stupid, so now you can actually use 2-3 pixels wide for ‘i’, and more for ‘w’ :)

This means even more text per line, as you don’t lose any space anymore on small letters. Plus, it looks much better.

If you look at NDS games out there that have text output ingame, like RPGs, Ace Atourney and all, you’ll see that that’s the kind of text they use :)

Disadvantages

If there were only advantages, there wouldn’t be any need for the plain text output system...

Low Speed...

Speed is the first and major issue when using these new text modes... Why ? Well, the normal output system uses tiles. To display a letter, it takes only 1 line of code : changing a number in the map to display the tile corresponding to the letter... However, in 8bit and 16c modes, you have to plot all the pixels ! To save time, pixels are plotted 4 by 4 or 8 by 8, but in all cases you have to know precisely where to plot them, and you have several lines to plot (8 for 8 pixel fonts), so it takes MUCH MORE time...

No Auto-Erase

When you write some text in normal text mode, it automatically overwrites the preceding text, simply because it changed which tiles were used in the map...

When you play with pixels, plotting a pixel doesn’t erase the pixels all over the place (or else you wouldn’t know what you’re doing ^^), so when you want to change a line of text in 8bit/16c, you first need to erase it... Either the whole screen or just a corner, but you’ll have to erase it. This makes 8bit/16c text good for display text files, for example, as it doesn’t require updating the text every VBL, but horrible for debugging, when each variable is updated on the screen every frame...

No Variable to Letters...

Last flaw... These functions do not take the %d, %f, and %s commands for displaying the variables’ content... This is really painfull, and I did it for a specific reason : these text modes are already pretty slow, and adding these features would have made them even slower...

There is a work-around, though (of course !) : using stdio to convert your stuff into another text array, then displaying that array.... (if someone could complete that please ^^) (done - davido2)(changed sprintf to snprintf; snprintf is safer - Ginto8)

Here’s an example:

char temp[100];
snprintf(temp, 100, "%s %d", "Here's a number:", 10); 
PA_SmartText(0,0,0,256,192,temp,1,1,1,999);

8bit vs 16c...

Ok, here comes the last thing to know before seeing the actual code... Which should you use between 8bit and 16c text...

16c : Speed

The main reason to use 16c text rather than 8bit is that it’s 2-4 times faster to draw on the screen, or to erase the whole screen...

Second reason ? It takes almost half less space in the Vram, which is nice :)

8bit : Functionnalities

8bit is slower, yeah... But it can also do things you can’t achieve with 16c text... To start off, 8bit can have 256 colors, while 16c only has... 16... That’s nice, can always help...

Plus, the major thing is that 8bit text can be displayed rotated (left or right), meaning you can actually write text to be read holding the DS the other way... This proves to be really good for applications (ebooks, etc...) and some games (just see Brain Age!), even though it might not be used most of the time...

Conclusion ?

In the end, you’ll want to use 16c rather than 8bit if you don’t have any special usage to it and just want a nice-looking font... 16c will be both faster and smaller in VRAM... If you need to have tons of colors and the ability to rotate the screen, you’ll definately want 8bit :)

16c Text

Because it’s the one I like best, we’ll start out by seeing this one...

Due to lack of time, I’ll just post the link to the example for now ^^

16c Example

	PA_Init16cBg(0 // screen (top/bottom)
	           , 3); // bg (0-4)
	PA_Init16cBg(1, 3);  // 16 color background init with default colors for text
	
	PA_16cText(1, //screen 
					10, 10, 255, 20, //x1, y1, x2, y2 position
					"Hello World", //text
					1, //color (1-10)
					0, // text size (0-4)
					100); // maximum number of characters (use like 10000 if you don't know) 
 

FAQ - Pad and Stylus

Q1. The stylus positions seem to be completely off ! Can you do something to change that fact ?!?

  • Hmm... No, sorry ! Ok, I’ll explain. But first, if you have a screen protector, remove it at check if it works better or not (the stylus was like 20 pixels off with the film on, for me, and only 2 off without it !). The current stylus code is known to not be perfect, but is a code that works best for some people (some other codes I tried where even better for me, but 20 pixels off for some people !) ; this comes from the fact that there are tons of different touch screens, and the code we use for the stylus just isn’t fit for all of them yet. Also, the stylus position being like 5-6 pixels off on the corners is normal, the hardware precision is much lower there...

Note: For the people with around 20 pixels off (Example, you try to press ‘Q’ and you get ‘A’) Go into your touch screen calibration and touch directly OUTSIDE of the mark it tells you to, which every direction you may be off, this will, for the most part fix it. You will need to calibrate it again for other things, however.

Also remember that when writing text and using the stylus coordinates to place it, you will need to divide the stylus X/Y coordinates by about 8. this is because when the OutputText(); function uses tiles and not full coordinates. MC

Q2. When I use Dualis and simulate the stylus by a mouse click... it hangs !

  • This is a known issue for Dualis r12, with the latest stylus code. It can be ‘fixed’ by replacing the arm9.dll by the arm9.dll found in Dualis r11 (though this will add the bugs that were corrected from r11 to r12, for other stuff, and notably break the large backgrounds)

Mollusk 29/11/2005 22:44

 
day3.txt · Last modified: 28/04/2010 18:18 by 84.186.38.150
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki