Page 1 of 2

Clipping Sprites

Posted: Tue Sep 30, 2008 8:49 pm
by Azorthy
It seems that clipping sprites right now is not working, like there are messed up ones when I select that are the whole tilesheet and I cna size it with my mouse, and others that are normal, and I cant solve it, it may be with the for loop under: Clip.

Code: Select all

/*This source code copyrighted by Lazy Foo' Productions (2004-2007) and may not be redestributed without written permission.*/

//The headers

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>
#include <fstream>
#include <iostream>
#include <windows.h>

using namespace std;

//Screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The frame rate
const int FRAMES_PER_SECOND = 60;

//Tile constants
const int TILE_WIDTH = 16;
const int TILE_HEIGHT = 16;
const int TOTAL_TILES_W = 240;
const int TOTAL_TILES_H = 240;
const int TILE_SPRITES = 22;

//The dimensions of the level
const int LEVEL_WIDTH = TILE_WIDTH*TOTAL_TILES_W;
const int LEVEL_HEIGHT = TILE_HEIGHT*TOTAL_TILES_H;

//The surfaces
SDL_Surface *screen = NULL;
SDL_Surface *tileSheet = NULL;

//Sprite from the tile sheet
SDL_Rect clips[ TILE_SPRITES ];

//The event structure 
SDL_Event event;

//The camera
SDL_Rect camera = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };

//The tile
class Tile
{
    private:
    //The attributes of the tile
    SDL_Rect box;
    
    //The tile type
    int type;
    
    public:
    //Initializes the variables
    Tile( int x, int y, int tileType );
    
    //Shows the tile
    void show();
    
    //Get the tile type
    int get_type();
    
    //Get the collision box
    SDL_Rect &get_box();
};

//The timer
class Timer
{
    private:
    //The clock time when the timer started
    int startTicks;
    
    //The ticks stored when the timer was paused
    int pausedTicks;
    
    //The timer status
    bool paused;
    bool started;
    
    public:
    //Initializes variables
    Timer();
    
    //The various clock actions
    void start();
    void stop();
    void pause();
    void unpause();
    
    //Gets the timer's time
    int get_ticks();
    
    //Checks the status of the timer
    bool is_started();
    bool is_paused();    
};

SDL_Surface *load_image( std::string filename ) 
{
    //The image that's loaded
    SDL_Surface* loadedImage = NULL;
    
    //The optimized surface that will be used
    SDL_Surface* optimizedImage = NULL;
    
    //Load the image
    loadedImage = IMG_Load( filename.c_str() );
    
    //If the image loaded
    if( loadedImage != NULL )
    {
        //Create an optimized surface
        optimizedImage = SDL_DisplayFormat( loadedImage );
        
        //Free the old surface
        SDL_FreeSurface( loadedImage );
        
        //If the surface was optimized
        if( optimizedImage != NULL )
        {
            //Color key surface
            SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ) );
        }
    }
    
    //Return the optimized surface
    return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL )
{
    //Holds offsets
    SDL_Rect offset;
    
    //Get offsets
    offset.x = x;
    offset.y = y;
    
    //Blit
    SDL_BlitSurface( source, clip, destination, &offset );
}

bool check_collision( SDL_Rect &A, SDL_Rect &B )
{
    //The sides of the rectangles
    int leftA, leftB;
    int rightA, rightB;
    int topA, topB;
    int bottomA, bottomB;

    //Calculate the sides of rect A
    leftA = A.x;
    rightA = A.x + A.w;
    topA = A.y;
    bottomA = A.y + A.h;
        
    //Calculate the sides of rect B
    leftB = B.x;
    rightB = B.x + B.w;
    topB = B.y;
    bottomB = B.y + B.h;
            
    //If any of the sides from A are outside of B
    if( bottomA <= topB )
    {
        return false;
    }
    
    if( topA >= bottomB )
    {
        return false;
    }
    
    if( rightA <= leftB )
    {
        return false;
    }
    
    if( leftA >= rightB )
    {
        return false;
    }
    
    //If none of the sides from A are outside B
    return true;
}

bool init()
{
    //Initialize all SDL subsystems
    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
    {
        return false;    
    }
    
    //Set up the screen
    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
    
    //If there was an error in setting up the screen
    if( screen == NULL )
    {
        return false;    
    }
    
    //Set the window caption
    SDL_WM_SetCaption( "Level Editior. Version 0.1", NULL );
    
    //If everything initialized fine
    return true;
}

bool load_files()
{
    //Load the tile sheet
    tileSheet = load_image( "TileSheet.bmp" );
    
    //If there was a problem in loading the tiles
    if( tileSheet == NULL )
    {
        return false;    
    }
    
    //If everything loaded fine
    return true;
}

void clean_up( Tile *tiles[][TOTAL_TILES_H] )
{
    //Free the surface
    SDL_FreeSurface( tileSheet );
    
    //Free the tiles
    for( int t = 0; t < TOTAL_TILES_W; t++ )
    {
        for ( int tt = 0; tt < TOTAL_TILES_H; tt++ )
        {
            //Get rid of old tile
            delete tiles[ t ] [ tt ];
        }
    }
    
    //Quit SDL
    SDL_Quit();
}

void set_camera()
{
    //Mouse offsets
    int x = 0, y = 0;
    
    //Get mouse offsets
    SDL_GetMouseState( &x, &y );
    
    //Move camera to the left if needed
    if( x < TILE_WIDTH )
    {
        camera.x -= 5;
    }
    
    //Move camera to the right if needed
    if( x > SCREEN_WIDTH - TILE_WIDTH )
    {
        camera.x += 5;
    }
    
    //Move camera up if needed
    if( y < TILE_WIDTH )
    {
        camera.y -= 5;
    }
    
    //Move camera down if needed
    if( y > SCREEN_HEIGHT - TILE_WIDTH )
    {
        camera.y += 5;
    }

    //Keep the camera in bounds.
    if( camera.x < 0 )
    {
        camera.x = 0;    
    }
    if( camera.y < 0 )
    {
        camera.y = 0;    
    }
    if( camera.x > LEVEL_WIDTH - camera.w )
    {
        camera.x = LEVEL_WIDTH - camera.w;    
    }
    if( camera.y > LEVEL_HEIGHT - camera.h )
    {
        camera.y = LEVEL_HEIGHT - camera.h;    
    } 
}

void put_tile( Tile *tiles[] [TOTAL_TILES_H], int tileType )
{
    //Mouse offsets
    int x = 0, y = 0;
    
    //Get mouse offsets
    SDL_GetMouseState( &x, &y );
    
    //Adjust to camera
    x += camera.x;
    y += camera.y;
    
    //Go through tiles
    for( int t = 0; t < TOTAL_TILES_W; t++ )
    {
        for ( int tt = 0; tt < TOTAL_TILES_H; tt++ )
        {
        //Get tile's collision box
        SDL_Rect box = tiles[ t ] [ tt ] ->get_box();
        
        //If the mouse is inside the tile
        if( ( x > box.x ) && ( x < box.x + box.w ) && ( y > box.y ) && ( y < box.y + box.h ) )
        {
            //Get rid of old tile
            delete tiles[ t ] [ tt ];
            
            //Replace it with new one
            tiles[ t ] [ tt ] = new Tile( box.x, box.y, tileType );
        }
        }
    }
}

void clip_tiles()
{
    /*
    //Clip the sprite sheet
    clips[ TILE_GRASS ].x = 0;
    clips[ TILE_GRASS ].y = 0;
    clips[ TILE_GRASS ].w = TILE_WIDTH;
    clips[ TILE_GRASS ].h = TILE_HEIGHT;
    
    clips[ TILE_GRASS_2 ].x = TILE_WIDTH;
    clips[ TILE_GRASS_2 ].y = 0;
    clips[ TILE_GRASS_2 ].w = TILE_WIDTH;
    clips[ TILE_GRASS_2 ].h = TILE_HEIGHT;
    
    clips[ TILE_DIRT ].x = (TILE_WIDTH*2);
    clips[ TILE_DIRT ].y = 0;
    clips[ TILE_DIRT ].w = TILE_WIDTH;
    clips[ TILE_DIRT ].h = TILE_HEIGHT;

    clips[ TILE_DIRT_2 ].x = (TILE_WIDTH*3);
    clips[ TILE_DIRT_2 ].y = 0;
    clips[ TILE_DIRT_2 ].w = TILE_WIDTH;
    clips[ TILE_DIRT_2 ].h = TILE_HEIGHT;

    clips[ TILE_DIRT_3 ].x = (TILE_WIDTH*4);
    clips[ TILE_DIRT_3 ].y = 0;
    clips[ TILE_DIRT_3 ].w = TILE_WIDTH;
    clips[ TILE_DIRT_3 ].h = TILE_HEIGHT;
        
    clips[ TILE_SAND ].x = (TILE_WIDTH*5);
    clips[ TILE_SAND ].y = 0;
    clips[ TILE_SAND ].w = TILE_WIDTH;
    clips[ TILE_SAND ].h = TILE_HEIGHT;
    
    clips[ TILE_WATER ].x = (TILE_WIDTH*6);
    clips[ TILE_WATER ].y = 0;
    clips[ TILE_WATER ].w = TILE_WIDTH;
    clips[ TILE_WATER ].h = TILE_HEIGHT;
    
    clips[ TILE_GRAVEL ].x = (TILE_WIDTH*7);
    clips[ TILE_GRAVEL ].y = 0;
    clips[ TILE_GRAVEL ].w = TILE_WIDTH;
    clips[ TILE_GRAVEL ].h = TILE_HEIGHT;
    
    clips[ TILE_WOOD ].x = (TILE_WIDTH*8);
    clips[ TILE_WOOD ].y = 0;
    clips[ TILE_WOOD ].w = TILE_WIDTH;
    clips[ TILE_WOOD ].h = TILE_HEIGHT;
    
    clips[ TILE_DANCE_RED ].x = (TILE_WIDTH*9);
    clips[ TILE_DANCE_RED ].y = 0;
    clips[ TILE_DANCE_RED ].w = TILE_WIDTH;
    clips[ TILE_DANCE_RED ].h = TILE_HEIGHT;
    
    clips[ TILE_DANCE_WHITE ].x = (TILE_WIDTH*10);
    clips[ TILE_DANCE_WHITE ].y = 0;
    clips[ TILE_DANCE_WHITE ].w = TILE_WIDTH;
    clips[ TILE_DANCE_WHITE ].h = TILE_HEIGHT;
    */
    for( int i = 0; i < TILE_SPRITES; i++)
    {
         if( i == 0 )
         {
            clips[ i ].x = 0;
            clips[ i ].y = 0;
            clips[ i ].w = TILE_WIDTH;
            clips[ i ].h = TILE_HEIGHT;    
         }
         else {
         clips[ i ].x = (TILE_WIDTH*i);
         clips[ i ].y = 0;
         clips[ i ].w = TILE_WIDTH;
         clips[ i ].h = TILE_HEIGHT;   
         }
    }
}

bool set_tiles( Tile *tiles[][TOTAL_TILES_H] )
{
    //The tile offsets
    int x = 0, y = 0;
    int tileType;
    
    //Open the map
    std::ifstream map( "test.map" );
    
    //If the map couldn't be loaded
    if( map == NULL )
    {
        //Initialize the tiles
        for( int t = 0; t < TOTAL_TILES_H; t++ )
        {
            for( int tt = 0; tt < TOTAL_TILES_W; tt++ )
            {
            //Put a floor tile
            tiles[ t ] [ tt ] = new Tile( tt*TILE_WIDTH, t*TILE_WIDTH, 0 );
            }
        }
    }
    else
    {
        //Initialize the tiles
        for( int t = 0; t < TOTAL_TILES_H; t++ )
        {
            for( int tt = 0; tt < TOTAL_TILES_W; tt++ )
            {
            map >> tileType;
            //Put a floor tile
            tiles[ t ] [ tt ] = new Tile( tt*TILE_WIDTH, t*TILE_WIDTH, tileType );
            }
        }
    
        //Close the file
        map.close();
    }
    
    return true;
}

void save_tiles( Tile *tiles[][TOTAL_TILES_W] )
{
    //Open the map
    std::ofstream map( "test.map" );
    
    //Go through the tiles
    for( int t = 0; t < TOTAL_TILES_W ; t++ )
    {
        for( int tt = 0; tt < TOTAL_TILES_W; tt++ )
        {
        //Write tile type to file
        map << tiles[ t ] [tt] ->get_type() << " ";
        }
    }
    
    //Close the file
    map.close();
}

Tile::Tile( int x, int y, int tileType )
{
    //Get the offsets
    box.x = x;
    box.y = y;
    
    //Set the collision box
    box.w = TILE_WIDTH;
    box.h = TILE_HEIGHT;
    
    //Get the tile type
    type = tileType;
}

void Tile::show()
{
    //If the tile is on screen
    if( check_collision( camera, box ) == true )
    {
        //Show the tile
        apply_surface( box.x - camera.x, box.y - camera.y, tileSheet, screen, &clips[ type ] );    
    }
}    

int Tile::get_type()
{
    return type;
}

SDL_Rect &Tile::get_box()
{
    return box;
}

Timer::Timer()
{
    //Initialize the variables
    startTicks = 0;
    pausedTicks = 0;
    paused = false;
    started = false;    
}

void Timer::start()
{
    //Start the timer
    started = true;
    
    //Unpause the timer
    paused = false;
    
    //Get the current clock time
    startTicks = SDL_GetTicks();    
}

void Timer::stop()
{
    //Stop the timer
    started = false;
    
    //Unpause the timer
    paused = false;    
}

void Timer::pause()
{
    //If the timer is running and isn't already paused
    if( ( started == true ) && ( paused == false ) )
    {
        //Pause the timer
        paused = true;
    
        //Calculate the paused ticks
        pausedTicks = SDL_GetTicks() - startTicks;
    }
}

void Timer::unpause()
{
    //If the timer is paused
    if( paused == true )
    {
        //Unpause the timer
        paused = false;
    
        //Reset the starting ticks
        startTicks = SDL_GetTicks() - pausedTicks;
        
        //Reset the paused ticks
        pausedTicks = 0;
    }
}

int Timer::get_ticks()
{
    //If the timer is running
    if( started == true )
    {
        //If the timer is paused
        if( paused == true )
        {
            //Return the number of ticks when the the timer was paused
            return pausedTicks;
        }
        else
        {
            //Return the current time minus the start time
            return SDL_GetTicks() - startTicks;
        }    
    }
    
    //If the timer isn't running
    return 0;    
}

bool Timer::is_started()
{
    return started;    
}

bool Timer::is_paused()
{
    return paused;    
}

int main( int argc, char* args[] )
{
    
    //Quit flag
    bool quit = false;
    
    //Current tile type
    int currentType = 0;
    
    //The tiles that will be used
    Tile *tiles[ TOTAL_TILES_W ] [TOTAL_TILES_H];
    
    //The frame rate regulator
    Timer fps;
    
    //Initialize
    if( init() == false )
    {
        return 1;
    }
    
    //Load the files
    if( load_files() == false )
    {
        return 1;
    }

    //Clip the tile sheet
    clip_tiles();
    
    //Set the tiles
    if( set_tiles( tiles ) == false )
    {
        return 1;    
    }
        
    //While the user hasn't quit
    while( quit == false )
    {
        //Start the frame timer
        fps.start();
        
        //While there's events to handle
        while( SDL_PollEvent( &event ) )
        {
            //When the user clicks
            if( event.type == SDL_MOUSEBUTTONDOWN )
            {
                //On left mouse click
                if( event.button.button == SDL_BUTTON_LEFT )
                {
                    //Put the tile
                    put_tile( tiles, currentType );
                }
                //On mouse wheel scroll
                else if( event.button.button == SDL_BUTTON_WHEELUP )
                {
                    //Scroll through tiles
                    currentType--;
                    
                    if( currentType < 0 )
                    {
                        currentType = TILE_SPRITES;
                    }
                }
                else if( event.button.button == SDL_BUTTON_WHEELDOWN )
                {
                    //Scroll through tiles
                    currentType++;
                    
                    if( currentType > TILE_SPRITES )
                    {
                        currentType = 0;
                    }
                }
            }
            
            //If the user has Xed out the window
            if( event.type == SDL_QUIT )
            {
                //Quit the program
                quit = true;
            }
        }
        
        //Set the camera
        set_camera();
        
        //Show the tiles
        for( int t = 0; t < TOTAL_TILES_W ; t++ )
        {
            for( int tt = 0; tt < TOTAL_TILES_W; tt++ )
            {
                //Write tile type to file
                tiles[ t ] [ tt ]->show();
            }
        }
        
        apply_surface( 0, 0, tileSheet, screen, &clips[ currentType ] );
        
        //Update the screen
        if( SDL_Flip( screen ) == -1 )
        {
            return 1;    
        }
        
        //Cap the frame rate
        if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
        {
            SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
        }
    }
    
    //Save the tile map
    save_tiles( tiles );
    
    //Clean up
    clean_up( tiles );
    
    delete tileSheet;
    
    return 0;    
}


Re: Clipping Sprites

Posted: Wed Oct 01, 2008 12:11 pm
by Dr. House
Okay, first of all. Nobody has responded to this, because you posted an entire program. Of that program, 90% was completely irrelevant, and only 10% had any sort of meaning with regard to your question.

You're talking about screwed up tiles, why do I care about your timer system or your mouse input? Let me answer for you--I don't.

But the funny thing is that had you posted the relevant pieces, we could've answered your question in about 10 seconds. The problem lies here:

Code: Select all

void clip_tiles()
{
    for( int i = 0; i < TILE_SPRITES; i++)
    {
         if( i == 0 )
         {
            clips[ i ].x = 0;
            clips[ i ].y = 0;
            clips[ i ].w = TILE_WIDTH;
            clips[ i ].h = TILE_HEIGHT;    
         }
         else {
         clips[ i ].x = (TILE_WIDTH*i);
         clips[ i ].y = 0;
         clips[ i ].w = TILE_WIDTH;
         clips[ i ].h = TILE_HEIGHT;   
         }
    }
}
Upon examination of the preceeding function (after I deleted the other irrelevant pieces), the problem hit me like a kick from my last girlfriend in the nuts.

Look, friend:

Code: Select all

const int TILE_WIDTH = 16;
const int TILE_HEIGHT = 16;
const int TOTAL_TILES_W = 240;
const int TOTAL_TILES_H = 240;
const int TILE_SPRITES = 22;
Now lets examine this. We have a spritesheet whose dimensions are 240x240. Sweet. Now we take into account that each tile is 16x16.

With these two values, we are able to see how many total tiles there are in the sheet. 240 pixels wide divided by 16 pixels per tile equals 15 tiles in each row. (240/16=15). Now the same applies for your height. You have 15x15 tiles on your sheet.

But your clipping function begs to differ!

Code: Select all

void clip_tiles()
{
    for( int i = 0; i < TILE_SPRITES; i++)
    {
         if( i == 0 )
         {
            clips[ i ].x = 0;
            clips[ i ].y = 0;
            clips[ i ].w = TILE_WIDTH;
            clips[ i ].h = TILE_HEIGHT;    
         }
         else {
         clips[ i ].x = (TILE_WIDTH*i);
         clips[ i ].y = 0;
         clips[ i ].w = TILE_WIDTH;
         clips[ i ].h = TILE_HEIGHT;   
         }
    }
}
I see two problems here. One, the if statement is pointless, but that's not causing the problem. Two, you're assuming that every sprite is on the same (top row).

Code: Select all

clips[ i ].x = (TILE_WIDTH*i);
         clips[ i ].y = 0;
         clips[ i ].w = TILE_WIDTH;
         clips[ i ].h = TILE_HEIGHT;   
clips.y=0. That's incorrect. Sure, it's correct for your first 15 tiles, because those are on the first row (where y should be 0). But after 15, you have to move down to the next row (so your 16-22 sprites are going to be fucked--to put it nicely).

I can't quite decipher your poorly constructed english, but I'm pretty sure this diagnosis fits your symptoms.

So here's your fix. Use this instead:

Code: Select all

void clip_tiles() {

int tileColumns = TOTAL_TILE_W/TILE_WIDTH;
int tileRows = TOTAL_TILE_H/TILE_HEIGHT;

//Loop through each row on the sheet
    for( int i = 0; i < tileRows; ++i) {
//Loop through each column on the sheet
        for(int j = 0; j < tileColumns; ++j) {

         clips[ i*tileColumns+j ].x = (TILE_WIDTH*j);
         clips[ i*tileColumns+j ].y = (TILE_HEIGHT*i);
         clips[ i*tileColumns+j ].w = TILE_WIDTH;
         clips[ i*tileColumns+j ].h = TILE_HEIGHT;   
        }
    }
}
Thank you, and have a nice day.

Oh, and one more thing. Your if statement was pointless. If 'i' were equal to 0, then TILE_WIDTH*i would've been 0 anyway.

*twirls cane*

Re: Clipping Sprites

Posted: Wed Oct 01, 2008 2:41 pm
by Azorthy
Thanks a lot I didn't know about the whole x/y thing so if i had a 240 width times a 16 height that i would have to move one row done. Now we need rep.

Re: Clipping Sprites

Posted: Wed Oct 01, 2008 2:48 pm
by Falco Girgis
Yeah. House's Clip() function that he fixed does it for you, though.

Re: Clipping Sprites

Posted: Wed Oct 01, 2008 5:37 pm
by Azorthy
Way different to open gl and allegro.

Re: Clipping Sprites

Posted: Wed Oct 01, 2008 6:56 pm
by Falco Girgis
I have no idea what you're trying to say, but what House did is platform independent.

Re: Clipping Sprites

Posted: Wed Oct 01, 2008 7:36 pm
by Azorthy
Well my tile sheet is actually all on one line, I fixed that and i still have this invisible tile, and sometimes a mouse decided clipping of the whole tile sheet I think it may also be under selection.

Re: Clipping Sprites

Posted: Wed Oct 01, 2008 7:57 pm
by Dr. House
So you failed to mention that your spritesheet size didn't match the GIGANTIC_TYPEDEFFED_NUMBERS at the beginning of the program, and you opted to throw the entire program at us (complete with 100+ lines of irrelevancies) and half-literate post describing the problem?

Then you continue to make posts that nobody can understand. My helping you ends here.

Re: Clipping Sprites

Posted: Wed Oct 01, 2008 8:04 pm
by Azorthy
I had a different tile set, now that I am making my own it changed and it turns out that the array needs an null ending character so...

clips [ TILE_SPRITES+1 ];

Will fix that and Install a reputation meter so I can spam Dr.House with good reputation.

Re: Clipping Sprites

Posted: Wed Oct 01, 2008 8:31 pm
by dandymcgee
Will fix that and Install a rep meter so I can spam Dr.House with good rep.
Run-on sentence.. makes it seem as if YOU are installing the rep(utation) meter. Also, saying the whole word makes it slightly more understandable. Glad someone could help you fix your clip problem :)

Re: Clipping Sprites

Posted: Thu Oct 02, 2008 8:45 am
by MarauderIIC
Azorthy wrote:I had a different tile set, now that I am making my own it changed and it turns out that the array needs an null ending character so...

clips [ TILE_SPRITES+1 ];

Will fix that and Install a reputation meter so I can spam Dr.House with good reputation.
Actually, there's a report button.

Re: Clipping Sprites

Posted: Thu Oct 02, 2008 1:52 pm
by dandymcgee
But wait.. isn't that for reporting BAD things? He wants to spam him with good reputation because he's thankful (that's my understanding).

Re: Clipping Sprites

Posted: Thu Oct 02, 2008 1:58 pm
by Falco Girgis
Dr. House is fueled purely by his own narcissism--he takes pride in being able to solve puzzles. I really doubt that asskissery will win the man over.

Re: Clipping Sprites

Posted: Thu Oct 02, 2008 2:04 pm
by dandymcgee
GyroVorbis wrote:Dr. House is fueled purely by his own narcissism--he takes pride in being able to solve puzzles. I really doubt that asskissery will win the man over.
Haha, word of the day: narcissism.

Re: Clipping Sprites

Posted: Thu Oct 02, 2008 2:49 pm
by MarauderIIC
dandymcgee wrote:But wait.. isn't that for reporting BAD things? He wants to spam him with good reputation because he's thankful (that's my understanding).
I dunno. Probably. I read sarcasm into the thankful bit.