• Welcome to Dark Bit Factory & Gravity.
 

[C++] Bitmap Scroller: Strings And Things.

Started by Clyde, September 07, 2009

Previous topic - Next topic

0 Members and 0 Guests are viewing this topic.

Clyde

Awesome stuff dude and thanks very much.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Clyde

I tried this for wrapping, but it's wrong.
if (curchar > scroller_length) start_pos=0;
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Jim

#22
Almost certainly you want >= instead of >

In C, if you have 5 chars in a string, it looks like this

char *message = "abcde";

But in memory, it looks like
a b c d e '\0'

That is, there are 6 chars, the 6th one being decimal 0.  That's how C knows where the end of the string is.  The length of this string, strlen(message) is 5.  If you check message[5] the answer is 0.  You are saying
if (curchar > scroller length)
ie. if curchar = 6.  If it's got that far, then message[6] has been read and we shouldn't have done that because it doesn't exist and/or could be anything - whatever is in memory after our message string.

Jim



Jim
Challenge Trophies Won:

Clyde

#23
Thanks man! :)

There must be gremlins on my PC, as i've gone back to this, but my font isnt displaying properly like before, it's got lime green borders around the letters that suggest errors someplace.

this is the bitmap text routine:

void update_bitmap_scroller( gfx_buffer *dest, anim_image *font, int pos_y )
{

int curchar= 0;
int x=(int) start_pos;

// find first character that's not outside the left border
while (scroller[curchar] && x+font->frame[scroller[curchar] - 32]->wwidth<0)
{
      x+=font->frame[scroller[curchar] - 32]->wwidth;
      curchar++;
 
                // doesnt work.
  //if (curchar >= scroller_length) start_pos=0;
}

// draw characters until right border reached
while (x<dest->wwidth && scroller[curchar])
{
char c= scroller[curchar] - 32;

draw_gfx_buffer2( dest, font->frame[c], x, pos_y );
x+=font->frame[c]->wwidth;

      curchar++;
}

start_pos-=scroll_speed;

}


And here's the routines used for loading from memory:


//classess.
class gfx_buffer
{
public:
int wwidth, height;
int wwidth2, height2;
unsigned int *pixels;

};

class anim_image
{
public:
int frame_wwidth, frame_height;
int total_frames;

gfx_buffer **frame;
};



gfx_buffer *load_gfx_buffer(unsigned char *raw, unsigned char *pal, int wwidth, int height)
{
//round width up to next multiple of 4
wwidth += ( 4-( wwidth&3 )) & 3;
//height += ( 4-( height&3 )) & 3;

//create a new image
gfx_buffer *buffer = create_gfx_buffer( wwidth, height );
   
//convert the palette to 32bit
unsigned int palette[256];
int index;

for ( index=0; index < 256; index++ )
palette[ index ] = (255<<24) | ( pal[ index*3 ] << 16) | ( pal[ index*3+1 ] << 8) | pal[ index*3+2 ];


//convert the pixels
for ( index=0; index<(wwidth*height); index++)
buffer->pixels[ index ] = palette[ *raw++ ];

return buffer;



anim_image *create_anim_images( gfx_buffer *srce, int wwidth, int height )
{
int frame_w= srce->wwidth / wwidth;
int frame_h= srce->height / height;
int total_frames= frame_w * frame_h;

anim_image *anim_buffer = new anim_image;

anim_buffer->frame=new gfx_buffer *[ total_frames ];
                           
int x,y,frame_number=0;
   
    for ( y=0; y<frame_h*height; y+=height )
{   
for ( x=0; x<frame_w*wwidth; x+=wwidth )
{     
anim_buffer->frame[ frame_number ]=create_gfx_buffer(wwidth,height);
            draw_gfx_buffer( anim_buffer->frame[frame_number],srce,-x,-y);
            frame_number+=1;
}
}
   
  anim_buffer->frame_wwidth = frame_w;
anim_buffer->frame_height = frame_h;
anim_buffer->total_frames = total_frames;
   
    return anim_buffer;

}



void draw_gfx_buffer( gfx_buffer *dest, gfx_buffer *srce, int pos_x, int pos_y )
{
unsigned int col=0;
int x_start=pos_x, x_end=pos_x+srce->wwidth-1;

if ( x_start<0 ) x_start=0;

    if ( x_end>=dest->wwidth ) x_end=dest->wwidth-1;

    if (x_start<=x_end)
{
int y_start=pos_y, y_end=pos_y+srce->height-1;

        if (y_start<0) y_start=0;
        if (y_end>=dest->height) y_end=dest->height-1;
       
if (y_start<=y_end)
{
unsigned int *srce_start= srce->pixels+(x_start-pos_x)+(y_start-pos_y) *srce->wwidth;
unsigned int *srce_end = srce->pixels+(x_start-pos_x)+(y_end-pos_y)   *srce->wwidth;
unsigned int *srce_ptr;

unsigned int *dest_start= dest->pixels + x_start+y_start*dest->wwidth;
unsigned int *dest_end =dest_start-x_start+x_end;
unsigned int *dest_ptr;

            while (srce_start<srce_end)
{           
srce_ptr=srce_start;
                dest_ptr=dest_start;
               
while (dest_ptr<dest_end)
{               
col=*srce_ptr;
                    if (col!=0) *dest_ptr=col;
                   
dest_ptr+=1;
                    srce_ptr+=1;

}

                dest_start+=dest->wwidth;
                dest_end+=dest->wwidth;
                srce_start+=srce->wwidth;
}

}
}
}


I think i've narrowed it down to the create_anim_image routine.
To explain it a bit more, part of the proceeding character / image is present on the actual one being drawn. so it's not formatting them correctly someplace in the creation process.

Cheers,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Jim

This was working before - which bit have you changed?  Have you tried looking at it in the debugger?

Jim
Challenge Trophies Won:

Clyde

#25
Ive not changed any of it which is why im thinking there's gremlins,
I have added a new create_anim_images for bitmap fonts that are a fixed width and height. as the other method was a chopper-esque route.

I think it might be to do with settings either in the C++ list, or the Linker, but im not an expert by any means; when I used the settings to make it smaller exe's with tinyptc & MSVCRTS.lib; im also getting those cpu.obj errors back too.

If think i'll try and see about uninstalling completely MSVC++ 2008 from my PC,, and make backups of stuff i've done so far and restart a fresh. As there's something a miss that I just cant quite explain. As they were working before as you rightly said. And Hell Fire mentioned about code can go a stray.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Jim

#26
Nooooo!!!!!!!!!!!  You've just got it all working!!!!!!  The gremlins are in your head!

There's just a bug in your code.  Do you reinstall FB every time your code doesn't work?

Zip up your code again and post it here and we'll fix it up.  Remember - that's .cpp, .h, .vcproj, .lib, .a files.  Not the giant .pdb or .ncb files which are useless to anyone.

Jim

Challenge Trophies Won:

Clyde

Your right mate, they are in my bonce! :D

Ok dude, will do a project to upload and with the suspect font. it might of been subject to being converted incorrect too; but will see if you spot anything a miss in the code first. And could you put me out of my mysery and the gremlins to rest, by showing me when to put the wrapping :D

I have discovered though, that when it draws the letters, black is still being shown. Only spotted that when i drew a frame on top of an effect.

Cheers Amigo,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Clyde

Here's the Gremlins Project - Humble Beginnings.cpp is the main file.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

hellfire

Quotemy font isnt displaying properly like before, it's got lime green borders around the letters that suggest errors someplace.
I don't have much time to look over your source right now but I don't see any green borders:

Looks like your characters are just off by a pixel or two and the upper font probably has enough margin to hide it.
Challenge Trophies Won:

Clyde

I've got it working now, which is a relief. it was a matter of rechecking the other posts for it, somehow i'd lost them.

the next string commands i'd like to challenge are mid$, left$ and right$.
an example:

left_string( text$, amount_of_characters )
same applies for right string.

left_string( "HELLO WORLD", 5 )
HELLO

right_string( "HELLO WORLD, 5 )
WORLD

i also dont know if in blitz or freebasic, it wraps if it goes out of bounds.

Cheers all,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

hellfire

#31
untested and with a few glasses of wine:

char* left(char *src, int count)
{
  int len= strlen(src);         // length of source string
  if (count>len) count= len;    // don't copy more than available
  char *dst= new char[count+1]; // allocate memory for new string
  memcpy(dst, src, count);      // copy string from the beginning
  dst[count]= 0;                // store 0-terminator at end of string
  return dst;                   // return new string
}



char* right(char *src, int count)
{
  int len= strlen(src);
  if (count>len) count= len;
  char *dst= new char[count+1];
  memcpy(dst, src+len-count, count);
  dst[count]= 0;
  return dst;
}


keep in mind that you have to delete the resulting string manually:

char *text= "hello world";
char *front= left(text, 5);
char *back= right(text, 5);
delete[] front;
delete[] back;


a better option is to use a proper string-class like std::string.
Personally I prefer the one coming with Qt but that's probably a bit much for now.
Challenge Trophies Won:

Clyde

Corker mate, will give this a go in a bit :D
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Clyde

Wonder how to incorpate a tag system, for example: hello eddie[pause 2000] nice to see you to see you [bounce 1,2,3] nice! [pause]
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

zawran

QuoteWonder how to incorpate a tag system, for example: hello eddie[pause 2000] nice to see you to see you [bounce 1,2,3] nice! [pause]

Have your code check to see if the next character is [ then read on and collect characters until you meet a ] after which you decide what to do with the command you have collected.

Clyde

im hopeless it crashes, and not sure.

void update_bitmap_scroller( gfx_buffer *dest, sint pos_y )
{
   int curchar= 0;
   int pos_x=(int) start_pos;

   // find first character that's not outside the left border
   if ( display==0 )
   {
      while ( message[curchar] && pos_x+font->frame[ message[curchar] - 32]->wwidth<0)
      {
         pos_x+=font->frame[ message[ curchar ] - 32]->wwidth;
         curchar++;
      }
   }
   
   if ( message[ curchar ]=='[' )
   {
      display=1;
      command_script+=message[ curchar ];
     
    if (message[curchar]==']')
      {
         if ( command_script=="PAUSE 1")
         {
            pause_mode=1;
            command_script="";
         }
         
         if ( command_script="PAUSE 2" )
         {
            pause_mode=2;
            command_script="";
         }
      }
//curchar+=1;   
}



   // wrap master 3000.
   if ( curchar >= message_length)
   {
      start_pos=0.0f;
   }
   
   // draw characters until right border reached
   while (pos_x<dest->wwidth && message[curchar])
   {
      char c=message[curchar] - 32;

      draw_gfx_buffer( dest, font->frame[c], pos_x, pos_y );
     
      pos_x+=font>frame[c]->wwidth;
      curchar++;
   }
   
   start_pos-=scroll_speed;

}
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

hellfire

This is a comparison:
if (command_script=="PAUSE 1")

This is an assignment:
if (command_script="PAUSE 2" )

What data-type is "command_script" ?
Challenge Trophies Won:

Jim

Clyde, in C++ strings don't work like they do in BASIC.

So
a = "X"
b = "X"

basic:
if a=b then print "YES"
will print YES

C:
if (a==b) printf("YES");
will not print anything.
The reason being it's comparing the address of a with the address of b, not the strings that they point to.

basic:
c=a+b
print c
will print XX

C:
c=a+b
won't even compile

This line
command_script+=message[ curchar ];
almost certainly doesn't do what you want it to do.  You are wanting to make a string in command_script by adding letters to the end.  That's not how strings work in C.  strings in C are just arrays of characters.  You might get some of what you want using C++'s 'string' class.

As Hellfire points out, it's really important not to get = and == mixed up.

Jim
Challenge Trophies Won:

Clyde

#38
Ok thanks!
command_script is the same as message:
static char *message1;
static char *command_script;

just dawned on me: command_script[index]=message[current_char];

edit - dont try this at home either.

void update_bitmap_scroller( gfx_buffer *dest, anim_image *font,  int pos_y )
{
static int command_index, execute;
int curchar= 0;
int pos_x=(int) start_pos;
// find first character that's not outside the left border
if ( display=0 )
{
  while ( message[curchar] && pos_x+font->frame[ message[curchar] - 32]->wwidth<0)
  {
   pos_x+=font->frame[ message[ curchar ] - 32]->wwidth;
   curchar++;
  }
}

if ( message[ curchar ]='[' )
{
  display=1;
  command_script[command_index]=scroller->message[ curchar ];
 
  if (scroller->message[curchar]=']')
  {
   execute=1;
  }
 
}
if ( execute=1 )
{
  if ( command_script[0]='W' && command_script[1]='A' && command_script[2]='I' && command_script[3]='T' )
  {
    pause=1;
 
  }
}
// wrap master 3000.
if ( curchar >= scroller_length)
{
         start_pos=0.0f;
}

// draw characters until right border reached
while (pos_x<dest->wwidth && message[curchar])
{
  char c= message[curchar] - 32;
  draw_gfx_buffer( dest, scroller->font->frame[c], pos_x, pos_y );
 
  pos_x+=font->frame[c]->wwidth;
  if ( pause!=0 ) curchar++;
                 }

start_pos-=scroll_speed;
}
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Jim

OK, but now you are writing to memory you don't own.
char *command_script;
is just thing that can hold a pointer.  Right now it's blank (or some random garbage) so it's pointing at nothing in particular.  You might get away with it just working, by not overwriting anything important, but one day it will cause a crash.

You need to initialise it to something, something big enough to hold your longest command strings, like this:

char *command_script = new char [50];


That will point it at 50 characters, but you have to remember to free it up at the end, like this

delete [] command_script;


You could instead declare

char command_script[50];

which gives you 50 chars of space (initially filled with garbage).

New problem:  You've used = instead of == in the new code.

if ( execute=1 )

is always true, because it's an assignment.  It puts the value 1 into execute and then does if (1) which is always true.
You want

if ( execute==1 )


When are you updating command_index?  Seems it will always be 0.

This is always true too

if ( command_script[0]='W' && command_script[1]='A' && command_script[2]='I' && command_script[3]='T' )

should be

if ( command_script[0]=='W' && command_script[1]=='A' && command_script[2]=='I' && command_script[3]=='T' )


This is long winded way of checking for strings though.  If you can arrange for command_script[4] to be 0 (perhaps when you see the ']' character you could stick it on the end then) then instead you can use

if (strcmp(command_script, "WAIT")==0)

You need #include <string.h> to use that.

Jim
Challenge Trophies Won: