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

Problem z klasami, sfml cpp

Object Storage Arubacloud
0 głosów
307 wizyt
pytanie zadane 12 stycznia 2020 w C i C++ przez Dawid_1900 Nowicjusz (210 p.)
edycja 12 stycznia 2020 przez Dawid_1900

Witam, 

Jestem początkującym, dlatego proszę o wyrozumiałość smiley

Piszę pacmana w sfml cpp i napotkałem pewien problem, mianowicie

class pos // klasa pomocnicza
{
public:
	int x;
	int y;
	const int Scale_times = 18;
	const int Scale_plus  = 8;
	pos() = default;
	pos(int px, int py);
	friend ostream& operator<<(ostream& fout, const pos& print);
};

class Plansza
{
protected: 
	int mMap[28][31] = { 0 };
	pos Duszki_pos[4];
	pos Pacman_pos;
	vector<pos> punkty;
	int Pkt_total;
public:

	Plansza();

	void wypisz_sie();

	Plansza(string name);

	void wczytaj(string nazwa);

	void uzupelnij_swoje_dane();

	enum TileType
	{
		Pill = 1,
		Wall = 3,
		PacMan = 4,
		Tunnel = 7,
		GhostSpawn = 9
	};

	void makeWallsMap(sf::RenderTarget& target);

	void drawHorizontalLine(sf::RenderTarget& rt, int x1, int x2, int y);

	void drawVerticalLine(sf::RenderTarget& rt, int y1, int y2, int x);

};
class Pacman: public Plansza, public Drawable
{
	int x = 0;
	int y = 0;
	
public:
	Pacman();
	Vector2f getPosition();
private:
	sf::CircleShape ksztalt;
	const float promien{ 10.0f };
	const float kulka_Velocity{ 3.0f };
	sf::Vector2f velocity{ kulka_Velocity, kulka_Velocity }; //wektor predkosci 2d
	virtual void drawPac(sf::RenderTarget& target, sf::RenderStates state) const;
};

Przy takiej strukturze danych, tworze obiekt Pacman gracz(); ale przy wywołaniu gracz.drawPac(…) kompilator pokazuje mi, że wyrażenie musi mieć typ klasy i nie bardzo wiem dlaczego może tak się dziać. Do tego mam pytanie odnośnie klasy Drawable, czy dziedziczenie jest konieczne pomimo tego, że i tak nadpisuje wirtualnie tą funkcję w klasie? Nie nadpisując klasa staje się wirtualna.

Main : 

RenderWindow window{ VideoMode(800,800), "Okienko", Style::Default};
    Plansza Map("Level1.txt");
    Map.wypisz_sie();
    Pacman g();
     
    while (window.isOpen())
    {
        Event evnt;
        while (window.pollEvent(evnt))
        {
            if (evnt.type == evnt.Closed)
                window.close();
        }
 
        g.drawPac(); // tutaj jest blad
 
        Map.makeWallsMap(window);
        window.display();
    }
 
    return 0;
}

Konstruktor klasy :

Pacman::Pacman()
{
    cout << "Konstruktor klasy!" << endl;
    int x = Pacman_pos.x * Pacman_pos.Scale_times + Pacman_pos.Scale_plus;
    int y = Pacman_pos.y * Pacman_pos.Scale_times + Pacman_pos.Scale_plus;
    ksztalt.setPosition(x, y);
    ksztalt.setRadius(this->promien);
    ksztalt.setFillColor(sf::Color::White);
    ksztalt.setOrigin(this->promien, this->promien);
 
}

 

komentarz 12 stycznia 2020 przez tkz Nałogowiec (42,000 p.)
Pokaż więcej kodu. Jak wywołujesz klasę etc.

1 odpowiedź

0 głosów
odpowiedź 12 stycznia 2020 przez Dawid_1900 Nowicjusz (210 p.)
Main: 

	RenderWindow window{ VideoMode(800,800), "Okienko", Style::Default};
	Plansza Map("Level1.txt");
	Map.wypisz_sie();
	Pacman g();
	
	while (window.isOpen())
	{
		Event evnt;
		while (window.pollEvent(evnt))
		{
			if (evnt.type == evnt.Closed)
				window.close();
		}

		g.drawPac(); // tutaj jest blad

		Map.makeWallsMap(window);
		window.display();
	}

	return 0;
}

Konstruktor klasy:

Pacman::Pacman()
{
	cout << "Konstruktor klasy!" << endl;
	int x = Pacman_pos.x * Pacman_pos.Scale_times + Pacman_pos.Scale_plus;
	int y = Pacman_pos.y * Pacman_pos.Scale_times + Pacman_pos.Scale_plus;
	ksztalt.setPosition(x, y);
	ksztalt.setRadius(this->promien);
	ksztalt.setFillColor(sf::Color::White);
	ksztalt.setOrigin(this->promien, this->promien);

}

 

komentarz 12 stycznia 2020 przez tkz Nałogowiec (42,000 p.)
drawPac(sf::RenderTarget& target, sf::RenderStates state)
drawPac();

1. To definicja metody, 2. to wywołanie owej metody, różnią się. 

komentarz 12 stycznia 2020 przez Dawid_1900 Nowicjusz (210 p.)

Faktycznie, nie zauważyłem tego.

Poprawiłem funkcje na takie jakie miałem w klasie Plansza:

void draw(sf::RenderTarget& target, sf::RenderStates state) const;

void Pacman::draw(sf::RenderTarget & target, sf::RenderStates state) const
{
	target.draw(this->ksztalt, state);
}

wywołanie w main: 
window.draw(g);


Ta konfiguracja działa dla klasy, która stworzylem w innym projekcie, praktycznie takiej samej
jak ta tutaj mianowicie: 
 class Kula : public sf::Drawable
{
public:
	Kula(float t_X, float t_Y);
	Kula() = delete; //nie mozna stworzyc bezargumentowym
	~Kula() = default;
	void update();

	sf::Vector2f getPosition();

	void moveUp();
	void moveDown();
	void moveLeft();
	void moveRight();

	float left();//zwracaja pozycje krawedzi
	float right();
	float top();
	float bottom();
private:
	sf::CircleShape ksztalt;
	const float promien{ 10.0f };
	const float kulka_Velocity{ 3.0f };
	sf::Vector2f velocity{ kulka_Velocity, kulka_Velocity }; //wektor predkosci 2d
	void draw(sf::RenderTarget& target, sf::RenderStates state) const ;
};

różnią się głownie dziedziczeniem, a funkcja tutaj nie działa. Pokazuje błędne przyjmowane parametry, pomimo, że dla klasy Kula działa poprawnie.

żeby zobrazowac problem dodałem funkcje zwracająca wartosc x:
int get_x();

i jej wywołanie w main: 
Pacman g();
	g.get_x();

Pokazuje się to samo co wcześniej, czyli g musi mieć typ klasy.

 

komentarz 12 stycznia 2020 przez Dawid_1900 Nowicjusz (210 p.)
Chodzi tutaj głownie o to:

Jest obiekt Plansza Map("Level1.txt");

Wpisując Map. dostaje podpowiedzi, jakie funkcje mogę użyc, a tworząc Pacman g();

i następnie wpisując g. nie wyświetla się nic, kompilator nie uznaje tego za obiekt klasy :/
komentarz 12 stycznia 2020 przez tkz Nałogowiec (42,000 p.)
Zwróć uwagę na specyfikatory zasięgu.
komentarz 12 stycznia 2020 przez Dawid_1900 Nowicjusz (210 p.)

Przeczytałem, o co może mniej więcej chodzić, ale dalej nie mam pojęcia co z tym zrobić frown

komentarz 12 stycznia 2020 przez tkz Nałogowiec (42,000 p.)
Ja tym bardziej. Nie podałeś problemu, co chcesz zrobić.
komentarz 12 stycznia 2020 przez Dawid_1900 Nowicjusz (210 p.)
Celem jest narysowanie obiektu PacMan w okienku(jak na razie jest po prostu kulka).

Problemem jest to, że po stowrzeniu obiektu, kompilator mówi mi, że nie jest to obiekt klasy, nie mogę odwołać się do żadnej funkcji z tej klasy.
komentarz 12 stycznia 2020 przez tkz Nałogowiec (42,000 p.)
Dlaczego draw jest wirtualne? Masz implementację tych metod?
komentarz 12 stycznia 2020 przez Dawid_1900 Nowicjusz (210 p.)

Jeżeli nie dam funkcji draw jako witrualnej, cala klasa bedzie wirtualna z racji dziedziczenia Drawable (tak przeczytalem w innych pytaniach na tym forum).

Wklejam poniżej cały kod, który do tej pory napisałem (pliki .cpp)

Pacman.cpp:

#include "Pacman.h"

Pacman::Pacman()
{
	cout << "Konstruktor klasy!" << endl;
	int x = Pacman_pos.x * Pacman_pos.Scale_times + Pacman_pos.Scale_plus;
	int y = Pacman_pos.y * Pacman_pos.Scale_times + Pacman_pos.Scale_plus;
	ksztalt.setPosition(x, y);
	ksztalt.setRadius(this->promien);
	ksztalt.setFillColor(sf::Color::White);
	ksztalt.setOrigin(this->promien, this->promien);

}



Vector2f Pacman::getPosition()
{
	return ksztalt.getPosition();
}

int Pacman::get_x()
{
	return x;
}


void Pacman::draw(sf::RenderTarget & target, sf::RenderStates state) const
{
	target.draw(this->ksztalt, state);
}

Plansza.cpp: 

#include "Plansza.h"
#include <fstream>
#include <vector>
#include <SFML/Graphics.hpp>
#include <iostream>
#include <sstream>



Plansza::Plansza()
{
}

void Plansza::wypisz_sie()
{
	cout << "////////////////////////////////////" << endl;
	cout << "mMap: " << endl;
	for (int i = 0; i < 28; i++)
	{
		for (int j = 0; j < 31; j++)
			cout << mMap[i][j] << " ";
		cout << endl;
	}
	cout << endl << endl;
	cout << "Pozycje duszkow: " << endl;
	for (int i = 0; i < 4; i++)
		cout << Duszki_pos[i];
	cout << endl;
	cout << "Pozycja Pacmana: " << Pacman_pos << endl;

}

Plansza::Plansza(string name)
{
	wczytaj(name);
	uzupelnij_swoje_dane();
}

void Plansza::wczytaj(std::string nazwa)
{

		ifstream plik;
		plik.open(nazwa);
		if (not plik.good())
		{
			cout << "Bledny plik wejsciowy z plansza!" << endl;
			getchar();
		}
		string linia;
		int y = 0;
		while (getline(plik, linia))
		{
			int x = 0;
			stringstream ss(linia);
			int temp;
			while (ss)
			{
				if (ss >> temp)
				{
					mMap[x][y] = temp;
					x++;
				}
			}
			y++;



		}
		plik.close();

}

void Plansza::uzupelnij_swoje_dane()
{
	int iter = 0;
	for (int i = 0; i < 28; i++)
	{
		for (int j = 0; j < 31; j++)
		{
			if (mMap[i][j] == Pill) punkty.push_back(pos(i, j));
			if (mMap[i][j] == PacMan) { Pacman_pos.x = i; Pacman_pos.y = j; };
			if (mMap[i][j] == GhostSpawn) { Duszki_pos[iter].x = i; Duszki_pos[iter].y = j; iter++; }
		}
	}


}

void Plansza::makeWallsMap(sf::RenderTarget & target)
{
	sf::Vertex arr[4];
	arr[0].color = sf::Color::Blue;
	arr[1].color = sf::Color::Blue;
	arr[2].color = sf::Color::Blue;
	arr[3].color = sf::Color::Blue;
	for (int x = 0; x < 27; ++x)
	{
		if ((mMap[x][0] == Wall) && (mMap[x + 1][0] == Wall)) drawHorizontalLine(target, x, x + 1, 0);
		if ((mMap[x][30] == Wall) && (mMap[x + 1][30] == Wall)) drawHorizontalLine(target, x, x + 1, 30);
	}
	for (int y = 0; y < 30; ++y)
	{
		if ((mMap[0][y] == Wall) && (mMap[0][y + 1] == Wall)) drawVerticalLine(target, y, y + 1, 0);
		if ((mMap[27][y] == Wall) && (mMap[27][y + 1] == Wall)) drawVerticalLine(target, y, y + 1, 27);
	}
	for (int x = 1; x < 27; ++x) for (int y = 1; y < 30; ++y)
	{
		if (mMap[x][y] == Wall)
		{
			if (mMap[x - 1][y] == Wall) drawHorizontalLine(target, x - 1, x, y);
			if (mMap[x + 1][y] == Wall) drawHorizontalLine(target, x + 1, x, y);
			if (mMap[x][y - 1] == Wall) drawVerticalLine(target, y - 1, y, x);
			if (mMap[x][y + 1] == Wall) drawVerticalLine(target, y + 1, y, x);
		}
	}//for x for y
}

void Plansza::drawHorizontalLine(sf::RenderTarget & rt, int x1, int x2, int y)
{
	sf::Vertex arr[4];
	arr[0].color = sf::Color::Blue;
	arr[1].color = sf::Color::Blue;
	arr[2].color = sf::Color::Blue;
	arr[3].color = sf::Color::Blue;
	arr[0].position = sf::Vector2f(16.f*(x1 + 0.5f), 16.f*(y + 0.5f) - 1.5f);
	arr[1].position = sf::Vector2f(16.f*(x1 + 0.5f), 16.f*(y + 0.5f) + 1.5f);
	arr[2].position = sf::Vector2f(16.f*(x2 + 0.5f), 16.f*(y + 0.5f) + 1.5f);
	arr[3].position = sf::Vector2f(16.f*(x2 + 0.5f), 16.f*(y + 0.5f) - 1.5f);
	rt.draw(arr, 4, sf::Quads);
}

void Plansza::drawVerticalLine(sf::RenderTarget & rt, int y1, int y2, int x)
{
	sf::Vertex arr[4];
	arr[0].color = sf::Color::Blue;
	arr[1].color = sf::Color::Blue;
	arr[2].color = sf::Color::Blue;
	arr[3].color = sf::Color::Blue;
	arr[0].position = sf::Vector2f(16.f*(x + 0.5f) - 1.5f, 16.f*(y1 + 0.5f));
	arr[1].position = sf::Vector2f(16.f*(x + 0.5f) + 1.5f, 16.f*(y1 + 0.5f));
	arr[2].position = sf::Vector2f(16.f*(x + 0.5f) + 1.5f, 16.f*(y2 + 0.5f));
	arr[3].position = sf::Vector2f(16.f*(x + 0.5f) - 1.5f, 16.f*(y2 + 0.5f));
	rt.draw(arr, 4, sf::Quads);
}

pos::pos(int px, int py)
	:x (px), y(py)
{
}

ostream & operator<<(ostream & fout, const pos & print)
{
	fout << "Pozycja X: " << print.x << ", Pozycja Y: " << print.y << endl;
	return fout;
}

Source.cpp:

#include <SFML/Graphics.hpp>
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include "Plansza.h"
#include "Pacman.h"
using namespace std;
using namespace sf;

int main()
{
	RenderWindow window{ VideoMode(800,800), "Okienko"};
	//RectangleShape mapa(Vector2f(1200.0f, 1200.0f));
	Plansza Map("Level1.txt");
	Map.wypisz_sie();
	Pacman g();
	g.get_x(); //Wyrazenie musi mieć typ klasy
	
	while (window.isOpen())
	{
		Event evnt;
		while (window.pollEvent(evnt))
		{
			if (evnt.type == evnt.Closed)
				window.close();
		}

		window.draw(g); // zła lista argumentów

		Map.makeWallsMap(window);
		window.display();
	}

	return 0;
}

 

komentarz 12 stycznia 2020 przez tkz Nałogowiec (42,000 p.)

https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1Drawable.php

Zobacz, że draw przyjmuje coś innego, niż Ty podajesz. Z tego co widzę na stackoverflow masz źle przeciążoną metodę draw. 

komentarz 12 stycznia 2020 przez Dawid_1900 Nowicjusz (210 p.)
Problem zażegnany, przy deklaracji obiektu niepotrzebnie dałem nawiasy funkcyjne.

Dziekuję za pomoc :D

Podobne pytania

0 głosów
1 odpowiedź 373 wizyt
pytanie zadane 11 września 2018 w C i C++ przez oliwzcak12 Użytkownik (550 p.)
0 głosów
3 odpowiedzi 1,681 wizyt
0 głosów
2 odpowiedzi 135 wizyt
pytanie zadane 1 maja 2019 w C i C++ przez NEFOS Początkujący (320 p.)

92,615 zapytań

141,465 odpowiedzi

319,782 komentarzy

61,997 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!

...