GP2X Early Days Into Sdl But ...


jimb

Still Fresh
Joined
Oct 15, 2005
Messages
32
Fellow coders,

I'm just getting into SDL and therefore I'm still at 'newbie' level 1.
So far, I have manged knocked up a tiny example which *should* display an image going around the screen in an arc using sin() and cos().

Only thing is, the image does not move. Any ideas?

Note: I have wrapped a few SDL functions here to make them easier for me to remember.



Main Code
Code:
#include <cmath>
#include "Blitz.h"
using namespace std;

//       blitz example #1

int main(int argc, char *argv[]){
    Graphics(320, 240, 0);
    SetTitle("Load/Display image");

    SDL_Surface *image=LoadBMP("testimage.bmp");
    
    float v;
    while (!AppClosed()){
          Cls();
          DrawImage(image,60+int(sin(v)*40.0),60+int(cos(v)*30.0));
          v+=0.009;
          Flip();
    }
    End();
}




The Blitz.h include:
Code:
#include <SDL/SDL.h>
  
// globals
SDL_Surface *screen; // main screen
int gfxW;         // graphics width
int gfxH;         // graphics height
Uint8 *inkeys;

// functions

void LockScreen(){
     if (SDL_MUSTLOCK(screen)){
     SDL_LockSurface(screen);
     }
}

void UnLockScreen(){
    if(SDL_MUSTLOCK(screen)){
    SDL_UnlockSurface(screen);
    }
}

void End(){
    SDL_Quit();
}

bool AppClosed(){
    SDL_Event event;
    if(!SDL_PollEvent(&event)) return 0;
    inkeys = SDL_GetKeyState(NULL);
    if(inkeys[SDLK_ESCAPE]) return 1;
    if(event.type == SDL_QUIT) return 1;
    return 0;
} 

void Graphics(int width, int height, bool full)
{
    gfxW = width;
    gfxH = height;

    if(SDL_Init(SDL_INIT_VIDEO) < 0){
       printf("Unable to init SDL: %s\n", SDL_GetError());
       SDL_Quit();
    }
    if(!full==0){
        screen = SDL_SetVideoMode(width,height,32,SDL_SWSURFACE|SDL_FULLSCREEN);
        //LockScreen();
    }
    else{
        screen = SDL_SetVideoMode(width,height,32,SDL_HWSURFACE|SDL_HWPALETTE);
    }
    if(screen == NULL)
    {
        printf("Unable to set video: %s\n", SDL_GetError());
        SDL_Quit();
    }
}

void SetTitle(char *text){
     SDL_WM_SetCaption(text, NULL);
}

void Flip(){
    SDL_UpdateRect(screen, 0, 0, 0, 0);
    SDL_Delay(1);
}

void Cls(int r=0,int g=0,int b=0){
    SDL_FillRect(screen, NULL, 65536 * r + 256 * g + b);
}

SDL_Surface *LoadBMP(char *file){
            SDL_Surface *img = SDL_LoadBMP(file);
            if ( img == NULL ){
               fprintf(stderr, "Error loading BMP %s: %s\n", file, SDL_GetError());
            }
            return img;
}

void DrawImage(SDL_Surface *img,int x,int y){     
     SDL_Rect dest;
     dest.x = x;
     dest.y = y;
     dest.w = img->w;
     dest.h = img->h;
     SDL_BlitSurface(img, NULL, screen, &dest);
}
 

fishybawb

Hired Geek
Joined
Jul 22, 2005
Messages
1,115
Age
43
Location
York, UK
Website
Visit site
I've got to dash now, but just a couple of things from a quick scan:

You're using the float "v" in main() without initialising it - that's a bad idea as you can't guarantee it's going to contain any value straight off.

You're not using double buffering. Even if the image was moving, you'd get tearing. Init the screen with: SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE | SDL_DOUBLEBUF); then in the Flip function, do an SDL_Flip(); after updating the rectangle.

Hope that helps, I'll come back later and give it a proper look :)
 

jimb

Still Fresh
Joined
Oct 15, 2005
Messages
32
Woo! Fixed by doing:

float v=0.0;

Something as simple as that.
I guess I've got a looong way to go yet.
If you can spot other bad programming practicies please let me know.

Thanks fishy.
 

yaustar

UK GP32 & GP2X Owner
Joined
Oct 18, 2003
Messages
2,714
Location
UK
Website
Visit site
Just two quick things and a question:

Initialise varibles before you use them (As you just found out ;) )
NEVER put code in header files. Function prototypes and definitions are fine but not actual code as the compiler will assume it's inline.

Are you using C or C++?
 

Squidge

Certified Guru
Joined
Nov 16, 2003
Messages
8,493
Location
UK
Website
Visit site
Normally the compiler doesn't assume code in header files is inline unless you actually tell it that. However, with standard functions (like what is shown here), if you include the .h file in two or more files, you'll get multiple declaration errors. You can get round this by making the functions static, but that will put a copy of the function into every file that #include's it.

Much better to keep the code in the .c file unless it's meant to be inlined.

Also, if a function is not meant to be called from any other file, make it static to avoid pulluting the global namespace.
 

jimb

Still Fresh
Joined
Oct 15, 2005
Messages
32
Are you using C or C++?
C++

I'm using the Dev C++ IDE plus SDL package.

Is it best to learn C or C++ for GP2X development?

I have placed the functions in a separate *.cpp file but I get lots of

[Linker] Undefined reference to screen

... plus all of the other globals.

I'm not sure how to cross-refence all this stuff.
Maybe I've got the #includes in the wrong place?


MAIN.CPP
Code:
#include <cmath>
#include "Blitz.h"
//#include "Blitz.cpp"

using namespace std;

//       blitz example #1

int main(int argc, char *argv[]){
    Graphics(320, 240, 0);
    SetTitle("Load/Display image");

    SDL_Surface *image=LoadBMP("testimage.bmp");
    SDL_Surface *brick=LoadBMP("brick.bmp");
    
    float v=0.0;
    while (!AppClosed()){
//          Cls();
          TileImage(brick);
          DrawImage(image,60+int(sin(v)*40.0),60+int(cos(v)*30.0));
          v+=0.009;
          Flip();
    }
    FreeImage(image);
    End();
}



BLITZ.H
Code:
#include <SDL/SDL.h>
  
// globals
extern SDL_Surface *screen; // main screen
extern int gfxW;         // graphics width
extern int gfxH;         // graphics height
extern Uint8 *inkeys;

// functions
void LockScreen();
void UnLockScreen();
void End();
bool AppClosed(); 
void Graphics(int width, int height, bool full);
void SetTitle(char *text);
void Flip();
void Cls(int r=0,int g=0,int b=0);
void Plot(int x, int y, int r=255, int g=255, int b=255);
SDL_Surface *LoadBMP(char *file);
void DrawImage(SDL_Surface *img,int x,int y);
void TileImage(SDL_Surface *img);
void FreeImage(SDL_Surface *img);



BLITZ.CPP
Code:
// functions

#include "Blitz.h"

void LockScreen(){
     if (SDL_MUSTLOCK(screen)){
        if (SDL_LockSurface(screen)<0) return;
     }
}

void UnLockScreen(){
    if(SDL_MUSTLOCK(screen)){
    SDL_UnlockSurface(screen);
    }
}

void End(){
    SDL_Quit();
}

bool AppClosed(){
    SDL_Event event;
    if(!SDL_PollEvent(&event)) return 0;
    inkeys = SDL_GetKeyState(NULL);
    if(inkeys[SDLK_ESCAPE]) return 1;
    if(event.type == SDL_QUIT) return 1;
    return 0;
} 

void Graphics(int width, int height, bool full)
{
    gfxW = width;
    gfxH = height;

    if(SDL_Init(SDL_INIT_VIDEO) < 0){
       printf("Unable to init SDL: %s\n", SDL_GetError());
       SDL_Quit();
    }
    if(!full==0){
        screen = SDL_SetVideoMode(width,height,32,SDL_SWSURFACE|SDL_FULLSCREEN);
        //LockScreen();
    }
    else{
        screen = SDL_SetVideoMode(width,height,32,SDL_HWSURFACE|SDL_HWPALETTE);
    }
    if(screen == NULL)
    {
        printf("Unable to set video: %s\n", SDL_GetError());
        SDL_Quit();
    }
}

void SetTitle(char *text){
     SDL_WM_SetCaption(text, NULL);
}

void Flip(){
    SDL_UpdateRect(screen, 0, 0, 0, 0);
    SDL_Delay(1);
}

void Cls(int r,int g,int b){
    SDL_FillRect(screen, NULL, 65536 * r + 256 * g + b);
}

void Plot(int x, int y, int r, int g, int b){
    Uint32 colorSDL = SDL_MapRGB(screen->format, r, g, b);
    Uint32 *bufp;
    bufp = (Uint32 *)screen->pixels + (y % gfxH) * screen->pitch / 4 + x % gfxW;
    *bufp = colorSDL;
}

SDL_Surface *LoadBMP(char *file){
            SDL_Surface *img = SDL_LoadBMP(file);
            if ( img == NULL ){
               fprintf(stderr, "Error loading BMP %s: %s\n", file, SDL_GetError());
            }
            return img;
}

void DrawImage(SDL_Surface *img,int x,int y){     
     SDL_Rect dest;
     dest.x = x;
     dest.y = y;
     dest.w = img->w;
     dest.h = img->h;
     SDL_BlitSurface(img, NULL, screen, &dest);
}

void TileImage(SDL_Surface *img){
     SDL_Rect dest;
     dest.x=0; dest.y=0;
     dest.w = img->w; dest.h = img->h;
     while(dest.y < gfxH){
             while(dest.x < gfxW){
                     SDL_BlitSurface(img, NULL, screen, &dest);
                     dest.x+=img->w;
             };
             dest.x=0; dest.y+=img->h;
     };
}

void FreeImage(SDL_Surface *img){
     SDL_FreeSurface(img);
}
 

Squidge

Certified Guru
Joined
Nov 16, 2003
Messages
8,493
Location
UK
Website
Visit site
It seems that you have "extern SDL_Surface *screen;" but you don't actually define 'screen' in a C file.

You should have:

extern SDL_Surface *screen;

in the .h file, and:

SDL_Surface *screen;

in exactly one C file.
 

woogal

Certified Guru
Joined
May 15, 2003
Messages
1,823
Age
46
Location
Newark, UK
Website
gp32.sector808.org
fishybawb posted on Oct 29 2005 at 03:18 PM said:
You're not using double buffering. Even if the image was moving, you'd get tearing. Init the screen with: SDL_SetVideoMode(width, height, 32, SDL_SWSURFACE | SDL_DOUBLEBUF); then in the Flip function, do an SDL_Flip(); after updating the rectangle.
On a software surface all SDL_Flip does is call SDL_UpdateRect(screen, 0, 0, 0, 0); ;). SDL_DOUBLEBUF is for hardware surfaces only.
 
Last edited by a moderator:

fishybawb

Hired Geek
Joined
Jul 22, 2005
Messages
1,115
Age
43
Location
York, UK
Website
Visit site
woogal posted on Oct 29 2005 at 06:25 PM said:
On a software surface all SDL_Flip does is call SDL_UpdateRect(screen, 0, 0, 0, 0); ;). SDL_DOUBLEBUF is for hardware surfaces only.

D'oh! You're absolutely right of course, my bad! :)
 
Last edited by a moderator:

jimb

Still Fresh
Joined
Oct 15, 2005
Messages
32
It seems that you have "extern SDL_Surface *screen;" but you don't actually define 'screen' in a C file
Ahh I see. I assumed these 'globals' were being defined in the Blitz.h file.
Righty dokee, I have now added this to the Blitz.cpp file and everything is good to go:
Code:
// globals
SDL_Surface *screen; // main screen
int gfxW;         // graphics width
int gfxH;         // graphics height
Uint8 *inkeys;

Thanks Squidge. Onwards and upwards.
 
C

codeninja

Guest
You better learn to make a habit of using fixed point math instead of floating point. Like DS using ARM9, floating point math on ARM processor is such a luxury that you can't really afford.
 

Ravnos

Asleep in Samsara
Joined
Sep 20, 2005
Messages
2,499
Age
40
Location
Edmonton, Alberta
Website
Visit site
codeninja posted on Oct 29 2005 at 01:33 PM said:
You better learn to make a habit of using fixed point math instead of floating point. Like DS using ARM9, floating point math on ARM processor is such a luxury that you can't really afford.

Doesn't one of the two processors have floating point support, though?
 
Last edited by a moderator:

skeezix

Internal Development
Joined
Mar 11, 2003
Messages
8,063
Website
www.codejedi.com
Let him worry about fixed-point later; while learnign, stick to basics :)

As to above.. an #include just means read that named file in; so if you include a file A into B and C, its copied to both, leading to duplicate definitions. An #include is just for declarations (externs, or typedefs, or enums, or struct naming, etc. Never any real code or physical declarations.) (Until you get to C++ templates, or C with inlines, and such. But avoid that for now :)

Good luck and ncie going,

jeff
 
C

codeninja

Guest
Ravnos posted on Oct 29 2005 at 12:43 PM said:
codeninja posted on Oct 29 2005 at 01:33 PM said:
You better learn to make a habit of using fixed point math instead of floating point.  Like DS using ARM9, floating point math on ARM processor is such a luxury that you can't really afford.

Doesn't one of the two processors have floating point support, though?

ARM9 supports floating point, but the processing time makes it all useless.
 
Last edited by a moderator:

Radek

Certified Guru
Joined
Oct 13, 2005
Messages
871
codeninja posted on Oct 29 2005 at 10:23 PM said:
Ravnos posted on Oct 29 2005 at 12:43 PM said:
codeninja posted on Oct 29 2005 at 01:33 PM said:
You better learn to make a habit of using fixed point math instead of floating point. Like DS using ARM9, floating point math on ARM processor is such a luxury that you can't really afford.

Doesn't one of the two processors have floating point support, though?

ARM9 supports floating point, but the processing time makes it all useless.

Directly in the instruction set?

There almost always a FPU could be emulated by an exceptions.

If Arm9 does indeed have a opcodes for float maths then it's somewhat more advanced than I thought.

But to the "point" it's not that hard to do floatpoint using just intengers. There is one issue thought what must be handled manually.
 
Last edited by a moderator:

Squidge

Certified Guru
Joined
Nov 16, 2003
Messages
8,493
Location
UK
Website
Visit site
codeninja posted on Oct 29 2005 at 09:23 PM said:
ARM9 supports floating point, but the processing time makes it all useless.

ARM9 doesn't support floating point in any shape or form, but GCC can emulate them using integers. DJW managed to even get some arm assembler fp stuff in a recent GCC4 build, so floating point stuff should be pretty nippy in that version (although of course no where near as fastest as native support).
 
Last edited by a moderator:

icurafu

The Hallucinogenic Elf
Joined
Sep 28, 2005
Messages
2,078
Location
Sydney, Australia
Website
gamesreborn.blogspot.com
It's been a while since I coded for a living, but from what I remember.

It's fairly normal to put get and set operations in headers, as well as statics.

Something I picked up from the code I worked with. Is this a bad habit?
 

yaustar

UK GP32 & GP2X Owner
Joined
Oct 18, 2003
Messages
2,714
Location
UK
Website
Visit site
Ok.. I think I was getting confused with the way MVC++ handles code in class definitions.. Inline functions should be REALLY short, one or two lines at most so GETS and SETS which are one liners should be fine...
 
Top