Advertisement

basic SFML help

Started by May 23, 2014 11:59 PM
7 comments, last by Servant of the Lord 10 years, 8 months ago

forewarning, im a noob, and will be for a long time, so if my code is aweful courteous suggestions would be appreciated.

first off im trying to run a simple function that allows we to swap the location of two sprites. but it isnt working, and im not quite sure what is wrong


//Function for swapping positions of sprites

void swapSprite(sf::Sprite a, sf::Sprite b)
{
	sf::Vector2f temp1, temp2;
	temp1 = b.getPosition();
	temp2 = a.getPosition();
	b.setPosition(temp2);
	a.setPosition(temp1);


}

secondly i was just looking for any advice on my code, because im sure it sucks. the game im writing is a simple, aweful tick tack toe game, really to this point ive got a basic game loop, that polls for events and draws stuff. the only event ive really worked on is looking to see if the mouse is clicked inside of the button area.

other than that havent done much with the game itself besides getting everything created and displayed

fyi there is some stupid random stuff in there, thats just me testing a few sfml features out :p


#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/Audio.hpp>
#include <iostream>

using namespace std;


//mutex makes locked data only able to be accessed by one thread
sf::Mutex mutex;

//Function for swapping positions of sprites

void swapSprite(sf::Sprite a, sf::Sprite b)
{
	sf::Vector2f temp1, temp2;
	temp1 = b.getPosition();
	temp2 = a.getPosition();
	b.setPosition(temp2);
	a.setPosition(temp1);


}

//button function, must edit
bool V2i_inRange(sf::Vector2i a, sf::Vector2f b, int xRange, int yRange)
{
	
	// perhaps use this :  sf::Vector2f mouse(a);	 if this code doesnt work
	if (b.x + xRange >= a.x && b.y + yRange >= a.y)
		if (b.x <= a.x && b.y <= a.y)
		{
		return true;
		}
		else
		{
			return false;
		}
	else

		return false;
}

//this is a thread, it runs while the main thread is still running when called
void func()
{


	mutex.lock();

	for (int n = 0; n < 10; n++)
		std::cout << "I'm thread number one" << std::endl;

	mutex.unlock();


}


int main()
{
	sf::RenderWindow window;
	sf::Clock clock;
	sf::Time t1;
	float sec;
	window.create(sf::VideoMode(800, 600, 32), "Loading...", sf::Style::Default);
	while (sec<1)
	{
		t1 = clock.getElapsedTime();
		sec = t1.asSeconds();
	}
	sf::Font font;
	if (!font.loadFromFile("Medici Text.ttf"))
		{
		cout << "Error loading file :(\n";
		}
	window.setVerticalSyncEnabled(true);
	
	//Graphic add
	sf::Texture ttt;
	sf::Sprite gameb, x1, x2,x3,x4,x5,x6,x7,x8,x9,o1,o2,o3,o4,o5,o6,o7,o8,o9;
	if (!ttt.loadFromFile("tttsprite.png"))
	{
		std::cout << "Sorry, bro your sprites didnt load/n";
	}
	sf::Texture button;
	sf::Sprite button1, button2, button3, button4, button5, button6, button7, button8, button9;
	if (!button.loadFromFile("norm.png"))
	{
		std::cout << "you be buttonless foo!";
	}
	gameb.setTexture(ttt);
	gameb.setPosition(150, 100);


	//sprites for X's and O's
	x1.setTexture(ttt);
	x1.setScale(0.75f, 0.75f);
	x1.setTextureRect(sf::IntRect(35, 88, 54, 54));
	x1.setColor(sf::Color(255, 255, 255, 128));
	x1.setPosition(-100, 0);
	o1.setTexture(ttt);
	o1.setScale(0.75f, 0.75f);
	o1.setTextureRect(sf::IntRect(35, 192, 54, 56));
	o1.setColor(sf::Color(255, 255, 255, 128));
	o1.setPosition(-100, 0);
	x1 = x2;
	x1 = x3;
	x1 = x4;
	x1 = x5;
	x1 = x6;
	x1 = x7;
	x1 = x8;
	x1 = x9;
	o1 = o9;
	o1 = o2;
	o1 = o3;
	o1 = o4;
	o1 = o5;
	o1 = o6;
	o1 = o7;
	o1 = o8;
	//make buttons for where player will click to add x
	button1.setTexture(button);
	button1.setScale(0.5f, 0.5f);
	button1.setPosition(310, 180);
	button2=button1;
	button3=button1;
	button4=button1;
	button5 = button1;
	button6 = button1;
	button7 = button1;
	button8 = button1;
	button9 = button1;
	button2.setPosition(370, 180);
	button3.setPosition(430,180);
	button4.setPosition(310, 240);
	button5.setPosition(370, 240);
	button6.setPosition(430, 240);
	button7.setPosition(310, 300);
	button8.setPosition(370, 300);
	button9.setPosition(430, 300);
	float buttonh=button1.getGlobalBounds().height;
	float buttonw = button1.getGlobalBounds().width;
	
	sf::Text text;
	text.setFont(font);
	text.setString("Press any key to continue");
	text.setCharacterSize(32);
	text.setColor(sf::Color::Red);
	//text.setStyle(sf::Text::Bold);

	//Loading screen music
	sf::Music music;
	music.setVolume(50);
	if (!music.openFromFile("loadingmusic.ogg"))
	{
		std::cout << "Wah Waaaaa, your music didn't load properly.\n";
	}
	music.play();

	//loading screen
	bool even = true,texts=true;
	float n = 0.0;
	while (even)
	{

		sf::Event event;
		while (window.pollEvent(event))
		{
			if (event.type == sf::Event::Closed)
			{
				music.stop();
				window.close();
				return 0;
			}
			if (event.type == sf::Event::KeyPressed)
			{

				even = false;
				
			}
			
		}
	   if (texts)
			{
				text.setCharacterSize(32+n);
				n=n+0.5;
				if (n == 5)
				{
					texts = false;
				}
			}
			if (!texts)
			{
				text.setCharacterSize(32 + n);
				n=n-0.5;
				if (n==0)
				{
					texts = true;
				}
			}
			
			window.clear(sf::Color::Black);
			window.draw(text);


			window.display();

	}
	music.stop();
	text.setString("Welcome to Basic Tick Tack Toe 2.0!");

	window.setTitle("Tick Tack Toe 2.0");

	//testing threads
	sf::Thread thread(&func);
	thread.launch();

	//this code makes sure that a complete line is handled while printing out statements from the func and here
	//first lock function called is completed before the other is allowed to activate
	mutex.lock();
	text.setColor(sf::Color::Black);
	for (int i = 0; i < 10; ++i)
		std::cout << "I'm the main thread" << std::endl;

	mutex.unlock();
	text.setCharacterSize(32);

	sf::Music theme;
	theme.setVolume(50);
	theme.setLoop(true);
	if (!theme.openFromFile("theme.ogg"))
	{
		std::cout << "Poor you, your theme won't play :(/n";
	}
	theme.play();

	//Main Program
	while (window.isOpen())
	{

		sf::Event event;
		while (window.pollEvent(event))
		{
			switch (event.type)
			{
			case sf::Event::Closed:
				window.close();
				break;
			case sf::Event::KeyPressed:
				break;
			case sf::Event::MouseButtonPressed:
				if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
				{
					// left mouse button is pressed: is it in range of button
					//get position of mouse, then x,y origin of object, then range of object
					if (V2i_inRange(sf::Mouse::getPosition(window), button1.getPosition(), buttonw, buttonh))
					{
						std::cout << "the button function works\n";
						swapSprite(x1, button1);

					}
				}
				break;
			case sf::Event::MouseMoved:
				break;
			default:
				break;
			}

			

			
		}
			window.clear(sf::Color::Red);
			window.draw(text);
			window.draw(gameb);
			window.draw(x1);
			window.draw(o1);
			window.draw(button1);
			window.draw(button3);
			window.draw(button4);
			window.draw(button5);
			window.draw(button6);
			window.draw(button7);
			window.draw(button8);
			window.draw(button9);
			window.draw(button2);

			window.display();

	}




	return 0;
}


first off im trying to run a simple function that allows we to swap the location of two sprites. but it isnt working, and im not quite sure what is wrong
//Function for swapping positions of sprites

void swapSprite(sf::Sprite a, sf::Sprite b)
{
sf::Vector2f temp1, temp2;
temp1 = b.getPosition();
temp2 = a.getPosition();
b.setPosition(temp2);
a.setPosition(temp1);


}

To beginn, the problem you have are your function arguments. You give them call by value instead call by reference. the correct code would be:


void swapSprite(sf::Sprite& a, sf::Sprite& b)
{
sf::Vector2f temp1, temp2;
temp1 = b.getPosition();
temp2 = a.getPosition();
b.setPosition(temp2);
a.setPosition(temp1);
}

or


void swapSprite(sf::Sprite& a, sf::Sprite& b)
{
    b.setPosition(a.getPosition());
    a.setPosition(b.getPosition());
}

The difference are the arguments. Call by value means you are just create copies.

if you use Call by reference you don't create a copy

and instead still works with on the same Object

Advertisement

D: gosh i cant believe i made that mistake! thanks for the help!

To beginn, the problem you have are your function arguments. You give them call by value instead call by reference. the correct code would be:


void swapSprite(sf::Sprite& a, sf::Sprite& b)
{
sf::Vector2f temp1, temp2;
temp1 = b.getPosition();
temp2 = a.getPosition();
b.setPosition(temp2);
a.setPosition(temp1);
}

or


void swapSprite(sf::Sprite& a, sf::Sprite& b)
{
    b.setPosition(a.getPosition());
    a.setPosition(b.getPosition());
}

The second version isn't the same as the first version. The first swaps the location of the two sprites, the second makes both sprites be set to the location of sprite A. (The temporaries have a purpose there).

ok so i fixed it, and my button moves when i click on it :D which is good, however i guess now my problem is what to do with the old button.

with the little knowlege i have this is what im intending to do (correct me if there is a better way)

window.clear

window.draw(every sprite ive created)

window.display

then using the pollEvent wait for the user to click on a button, swap the button with an x, then have a simple function to have the computer choose its own move. however im having trouble moving my sprites off the screen, is that something i should be doing? or is there a method i should use that would be better for what im trying to do?

ohunsure.png ... after you said it Servant, you are absolutly right. It's to late/early here in germany 2am, anyway. sorry my mistake

---

Instead moving the Button offscreen you could perhaps use if-else conditions to decide which texture of the Button you want draw

each loop. as quick idea.

for now I'm say good night biggrin.png

Advertisement

Have you checked out SFGUI? It's a GUI library for SFML - I haven't used it myself, but it looks pretty feature-full.

At a general level though, you want to separate (at least conceptually) the state of your game's data from the drawing of your game.

I wouldn't be swapping sprite positions - instead, I'd only draw the sprites that are visible and just not draw the sprites that aren't visible. One way of doing that is to wrap your "button" into its own class, and let that class decide when to show and when to hide each of the two appearances.

see i thought about a gui library, but i really wanted to just write a simple button, and not have to learn all that new stuff right now.

ok i like what you're telling me but im not quite sure of implementation, i have thought of that but from my basic knowlege of all of this, i cant quite figure out what i should do to say draw these and dont draw these. perhaps put all of my sprites into a class and have a boolean value for each of them, and if that boolean is true then draw it? or is there a command that i havent figured out yet that would be better?

You don't want to put all your sprites in a class, just have a class that is a "button", and only put button-sprites in that class. Yes, you can use a boolean to indicate which of the two sprites to draw.

Something like: (fake code to demonstrate what I mean - this code won't actually compile)


enum ButtonState {Normal, Hovered, Pressed};

class Button
{
private:
     Sprite buttonNormalSprite;
     Sprite buttonHoveredSprite;
     Sprite buttonPressedSprite;

     ButtonState currentState;

public:
      void Draw(renderTarget)
      {
            if(this->currentState == Hovered)
            {
                  renderTarget.Draw(buttonHoveredSprite);
            }
            else if(this->currentState == Pressed)
            {
                  renderTarget.Draw(buttonPressedSprite);
            }
            else
            {
                  renderTarget.Draw(buttonNormalSprite);
            }
      }
      
      //Returns true when the button is actually triggered.
      bool HandleEvent(event)
      {
           bool withinMouseRectangle = WithinRect(this->rectangle, mousePosition);
           
            if(event is mouse movement && this->currentState != Pressed)
            {
                 if(withinMouseRectangle)
                 {
                       this->currentState = Hovered;
                 }
                 else
                 {
                       this->currentState = Normal;
                 }
            }
            else if(event is mouse button press)
            {
                 if(withinMouseRectangle)
                 {
                       this->currentState = Pressed;
                 }
                 else
                 {
                       this->currentState = Normal;
                 }
            }
            else if(event is mouse button release)
            {
                 if(withinMouseRectangle)
                 {
                       if(this->currentState == Pressed)
                       {
                             this->currentState = Hovered;
                             return true; //Button was clicked.
                       }
                       else
                       {
                             this->currentState = Hovered;
                       }
                 }
                 else
                 {
                       this->currentState = Normal;
                 }
            }

            return false;
      }
     
};

This topic is closed to new replies.

Advertisement