Hi i am trying to create a racing game and at the moment i have keyboard input which moves the player around at the same continous speed. I am wanting it to speed the player up however the longer you hold the key down for. Any simple way i can achieve this?

#include "SDL.h"
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>

#pragma comment(lib,"Winmm.lib")


/* ---------------------------------------------------------------------- */
/* Defines/Enumerations                                                   */
/* ---------------------------------------------------------------------- */

#define SPEED 2
#define GAMETIME 30  //inactivity for 30s quits game

/* ---------------------------------------------------------------------- */
/* Type Declarations                                                      */
/* ---------------------------------------------------------------------- */

struct PLAYER
{
  //SDL_Rect pos;
  SDL_Surface *sprite;
  Sint32 dir;
  Sint32 life;
  Sint32 score;
  float by;
  float bx;
  float pos_y;
  float pos_x;
  bool up, right, left, down;
  bool w, s, a, d;
  


};

struct BALL
{
  //SDL_Rect pos;
  SDL_Surface *sprite;
  float bx, by;
  float pos_x, pos_y;

};

/* ---------------------------------------------------------------------- */
/* Global Data                                                            */
/* ---------------------------------------------------------------------- */

/// The start time
SDL_Surface *SCREEN;

/// Some Sprites
SDL_Surface *background, *intro, *numbers;

PLAYER playerA, playerB;
BALL ball;

SDL_Joystick *joy0;
Uint32 iTicksLastKey=0;  //inactivity counter
Uint32 TicksElapsed=0; //ticks elapsed since last update
Sint16 iMoveX;
Sint16 iMoveY;
Sint16 iMoveXOld;  //for comparing the last value
Sint16 iMoveYOld;
float ballspeed=85; //ball speed, number of pixels ball travels in one second
SDL_Surface *level;

/* ---------------------------------------------------------------------- */
/* Helper                                                                 */
/* ---------------------------------------------------------------------- */

void go();

/// Handle events
bool handleEvents()
{
  SDL_Event event;
 
    while (SDL_PollEvent(&event))
    {
    switch(event.type)
        {
            case SDL_KEYDOWN:
            {
                switch(event.key.keysym.sym)
                {
                    case SDLK_UP:   { playerB.up = true; break; }
                    case SDLK_DOWN: { playerB.down =  true; break; }
                    case SDLK_LEFT: { playerB.left =  true; break; }
                    case SDLK_RIGHT: { playerB.right =  true; break; }
                    case SDLK_w:    { playerA.w = true; break; }
                    case SDLK_s:    { playerA.s =  true; break; }
                    case SDLK_a:    { playerA.a = true; break; }
                    case SDLK_d:    { playerA.d =  true; break; }
                    case SDLK_SPACE:
                    {
                       if (ball.bx == 0 && ball.by == 0)
                        {
                            go();
                            playerA.life = 3;
                            playerB.life = 3;
                            playerA.score = 0;
                            playerB.score = 0;
                        }
                    }
                    break;
                    case SDLK_ESCAPE: { return false; } // quits
                    default: { break; }
                }
            }
            break;
            case SDL_KEYUP:
            {
                    iTicksLastKey=SDL_GetTicks();  //remember the time of last key release
                    switch(event.key.keysym.sym)
                    {
                    case SDLK_UP:   { playerB.up = false; break; }
                    case SDLK_DOWN: { playerB.down =  false; break; }
                    case SDLK_LEFT: { playerB.left =  false; break; }
                    case SDLK_RIGHT: { playerB.right =  false; break; }
                    case SDLK_w:    { playerA.w = false; break; }
                    case SDLK_s:    { playerA.s =  false; break; }
                    case SDLK_a:    { playerA.a = false; break; }
                    case SDLK_d:    { playerA.d =  false; break; }
                     { playerA.dir = 0; break; }
                    default: { break; }
                    }
            }
            break;
            case SDL_QUIT: { return false; }
            default: { break; }
        }
    }
    return true;
}

/// Draws the score and life status
void overlay()
{
  char buffer[16];
  SDL_Rect dst, src;
  Sint32 i;

  src.y = 0; src.w = 12; src.h = 14;
  dst.y = 0; dst.w = 12; dst.h = 14;

  sprintf(buffer, "%04d", playerA.score);
  for(i=0; buffer[i]; i++)
    {
    src.x = ((Sint32) buffer[i] - (Sint32) '0') * 12;
    dst.x = i * 12;
    SDL_BlitSurface(numbers, &src, SCREEN, &dst);
  }

  sprintf(buffer, "%04d", playerB.score);
  for(i=0; buffer[i]; i++)
    {
    src.x = ((Sint32) buffer[i] - (Sint32) '0') * 12;
    dst.x = 320 - (4-i) * 12;
    SDL_BlitSurface(numbers, &src, SCREEN, &dst);
  }

  dst.y = 0; dst.w = (ball.sprite)->w; dst.h = (ball.sprite)->h;
  for(i=0; i<playerA.life; i++)
    {
    dst.x = 50 + i * (dst.w + 2);
    SDL_BlitSurface(ball.sprite, NULL, SCREEN, &dst);
  }

  for(i=0; i<playerB.life; i++)
    {
    dst.x = 270 - (3-i) * (dst.w + 2);
    SDL_BlitSurface(ball.sprite, NULL, SCREEN, &dst);
  }
}

void go()
{
    ball.bx = 0;
    while (ball.bx == 0) ball.bx = (rand() % 3) - 1;
    ball.by = (rand() % 3) - 1;
ball.bx=1;
ball.by=1;
    (ball.pos_x) = 160-(ball.sprite)->w/2;
    (ball.pos_y) = 120-(ball.sprite)->h/2;
    TicksElapsed=SDL_GetTicks();
}

//rounds a float to an int
int iRound(float f)
{
    return int(f + 0.5);
}

/* ---------------------------------------------------------------------- */
/* Main Program                                                           */
/* ---------------------------------------------------------------------- */
int main(int argc, char *argv[])
{
 
	PlaySound("cirque.wav",NULL,SND_FILENAME|SND_ASYNC | SND_LOOP);
	
  Sint32 delta;
 
  // --------------------------------------------------
  // SDL initialisation
  // --------------------------------------------------
  if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_JOYSTICK) < 0)
    {
    printf("Couldn't initialize SDL: %s\n", SDL_GetError());
    return -1;
  }

  SCREEN = SDL_SetVideoMode(500, 340, 24, SDL_DOUBLEBUF /*|SDL_FULLSCREEN*/);
  if (!SCREEN)
    {
    printf("Couldn't set 320x240, 24bit video mode: %s\n", SDL_GetError());
    return -2;
  }

  SDL_WM_SetCaption("Pony Pong", "Pony Pong");
  SDL_EnableKeyRepeat(10, SDL_DEFAULT_REPEAT_INTERVAL);
  SDL_ShowCursor(0);

  // --------------------------------------------------
  // Game initialisation
  // --------------------------------------------------
 
  srand(12345);
  playerA.sprite = SDL_LoadBMP("player1.bmp");
    SDL_SetColorKey(playerA.sprite, SDL_SRCCOLORKEY, 0x000000);  //makes black transparent
  playerB.sprite = SDL_LoadBMP("player2.bmp");
    SDL_SetColorKey(playerB.sprite, SDL_SRCCOLORKEY, 0x000000);  //makes black transparent
  ball.sprite = SDL_LoadBMP("ball.bmp");
    SDL_SetColorKey(ball.sprite, SDL_SRCCOLORKEY, 0x000000);  //makes black transparent

  background = SDL_LoadBMP("background.bmp");
  level = SDL_LoadBMP("level.bmp");
  intro = SDL_LoadBMP("intro.bmp");
  numbers = SDL_LoadBMP("numbers.bmp");

    //Check for joysticks:
    int num_joy;
    num_joy=SDL_NumJoysticks();
    printf("%d joysticks found\n", num_joy);
    for (int i=0;i<num_joy;i++) { printf("  %s\n", SDL_JoystickName(i)); }

    if (SDL_NumJoysticks()>0) joy0=SDL_JoystickOpen(0);
    if (joy0)
    {
        printf("Opened Joystick 0\n");
        printf("  Name: %s\n", SDL_JoystickName(0));
        printf("  Number of Axes: %d\n", SDL_JoystickNumAxes(joy0));
        printf("  Number of Buttons: %d\n", SDL_JoystickNumButtons(joy0));
       // printf("  Number of Balls: %d\n", SDL_JoystickNumBalls(joy0));
    }
    else { printf("Couldn't open Joystick 0\n"); }

  (playerA.pos_x) = 8;
    (playerA.pos_y) = 120-((playerA.sprite)->h/2);
  //(playerA.pos).w = (playerA.sprite)->w;
    //(playerA.pos).h = (playerA.sprite)->h;

  (playerB.pos_x) = 312-((playerB.sprite)->w);
    (playerB.pos_y) = 120-((playerB.sprite)->h/2);
//  (playerB.pos).w = (playerB.sprite)->w;
//    (playerB.pos).h = (playerB.sprite)->h;

  /*(ball.pos_x) = 160-(ball.sprite)->w/2;
    (ball.pos_y) = 120-(ball.sprite)->h/2;
  //(ball.pos).w = (ball.sprite)->w;
    //(ball.pos).h = (ball.sprite)->h;*/

  // --------------------------------------------------
  // Game loop
  // --------------------------------------------------
    while (handleEvents())
    {
    // --------------------------------------------------
    // Game logic
    // --------------------------------------------------

        //after 30s of inactivity quit game
        if ((SDL_GetTicks()-iTicksLastKey)>(GAMETIME*1000)) { break; }

        if (((SDL_JoystickGetButton(joy0, 0)) ||  //fire, start game
             (SDL_JoystickGetButton(joy0, 1)) ||
             (SDL_JoystickGetButton(joy0, 2)) ||
             (SDL_JoystickGetButton(joy0, 3)) ||
             (SDL_JoystickGetButton(joy0, 4)) ||
             (SDL_JoystickGetButton(joy0, 5)) ||
             (SDL_JoystickGetButton(joy0, 6)) ||
             (SDL_JoystickGetButton(joy0, 7))) &&
             ((ball.bx==0) && (ball.by==0)))
        {
            iTicksLastKey=SDL_GetTicks();  //remember the time of last key press
            go();
            playerA.life=playerB.life=3;
            playerA.score=playerB.score=0;
        }
           
        int Delta=SDL_GetTicks()-TicksElapsed;

        // Update position of sprites
        if (joy0)  //if joystick connected
        {
            //SDL_JoystickUpdate();
            iMoveXOld=iMoveX;
            iMoveYOld=iMoveY;
            iMoveX=SDL_JoystickGetAxis(joy0, 0);  //move joy 0 axxis 0 (-32768 to 32768)
            iMoveY=SDL_JoystickGetAxis(joy0, 1);  //move joy 0 axxis 1 (-32768 to 32768)
            (playerA.pos_y)=(int)(((((float)iMoveX)/65335)+0.5)*(240-(playerA.sprite)->h));
            (playerB.pos_y)=(int)(((((float)iMoveY)/65335)+0.5)*(240-(playerB.sprite)->h));
            if ((iMoveX!=iMoveXOld) || (iMoveY!=iMoveYOld)) { iTicksLastKey=SDL_GetTicks(); }  //remember the time of last movement
        }
        else  //otherwise keyboard
        {
            if (playerA.dir != 0)
            {
                (playerA.pos_y)+=((Delta*ballspeed)/1000)*playerA.dir;
                if ((playerA.pos_y) >= 240-(playerA.sprite)->h)
                {
                    (playerA.pos_y) = 240-(playerA.sprite)->h;
                }
                else if ((playerA.pos_y) <= 0)
                {
                    (playerA.pos_y) = 0;
                }
            }
            if (playerB.dir != 0)
            {

                (playerB.pos_y)+=((Delta*ballspeed)/1000)*playerB.dir;
                if ((playerB.pos_y) >= 240-(playerB.sprite)->h)
                {
                    (playerB.pos_y) = 240-(playerB.sprite)->h;
                }
                else if ((playerB.pos_y) <= 0)
                {
                    (playerB.pos_y) = 0;
                }
            }
        }

        if (playerB.up == true) {
            (playerB.pos_y)-=((Delta*ballspeed)/1000);
            }
        if (playerB.down == true) {
            (playerB.pos_y)+=((Delta*ballspeed)/1000);
            }
        if (playerB.left == true) {
            (playerB.pos_x)-=((Delta*ballspeed)/1000);
        }
        if (playerB.right == true) {
            (playerB.pos_x)+=((Delta*ballspeed)/1000);
        }
        if (playerB.pos_y > level->h - playerB.sprite->h) {
            playerB.pos_y = level->h - playerB.sprite->h ;
        }
        if (playerB.pos_y < 0) {
            playerB.pos_y = 0;
        }
        if (playerB.pos_x > level->w - playerB.sprite->w) {
            playerB.pos_x = level->w- playerB.sprite->w;
        }
        if (playerB.pos_x < 0) {
            playerB.pos_x = 0;
        }

       
        if (playerA.w == true){

            (playerA.pos_y)-=((Delta*ballspeed)/1000);
            }
        if (playerA.s == true){

            (playerA.pos_y)+=((Delta*ballspeed)/1000);
            }
        if (playerA.a == true){

            (playerA.pos_x)-=((Delta*ballspeed)/1000);
        }
        if (playerA.d == true){

            (playerA.pos_x)+=((Delta*ballspeed)/1000);
        }

        if (playerA.pos_y > level->h - playerA.sprite->h) {
            playerA.pos_y = level->h - playerA.sprite->h ;
        }
        if (playerA.pos_y < 0) {
            playerA.pos_y = 0;
        }
        if (playerA.pos_x > level->w - playerA.sprite->w) {
            playerA.pos_x = level->w- playerA.sprite->w;
        }
        if (playerA.pos_x < 0) {
            playerA.pos_x = 0;
        }

        // Update ball
        //(ball.pos_x) += ball.bx;
        //(ball.pos_y) += ball.by;
        (ball.pos_x)+=((Delta*ballspeed)/1000)*ball.bx;
        (ball.pos_y)+=((Delta*ballspeed)/1000)*ball.by;
        TicksElapsed=SDL_GetTicks();

        // (*) Reflection on top and bottom of screen
        if ((ball.pos_y) <= 0 || (ball.pos_y) >= 240-(ball.sprite)->h)
        {
            ball.by = -ball.by;
        }

        //player A paddle Reflektion:
        delta=(ball.pos_y)-(playerA.pos_y);
        if (((ball.pos_x)<=8+(playerA.sprite)->w) &&  //in reach of the paddle
            ((ball.pos_x)>=8) &&  //not too far left
            (delta>=0) &&  //not above paddle
            (delta<=(playerA.sprite)->h) &&  //not below
            (ball.bx<0))  //ball flies to the left
        {
            if (ball.bx < 0) { ball.bx = 1; } else { ball.bx = -1; }
            //ball.bx *= (2+abs((delta - ((playerA.sprite)->h/2))) / 6);
            //ball.by = (delta - ((playerA.sprite)->h/2)) / 4;
            playerA.score++;
        }
        if ((ball.pos_x)<0)  //left out
        {
            playerA.life--;
            playerB.score += 10;
            if (playerA.life == 0)
            {
                //Restart game:
                ball.bx = 0;
                ball.by = 0;
                (ball.pos_x) = 160-(ball.sprite)->w/2;
                (ball.pos_y) = 120-(ball.sprite)->h/2;
            }
            else { go(); }
        }

        //player B paddle Reflektion:
        delta=(ball.pos_y)-(playerB.pos_y);
        if (((ball.pos_x)+(ball.sprite)->w>=312-(playerB.sprite)->w) &&  //in reach of the paddle
            ((ball.pos_x)+(ball.sprite)->w<=312) &&  //not too far right
            (delta>=0) &&  //not above paddle
            (delta<=(playerB.sprite)->h) &&  //not below
            (ball.bx>0))  //ball flies to the right
        {
            if (ball.bx < 0) { ball.bx = 1; } else { ball.bx = -1; }
            //ball.bx *= (2+abs((delta - ((playerB.sprite)->h/2))) / 6);
            //ball.by = (delta - ((playerB.sprite)->h/2)) / 4;
            playerB.score++;
        }
        if ((ball.pos_x)+(ball.sprite)->w>320)  //right out
        {
            playerB.life--;
            playerA.score += 10;
            if (playerB.life == 0)
            {
                //Restart game:
                ball.bx = 0;
                ball.by = 0;
                (ball.pos_x) = 160-(ball.sprite)->w/2;
                (ball.pos_y) = 120-(ball.sprite)->h/2;
            }
            else go();
        }

    // --------------------------------------------------
    // Draw game screen
    // --------------------------------------------------
        if (ball.bx == 0 && ball.by == 0) { SDL_BlitSurface(intro, NULL, SCREEN, NULL); }
        else                              { SDL_BlitSurface(background, NULL, SCREEN, NULL); }
       
    SDL_Rect halfscreen;
    halfscreen.x=0;
    halfscreen.y=0;
    halfscreen.w=SCREEN->w/2;
    halfscreen.h=SCREEN->h;
   
    SDL_Rect levelrect;//Left hand side screen
    levelrect.x=iRound(playerB.pos_x-SCREEN->w/4);
    levelrect.y=iRound(playerB.pos_y-SCREEN->h/2);
    levelrect.w=SCREEN->w/2;
    levelrect.h=SCREEN->h;
    SDL_BlitSurface(level, &levelrect, SCREEN, &halfscreen);

    halfscreen.x=SCREEN->w/2;

    levelrect.x=iRound(playerA.pos_x-SCREEN->w/28);//right hand side screen
    levelrect.y=iRound(playerA.pos_y-SCREEN->h/10);
    levelrect.w=SCREEN->w;
    levelrect.h=SCREEN->h;
    SDL_BlitSurface(level, &levelrect, SCREEN, &halfscreen);
   
    overlay();

    SDL_Rect p1;
    p1.x=(SCREEN->w/4-playerA.sprite->w/5);
    p1.y=(SCREEN->h/2-playerA.sprite->h/2);
    p1.w=(playerA.sprite)->w;
    p1.h=(playerA.sprite)->h;
    SDL_BlitSurface(playerA.sprite, NULL, SCREEN, &p1);

    SDL_Rect p2;
    p2.x=(SCREEN->w/2+SCREEN->w/4-playerB.sprite->w/2);
    p2.y=(SCREEN->h/2-playerB.sprite->h/2);
    p2.w=(playerB.sprite)->w;
    p2.h=(playerB.sprite)->h;
    SDL_BlitSurface(playerB.sprite, NULL, SCREEN, &p2);

    SDL_Rect r;
    r.x=iRound(ball.pos_x);
    r.y=iRound(ball.pos_y);
    r.w= (ball.sprite)->w;
    r.h= (ball.sprite)->w;
    SDL_BlitSurface(ball.sprite, NULL, SCREEN, &r);

    SDL_Flip(SCREEN);
  }

  // --------------------------------------------------
  // Clean up
  // --------------------------------------------------
    if ((joy0) && (SDL_JoystickOpened(0))) { SDL_JoystickClose(joy0); }
  SDL_Quit();
  return 0;
}

Recommended Answers

All 4 Replies

I would suggest keeping your questions and related code as short and sweet as possible. For example, in this case, all you want to know is how to tell how long a key has been held down for, correct?

Unfortunately I don't know how to do that! (sorry)

Dave

Actually my question was how to speed the player up as stated in the topic header.

Right, but no one else will learn anything by learning how to speed up your player - on a forum like this, ideally (at least in my opinion) the problem should be abstracted as far as possible so that it will help in as many cases as possible once it gets to the archives. So my point is, if someone helps you figure out how to get the hold down time of a key (a general thing), then it would be up to you to apply it to your specific problem (moving the player).

See what I mean?

Dave

Right, but no one else will learn anything by learning how to speed up your player - on a forum like this, ideally (at least in my opinion) the problem should be abstracted as far as possible so that it will help in as many cases as possible once it gets to the archives. So my point is, if someone helps you figure out how to get the hold down time of a key (a general thing), then it would be up to you to apply it to your specific problem (moving the player).

See what I mean?

Dave

Yes i see what you mean, however i don't really know C++ and would appreciate as much help as someone, who knows what they are doing, is willing to give.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.