0

When I try to compile the following lesson http://lazyfoo.net/downloads/index.php?file=SDLTut_lesson19

I have this output in Visual Studio 2010:

1>------ Build started: Project: 19-circularcollisiondetect, Configuration: Debug Win32 ------
1>Build started 02/03/2012 03:47:51.
1>InitializeBuildStatus:
1>  Touching "Debug\19-circularcollisiondetect.unsuccessfulbuild".
1>ClCompile:
1>  main.cpp
1>c:\users\fab\desktop\c++\sdl 1.2.15\19-circularcollisiondetect\19-circularcollisiondetect\main.cpp(140): error C2668: 'pow' : ambiguous call to overloaded function
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\math.h(583): could be 'long double pow(long double,int)'
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\math.h(535): or       'float pow(float,int)'
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\math.h(497): or       'double pow(double,int)'
1>          while trying to match the argument list '(int, int)'
1>c:\users\fab\desktop\c++\sdl 1.2.15\19-circularcollisiondetect\19-circularcollisiondetect\main.cpp(140): error C2668: 'pow' : ambiguous call to overloaded function
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\math.h(583): could be 'long double pow(long double,int)'
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\math.h(535): or       'float pow(float,int)'
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\math.h(497): or       'double pow(double,int)'
1>          while trying to match the argument list '(int, int)'
1>c:\users\fab\desktop\c++\sdl 1.2.15\19-circularcollisiondetect\19-circularcollisiondetect\main.cpp(162): warning C4018: '<' : signed/unsigned mismatch
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:00.80
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

How can I fix it? I'm using Visual Studio 2010 and SDL 1.2.15. I didn't modify the original code. Could you verify if you can compile it?

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

//The headers
#include "SDL.h"
#include "SDL_image.h"
#include <string>
#include <vector>
#include <cmath>

//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 = 20;

//The dot attributes
const int DOT_WIDTH = 20;

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

//The event structure
SDL_Event event;

//A circle structure
struct Circle
{
    int x, y;
    int r;
};

//The dot
class Dot
{
private:
    //The area of the dot
    Circle c;

    //The velocity of the dot
    int xVel, yVel;

public:
    //Initializes the variables
    Dot();

    //Takes key presses and adjusts the dot's velocity
    void handle_input();

    //Moves the dot
    void move( std::vector<SDL_Rect> &rects, Circle &circle );

    //Shows the dot on the screen
    void show();
};

//The timer class
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 );
}

double distance( int x1, int y1, int x2, int y2 )
{
    //Return the distance between the two points
    return sqrt( pow( x2 - x1, 2 ) + pow( y2 - y1, 2 ) );
}

bool check_collision( Circle &A, Circle &B )
{
    //If the distance between the centers of the circles is less than the sum of their radii
    if( distance( A.x, A.y, B.x, B.y ) < ( A.r + B.r ) )
    {
        //The circles have collided
        return true;
    }

    //If not
    return false;
}

bool check_collision( Circle &A, std::vector<SDL_Rect> &B )
{
    //Closest point on collision box
    int cX, cY;

    //Go through the B boxes
    for( int Bbox = 0; Bbox < B.size(); Bbox++ )
    {
        //Find closest x offset
        if( A.x < B[ Bbox ].x )
        {
            cX = B[ Bbox ].x;
        }
        else if( A.x > B[ Bbox ].x + B[ Bbox ].w )
        {
            cX = B[ Bbox ].x + B[ Bbox ].w;
        }
        else
        {
            cX = A.x;
        }

        //Find closest y offset
        if( A.y < B[ Bbox ].y )
        {
            cY = B[ Bbox ].y;
        }
        else if( A.y > B[ Bbox ].y + B[ Bbox ].h )
        {
            cY = B[ Bbox ].y + B[ Bbox ].h;
        }
        else
        {
            cY = A.y;
        }

        //If the closest point is inside the circle
        if( distance( A.x, A.y, cX, cY ) < A.r )
        {
            //This box and the circle have collided
            return true;
        }
    }

    //If the shapes have not collided
    return false;
}

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( "Move the Dot", NULL );

    //If everything initialized fine
    return true;
}

bool load_files()
{
    //Load the dot image
    dot = load_image( "dot.bmp" );

    //If there was a problem in loading the dot
    if( dot == NULL )
    {
        return false;
    }

    //If everything loaded fine
    return true;
}

void clean_up()
{
    //Free the surface
    SDL_FreeSurface( dot );

    //Quit SDL
    SDL_Quit();
}

Dot::Dot()
{
    //Initialize the offsets and dimentions
    c.x = DOT_WIDTH / 2;
    c.y = DOT_WIDTH / 2;
    c.r = DOT_WIDTH / 2;

    //Initialize the velocity
    xVel = 0;
    yVel = 0;
}

void Dot::handle_input()
{
    //If a key was pressed
    if( event.type == SDL_KEYDOWN )
    {
        //Adjust the velocity
        switch( event.key.keysym.sym )
        {
        case SDLK_UP: yVel -= 1; break;
        case SDLK_DOWN: yVel += 1; break;
        case SDLK_LEFT: xVel -= 1; break;
        case SDLK_RIGHT: xVel += 1; break;
        }
    }
    //If a key was released
    else if( event.type == SDL_KEYUP )
    {
        //Adjust the velocity
        switch( event.key.keysym.sym )
        {
        case SDLK_UP: yVel += 1; break;
        case SDLK_DOWN: yVel -= 1; break;
        case SDLK_LEFT: xVel += 1; break;
        case SDLK_RIGHT: xVel -= 1; break;
        }
    }
}

void Dot::move( std::vector<SDL_Rect> &rects, Circle &circle )
{
    //Move the dot left or right
    c.x += xVel;

    //If the dot went too far to the left or right or has collided with the other shapes
    if( ( c.x - DOT_WIDTH / 2 < 0 ) || ( c.x + DOT_WIDTH / 2 > SCREEN_WIDTH ) || ( check_collision( c, rects ) ) || ( check_collision( c, circle ) ) )
    {
        //Move back
        c.x -= xVel;
    }

    //Move the dot up or down
    c.y += yVel;

    //If the dot went too far up or down or has collided with the other shapes
    if( ( c.y - DOT_WIDTH / 2 < 0 ) || ( c.y + DOT_WIDTH / 2 > SCREEN_HEIGHT ) || ( check_collision( c, rects ) ) || ( check_collision( c, circle ) ) )
    {
        //Move back
        c.y -= yVel;
    }
}

void Dot::show()
{
    //Show the dot
    apply_surface( c.x - c.r, c.y - c.r, dot, screen );
}

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 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;

    //Make the dot
    Dot myDot;

    //Make the shapes
    std::vector<SDL_Rect> box( 1 );
    Circle otherDot;

    //Set the shapes' attributes
    box[ 0 ].x = 60;
    box[ 0 ].y = 60;
    box[ 0 ].w = 40;
    box[ 0 ].h = 40;

    otherDot.x = 30;
    otherDot.y = 30;
    otherDot.r = DOT_WIDTH / 2;

    //The frame rate regulator
    Timer fps;

    //Initialize
    if( init() == false )
    {
        return 1;
    }

    //Load the files
    if( load_files() == 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 ) )
        {
            //Handle events for the dot
            myDot.handle_input();

            //If the user has Xed out the window
            if( event.type == SDL_QUIT )
            {
                //Quit the program
                quit = true;
            }
        }

        //Move the dot
        myDot.move( box, otherDot );

        //Fill the screen white
        SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) );

        //Show the box
        SDL_FillRect( screen, &box[ 0 ], SDL_MapRGB( screen->format, 0x00, 0x00, 0x00 ) );

        //Show the other dot
        apply_surface( otherDot.x - otherDot.r, otherDot.y - otherDot.r, dot, screen );

        //Show our dot
        myDot.show();

        //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() );
        }
    }

    //Clean up
    clean_up();

    return 0;
}
genpfault
  • 51,148
  • 11
  • 85
  • 139
  • Simply because you cannot pass `int`s as the parameters to `pow`. See [this post](http://stackoverflow.com/questions/2398442/why-isnt-int-powint-base-int-exponent-in-the-standard-c-libraries) for details on rationale behind it. You can choose either of the solution provided based on the precision you need in your function – another.anon.coward Mar 02 '12 at 04:26
  • A small tip for future questions, try to keep the code sample as small as possible. In other words a [Short, Self Contained, Correct (Compilable), Example](http://sscce.org/). – Some programmer dude Mar 02 '12 at 06:31

2 Answers2

1

As the error shows:

1>c:\users\fab\desktop\c++\sdl 1.2.15\19-circularcollisiondetect\19-circularcollisiondetect\main.cpp(140): error C2668: 'pow' : ambiguous call to overloaded function
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\math.h(583): could be 'long double pow(long double,int)'
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\math.h(535): or       'float pow(float,int)'
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\math.h(497): or       'double pow(double,int)'

You're passing two integers into pow(), yet it takes either a long double and int, float and int, or double and int. Casting one of them should fix this for you, e.g.:

return sqrt( pow((double)(x2 - x1), 2 ) + pow((double)(y2 - y1), 2 ) );

I've used double here as it will more accurately represent the full range of integers than a float without being overkill, but if you're dealing with small numbers (in the 100s and 1000s) you could probably just use a float.

Matt Lacey
  • 8,227
  • 35
  • 58
0

The error is basically saying that there are multiple definitions for the math function pow, and the compiler does not know which one to automatically choose in this situation. Try explicitly casting the integers (x1, x2, y1, y2) in the line:

return sqrt( pow( x2 - x1, 2 ) + pow( y2 - y1, 2 ) );

...to floats like so:

return sqrt( pow( (float)( x2 - x1 ), 2 ) + pow( (float)( y2 - y1 ), 2 ) );
Alex Z
  • 2,500
  • 2
  • 19
  • 23