• Welcome to Dark Bit Factory & Gravity.
 

[C++] Converting FreeBASIC Pointer Types into a Class

Started by Clyde, August 14, 2009

Previous topic - Next topic

0 Members and 0 Guests are viewing this topic.

Clyde

Sure thing dude, and that's really swell of you.

[ ed 209 ] i've included a zip archive of the individual files used including the tinyptc MSVC lib, and thanks for your time in this matter. [ / ed209 ]

Very cool and cheers,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Shockwave

Off topic:

QuoteSure thing dude, and that's really swell of you.

Do you talk like that in real life?

On Topic:

Thanks for not giving with it Clyde and Jim, good luck.
Shockwave ^ Codigos
Challenge Trophies Won:

hellfire

Clyde, you just have a typo in create_anim_images:
for ( y_test=y; y_test<(y+height-1); y_test=+1)
should be:
for ( y_test=y; y_test<(y+height-1); y_test+=1)

It's easy to find such stuff by simply stepping through the code with the debugger.
Challenge Trophies Won:

TinDragon

Also in your main loop you have one as well

draw_gfx_buffer( screen_buffer, font_one->images[19], 0, 0 );


Should be
draw_gfx_buffer( screen_buffer, font_one->frame[19], 0, 0 );

Since you dont have an "images" in that class, which should be an error when trying to compile. BTW displays a 5 on screen but has some white lines like its offcentre, probably your sizes are slightly out ;)

[edit]god i made typo's giving you the info  :D

Jim

My guess is that part of the problem is in the display code

if (x+pos_x>0)
if (x+pos_x<dest->wwidth-1)
if (y+pos_y>0)
if (y+pos_y<dest->height-1)

and that we have a selection of 'off by one' errors here

if (x+pos_x>=0)
if (x+pos_x<dest->wwidth)
if (y+pos_y>=0)
if (y+pos_y<dest->height)

With those fixed you can now draw on the first and last scanlines and first and last pixels of every scanline.

I think there are similar problems in the code that's copying the characters out of the big sprite into the small ones, causing the offset.
Clyde, in C++ all arrays count from 0 and finish one index sooner than in FB. So,
int number[3];
has 3 ints in it.  number[0], number[1], number[2].  It's a bad error to use number[3].
Also, in FB the For loops go for one more iteration
For a=0 To 3
a=0, a=1, a=2, a=3
Where in C++
for (int a=0; a < 3; a++)
a=0, a=1, a=2

It looks like you've adjusted for this in most places, but I think there are still some problems.  Worth just doing a quick compare with the FB and C++ for all the If and For to check.

Jim
Challenge Trophies Won:

Clyde

Thanks all for the info, will have a gander in a mo, need to switch to the other OS that has VS C++ on it.

JC2K: I forgot I had changed that, when I was collecting the files for zipping, I missed one when spring cleaning it.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Clyde

Awesome!! with a capital A :)
I owe you all a pint of what ever takes your fancy! :)

Thanks so much dudes!!!!!,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Clyde

With this print_text function, it doesnt draw the correct letters, it always draws from the first ( 0 ) frame upto how ever long it is, but not the corresponding letter for example:

text="CLYDE"
output:
[space] ! " £ $ %


void print_text( gfx_buffer *dest, anim_image *font, int pos_x, int pos_y, char *message )
{
int len=strlen( message ); //length of the message text.

for ( int a=0; a<len; a++)
{
char frame=message[a]-32; //splits message into appropriate letter.

if (frame>=0 )
if ( frame<=font->total_frames-1 )
{
draw_gfx_buffer( dest, font->frame[a], pos_x, pos_y );
pos_x+=font->frame[a]->wwidth;
}

} // next a

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


Challenge Trophies Won:

hellfire

Quotedraw_gfx_buffer( dest, font->frame[a], pos_x, pos_y );
You don't want to draw character "a" (which counts the letters in your string) but "frame".
Challenge Trophies Won:

Clyde

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


Challenge Trophies Won:

Clyde

I thought all was ok, but it's not taking the correct widths per frame into account, they're all 64x64, when they should be ( width upto 64 + space )  * 64.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Jim

Problem is here (in two places):

if (srce->pixels[ (x_test)+(y_test) * srce->wwidth]!=0)

should be

if (srce->pixels[ (x_test)+(y_test) * srce->wwidth]!=0xff000000)

That fixes most of the width-based stuff, though there's still something else wrong

Jim
Challenge Trophies Won:

Jim

Tidied up some more off-by-ones in the for loops.  Here's the whole thing working:

//
// includes.
//
#include <windows.h>
#include "tinyptc_ext.h"

extern unsigned char us64_pal[]; // 64 distinguishes a variable font based around max width of 64, height == 64
extern unsigned char us64_raw[]; // i am unsure if this font is 8*8, or 8*16 ( including upper and lower case characters )

//
// classes.
//
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;
};

//
// function declarations.
//
int set_graphics( char *title, int wwidth, int height );

gfx_buffer *create_gfx_buffer( int wwidth, int height);
gfx_buffer *load_gfx_buffer( unsigned char *pal, unsigned char *raw, int wwidth, int height);

anim_image *create_anim_images( gfx_buffer *srce, int wwidth, int height, int blank_wwidth, int min_wwidth, int spacing );
anim_image *create_anim_images2( gfx_buffer *srce, int wwidth, int height );
//
// sub routines.
//
void draw_gfx_buffer( gfx_buffer *dest, gfx_buffer *srce, int pos_x, int pos_y );
void print_text( gfx_buffer *dest, anim_image *font, int pos_x, int pos_y, char *message );

int main()
{
//
// initializing.
//
gfx_buffer *screen_buffer=create_gfx_buffer( 640, 480 );

gfx_buffer *font_image=load_gfx_buffer( us64_raw, us64_pal, 512, 512 );
anim_image *font_one=create_anim_images( font_image, 64, 64, 32, 2, 1 );

set_graphics( "gRaPhIcS aNtIcS", 640, 480 );


// main program loop.
while (1)
{
// clear screen.
for( int index=0; index<(screen_buffer->wwidth*screen_buffer->height); index++)
screen_buffer->pixels[index]=0x000000;
// next index

// remove remarks to test the image has been loaded successfully.
//draw_gfx_buffer( screen_buffer, font_one->frame[19], 0, 0 );
//draw_gfx_buffer( screen_buffer, font_image, 0, 0 );

print_text(screen_buffer, font_one, 10,10, "HELLO");

// render to the screen buffer.
ptc_update( &screen_buffer->pixels[0] );

} // wend.

} // end function main()

void print_text( gfx_buffer *dest, anim_image *font, int pos_x, int pos_y, char *message )
{
int len=strlen( message ); //length of the message text.

for ( int a=0; a<len; a++)
{
char frame=message[a]-32; //splits message into appropriate letter.

if (frame>=0 )
if ( frame<=font->total_frames-1 )
{
draw_gfx_buffer( dest, font->frame[frame], pos_x, pos_y );
pos_x+=font->frame[frame]->wwidth;
}

} // next a

} // end function

int set_graphics( char *title, int wwidth, int height )
{
ptc_allowclose(1);
ptc_setflip(1);

ptc_setdialog(1,"Would You Prefer Full Screen Dude?",1,0);

if (!ptc_open( title,wwidth,height))
return 1;
else
return 0;
// end if.

}


gfx_buffer *create_gfx_buffer( int wwidth, int height )
{
gfx_buffer *buffer = new gfx_buffer;

buffer->pixels = new unsigned int [wwidth*height];

buffer->wwidth = wwidth;
buffer->height = height;

buffer->wwidth2=wwidth/2;
buffer->height2=height/2;

return buffer;

}


void draw_gfx_buffer( gfx_buffer *dest, gfx_buffer *srce, int pos_x, int pos_y )
{
for (int y=0; y<srce->height; y++)
for (int x=0; x<srce->wwidth; x++)

if (x+pos_x>=0)
if (x+pos_x<dest->wwidth)
if (y+pos_y>=0)
if (y+pos_y<dest->height)

dest->pixels[ (x+pos_x)+(y+pos_y) * dest->wwidth ]=srce->pixels[ x+y*srce->wwidth ];
// next x.
//next y
}




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;

//
// create a new image.
//
gfx_buffer *buffer = create_gfx_buffer( wwidth, height );

//
// convert the palette to 32 bit.
//
unsigned int palette[256];
int index;

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

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

return buffer;
}

anim_image *create_anim_images( gfx_buffer *srce, int wwidth, int height, int blank_wwidth, int min_wwidth, int spacing )
{
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 ];

if (blank_wwidth==0)
blank_wwidth=wwidth;

if (min_wwidth>wwidth)
min_wwidth=wwidth;

int frame_number=0, x=0, y=0, test_l=0, test_r=0, x_test=0, y_test=0;

for (y=0; y<frame_h*height; y+=height )
{
for (x=0; x<frame_w*wwidth; x+=wwidth )
{
//
// test x.
//
test_r=x;

for ( x_test=x; x_test<(x+wwidth); x_test+=1 )
{
for ( y_test=y; y_test<(y+height); y_test+=1 )
{
if (srce->pixels[ (x_test)+(y_test) * srce->wwidth]!=0xff000000)
test_r=x_test;
} // next y_test.
} //next x_test.


//
// test l.
//
test_l=x+wwidth-1;

for ( x_test=x+wwidth-1; x_test>=x; x_test-=1 )
{
for ( y_test=y; y_test<y+height; y_test+=1)
{
if (srce->pixels[ (x_test)+(y_test)*srce->wwidth]!=0xff000000)
test_l=x_test;

}// next y_test.
}// next x_test.


//
// bob the builder time! :)
//
if (test_r>=test_l)
{   
test_l-=spacing >> 1;
test_r+=spacing-(spacing >> 1);

if (test_r-test_l<min_wwidth)
{
x_test=min_wwidth-(test_r-test_l);
test_r+=x_test >> 1 ;
test_l-=x_test-(x_test >> 1);
} //end if

if (test_r>x+wwidth-1) //then
test_r=x+wwidth-1;
// end if



if (test_l<x) // then
test_l=x;
// end if

anim_buffer->frame[frame_number]=create_gfx_buffer(test_r-test_l+1,height);
draw_gfx_buffer( anim_buffer->frame[frame_number],srce,-test_l,-y);




}
else
{
anim_buffer->frame[frame_number]=create_gfx_buffer(blank_wwidth,height);
} // end if

frame_number+=1;

} // next x
} // next y

anim_buffer->frame_wwidth = frame_w;
anim_buffer->frame_height = frame_h;
anim_buffer->total_frames = total_frames;

return anim_buffer;
}


Jim
Challenge Trophies Won:

Clyde

Thats just perfect, a great pressie! :D
So you need to be exact with your value checking!

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


Challenge Trophies Won:

Clyde

you may of noticed me using this slow method of clearing the screen, any ideas on how to improve upon it?


for( int index=0; index<(screen_buffer->wwidth*screen_buffer->height); index++)
screen_buffer->pixels[index]=0x000000;


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


Challenge Trophies Won:

Jim

Make sure you have

#include <string.h>

at the top, then replace the for loop with

memset(screen_buffer->pixels, 0, screen_buffer->wwidth*screen_buffer->height * sizeof(unsigned int));


Jim
Challenge Trophies Won:

Clyde

Cheers Jim! :)

I get the following when ever I use sin / cos. Im wondering if this is telling me to add MSVCRT.lib or something else to the linker?

MSVCRT.lib(cpu_disp.obj) : warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators

how i use sin to avoid conversion warnings / loss of data errors:

mockup example:

float sinx;
int sinxx;

sinx=(float) sin( [i]insert_formula[/i] );
sinxx=(int) sinx;
draw( sinxx, 200, 0xFFFF0000 ); // ( usage - posx as int, posy as int, colour as unsigned int )
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.


Challenge Trophies Won:

Jim

To use sin() etc. you should

#include <math.h>

You can ignore the warnings.  I have already explained to you in this thread about the loss of precision warnings.

The .CRT warning is some problem in your project settings.  It's just a warning.  I don't know what's triggering it.  Can you post a zip of all your files again?

Jim
Challenge Trophies Won:

TinDragon

sinx=(float) sin( [i]insert_formula[/i] );

I would think that should be "float sin(float whatever);" which is only available in C++ if the compiler help is correct. TBH if your using float values then use sinf() which expects a float in and gives a float out, which Jim mentioned earlier in this very thread, sin() works with doubles so will likely give the warning double to float conversion or something similiar, which you can ignore but it is better to fix imho.




hellfire

Generally VC++ is a bit picky with double/float conversions by default which results in a store and reload of every intermediary result.
To get around this you can set the fpu-precision to "fast" in the C++ settings.
But keep in mind that "missing" rounding leads to different results.

A simple example:

  float sum= 0.0f;
  for (float x=0.0f;x<10.0f;x+=0.1f)
  {
     float y= sin(x);
     sum+=y;
  }
  printf("result: %f \n", sum);



disassembly with fpu-precision "fast"

00401006  fldz            
00401008  fld         st(0)
0040100A  fld         dword ptr [402100h]
00401010  fld         dword ptr [4020FCh]
00401016  jmp         main+1Ah (40101Ah)
00401018  fxch        st(3)
0040101A  fld         st(3)
0040101C  fsin            
0040101E  faddp       st(3),st
00401020  fxch        st(3)
00401022  fadd        st,st(1)
00401024  fcom        st(3)
00401026  fnstsw      ax  
00401028  test        ah,5
0040102B  jnp         401018h

result: 18.647397

...and "precise"

00401009  fldz            
0040100B  fst         dword ptr [esp+38h]
0040100F  fstp        dword ptr [esp+34h]
00401013  fld         dword ptr [esp+34h]
00401017  call        _CIsin (401870h)
0040101C  fstp        dword ptr [esp+3Ch]
00401020  fld         dword ptr [esp+3Ch]
00401024  fadd        dword ptr [esp+38h]
00401028  fstp        dword ptr [esp+38h]
0040102C  fld         dword ptr [esp+34h]
00401030  fadd        qword ptr [402100h]
00401036  fstp        dword ptr [esp+34h]
0040103A  fld         dword ptr [4020FCh]
00401040  fld         dword ptr [esp+34h]
00401044  fcom        st(1)
00401046  fnstsw      ax  
00401048  fstp        st(1)
0040104A  test        ah,5
0040104D  jnp         main+17h (401017h)

result: 18.647362

Challenge Trophies Won: