Lazy Foo SDL tutorial # 23 [help me plz]

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
Aspirer
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 47
Joined: Tue May 01, 2012 8:20 pm

Lazy Foo SDL tutorial # 23 [help me plz]

Post by Aspirer »

While I work on fixing this myself, I figured I would post the code to see if any of you can figure it out.

This doesn't qualify as that forum rule "don't post a long list of code and expect us to debug" does it?

Code: Select all

#include"stdafx.h" //Required header for Windows, or MS Visual Studio, don't remember which.
#include"SDL.h"
#include"SDL_ttf.h"
#include"SDL_image.h"
#include<string>
#include<sstream>
#include<cmath>
#include<vector>

TTF_Font *font = NULL;

const int DOT_WIDTH = 20;
const int DOT_HEIGHT = 20;
const int LEVEL_WIDTH = 1280;
const int LEVEL_HEIGHT = 960;

const int FRAMES_PER_SECOND = 30;

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

int frame = 0 ;

SDL_Surface *background = NULL;
SDL_Surface *screen = NULL;
SDL_Surface * message = NULL;
SDL_Surface * frametext = NULL;
SDL_Surface *dot = NULL;
SDL_Surface *timesurf = NULL;
                             
bool quit = false;
   
SDL_Event event;   

SDL_Color textcolor = {0,0,255};

void apply_surface (int x, int y, SDL_Surface *source, SDL_Surface *destination, SDL_Rect *clip = NULL) {

	SDL_Rect offset;
	offset.x = x;
	offset.y = y;

	SDL_BlitSurface(source, clip , screen, &offset); //Ok.
}

class StringInput {
private: 
std::string str;
SDL_Surface * text;

public: 
	StringInput();
	~StringInput();
	void handle_input();
	void show_centered();
}   ;

StringInput::StringInput()
{

	str = "";

	text = NULL;

	SDL_EnableUNICODE(SDL_ENABLE); 

}
StringInput::~StringInput() {

	SDL_FreeSurface(text);

	SDL_EnableUNICODE(SDL_DISABLE);
}

void StringInput::show_centered() {

	if (text != NULL) {
		apply_surface( 20, 100, text, screen); //Changed the location of the text for my own reasons.
	}

}

void StringInput::handle_input() {

if (event.type == SDL_KEYDOWN) {

	std::string temp = str;

	if ( str.length() <= 16) {
		if ( event.key.keysym.unicode == (Uint16) ' ' ) {
			str += (char)event.key.keysym.unicode;
		}
		else if ( event.key.keysym.unicode >= (Uint16)'0' && event.key.keysym.unicode <= (Uint16) '9' ) 
		{
			str+= (char) event.key.keysym.unicode;
		}
		else if ( event.key.keysym.unicode >= (Uint16)'A' && event.key.keysym.unicode <= (Uint16) 'Z' ) 
		{
			str+=  (char) event.key.keysym.unicode;
		}
		else if ( event.key.keysym.unicode >= (Uint16)'a' && event.key.keysym.unicode <= (Uint16) 'z' ) 
		{
			str+= (char) event.key.keysym.unicode;
		}
	}
		if (event.key.keysym.unicode == SDLK_BACKSPACE && str.length() != 0) {
			str.erase(str.length() - 1);
		}
		if (str != temp) {
			SDL_FreeSurface (text);
			text = TTF_RenderText_Solid(font, str.c_str(), textcolor);
		}
	}
}
	class Timer {
	private: 
		int startticks;
		int pausedticks;
			 
		bool started;
		bool paused;
	public:
		Timer();
		void start();
		void stop();
		void pause();
		void unpause();
		int get_ticks();
		bool is_started();
		bool is_paused();
	};

	Timer::Timer() {

		startticks = 0;
		pausedticks = 0;
		paused = false;
		started = false;
	}

	void Timer::start() {
		started = true;
		paused = false;
		startticks = SDL_GetTicks();

	}
	void Timer::stop() 
	{
		started = false;
		paused = false;

	}

	int Timer::get_ticks() {	

		if (started == true ) {

			if (paused == true ) {

				return pausedticks;
			}
			else {
				return SDL_GetTicks() - startticks;
			}
		}
		return 0;
	}

		void Timer::pause() {
			if ( started == true && paused == false ) {
				paused = true;
				pausedticks = SDL_GetTicks() - startticks;
		
			}
		}

		void Timer::unpause() {
			if (paused == true) {

			paused = false;
			startticks = SDL_GetTicks() - startticks;
			pausedticks = 0;
		}
	}

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

			
void clean_up()
{
    //Free the surfaces
    SDL_FreeSurface( background );
	SDL_FreeSurface (screen);
	SDL_FreeSurface( dot );
	SDL_FreeSurface (frametext);
	SDL_FreeSurface (message);
    //Close the font

	TTF_CloseFont( font );

	TTF_Quit();

    //Quit SDL
    SDL_Quit();
}


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 = SDL_LoadBMP( 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;
}
bool init()
{
    //Initialize all SDL subsystems
    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
    {
        return false;
    }

	if (TTF_Init() == - 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( "Press an Arrow Key", NULL );

    //If everything initialized fine
    return true;
}

bool load_files()
{
    //Load the background image
    background = load_image( "background.bmp" );
	dot = load_image( "dot.bmp" );
    //Open the font
	font = TTF_OpenFont("lazy.ttf", 42);
	//If there was a problem in loading the background
	if( background == NULL || dot == NULL || font == NULL )
    {
        return false;
    }
    //If everything loaded fine
    return true;
}





int main ( int argc, char* args[] )
{
	bool nameEntered = false;

	Timer myTime;
	Timer fps;

	StringInput name;

	if (init() == false ) {
		return false;
	}
	if (load_files() == false) {

		return false;
	}

myTime.start(); //The time the loop started. Keeps track of the time.


message = TTF_RenderText_Solid( font, "New High Score! Enter Name:", textcolor );

while (quit == false ) //Loop to do stuff within.
{
	fps.start(); //Frame timer.
	std::stringstream time; //Something to convert the time into a string, along with a message.
	while (SDL_PollEvent( &event ) ) { //Gets an event every time the loop passes.
		
		if ( event.type  == SDL_QUIT ) {
			fps.stop();
			myTime.stop();
			quit = true; //Duh.
		}
		if (nameEntered == false) 
		{

			name.handle_input();
	if( ( event.type == SDL_KEYDOWN ) && ( event.key.keysym.sym == SDLK_RETURN ) ) 
	{	
		nameEntered = true;

			SDL_FreeSurface ( message);

			message = TTF_RenderText_Solid( font, "Rank: 1St ", textcolor);

			}
		}
	}

	apply_surface( 0, 0, background, screen );
	
	apply_surface( 20, 100, message, screen ); //Changed the location of the text for my own reasons.

	name.show_centered();

	time << "Time: " << myTime.get_ticks() / 1000.f; //Put the phrase "Time: " and the current time since the start of the loop, since its in milliseconds, we divide it by 1000 because there are 1000 milliseconds in one second.

	timesurf = TTF_RenderText_Solid(font, time.str().c_str(), textcolor); //Put the time text into timesurf (short for time surface).

	apply_surface( 50 , 10 , timesurf , screen); 

	SDL_FreeSurface(timesurf);
		
	frametext = TTF_RenderText_Solid(font, "Testing frame rate" , textcolor); //Frame message, shows how fast the framerate is in a visual way.

	apply_surface(( SCREEN_WIDTH - frametext->w ) / 2, ((SCREEN_HEIGHT + frametext->h * 2 ) / FRAMES_PER_SECOND ) * (frame % FRAMES_PER_SECOND ) - frametext->h, frametext, screen); //Render the text showing the framerate message.

	if (SDL_Flip (screen) == - 1) {
		return false;
	}
	frame += 1; //Frame counter. Used to 
        if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
        {
            SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
        }

}
clean_up();
return 0;

}
Please note, I have been over this a few times, I don't know what is wrong with it. I will continue looking.
"We got more information out of a German general with a game of chess or Ping-Pong than they do today, with their torture" --Henry Kolm
User avatar
Light-Dark
Dreamcast Developer
Dreamcast Developer
Posts: 307
Joined: Sun Mar 13, 2011 7:57 pm
Current Project: 2D RPG & NES Platformer
Favorite Gaming Platforms: NES,SNES,N64,Genesis,Dreamcast,PC,Xbox360
Programming Language of Choice: C/++
Location: Canada

Re: Lazy Foo SDL tutorial # 23 [help me plz]

Post by Light-Dark »

I don't mind a shit tonne of code, but if you can't detail what exactly is going wrong it makes it quite tedious and hard to help you in which most people are just going to walk away, so can you please explain what exactly is wrong?
<tpw_rules> LightDark: java is a consequence of inverse moore's law: every 18 months, the average program will be twice as slow. therefore, computers always run at the same percevied speed. java's invention was a monumental step
Image
Aspirer
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 47
Joined: Tue May 01, 2012 8:20 pm

Re: Lazy Foo SDL tutorial # 23 [help me plz]

Post by Aspirer »

Oops, my bad!

When it runs it doesn't take input. The text "New high score! Enter name: " appears, and when I hit enter it switches to "rank: 1st", but no text I try to enter appears.

I would also like to make a log file, but for some reason I can't get the program to recognize the header or the indentifiers. I'm assuming this has something to do with linking the headers like I did with the SDL ones, am I right? Does MS VS 2012 Express come with those files? All I need to do is create a text file to write to, so I'm attempting to use the "ofstream" header.
"We got more information out of a German general with a game of chess or Ping-Pong than they do today, with their torture" --Henry Kolm
User avatar
Ginto8
ES Beta Backer
ES Beta Backer
Posts: 1064
Joined: Tue Jan 06, 2009 4:12 pm
Programming Language of Choice: C/C++, Java

Re: Lazy Foo SDL tutorial # 23 [help me plz]

Post by Ginto8 »

<ofstream> is one of many standard C++ headers, and if any compiler doesn't support it (I'm sure MSVC++ does), it's an incomplete C++ implementation.

Regarding your bug, I see no reason why you should be surprised by that behavior; it's exactly what you programmed it to do. Nowhere do I see the program taking textual input; it checks for a quit event, and it checks for the enter-key trigger, but that's all. It can't take user input if you don't tell it to.
Quit procrastinating and make something awesome.
Ducky wrote:Give a man some wood, he'll be warm for the night. Put him on fire and he'll be warm for the rest of his life.
User avatar
Light-Dark
Dreamcast Developer
Dreamcast Developer
Posts: 307
Joined: Sun Mar 13, 2011 7:57 pm
Current Project: 2D RPG & NES Platformer
Favorite Gaming Platforms: NES,SNES,N64,Genesis,Dreamcast,PC,Xbox360
Programming Language of Choice: C/++
Location: Canada

Re: Lazy Foo SDL tutorial # 23 [help me plz]

Post by Light-Dark »

Regarding your header problem just use #include <fstream> that should work fine.
Then do std::ofstream file;
<tpw_rules> LightDark: java is a consequence of inverse moore's law: every 18 months, the average program will be twice as slow. therefore, computers always run at the same percevied speed. java's invention was a monumental step
Image
Aspirer
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 47
Joined: Tue May 01, 2012 8:20 pm

Re: Lazy Foo SDL tutorial # 23 [help me plz]

Post by Aspirer »

Gee, I feel stupid! I had a slight notion the program wasn't written to do that... I just don't understand why the tutorial is called "String input" when it doesn't accept strings! Also, the handle_input() function appears to take keystrokes and put them into str, that's what got me.

Thanks


edit: I discovered the root of the streams not working. I haven't used the line:

Code: Select all

using namespace std;
in some time due to the structure of these tutorials. I didn't include it.

Also, I need to link the headers to the file, but I don't know where I could find them... any suggestions?
"We got more information out of a German general with a game of chess or Ping-Pong than they do today, with their torture" --Henry Kolm
User avatar
bbguimaraes
Chaos Rift Junior
Chaos Rift Junior
Posts: 294
Joined: Wed Apr 11, 2012 4:34 pm
Programming Language of Choice: c++
Location: Brazil
Contact:

Re: Lazy Foo SDL tutorial # 23 [help me plz]

Post by bbguimaraes »

Actualy, the purpose of the tutorial is to create a "virtual text box", where you can enter a string and it will display it on the screen as you type. Everytime you press a key, it appends it to a string, which is rendered on the screen.
Aspirer wrote:Also, I need to link the headers to the file, but I don't know where I could find them... any suggestions?
A little confusion here. You include header files, which are regular files just like the ones you create, containing declarations of functions. What you link are libraries, which contain the actual implementation.

So headers are include

Code: Select all

#include
statements, while linking libraries to your code is a little more complicated, because it depends on your compiler. If it's Visual Studio:
some guy in a forum wrote:Just go to project properties -> Configuration properties -> Linker.
Goto to ->General and set the "Additional Library directories" to point to your lib file directory.

Then goto to Linker -> Input and type in your lib file name e.g. mystaticlib.lib in the "Additional Dependencies" field
Aspirer
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 47
Joined: Tue May 01, 2012 8:20 pm

Re: Lazy Foo SDL tutorial # 23 [help me plz]

Post by Aspirer »

Actualy, the purpose of the tutorial is to create a "virtual text box", where you can enter a string and it will display it on the screen as you type. Everytime you press a key, it appends it to a string, which is rendered on the screen.
That's exactly what I meant. For some reason nothing appears where the text should when I type.

The header/library thing I fixed, like I said I did not include this: "using namespace std;".

An edit: I need to write to files. The only resource I know of was the cplusplus.com tutorial, but when I run it after adding my code and #include's, I get an LNK 2019 error.
1>------ Build started: Project: KeypressSDL, Configuration: Debug Win32 ------
1> StringInput.cpp
1>StringInput.obj : error LNK2019: unresolved external symbol __imp___CrtDbgReportW referenced in function "public: char const & __thiscall std::_String_const_iterator<char,struct std::char_traits<char>,class std::allocator<char> >::operator*(void)const " (??D?$_String_const_iterator@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEABDXZ)
1>C:\Users\User\Documents\Visual Studio 2010\Projects\AnAlreadySetupSDLFile\Debug\KeypressSDL.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
"We got more information out of a German general with a game of chess or Ping-Pong than they do today, with their torture" --Henry Kolm
Post Reply