Continuing the first post, I am now going to discuss TrueType fonts manipulation and explain the transparency/opacity mechanism used by SDL. Besides, I am going to present the audio and events management. You should download sdl_part2 before beginning.
TrueType fonts manipulation
The SDL_ttf library provides TrueType fonts support. Proper initialization is required before usage:
1 | SDLTTF.init(); |
The first step is font loading. SDL_ttf supports two font formats: TTF and FON. The included “font.ttf” file is loaded by:
1 | SDLTrueTypeFont font = SDLTTF.openFont("font.ttf", 16); |
As you can see above, the openFont method has a second parameter: font size. You have to choose the size of your loaded font instance. This size cannot be changed. If you need a different size, then you will have to load the same font again, creating a new instance with a different size.
Now we are going to create and draw a string in the screen:
1 2 3 4 | SDLColor textColor = new SDLColor(0, 0, 255); SDLSurface textSurface = font.renderTextSolid("SDL_ttf: Hello world!", textColor); textSurface.blitSurface( screen, new SDLRect(0, 350) ); screen.flip(); |
The first line defines a blue color. The second line renders the “Hello world” string into a surface. I don’t now if you remember my last post, but I repeat it again: everything in SDL is represented as a surface. The last two lines blit the text surface and the screen surface together.
Transparency manipulation
If you open our application right now, you will realize our sprite (loaded image) contains a very strange purple color. Before start talking about transparency, I will first show you why it is necessary. Not just necessary, but mandatory! The code snippet below will draw another instance of our previous loaded sprite:
1 2 | spriteSurface.blitSurface( screen, new SDLRect(310, 250) ); screen.flip(); |
Running the application you will see the new instance of our sprite inside a red rotated rectangle (previously drawn). Now, I don’t expect the lower surface (rectangle) to be entirely covered by the sprite surface. I don’t even want to see that purple color anymore! However, that purple is very important: it is our key color! It indicates to SDL which color will be used for transparency effect. Now, instead of blitering the sprite surface as we did above, let’s try this way:
1 2 3 4 | long colorKey = SDLVideo.mapRGB( spriteSurface.getFormat(), 255, 0, 255 ); spriteSurface.setColorKey(SDLVideo.SDL_SRCCOLORKEY, colorKey); spriteSurface.blitSurface( screen, new SDLRect(310, 250) ); screen.flip(); |
We need transparency because our sprites usually will contain unutilized area. For instance: if you need to draw an opened door, the passage will have to be transparent. Otherwise you won’t be able to see through that door!
There is a lot more to discuss about transparency and blit techniques. However, we are going to have this conversation when I start talking about my isometric engine (next post).
Audio manipulation
The SDL_mixer library provides audio support. The following code snippet initializes the library before usage:
1 | SDLMain.init(SDLMain.SDL_INIT_AUDIO); |
After initialization, we need to initialize the mixer and open an audio channel:
1 2 | SDLMixer.openAudio(44100, SDLMixer.AUDIO_S16, 1, 1024); SDLMixer.volume(-1, 100); |
The first line creates our mixer: 44.100Hz, 16bit, ONE channel, 1024bytes per output sample). We are creating only one channel here, but you can have several. The second line sets the maximum volume for all channels. Again, you can specify distinct volumes for each channel. The next code snippet loads and plays an audio effect:
1 2 | MixChunk effect = SDLMixer.loadWAV("building.wav"); SDLMixer.playChannel(-1, effect, 0); |
The first line loads the audio effect file. SDL_mixer supports the following audio effect file formats: WAVE, AIFF, RIFF, OGG, and VOC. Then, the second line plays our audio effect in the first free channel (-1 as first parameter). The last parameter indicates how many times the audio effect should be repeated (0 is none).
Music manipulation
Besides audio effects, SDL_mixer provides separated functions for music playing. Music and audio effects are played independently. You only need to initialize SDL_mixer once (already done by now). However, you have to set up the music volume:
1 | SDLMixer.volumeMusic(40); |
The next step is load play the music. SDL_mixer supports the following music file formats: WAVE, MOD, MIDI, OGG, MP3. The first line of the next code snippet loads a music file, while the second line plays the music forever (-1 as second parameter indicates infinite loop).
1 2 | MixMusic music = SDLMixer.loadMUS("Cecil_Gant-I_Wonder.mp3"); SDLMixer.playMusic(music, -1); |
Event manipulation
SDL provides support for mouse, keyboard and joystick events management. Now, instead of making our application sleep for a while before finalization, we will wait for ESCAPE key to close the application:
1 2 3 4 5 6 7 8 | for (;;) { SDLEvent event = SDLEvent.waitEvent(); if (event instanceof SDLKeyboardEvent) { SDLKeyboardEvent keyEvent = (SDLKeyboardEvent) event; if ( keyEvent.getSym() == SDLKey.SDLK_ESCAPE ) break; } } |
The event initialization procedure is included in the SDL video one. One call initializes both systems. The code snippet above contains one endless event management loop. In this initial example, we are waiting for a keyboard event, specially the ESC key. Line 3 blocks until a new event is available. Line 4 checks the event type. After a break (line 8), the main thread will end and our application will be closed.
Now, let’s do something far more interesting: write the pressed key code in the screen (left-top red box). To achieve this, we will add an else-statement to our if-statement, like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | for (;;) { SDLEvent event = SDLEvent.waitEvent(); if (event instanceof SDLKeyboardEvent) { SDLKeyboardEvent keyEvent = (SDLKeyboardEvent) event; if ( keyEvent.getSym() == SDLKey.SDLK_ESCAPE ) { break; } else { redSurface.blitSurface(screen, redRect); String keyString = "Key: "+ keyEvent.getSym(); SDLColor keyColor = new SDLColor(0, 0, 0); SDLSurface keySurface = font.renderTextSolid(keyString, keyColor); keySurface.blitSurface(screen); screen.flip(); } } } |
There are several other SDL events you can play with. I advice you to try out by your own SDLMouseButtonEvent and SDLMouseMotionEvent at least.
So far
So far I have gave you a wide SDL overview. You are now able to develop very interesting applications with SDL.
Next post
In the next post I will talk about my isometric engine. It offers several layers of abstraction on top of SDL. You can manipulate Java objects (like buildings and people) in a very high-level manner. I will present the engine’s architecture and discuss SDL weaknesses and how did I address them.