Skip to content
theZiz edited this page May 15, 2013 · 12 revisions

Welcome to the second Tutorial about "sparrowCore".

Table of Contents

About the seperation

First of all some words about the fragmentation of sparrow3d and these wiki Tutorials. I divided sparrow3d currently in 11 parts: sparrowCore, sparrowPrimitives, sparrowSprite, sparrowFont, sparrowMath, sparrowRenderer, sparrowMesh, sparrowFile, sparrowText, sparrowSound and sparrowNet. Most of the times I will omit the "sparrow" in the fragment names. Each of these parts has an own (more or less) sepperated functionality, which will be explained each time in the related Tutorial here at the sparrow3d wiki.

The reasons for the seperation are:

  • faster compiling, because only changed files need to be compiled again
  • seperation of not coherent functionalities. Only because of this some application could use 3D rendering, but don't use the event handling. So the parts of sparrow3d interact among themselves with the same functions you get from the library.
  • system: Without this seperation I would not now, where to start in a Tutorial. ^^

The initialisation

Most of the parts have own initialisation routines. But if you use sparrowCore, most of them will aready be called by the Core initialisation function spInitCore. This function setups some internal variables and initialises the sparrowPrimitives and sparrowMath functionalities.

After seting up sparrowCore you are able to create the main window with spCreateDefaultWindow. If you want to have more access to some window settings use spCreateWindow instead. These functions return a pointer to an SDL_Surface. You don't have to save it for later use, spGetWindowSurface will return it, whenever you need it, but of course reading a variable is faster than a function call. ;-)

Now the first REALLY important property of sparrow3D: sparrow3D differs between the window surface and the RenderTarget. Sparrow3D is possible to draw everything on EVERY SDL surface, not only the window surface. In most cases you will ignore this, but in testtarget.c you will see some examples of this functionality. Anyway: To select the window as RenderTarget you have to call spSelectRenderTarget. Because of this being a sparrowPrimitives function, I will explain more in the Primitives Tutorial.

The heart of your game - the loop function

spLoop is one of the most important functions you will call and have to understand. You give it four feedback function pointer. That means at several points in the game loop these functions will be called. The fifth parameter is about frame limiting. It is a time value in milli seconds, after which a frame is drawn. E.g. if you set it to 10 at most every 10 ms a frame is drawn. That would be at most 100 frames per second. The feedback functions are:

  • spDraw is called for drawing stuff. Every drawing action you do, you should do here. Don't mix calculation and drawing code. It's confusing and just wrong. ;-) If you gave spLoop a time for waiting between every frame, this function will be at most drawn again after this time.
  • spCalc is called for calculating stuff. It is called every time if at least 1 milli second passed since the last calc call. The time (which - keep in mind! - is always greater than zero) since the last call is given as parameter. Do your calculation stuff in this function. As said at spDraw: Don't mix calculation and drawing!
  • spResize will be called every time your window will be resized. At handhelds it could be, that it is never called: Because of the small screen most of the times you will use fullscreen at native resolution - why should you resize? But it may be usefull for bigger screens or not full screen usage, e.g. if you wan't to reload pictures or the font in different sizes. The new resolution is given as parameters.
  • spEvent is called everytime a event it toggled. Most of the event handling sparrowCore does for you, but if you wait for some special event sparrowCore does not handle or not in the way you need it, feel free to react yourself. The event is given as SDL_Event pointer.
spLoop finishes, when the spCalc function returns a value uneven zero. This value will be returned by spLoop. That means: If you don't give a calc function to spLoop, there is no possibility to finish the loop! In fact, that doesn't make sense at all. ;)

You can call spLoop in some spLoop call if you want (yo dawg, I heard you like loops...). E.g. you have a spLoop call for drawing and calculation the menu and you call spLoop IN the spCalc function of the menu for running some menu point. If the menu point run finishes, the time given to spCalc of the menu calculations will be the time since the last call of the menu point calculation function. A small example for better understanding:

 int drawGame( void ) {
    //draw game stuff
 }
 int calcGame( Uint32 steps) {
    //do game stuff
 }
 int drawMenu( void ) {
    //draw menu stuff
 }
 int calcMenu( Uint32 steps) {
    //do menu stuff
    if (condition_to_enter_menu_point)
        spLoop(drawGame,calcGame,0,NULL,NULL);
 }
 //Somewhere in the main functions:
 spLoop(drawMenu,calcMenu,0,NULL,NULL);

In this case if condition_to_enter_menu_point is true, spLoop will be called in another spLoop call and if the internal spLoop call finishes, because calcGame returns a value uneven 0, the time given to calcMenu will be the time since the last call of calcGame, NOT the last call of calcMenu (which could date back a long time).

The generic input device

An important part of sparrow3d is the generic input device. It has two axis, which you can read digital or analog, four buttons, which are located on the right (like on any real device), two shoulder buttons and two functional buttons, often called "Start", "Select" or "Menu". To get the input use spGetInput to get a pointer to an spInput struct. The most interesting variables of this struct are the arrays / pointer button, axis and analog_axis. Use the first e.g. with

 input->button[SP_BUTTON_A]

to get or set the value of the button A of the device. As you may notice: The Button A can be at any place on different devices. So often is makes more sense to use e.g.

 input->button[SP_BUTTON_LEFT]

instead. That will be the leftest of the four main buttons on every device. Furthermore SP_BUTTON_UP, SP_BUTTON_RIGHT and SP_BUTTON_DOWN are possible. For more definitions have a look at the defines.

The variable axis and analog_axis work similar. To get the horizontal value use

 input->axis[0]

and

 input->axis[1]

for the vertical axis. analog_axis works in the same way. axis returns a -1 for left/up, 0 for no movement in this axis and 1 for right/down. analog_axis works similar, but returns a range from SP_ANALOG_AXIS_MIN to SP_ANALOG_AXIS_MAX. If a device only have digital axis, nevertheless an analog device is emulated. But keep in mind, that this means, that on some devices the analog_axis only returns SP_ANALOG_AXIS_MIN, 0 and SP_ANALOG_AXIS_MAX.

Much more stuff

There are much more functions in sparrowCore. The best idea is to have a look at the examples and at sparrowCore.h for an overview about the possibilites. The most important function not descriped yet is spFlip. With this function everything drawn to the screen surface will be shown on the screen. So call it at the end of your drawing step. ;)

The next Tutorial will be about the basic principle of sparrow3d calculations, sparrowMath