0
\$\begingroup\$

I'm following along with the LazyFoo tutorial to create the basis for a simple arcade space shooter. I'm trying to get the sprite moving through the map while being tracked by the camera. The code I have works in the x direction but doesn't scroll/follow in the y direction. I can't figure out why because the code for both directions is the same.

Here's what I have, the camera function is at the bottom (line 300ish) in the main function.


#include <iostream>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <sstream>
#include <string>
#include <SDL2/SDL_image.h>

SDL_DisplayMode current;


const int LEVEL_WIDTH = 1280;
const int LEVEL_HEIGHT = 960;
int SCREEN_WIDTH = 1000;
int SCREEN_HEIGHT = 1000;

SDL_Window* gWindow = NULL;

SDL_Surface* gScreenSurface = NULL;

SDL_Texture* ship = NULL;

SDL_Renderer* gRenderer = NULL;

//Texture wrapper class
class LTexture
{
    public:
        //Initializes variables
        LTexture();
        
        //Deallocates memory
        ~LTexture();

        //Loads image at specified path
        bool loadFromFile( std::string path );

        //Deallocates texture
        void free();

        //Renders texture at given point
        void render( int x, int y, SDL_Rect* clip = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip = SDL_FLIP_NONE );

        //Gets image dimensions
        int getWidth();
        int getHeight();
        void setWidth( int width );
        void setHeight( int height );

        private:
        
        //The actual hardware texture
        
        SDL_Texture* mTexture;
        
        //Image dimensions                                                                  
        int mWidth;
        int mHeight;
};

LTexture::LTexture() {

    mTexture = NULL;
    mWidth = 0;
    mHeight = 0;

}

LTexture::~LTexture() {
    free();
}

bool LTexture::loadFromFile( std::string path ) {

    free();

    SDL_Texture* newTexture = NULL;

    SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
//  SDL_SetColorKey( loadedSurface, SDL_TRUE, SDL_MapRGB( loadedSurface->format, 0, 0xFF, 0xFF ) );

    newTexture = SDL_CreateTextureFromSurface( gRenderer, loadedSurface);

    mWidth = loadedSurface->w;
    mHeight = loadedSurface->h;

    SDL_FreeSurface( loadedSurface );

    mTexture = newTexture;
    return mTexture != NULL;
}

void LTexture::free() {

    if (mTexture != NULL) {
        SDL_DestroyTexture( mTexture );
        mTexture = NULL;
        mWidth = 0;
        mHeight = 0;
    }
}

void LTexture::render( int x, int y, SDL_Rect* clip, double angle, SDL_Point* center, SDL_RendererFlip flip ) {
    
    SDL_Rect renderQuad = { x, y, mWidth, mHeight };

    if ( clip != NULL ) {
        renderQuad.h = clip->h;
        renderQuad.w = clip->w;
    }

    SDL_RenderCopyEx( gRenderer, mTexture, clip, &renderQuad, angle, center, flip );
}

int LTexture::getWidth() {
    return mWidth;
}

int LTexture::getHeight() {
    return mHeight;
}

void LTexture::setWidth( int width ) {
    mWidth = width;
}

void LTexture::setHeight( int height ) {
    mHeight = height;
}

class Ship {

    public:
        // Ship dimensions
        const static int SHIP_HEIGHT = 100;
        const static int SHIP_WIDTH = 100;

        // Ship maximum velocity
        static const int SHIP_VELOCITY = 10;
        
        Ship();

        void handleEvent( SDL_Event &e );
        
        int getVelY();
        int getVelX();
        int getPosX();
        int getPosY();

        void move();

        void render( int camX, int camY );
    
    private:
        int mPosX, mPosY;
        int mVelX, mVelY;


};

LTexture shipTexture;
LTexture backgroundTexture;

Ship::Ship() {
    
    mPosX = 0;
    mPosY = 0;
    mVelX = 0;
    mVelY = 0;
}

int Ship::getVelY() {
    return mVelY;
}

int Ship::getVelX() {
    return mVelX;
}

void Ship::handleEvent( SDL_Event &e ) {

    if ( e.type == SDL_KEYDOWN && e.key.repeat == 0 ) {
        
        switch (e.key.keysym.sym) {
            case SDLK_UP: mVelY -= SHIP_VELOCITY; break;
            case SDLK_DOWN: mVelY += SHIP_VELOCITY; break;
            case SDLK_LEFT: mVelX -= SHIP_VELOCITY; break;
            case SDLK_RIGHT: mVelX += SHIP_VELOCITY; break;
        }
    }

    else if ( e.type == SDL_KEYUP && e.key.repeat == 0 ) {

        switch (e.key.keysym.sym) {
            case SDLK_UP: mVelY += SHIP_VELOCITY; break;
            case SDLK_DOWN: mVelY -= SHIP_VELOCITY; break;
            case SDLK_LEFT: mVelX += SHIP_VELOCITY; break;
            case SDLK_RIGHT: mVelX -= SHIP_VELOCITY; break;
        }
    }
}

void Ship::move() {
    
    mPosX += mVelX;

    if ( mPosX < 0 || mPosX + SHIP_WIDTH > LEVEL_WIDTH ) {
        mPosX -= mVelX;
    }
    
    mPosY += mVelY;

    if ( mPosY < 0 || mPosY + SHIP_HEIGHT > LEVEL_HEIGHT ) {
        mPosY -= mVelY;
    }

}

void Ship::render( int camX, int camY ) {
    
    double angle;
    
    if ( mVelX > 0 )
        angle = 90.0;
    if ( mVelX < 0 )
        angle = 270.0;
    if ( mVelY > 0 )
        angle = 180.0;
    if ( mVelY < 0 )
        angle = 0.0;

    shipTexture.render( mPosX - camX, mPosY - camY, NULL, angle, NULL );

}

int Ship::getPosX() {
    return mPosX;
}

int Ship::getPosY() {
    return mPosY;
}

void init() {
    
    // Load window and associates surface
    SDL_Init( SDL_INIT_VIDEO );
    gWindow = SDL_CreateWindow ( "Video Game v1.0", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
    gRenderer = SDL_CreateRenderer ( gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );

    SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
    // Enable PNG loading
    int imgFlags = IMG_INIT_PNG;
    IMG_Init( imgFlags );
    
    // Format screen size
    SDL_DisplayMode current;
    SDL_GetCurrentDisplayMode(0, &current );
    SCREEN_WIDTH = current.w;
    SCREEN_HEIGHT = current.h;
    SDL_Log("Display #%d: current display mode is %dx%dpx @ %dhz.", 0, current.w, current.h, current.refresh_rate);

}

void loadMedia() {

    shipTexture.loadFromFile( "8.png" );
    backgroundTexture.loadFromFile( "509906.png" );
    backgroundTexture.setWidth( SCREEN_WIDTH );
    backgroundTexture.setHeight( SCREEN_HEIGHT );
}

void close() {

    shipTexture.free();

    SDL_DestroyWindow( gWindow );
    gWindow = NULL;
    
    SDL_DestroyRenderer( gRenderer );
    gRenderer = NULL;

    SDL_Quit();
    IMG_Quit();
    
}

int main( int argc, char* args[] ) {
    
    bool quit = false;
    SDL_Event e;
    Ship ship;
    SDL_Rect camera = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };
    init();
    loadMedia();

    while( !quit ) {
    
        while ( SDL_PollEvent( &e ) !=0 ) {
            if( e.type == SDL_QUIT ) {
                quit = true;
            }
            ship.handleEvent( e );
        }
        
        ship.move();

        camera.x = ( ship.getPosX() + Ship::SHIP_WIDTH / 2 ) - SCREEN_WIDTH / 2;
        camera.y = ( ship.getPosY() + Ship::SHIP_HEIGHT / 2 ) - SCREEN_HEIGHT / 2;
        
        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;

        // Clear the screen
        SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
        SDL_RenderClear( gRenderer );
        
        backgroundTexture.render( 0, 0, &camera );
        ship.render( camera.x, camera.y );
        
        // Update screen
        SDL_RenderPresent( gRenderer );
    
    }

    close();

    return 0;
}





```
\$\endgroup\$
1
  • \$\begingroup\$ What did you do to debug your code? Did you try to print the behaviour of your variables on the console and see why it doesn't change? \$\endgroup\$
    – Vaillancourt
    Sep 19 at 12:37

1 Answer 1

1
\$\begingroup\$

Assuming

LEVEL_HEIGHT = 960
camera.h = SCREEN_HEIGHT = 1000

And the code

if ( camera.y > LEVEL_HEIGHT - camera.h )

We can deduce that

range_of_action = LEVEL_HEIGHT - camera.h = 960 - 1000 = -40

We can conclude that the camera will always be at -40.

Your level is smaller than the field where you can scroll your camera.

To fix this, give more room for your camera to move, increase the size of your level.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .