SDL Wii/tutorial

From WiiBrew
Jump to navigation Jump to search

Foreword

First of all I want to thank everybody who made it possible to work with SDL on the Wii. I personally think SDL is one of the best libraries to begin with and that's why I want to write a simple tutorial. As is written on the main page of the SDL page, SDL is currently incomplete. If you try other things than written in this tutorial you may find bugs.

The source code in lesson 1 will be our template and you always have to begin with it.

This tutorial is written by GabberNL. If you want to contact me, go to my talk page.

Installation

You have to download the latest version of the Wii SDL library in the SDL Wii SVN. The normal SDL Wii and the SDL Wii Dependencies. After that:

  • Copy all of the header files $DEVKITPRO/libogc/include/SDL/
  • Copy all of the *.a files to $DEVKITPRO/libogc/lib/wii/

You have to put the libs in the right order in your makefile:

LIBS := -lSDL_ttf -lSDL_gfx -lSDL_mixer -lSDL_image -lfreetype -ljpeg -lpng -lz -lSDL -lfat -lwiiuse -lbte -logc -lm -lwiikeyboard

Find the line "LIBDIRS :=" and put: LIBDIRS := $(DEVKITPRO)/portlibs/ppc

Lesson 1: Making a red background

// normal includes
#include <stdlib.h>
#include <time.h>
#include <gccore.h>
#include <wiiuse/wpad.h> 

// SDL includes
#include <SDL/sdl.h>
#include <SDL/sdl_image.h>

// screen surface, the place where everything will get print onto
SDL_Surface *screen = NULL;

void init(){
	
    // initialize SDL video. If there was an error SDL shows it on the screen
    if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0 )
    {
        fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError() );
		SDL_Delay( 5000 );
        exit(EXIT_FAILURE);
    }
	
    // button initialization
    WPAD_Init();
 
    // make sure SDL cleans up before exit
    atexit(SDL_Quit);
    SDL_ShowCursor(SDL_DISABLE);
 
    // create a new window
    screen = SDL_SetVideoMode(640, 480, 16, SDL_DOUBLEBUF);
    if ( !screen )
    {
        fprintf(stderr, "Unable to set video: %s\n", SDL_GetError());
		SDL_Delay( 5000 );
        exit(EXIT_FAILURE);
    }
}

// this will be used in further lessons, not in lesson 1
void apply_surface ( int x, int y, SDL_Surface* source, SDL_Surface* destination ){
     
     // make a temporary rectangle to hold the offsets
     SDL_Rect offset;
     
     // give the offsets to the rectangle
     offset.x = x;
     offset.y = y;
     
     // blit the surface
     SDL_BlitSurface( source, NULL, destination, &offset );
}

void cleanup(){
	
     // we have to quit SDL
     SDL_Quit();
     exit(EXIT_SUCCESS);
}

int main(int argc, char** argv){
	// main function. Always starts first
	
	// to stop the while loop
	bool done = false;
	
	// start init() function
	init();
	
	// this will make the red background
	// the first argument says it must be placed on the screen
	// the third argument gives the color in RGB format. You can change it if you want
	SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 255, 0, 0));
	
	// this is the endless while loop until done = true
	while (!done)
        {
		// scans if a button was pressed
                WPAD_ScanPads();
		u32 held = WPAD_ButtonsHeld(0);
		
		// if the homebutton is pressed it will set done = true and it will fill the screen
		// with a black background
		if(held & WPAD_BUTTON_HOME){
			done=true;
			SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
		}
		
		// SDL_Flip refreshes the screen so it will show the updated screen
		SDL_Flip(screen);
        }
 
	// start cleanup() function
	cleanup();
 
    return 0;
}

Lesson 2: Showing an image as a background

For lesson 2 you need to have the template from lesson 1. (the whole source code..) Then you need a background image. You can take one from here: [1]. Press F5 if you get a 404 error.

Lets begin..

In lesson 1, we made a SDL_Surface called screen. Now, we have to make a SDL_Surface called background. Put it under the declaration of the screen surface.

SDL_Surface *background = NULL;

We have to load the background image. We will be using the SDL_LoadBMP() function. You have to put the place of your background image between the brackets. Warning: SDL loads from the root directory! If loading the background image didn't work it will print "Loading Error!" on the screen.

background = SDL_LoadBMP("sd:/apps/SDL/background.bmp");
	if( background == NULL ){
		printf("Loading Error!");
	}

We are going to use the apply_surface function. In the main(), put this under init(). The first two arguments will hold the X and Y offsets. The third argument holds the surface you want to be shown on the fourth argument, in this case the screen.

apply_surface(0, 0, background, screen);

This is the apply_surface function. It just takes the background surface and puts it on the screen surface. It first makes a SDL rectangle called offset. After that it will get the X and Y offsets in a variable called offset. Then it will blit the surface what means SDL will show the image on the predefined surface.

void apply_surface ( int x, int y, SDL_Surface* source, SDL_Surface* destination ){
     
     // make a temporary rectangle to hold the offsets
     SDL_Rect offset;
     
     // give the offsets to the rectangle
     offset.x = x;
     offset.y = y;
     
     // blit the surface
     SDL_BlitSurface( source, NULL, destination, &offset );
}

Everytime we are making a new screen, we have to free the surface so you wont make any memory leaks. In cleanup() you have to put this after SDL_Quit():

SDL_FreeSurface(background);

We don't have to free the surface of the screen because SDL_Quit() will take care of that.

If everything was done allright SDL will show a nice background in your application. The full source code:

// normal includes
#include <stdlib.h>
#include <time.h>
#include <gccore.h>
#include <wiiuse/wpad.h> 

// SDL includes
#include <SDL/sdl.h>
#include <SDL/sdl_image.h>

// the surfaces
SDL_Surface *screen = NULL;
SDL_Surface *background = NULL;

void init(){
	
	// initialize SDL video. If there was an error SDL shows it on the screen
    if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0 )
    {
        fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError() );
		SDL_Delay( 5000 );
        exit(EXIT_FAILURE);
    }
	
	// button initialization
	WPAD_Init();
 
    // make sure SDL cleans up before exit
    atexit(SDL_Quit);
    SDL_ShowCursor(SDL_DISABLE);
 
    // create a new window
    screen = SDL_SetVideoMode(640, 480, 16, SDL_DOUBLEBUF);
    if ( !screen )
    {
        fprintf(stderr, "Unable to set video: %s\n", SDL_GetError());
		SDL_Delay( 5000 );
        exit(EXIT_FAILURE);
    }
	
	// load the background image using SDL_LoadBMP
	// Make sure you use "sd:/" because SDL loads from the root!
	
	background = SDL_LoadBMP("sd:/apps/SDL/background.bmp");
	if( background == NULL ){
		printf("Loading Error!");
	}
}

void apply_surface ( int x, int y, SDL_Surface* source, SDL_Surface* destination ){
     
	 // make a temporary rectangle to hold the offsets
     SDL_Rect offset;
     
     // give the offsets to the rectangle
     offset.x = x;
     offset.y = y;
     
     // blit the surface
     SDL_BlitSurface( source, NULL, destination, &offset );
}

void cleanup(){
	
	// we have to quit SDL and free the surface of background
	SDL_Quit();
	SDL_FreeSurface(background);
	exit(EXIT_SUCCESS);
}

int main(int argc, char** argv){
	// main function. Always starts first
	
	// to stop the while loop
	bool done = false;
	
	// start init() function
	init();
	
	// apply surface on screen
	apply_surface(0, 0, background, screen);
	
	// this is the endless while loop until someone presses the home button on the wiimote
	while (!done)
    {
		// scans if a button was pressed
        WPAD_ScanPads();
		u32 held = WPAD_ButtonsHeld(0);
		
		// if the homebutton is pressed it will set done = true and it will fill the screen
		// with a black background
		if(held & WPAD_BUTTON_HOME){
			done=true;
			SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0, 0, 0));
		}
		
		// SDL_Flip refreshes the screen so it will show the updated screen
		SDL_Flip(screen);
    }
 
	// start cleanup() function
	cleanup();
 
    return 0;
}

P.S. I'm dutch, so my English may be not so good. Feel free to correct any errors in my language.