• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

SFML - Wskaźnik na menu gry

Object Storage Arubacloud
0 głosów
644 wizyt
pytanie zadane 15 maja 2015 w C i C++ przez Adrian1999 Nałogowiec (34,570 p.)

Mam pytaie czy można zrobić wskaźnik który będzie sam w sobie zmieniał kolor danego sf::Text ? Bo mój sposób jest chyba troszke jakiś taki dziwny i jeżeli bym chciał wywołać funkcje którą wywoła przycisk enter czy coś musiałbym switcha zrobić czy ,,coś =1 " jak tak to uruchom te funkcje 

aktualnie nie chodzi mi o skrócenie kodu, potem będę nad tym myśleć teraz tylko o tym jak można zrobić tą rzecz co napisałem wyżej

#include <SFML\Graphics.hpp>
#include <iostream>

sf::RenderWindow window(sf::VideoMode(1024, 768, 32), "SFML 2.2");

void wskaznik(sf::Text tablica[])
{
	sf::Text chwilowa;
	tablica[0].setColor(sf::Color::Green);
}


int main()
{
	
	sf::Font s;
	if (!s.loadFromFile("arial.ttf")){ std::cout << "BLAD!"; }
	sf::Text tekst[3];
	for (int i = 0; i <= 2;i++)
	tekst[i].setFont(s);
	tekst[0].setString("Nowa Gra");
	tekst[1].setString("Wczytaj");
	tekst[2].setString("Zapisz");
	tekst[0].setPosition(412, 10);
	tekst[1].setPosition(412, 70);
	tekst[2].setPosition(412, 130);
	int cos = 0;;
	while (window.isOpen())
	{
		sf::Event event;
		while (window.pollEvent(event))
		{
			if (event.type == sf::Event::Closed) window.close();
			if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::S)) {
				if (cos == 2){ cos = 0; }
				else cos += 1;
			}
		}
		window.clear();
		for (int i = 0; i <= 2; i++)
			tekst[i].setColor(sf::Color::White);
		wskaznik(tekst+cos);
		for (int i = 0; i <= 2; i++)
		window.draw(tekst[i]);

		window.display();
	}
}

 

1 odpowiedź

0 głosów
odpowiedź 15 maja 2015 przez MrWeb Stary wyjadacz (10,200 p.)

Cześć,

Proszę, wytłumacz mi o co Ci chodzi

czy można zrobić wskaźnik który będzie sam w sobie zmieniał kolor danego sf::Text ?

Dla mnie brzmi jak fragment poezji Cypriana Kamila Norwida cheeky

Wskaźnik może wskazywać na zmienną/tablicę zmiennych lub funkcję,  a wskaźnik który sam w sobie będzie zmieniał zmienną to coś nowego dla mnie :D
Stworzyłeś funkcję która chyba miała zmieniać kolor, i pewnie działała, ale nie jest ona wydajna, choćby dlatego, że tworzysz w niej niepotrzebny obiekt klasy sf::Text, a argumentem funkcji jest cała tablica tekstów zamiast jednego...

Pozwoliłem sobie poprawić kod, tak byś sam mógł zauważyć błędy lub ewentualne poprawki wydajności.

#include <SFML\Graphics.hpp>
#include <iostream>

void changeColor(sf::Text& text)
{
  static bool isRed = true;
  
  if(isRed)
  {
    text.setColor(sf::Color::Green);
    isRed = false;
  }
  else
  {
    text.setColor(sf::Color::Green);
    isRed = true;
  }
}


int main()
{
  sf::RenderWindow window(sf::VideoMode(1024, 768), "SFML 2.2");

  sf::Font s;
  if (!s.loadFromFile("arial.ttf")) 
  {
    //wg mnie tutaj program powinien się kończyć
    //bo dalej tylko masz błędny obiekt font i program się wysypie
    //przy próbie narysowania tekstu lub nic się nie pojawi
    std::cout << "BLAD!"; 
    //return 0; //w razie czego wystarczy odkomentować
  }

  sf::Text tekst[3];
    
  for (int i = 0; i <= 2;i++)
    tekst[i].setFont(s);
    
  tekst[0].setString("Nowa Gra");
  tekst[1].setString("Wczytaj");
  tekst[2].setString("Zapisz");
  
  tekst[0].setPosition(412, 10);
  tekst[1].setPosition(412, 70);
  tekst[2].setPosition(412, 130);
  
  int pos = -1;
  while (window.isOpen())
  {
    sf::Event event;
    while (window.pollEvent(event))
    {
      if (event.type == sf::Event::Closed) 
        window.close();
      
      if (event.type == sf::Event::KeyPressed) 
      {
        if(event.key.code == sf::Keyboard::S) //eventy dla S (menu w dół)
        {
          for (int i = 0; i <= 2; i++) //wyzeruj wszystkie kolory
            tekst[i].setColor(sf::Color::White);
          
          if (++pos == 3) pos = 0; //zmień tylko aktualny kolor na którym jesteś
          text[pos].setColor(sf::Color::Green);
        }
        
        if(event.key.code == sf::Keyboard::E)
        {
          std::cout << "włączam opcję nr" << pos + 1 << std::endl; //pos + 1 bo adresowanie od 0
        }
      }
    }
    
    window.clear(); //wyczyść okno
    
    for (int i = 0; i <= 2; i++)
      window.draw(tekst[i]); //narysuj tekst
 
    window.display(); //wyświetl okno
  }
}

Napisałem funkcję do zmiany koloru, wystarczy podać obiekt klasy sf::Text i przy każdym kolejnym wywołaniu powinien zmienić kolor ale nie testowałem jej więc nie wiem czy działa.

Uwaga, nie kompilowałem i nie uruchamiałem kodu, pisałem wszystko z pamięci w notatniku więc zastrzegam sobie uwag dotyczących błędów logicznych lub składniowych.

komentarz 15 maja 2015 przez Adrian1999 Nałogowiec (34,570 p.)

Wiesz co strasznie mi ktoś do głowy wbił by oszczędzać pamięć... Nie wiem skąd zaczełem kombinować i nie wiem wszędzie próbuje zrobić ,,klasa ja = new klasa" i jakoś to mi niewychodzi, powiedz mi czy robię dobrze. i jeżeli mógłbyś udziel mi rad gdzie używać tego new bo moja głowa sama mówi rób tu zrobisz skasuje będziesz mieć więcej pamięci

#include <SFML\Graphics.hpp>
#include <iostream>
#include <windows.h>
int main();
class pierwsze : sf::Drawable
{
	private:
		sf::Font s;
		int cos = 0;
		
public:
	sf::Text tekst[3];
	void wskaznik(sf::Text tablica[])
{
	sf::Text chwilowa;
	tablica[0].setColor(sf::Color::Green);
}
	pierwsze()
	{
	if (!s.loadFromFile("arial.ttf")){ std::cout << "BLAD!"; }
		for (int i = 0; i <= 2; i++)
			tekst[i].setFont(s);
		tekst[0].setString("Nowa Gra");
		tekst[1].setString("Wczytaj");
		tekst[2].setString("Zapisz");
		tekst[0].setPosition(412, 10);
		tekst[1].setPosition(412, 70);
		tekst[2].setPosition(412, 130);

	}
	~pierwsze()
	{
		std::cout << "UMIErAM!";
	}
private:
	virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
	{

		target.draw(tekst[0]);
		target.draw(tekst[1]);
		target.draw(tekst[2]);
	}
};

bool glowny(pierwsze s, sf::RenderWindow& window)
{
	while (window.isOpen()){
		sf::Event cos;
		while (window.pollEvent(cos))
		{
			if (cos.type == sf::Event::Closed)
				window.close();
			if ((cos.type == sf::Event::KeyPressed) && (cos.key.code == sf::Keyboard::Q))return false; break;
		}

		window.clear(sf::Color::Green);
		for (int i = 0; i <= 2; i++)
			window.draw(s.tekst[i]);
		window.display();

	}
}
class graj
{
	sf::RectangleShape kwadrat;
	sf::Event cos;
public:
	void gra(sf::RenderWindow& window)
	{
		
		kwadrat.setSize(sf::Vector2f(40, 40));
		kwadrat.setPosition(50, 40);
		while (window.isOpen()){

			while (window.pollEvent(cos))
			{
				if (cos.type == sf::Event::Closed)
					window.close();
			}
			window.clear(sf::Color::Green);
			window.draw(kwadrat);
			window.clear();

		}
	}
	virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
	{

		target.draw(kwadrat);
	}
};

int main()
{
	sf::RenderWindow window(sf::VideoMode(1024, 768, 32), "SFML 2.2");
	pierwsze *as = new pierwsze;

		std::cout << as << std::endl;
			
		glowny(*as, window);
delete as;
window.clear(sf::Color::Green);
graj a;
a.gra(window);
	return 0;
}

 

komentarz 16 maja 2015 przez MrWeb Stary wyjadacz (10,200 p.)

Przede wszystkim, dopóki nie opanujesz w 100% pamięci dynamicznej (new, delete) program będzie się sypał w nieoczekiwanych momentach i potem będzie Ci trudno namieżyć błąd a jeśli użyjesz wszędzie zmiennych automatycznych (int a;) tych błędów będzie zdecydowanie mniej. Problem w tym, że pamięć dynamiczna wymaga doświadczenia.
Według mnie korzystasz z alokacji trochę na ślepo nie rozmiejąc w całości co się dzieje z programem... Stwórz nowy projekt, włącz tą lekcję https://www.youtube.com/watch?v=0DQl74alJzw&index=11&list=PLOYHgt8dIdoxx0Y5wzs7CFpmBzb40PaDo i po kolei przepracuj wszystko co zostało pokazane w poradniku.

A co do kodu, dla mnie to jakaś masakra.

Nazwy klas pisze się z dużej litery, 

klasa graj nie dziedziczy z klasy sf::Drawable a mimo to przeciążasz w niej metodę draw()

Nie zastosowałeś żadnych zmian w kodzie które Ci podałem, 

W klasach panuje śmietnik, np: w klasie pierwsze masz u góry jakieś zmienne, potem jakieś metody i znowu zmienne... to wszystko można by ładnie poukładać,

nazwy zmiennych i metod są bez sensu... Co mi mówi zmienna "cos" ? Do czego ona służy ? Albo wskaźnik "*as", Obiekt klasy graj nazwany po prostu "a"... Po pewnym czasie będziesz miał alfabet a nie zmienne....

Wcięcia raz są, a raz ich nie ma, gdzieś masz klamry rozwijane w jednej lini, a gdzieś w dwóch. Nawet nie wspomnę o main'ie...

Linia 98 - tutaj widać że nie wiesz co tak naprawdę robisz. Ta linia wypisze adres który zawiera wskaźnik czyli po prostu adres do obiektu na stercie. Chciałeś w ten sposób sprawdzić czy obiekt powstał ? 

Błędy logiczne :

linia 53 aż się prosi o błędy. Przy ifie nie dodałeś klamr przez co instrukcja break zawsze będzie się wykonywać. Nie zauważysz tego błędu na początku bo ta pętla i tak nic nie robi ale gdybyś dodał obsługę kolejnych przycisków to byś się zdziwił dlaczego komputer nie reaguje.

Chciałeś zrobić super optymalne alokacje pamięci, a w gruncie rzeczy i tak wszystko się kopiuje. Linia 45 - argument pierwsze jest przekazywany przez wartość czyli że za każdym razem gdy wywołujesz tą funkcję te argumenty będą stworzone od nowa.

Dwie pętle do obsługi eventów - aż się prosi o błędy. Te pętle będą sobie nawzajem przeszkadzać.

 

 

Poniżej masz ten sam kod poprawiony tylko w aspekcie stylistycznym. Porównaj proszę uważnie twój kod z moją wersją... Widzisz coś ciekawego ? Jest czytelniejszy. A przecież to ty go piszesz więc powinno Ci zależeć na tym żebyś mógł przeczytać własny kod. To trochę tak jakbyś napisał wypracowanie a nie potrafiłbyś przeczytać co sam napisałeś. 

#include <SFML\Graphics.hpp>
#include <iostream>
#include <windows.h>

class Graj
{
  public:
  void gra(sf::RenderWindow& window)
  {
    kwadrat.setSize(sf::Vector2f(40, 40));
    kwadrat.setPosition(50, 40);
    
    while (window.isOpen())
    {
      while (window.pollEvent(cos))
      {
        if (cos.type == sf::Event::Closed)
          window.close();
      }
      
      window.clear(sf::Color::Green);
      window.draw(kwadrat);
      window.clear();
    }
  }
  
  private:
  virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
  {
    target.draw(kwadrat);
  }
  
  private:
  sf::RectangleShape kwadrat;
  sf::Event cos;
};

/////////////////////////////////////////////////////////

class Pierwsze : sf::Drawable
{
  public:
  
  void wskaznik(sf::Text tablica[])
  {
    sf::Text chwilowa;
    tablica[0].setColor(sf::Color::Green);
  }
  
  Pierwsze()
  {
    if (!s.loadFromFile("arial.ttf")) std::cout << "BLAD!";
      
    for (int i = 0; i <= 2; i++)
      tekst[i].setFont(s);
  
    tekst[0].setString("Nowa Gra");
    tekst[1].setString("Wczytaj");
    tekst[2].setString("Zapisz");
    tekst[0].setPosition(412, 10);
    tekst[1].setPosition(412, 70);
    tekst[2].setPosition(412, 130);
  }
  
  ~Pierwsze()
  {
    std::cout << "UMIERAM!";
  }
  
  private:
    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
  {
    target.draw(tekst[0]);
    target.draw(tekst[1]);
    target.draw(tekst[2]);
  }
    
  //////////////////////////////////////////////////////
  
  public:
  sf::Text tekst[3];

  private:
  sf::Font s;
  int cos = 0;
};


bool glowny(pierwsze s, sf::RenderWindow& window)
{
  while (window.isOpen())
  {
    sf::Event cos;
    while (window.pollEvent(cos))
    {
      if (cos.type == sf::Event::Closed)
        window.close();
      
      if ((cos.type == sf::Event::KeyPressed) && (cos.key.code == sf::Keyboard::Q))return false;
    }
 
    window.clear(sf::Color::Green);
    
    for (int i = 0; i <= 2; i++)
      window.draw(s.tekst[i]);
      
    window.display();
 
  }
}



int main()
{
  sf::RenderWindow window(sf::VideoMode(1024, 768, 32), "SFML 2.2");
  
  Pierwsze *as = new Pierwsze;
  std::cout << as << std::endl;
  glowny(*as, window);
  delete as;
  
  window.clear(sf::Color::Green);
  
  graj a;
  a.gra(window);
  
  return 0;
}

Jeśli Cię uraziłem moją opinią dot. kodu - przepraszam, ale naprawdę, ten kod to masakra. Obejrzyj jeszcze raz lekcje o programowaniu obiektowym, przećwicz wszystko jeszcze raz i dopiero po tym zabierz się za tworzenie gry, bo nawet jeśli ten kod który napisałeś działa, to po dodaniu nowych rzeczy na 100% zacznie się sypać i sam nie będziesz wiedział co robisz. Co więcej, gdy zostawisz ten kod na tydzień lub dwa będziesz się zastanawiał "co autor miał na myśli".

komentarz 16 maja 2015 przez Adrian1999 Nałogowiec (34,570 p.)

Wiem że masakra, zaczełem teraz nad starannością pracować kodu 

class Gra : sf::Drawable
{
	
	sf::Font czcionka; // jak nazwa mowi wybieramy czcionke
	sf::Text wybierz[3]; // Slowa ktore maja zostac narysowane zainicjowanie ich *
	unsigned int sru = 0;
public:
	Gra(void); // Konstruktor
	bool autor(sf::RenderWindow& okno);
	void zaznaczony(sf::Text tekst[]); // iluzja zaznaczania
	void menu(); // główna klasa
	void zwrocevent();
	
	~Gra(); // Destruktor
private:
	//Rysowanie postaci
	virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
	{
		for (int i = 0; i <= 2;i++)
		target.draw(wybierz[i]);
	}
};

Kod w pliku cpp. też mi się zdaje znacznie bardziej poukładany tamto było kasuj nowe kasuj nowe, a teraz staram się robić z głową. Zaczełem również stosować komentarze, i robić według tutka pana Szymona, czyli w głównej klasie voidy wywołujące menu itd. Dziękuje za uwagę * 

komentarz 16 maja 2015 przez MrWeb Stary wyjadacz (10,200 p.)
Noooo, teraz jest naprawdę dobrze, aż nie mam się do czego przyczepić.

Nie bierz za bardzo do siebie tych uwag bo gdy programowanie Cię wciągnie, i gdy będzie więcej sukcesów niż błędów zrozumiesz dlaczego tak bardzo zależało mi na stylistyce a na tą chwilę poprostu musiałem użyć trochę ostrzejszych słów :)

Podobne pytania

0 głosów
1 odpowiedź 528 wizyt
pytanie zadane 11 marca 2018 w C i C++ przez zpawlo00 Początkujący (310 p.)
+1 głos
0 odpowiedzi 562 wizyt
pytanie zadane 5 sierpnia 2016 w Nasze projekty przez obl Maniak (51,280 p.)
0 głosów
3 odpowiedzi 2,584 wizyt
pytanie zadane 17 kwietnia 2016 w C i C++ przez Munvik Dyskutant (9,350 p.)

92,620 zapytań

141,474 odpowiedzi

319,815 komentarzy

62,005 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...