text: #include "LTexture.h"
  #include <stdio.h>
  
  const int SCREEN_WIDTH = 640;
  const int SCREEN_HEIGHT = 480;
  //Analog joystick dead zone
  const int JOYSTICK_DEAD_ZONE = 8000;
  
  //Starts up SDL and creates window
  bool init();
  
  //Loads media
  bool loadMedia();
  
  //Frees media and shuts down SDL
  void closeAll();
  
  //The window we'll be rendering to
  SDL_Window* gWindow = NULL;
  //The window renderer
  SDL_Renderer* gRenderer = NULL;
  //Game Controller 1 handler
  SDL_Joystick* gGameController = NULL;
  
  //Scene textures
  LTexture gArrowTexture;
  
  LTexture::LTexture()
  {
  	//Initialize
  	mTexture = NULL;
  	mWidth = 0;
  	mHeight = 0;
  }
  
  LTexture::~LTexture()
  {
  	//Deallocate
  	free();
  }
  
  bool LTexture::loadFromFile(std::string path)
  {
  	//Get rid of preexisting texture
  	free();
  
  	//The final texture
  	SDL_Texture* newTexture = NULL;
  
  	//Load image at specified path
  	SDL_Surface* loadedSurface = IMG_Load(path.c_str());
  	if (loadedSurface == NULL)
  	{
  		printf("Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError());
  	}
  	else
  	{
  		//Color key image
  		SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, 0, 0xFF, 0xFF));
  		//Create texture from surface pixels
  		newTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface);
  		if (newTexture == NULL)
  		{
  			printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
  		}
  		else
  		{
  			//Get image dimensions
  			mWidth = loadedSurface->w;
  			mHeight = loadedSurface->h;
  		}
  
  		//Get rid of old loaded surface
  		SDL_FreeSurface(loadedSurface);
  	}
  
  	//Return success
  	mTexture = newTexture;
  	return mTexture != NULL;
  }
  
  void LTexture::free()
  {
  	//Free texture if it exists
  	if (mTexture != NULL)
  	{
  		SDL_DestroyTexture(mTexture);
  		mTexture = NULL;
  		mWidth = 0;
  		mHeight = 0;
  	}
  }
  
  void LTexture::setColor(Uint8 red, Uint8 green, Uint8 blue)
  {
  	//Modulate texture rgb
  	SDL_SetTextureColorMod(mTexture, red, green, blue);
  }
  
  void LTexture::setBlendMode(SDL_BlendMode blending)
  {
  	//Set blending function
  	SDL_SetTextureBlendMode(mTexture, blending);
  }
  
  void LTexture::setAlpha(Uint8 alpha)
  {
  	//Modulate texture alpha
  	SDL_SetTextureAlphaMod(mTexture, alpha);
  }
  
  void LTexture::render(int x, int y, SDL_Rect* clip, double angle, SDL_Point* center, SDL_RendererFlip flip)
  {
  	//Set rendering space and render to screen
  	SDL_Rect renderQuad = { x, y, mWidth, mHeight };
  
  	//Set clip rendering dimensions
  	if (clip != NULL)
  	{
  		renderQuad.w = clip->w;
  		renderQuad.h = clip->h;
  	}
  
  	//Render to screen
  	//SDL_RenderCopy(gRenderer, mTexture, clip, &renderQuad);
  	SDL_RenderCopyEx(gRenderer, mTexture, clip, &renderQuad, angle, center, flip);
  }
  
  int LTexture::getWidth()
  {
  	return mWidth;
  }
  
  int LTexture::getHeight()
  {
  	return mHeight;
  }
  
  bool init()
  {
  	//Initialization flag
  	bool success = true;
  
  	//Initialize SDL
  	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
  	{
  		printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
  		success = false;
  	}
  	else
  	{
  		//Set texture filtering to linear
  		if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
  		{
  			printf("Warning: Linear texture filtering not enabled!");
  		}
  
  		//Check for joysticks
  		if( SDL_NumJoysticks() < 1 )
  		{
  		    printf( "Warning: No joysticks connected!\n" );
  		}
  		else
  		{
  		    //Load joystick
  		    gGameController = SDL_JoystickOpen( 0 );
  		    if( gGameController == NULL )
  		    {
  		        printf( "Warning: Unable to open game controller! SDL Error: %s\n", SDL_GetError() );
  		    }
  		}
  
  		//Create window
  		gWindow = SDL_CreateWindow("Hello World", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
  		if (gWindow == NULL)
  		{
  			printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
  			success = false;
  		}
  		else
  		{
  			//Create renderer for window
  			gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
  			if (gRenderer == NULL)
  			{
  				printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
  				success = false;
  			}
  			else
  			{
  				//Initialize renderer color
  				SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
  
  				//Initialize PNG loading
  				int imgFlags = IMG_INIT_PNG;
  				if (!(IMG_Init(imgFlags) & imgFlags))
  				{
  					printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
  					success = false;
  				}
  			}
  
  		}
  	}
  
  	return success;
  }
  
  bool loadMedia()
  {
  	//Loading success flag
  	bool success = true;
  
  	//Load texture
  	if (!gArrowTexture.loadFromFile("19_Gamepads_and_Joysticks/preview.png"))
  	{
  		printf("Failed to load press texture!\n");
  		success = false;
  	}
  
  	return success;
  }
  
  void closeAll()
  {
  	//Free loaded images
  	gArrowTexture.free();
  
  	//Close game controller
  	SDL_JoystickClose( gGameController );
  	gGameController = NULL;
  
  	//Destroy window    
  	SDL_DestroyRenderer(gRenderer);
  	SDL_DestroyWindow(gWindow);
  	gWindow = NULL;
  	gRenderer = NULL;
  
  	//Quit SDL subsystems
  	IMG_Quit();
  	SDL_Quit();
  }
  
  int main(int argc, char *argv[])
  {
  	if (!init())
  	{
  		printf("Failed to initialize!\n");
  	}
  	else
  	{
  		//Load media
  		if (!loadMedia())
  		{
  			printf("Failed to load media!\n");
  		}
  		else
  		{
  			//Main loop flag
  			bool quit = false;
  
  			//Event handler
  			SDL_Event e;
  
  			//Normalized direction
  			int xDir = 0;
  			int yDir = 0;
  
  			//While application is running
  			while (!quit)
  			{
  				//Handle events on queue
  				while (SDL_PollEvent(&e) != 0)
  				{
  					//User requests quit
  					if (e.type == SDL_QUIT)
  					{
  						quit = true;
  					}
  					else if( e.type == SDL_JOYAXISMOTION )
  					{
  						//Motion on controller 0
  						if( e.jaxis.which == 0 )
  						{                        
  						    //X axis motion
  						    if( e.jaxis.axis == 0 )
  						    {
  						        //Left of dead zone
  						        if( e.jaxis.value < -JOYSTICK_DEAD_ZONE )
  						        {
  						            xDir = -1;
  						        }
  						        //Right of dead zone
  						        else if( e.jaxis.value > JOYSTICK_DEAD_ZONE )
  						        {
  						            xDir =  1;
  						        }
  						        else
  						        {
  						            xDir = 0;
  						        }
  						    }                            
  						    //Y axis motion
  						    else if( e.jaxis.axis == 1 )
  						    {
  						        //Below of dead zone
  						        if( e.jaxis.value < -JOYSTICK_DEAD_ZONE )
  						        {
  						            yDir = -1;
  						        }
  						        //Above of dead zone
  						        else if( e.jaxis.value > JOYSTICK_DEAD_ZONE )
  						        {
  						            yDir =  1;
  						        }
  						        else
  						        {
  						            yDir = 0;
  						        }
  						    }
  						}
  					}
                  
  				}
  				
  				//Clear screen
  				SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
  				SDL_RenderClear(gRenderer);
  
  				//Calculate angle
  				double joystickAngle = atan2( (double)yDir, (double)xDir ) * ( 180.0 / M_PI );
  				
  				//Correct angle
  				if( xDir == 0 && yDir == 0 )
  				{
  				    joystickAngle = 0;
  				}                
  				
  				//Render joystick 8 way angle
                  		gArrowTexture.render( ( SCREEN_WIDTH - gArrowTexture.getWidth() ) / 2, ( SCREEN_HEIGHT - gArrowTexture.getHeight() ) / 2, NULL, joystickAngle );
  
  				//Update screen
  				SDL_RenderPresent(gRenderer);
  			}
  		}
  	}
  	
  	closeAll();
  
  	return 0;
  }
  