tBane Temat założony przez niniejszego użytkownika |
Dziedziczenie funkcji z klasy bazowej » 2024-02-11 18:01:38 Witam. Napisałem program, który nie działa i nie wiem dlaczego. W klasie bazowej stworzyłem funkcję GameObject::collisionWithPoint(float px, float py), a w klasach pochodnych próbuję ją wywołać i wyrzuca mi błąd. Wiem, że ten problem mogę rozwiązać tworząc dwie klasy Villager::collisionWithPoint(float px, float py), Building::collisionWithPoint(float px, float py), ale jest to nieoptymalne, gdyż przy większej ilości klas pochodnych duplikowałbym kod. Jak rozwiązać ten problem ? main.cpp#include <iostream> #include <vector>
#include <SFML/Graphics.hpp> using namespace std;
#include "villager.hpp"
sf::RenderWindow * window;
std::vector < Building * > buildings; std::vector < Villager * > villagers; std::vector < Villager * > selectedVillagers;
bool cursor_press; float cursor_start_x, cursor_start_y, cursor_end_x, cursor_end_y; float select_x1, select_x2, select_y1, select_y2; sf::RectangleShape * dragArea;
void deselectVillagers() { for( auto & sv: selectedVillagers ) { sv->isSelected = false; } selectedVillagers.clear(); }
void selectVillagers( float x, float y ) { selectedVillagers.clear(); for( auto & v: villagers ) { if( v->collisionWithPoint( x, y ) ) if( v->isSelected ) { v->isSelected = false; } else { v->isSelected = true; } if( v->isSelected ) selectedVillagers.push_back( v ); } }
void selectVillagers( float x, float y, float width, float height ) { for( auto & v: villagers ) { if( v->collisionWithRectangle( x, y, width, height ) ) v->isSelected = true; if( v->isSelected ) selectedVillagers.push_back( v ); } }
void setTargetForVillagers( float x, float y ) { GameObject * target = NULL; for( auto & v: villagers ) if( v->collisionWithPoint( x, y ) ) target = v; for( auto & b: buildings ) if( b->collisionWithPoint( x, y ) ) target = b; if( target == NULL ) { for( auto & sv: selectedVillagers ) { sv->state = states::goToLocation; sv->target_x = x; sv->target_y = y; } } else { for( auto & sv: selectedVillagers ) { if( sv != target ) { sv->state = states::goToGameObject; sv->target = target; } } } }
void updateVillagers() { for( auto & v1: villagers ) for( auto & v2 : villagers ) { float d = sqrt( pow( v1->x - v2->x, 2.0f ) + pow( v1->y - v2->y, 2.0f ) ); if( d < v1->radius + v2->radius && d > 0.0f ) { v1->x +=( v1->x - v2->x ) *( v1->radius + v2->radius - d ) /( d * 2 ); v1->y +=( v1->y - v2->y ) *( v1->radius + v2->radius - d ) /( d * 2 ); v2->x -=( v1->x - v2->x ) *( v1->radius + v2->radius - d ) /( d * 2 ); v2->y -=( v1->y - v2->y ) *( v1->radius + v2->radius - d ) /( d * 2 ); } } for( auto & v: villagers ) v->update(); }
void renderVillagers( sf::RenderWindow * window ) { for( auto & v: villagers ) v->render( window ); }
void renderBuildings( sf::RenderWindow * window ) { for( auto & b: buildings ) b->render( window ); }
int main() { window = new sf::RenderWindow( sf::VideoMode( 720, 480 ), "village" ); window->setFramerateLimit( 60 ); buildings.clear(); villagers.clear(); selectedVillagers.clear(); buildings.push_back( new Building( "village", 360, 240 ) ); villagers.push_back( new Villager( "Odyn", 100, 100 ) ); villagers.push_back( new Villager( "Uruk", 200, 100 ) ); villagers.push_back( new Villager( "Harc", 200, 300 ) ); villagers.push_back( new Villager( "Zahn", 150, 250 ) ); cursor_press = false; cursor_end_x = cursor_start_x = sf::Mouse::getPosition( * window ).x; cursor_end_y = cursor_start_y = sf::Mouse::getPosition( * window ).y; select_x2 = select_x1 = cursor_end_x; select_y2 = select_y1 = cursor_end_y; dragArea = new sf::RectangleShape(); dragArea->setFillColor( sf::Color( 48.0f, 48.0f, 128.0f, 128.0f ) ); while( window->isOpen() ) { sf::Event ev; while( window->pollEvent( ev ) ) { cursor_press = false; if( ev.type == sf::Event::Closed ) window->close(); if( ev.type == sf::Event::MouseButtonPressed && sf::Mouse::isButtonPressed( sf::Mouse::Left ) && sf::Keyboard::isKeyPressed( sf::Keyboard::LShift ) ) { cursor_end_x = cursor_start_x = sf::Mouse::getPosition( * window ).x; cursor_end_y = cursor_start_y = sf::Mouse::getPosition( * window ).y; selectVillagers( cursor_end_x, cursor_end_y ); } else if( ev.type == sf::Event::MouseButtonPressed && sf::Mouse::isButtonPressed( sf::Mouse::Left ) ) { cursor_end_x = cursor_start_x = sf::Mouse::getPosition( * window ).x; cursor_end_y = cursor_start_y = sf::Mouse::getPosition( * window ).y; deselectVillagers(); selectVillagers( cursor_end_x, cursor_end_y ); } else if( ev.type == sf::Event::MouseButtonPressed && sf::Mouse::isButtonPressed( sf::Mouse::Right ) ) { setTargetForVillagers( sf::Mouse::getPosition( * window ).x, sf::Mouse::getPosition( * window ).y ); } else if( ev.type == sf::Event::MouseMoved && sf::Mouse::isButtonPressed( sf::Mouse::Left ) ) { cursor_press = true; cursor_end_x = sf::Mouse::getPosition( * window ).x; cursor_end_y = sf::Mouse::getPosition( * window ).y; select_x1 = cursor_start_x; select_x2 = cursor_end_x; select_y1 = cursor_start_y; select_y2 = cursor_end_y; if( cursor_start_x > cursor_end_x ) swap( select_x1, select_x2 ); if( cursor_start_y > cursor_end_y ) swap( select_y1, select_y2 ); float x =( select_x1 + select_x2 ) / 2.0f; float y =( select_y1 + select_y2 ) / 2.0f; float w = select_x2 - select_x1; float h = select_y2 - select_y1; deselectVillagers(); selectVillagers( cursor_end_x, cursor_end_y ); selectVillagers( x, y, w, h ); } dragArea->setPosition( select_x1, select_y1 ); dragArea->setSize( sf::Vector2f( select_x2 - select_x1, select_y2 - select_y1 ) ); } updateVillagers(); window->clear( sf::Color( 48.0f, 96.0f, 48.0f ) ); renderVillagers( window ); renderBuildings( window ); if( cursor_press ) window->draw( * dragArea ); window->display(); } return 0; }
Villager.hpp#ifndef Villager_hpp #define Villager_hpp
#include <iostream> #include <SFML/Graphics.hpp> using namespace std;
class GameObject { public: float x, y, radius; sf::CircleShape * shape; GameObject( float, float, float ); ~GameObject(); bool collisionWithPoint( float, float ); virtual void update(); virtual void render( sf::RenderWindow * ); };
class Building : public GameObject { public: string name; Building( string, float, float ); ~Building(); virtual void update(); virtual void render( sf::RenderWindow * ); };
enum class states { waiting, goToLocation, goToGameObject };
class Villager : public GameObject { public: string name; float angle; float moveSpeed; float range; bool isSelected; sf::CircleShape * rangeShape; states state; GameObject * target; float target_x, target_y; Villager( string, float, float ); ~Villager(); bool collisionWithPoint( float, float ); bool collisionWithRectangle( float, float, float, float ); virtual void update(); virtual void render( sf::RenderWindow * ); };
#endif
Villager.cpp#include "Villager.hpp" #define PI 3.14159265358979323846
GameObject::GameObject( float x, float y, float radius ) { this->x = x; this->y = y; this->radius = radius; }
GameObject::~GameObject() { }
bool GameObject::collisionWithPoint( float px, float py ) { float radians = atan2( py - y, px - x ); float xx = x + radius * cos( radians ); float yy = y + radius * sin( radians ); if( pow( px - x, 2 ) + pow( py - y, 2 ) < radius * radius ) return true; else return false; }
void GameObject::update() { }
void GameObject::render( sf::RenderWindow * window ) { window->draw( * shape ); }
Building::Building( string name, float x, float y ) : GameObject( x, y, 64.0f ) { this->name = name; shape = new sf::CircleShape( radius ); shape->setOrigin( radius, radius ); shape->setPosition( x, y ); shape->setFillColor( sf::Color( 64.0f, 64.0f, 64.0f ) ); shape->setOutlineThickness( 4.0f ); shape->setOutlineColor( sf::Color( 16.0f, 16.0f, 16.0f ) ); }
Building::~Building() { }
void Building::update() { }
void Building::render( sf::RenderWindow * window ) { window->draw( * shape ); }
Villager::Villager( string name, float x, float y ) : GameObject( x, y, 16.0f ) { this->name = name; this->angle = 0.0f; this->moveSpeed = 1.0f; this->range = 32.0f; isSelected = false; shape = new sf::CircleShape( radius ); shape->setOrigin( radius, radius ); shape->setPosition( x, y ); shape->setFillColor( sf::Color( 128.0f, 128.0f, 128.0f ) ); shape->setOutlineThickness( 4.0f ); shape->setOutlineColor( sf::Color( 16.0f, 16.0f, 16.0f ) ); rangeShape = new sf::CircleShape( range ); rangeShape->setOrigin( range, range ); rangeShape->setPosition( x, y ); rangeShape->setFillColor( sf::Color( 128.0f, 48.0f, 48.0f, 128.0f ) ); rangeShape->setOutlineThickness( 4.0f ); rangeShape->setOutlineColor( sf::Color( 128.0f, 16.0f, 16.0f, 128.0f ) ); state = states::waiting; target = NULL; target_x = target_y = 0; }
Villager::~Villager() { }
bool Villager::collisionWithRectangle( float rx, float ry, float rwidth, float rheight ) { float radians = atan2( ry - y, rx - x ); float xx = x + radius * cos( radians ); float yy = y + radius * sin( radians ); if( xx > rx - rwidth / 2.0f && xx < rx + rwidth / 2.0f && yy > ry - rheight / 2.0f && yy < ry + rheight / 2.0f ) return true; else return false; }
void Villager::update() { if( state == states::goToLocation ) { if( target_x == x && target_y == y ) { state = states::waiting; } else if( pow( target_x - x, 2 ) + pow( target_y - y, 2 ) < moveSpeed * moveSpeed ) { float radians = atan2( target_y - y, target_x - x ); x = target_x; y = target_y; angle = radians * 180.0f / PI; } else { float radians = atan2( target_y - y, target_x - x ); x += moveSpeed * cos( radians ); y += moveSpeed * sin( radians ); angle = radians * 180.0f / PI; } } else if( state == states::goToGameObject ) { if( pow( target->x - x, 2 ) + pow( target->y - y, 2 ) > 2.0f * range * range ) { float radians = atan2( target->y - y, target->x - x ); x += moveSpeed * cos( radians ); y += moveSpeed * sin( radians ); angle = radians * 180.0f / PI; } } shape->setPosition( x, y ); rangeShape->setPosition( x, y ); if( isSelected == true ) shape->setFillColor( sf::Color( 128.0f, 48.0f, 48.0f ) ); else shape->setFillColor( sf::Color( 128.0f, 128.0f, 128.0f ) ); }
void Villager::render( sf::RenderWindow * window ) { window->draw( * rangeShape ); window->draw( * shape ); }
|
|
pekfos |
» 2024-02-11 18:31:51 Wywal collisionWithPoint z Villager. Tym zapisem mówisz że ta klasa ma swoją własną wersję tej metody, a takiej nie dostarczyłeś. Następnym razem podaj komunikat błędu... |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-02-11 18:40:51 Done. Wypadło mi to z głowy ale nadal mam ten sam błąd... Co oznaczają takie błędy zazwyczaj ?? |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-02-11 18:47:46 Już wiem, zapodziałem gdzieś jedną funkcję.. Mam rozwiązanie. main.cpp#include <iostream> #include <vector>
#include <SFML/Graphics.hpp> using namespace std;
#include "villager.hpp"
sf::RenderWindow * window;
std::vector < Building * > buildings; std::vector < Villager * > villagers; std::vector < Villager * > selectedVillagers;
bool cursor_press; float cursor_start_x, cursor_start_y, cursor_end_x, cursor_end_y; float select_x1, select_x2, select_y1, select_y2; sf::RectangleShape * dragArea;
void deselectVillagers() { for( auto & sv: selectedVillagers ) { sv->isSelected = false; } selectedVillagers.clear(); }
void selectVillagers( float x, float y ) { selectedVillagers.clear(); for( auto & v: villagers ) { if( v->collisionWithPoint( x, y ) ) if( v->isSelected ) { v->isSelected = false; } else { v->isSelected = true; } if( v->isSelected ) selectedVillagers.push_back( v ); } }
void selectVillagers( float x, float y, float width, float height ) { for( auto & v: villagers ) { if( v->collisionWithRectangle( x, y, width, height ) ) v->isSelected = true; if( v->isSelected ) selectedVillagers.push_back( v ); } }
void setTargetForVillagers( float x, float y ) { GameObject * target = NULL; for( auto & v: villagers ) if( v->collisionWithPoint( x, y ) ) target = v; for( auto & b: buildings ) if( b->collisionWithPoint( x, y ) ) target = b; if( target == NULL ) { for( auto & sv: selectedVillagers ) { sv->state = states::goToLocation; sv->target_x = x; sv->target_y = y; } } else { for( auto & sv: selectedVillagers ) { if( sv != target ) { sv->state = states::goToGameObject; sv->target = target; } } } }
void updateVillagers() { for( auto & v1: villagers ) for( auto & v2 : villagers ) { float d = sqrt( pow( v1->x - v2->x, 2.0f ) + pow( v1->y - v2->y, 2.0f ) ); if( d < v1->radius + v2->radius && d > 0.0f ) { v1->x +=( v1->x - v2->x ) *( v1->radius + v2->radius - d ) /( d * 2 ); v1->y +=( v1->y - v2->y ) *( v1->radius + v2->radius - d ) /( d * 2 ); v2->x -=( v1->x - v2->x ) *( v1->radius + v2->radius - d ) /( d * 2 ); v2->y -=( v1->y - v2->y ) *( v1->radius + v2->radius - d ) /( d * 2 ); } } for( auto & v: villagers ) v->update(); }
void renderVillagers( sf::RenderWindow * window ) { for( auto & v: villagers ) v->render( window ); }
void renderBuildings( sf::RenderWindow * window ) { for( auto & b: buildings ) b->render( window ); }
int main() { window = new sf::RenderWindow( sf::VideoMode( 720, 480 ), "village" ); window->setFramerateLimit( 60 ); buildings.clear(); villagers.clear(); selectedVillagers.clear(); buildings.push_back( new Building( "village", 360, 240 ) ); villagers.push_back( new Villager( "Odyn", 100, 100 ) ); villagers.push_back( new Villager( "Uruk", 200, 100 ) ); villagers.push_back( new Villager( "Harc", 200, 300 ) ); villagers.push_back( new Villager( "Zahn", 150, 250 ) ); cursor_press = false; cursor_end_x = cursor_start_x = sf::Mouse::getPosition( * window ).x; cursor_end_y = cursor_start_y = sf::Mouse::getPosition( * window ).y; select_x2 = select_x1 = cursor_end_x; select_y2 = select_y1 = cursor_end_y; dragArea = new sf::RectangleShape(); dragArea->setFillColor( sf::Color( 48.0f, 48.0f, 128.0f, 128.0f ) ); while( window->isOpen() ) { sf::Event ev; while( window->pollEvent( ev ) ) { cursor_press = false; if( ev.type == sf::Event::Closed ) window->close(); if( ev.type == sf::Event::MouseButtonPressed && sf::Mouse::isButtonPressed( sf::Mouse::Left ) && sf::Keyboard::isKeyPressed( sf::Keyboard::LShift ) ) { cursor_end_x = cursor_start_x = sf::Mouse::getPosition( * window ).x; cursor_end_y = cursor_start_y = sf::Mouse::getPosition( * window ).y; selectVillagers( cursor_end_x, cursor_end_y ); } else if( ev.type == sf::Event::MouseButtonPressed && sf::Mouse::isButtonPressed( sf::Mouse::Left ) ) { cursor_end_x = cursor_start_x = sf::Mouse::getPosition( * window ).x; cursor_end_y = cursor_start_y = sf::Mouse::getPosition( * window ).y; deselectVillagers(); selectVillagers( cursor_end_x, cursor_end_y ); } else if( ev.type == sf::Event::MouseButtonPressed && sf::Mouse::isButtonPressed( sf::Mouse::Right ) ) { setTargetForVillagers( sf::Mouse::getPosition( * window ).x, sf::Mouse::getPosition( * window ).y ); } else if( ev.type == sf::Event::MouseMoved && sf::Mouse::isButtonPressed( sf::Mouse::Left ) ) { cursor_press = true; cursor_end_x = sf::Mouse::getPosition( * window ).x; cursor_end_y = sf::Mouse::getPosition( * window ).y; select_x1 = cursor_start_x; select_x2 = cursor_end_x; select_y1 = cursor_start_y; select_y2 = cursor_end_y; if( cursor_start_x > cursor_end_x ) swap( select_x1, select_x2 ); if( cursor_start_y > cursor_end_y ) swap( select_y1, select_y2 ); float x =( select_x1 + select_x2 ) / 2.0f; float y =( select_y1 + select_y2 ) / 2.0f; float w = select_x2 - select_x1; float h = select_y2 - select_y1; deselectVillagers(); selectVillagers( cursor_end_x, cursor_end_y ); selectVillagers( x, y, w, h ); } dragArea->setPosition( select_x1, select_y1 ); dragArea->setSize( sf::Vector2f( select_x2 - select_x1, select_y2 - select_y1 ) ); } updateVillagers(); window->clear( sf::Color( 48.0f, 96.0f, 48.0f ) ); renderVillagers( window ); renderBuildings( window ); if( cursor_press ) window->draw( * dragArea ); window->display(); } return 0; }
Villager.hpp#ifndef Villager_hpp #define Villager_hpp
#include <iostream> #include <SFML/Graphics.hpp> using namespace std;
class GameObject { public: float x, y, radius; sf::CircleShape * shape; GameObject( float, float, float ); ~GameObject(); bool collisionWithPoint( float, float ); bool collisionWithRectangle( float, float, float, float ); virtual void update(); virtual void render( sf::RenderWindow * ); };
class Building : public GameObject { public: string name; Building( string, float, float ); ~Building(); virtual void update(); virtual void render( sf::RenderWindow * ); };
enum class states { waiting, goToLocation, goToGameObject };
class Villager : public GameObject { public: string name; float angle; float moveSpeed; float range; bool isSelected; sf::CircleShape * rangeShape; states state; GameObject * target; float target_x, target_y; Villager( string, float, float ); ~Villager(); virtual void update(); virtual void render( sf::RenderWindow * ); };
#endif
Villager.cpp#include "Villager.hpp" #define PI 3.14159265358979323846
GameObject::GameObject( float x, float y, float radius ) { this->x = x; this->y = y; this->radius = radius; }
GameObject::~GameObject() { }
bool GameObject::collisionWithPoint( float px, float py ) { float radians = atan2( py - y, px - x ); float xx = x + radius * cos( radians ); float yy = y + radius * sin( radians ); if( pow( px - x, 2 ) + pow( py - y, 2 ) < radius * radius ) return true; else return false; }
bool GameObject::collisionWithRectangle( float rx, float ry, float rwidth, float rheight ) { float radians = atan2( ry - y, rx - x ); float xx = x + radius * cos( radians ); float yy = y + radius * sin( radians ); if( xx > rx - rwidth / 2.0f && xx < rx + rwidth / 2.0f && yy > ry - rheight / 2.0f && yy < ry + rheight / 2.0f ) return true; else return false; }
void GameObject::update() { }
void GameObject::render( sf::RenderWindow * window ) { window->draw( * shape ); }
Building::Building( string name, float x, float y ) : GameObject( x, y, 64.0f ) { this->name = name; shape = new sf::CircleShape( radius ); shape->setOrigin( radius, radius ); shape->setPosition( x, y ); shape->setFillColor( sf::Color( 64.0f, 64.0f, 64.0f ) ); shape->setOutlineThickness( 4.0f ); shape->setOutlineColor( sf::Color( 16.0f, 16.0f, 16.0f ) ); }
Building::~Building() { }
void Building::update() { }
void Building::render( sf::RenderWindow * window ) { window->draw( * shape ); }
Villager::Villager( string name, float x, float y ) : GameObject( x, y, 16.0f ) { this->name = name; this->angle = 0.0f; this->moveSpeed = 1.0f; this->range = 32.0f; isSelected = false; shape = new sf::CircleShape( radius ); shape->setOrigin( radius, radius ); shape->setPosition( x, y ); shape->setFillColor( sf::Color( 128.0f, 128.0f, 128.0f ) ); shape->setOutlineThickness( 4.0f ); shape->setOutlineColor( sf::Color( 16.0f, 16.0f, 16.0f ) ); rangeShape = new sf::CircleShape( range ); rangeShape->setOrigin( range, range ); rangeShape->setPosition( x, y ); rangeShape->setFillColor( sf::Color( 128.0f, 48.0f, 48.0f, 128.0f ) ); rangeShape->setOutlineThickness( 4.0f ); rangeShape->setOutlineColor( sf::Color( 128.0f, 16.0f, 16.0f, 128.0f ) ); state = states::waiting; target = NULL; target_x = target_y = 0; }
Villager::~Villager() { }
void Villager::update() { if( state == states::goToLocation ) { if( target_x == x && target_y == y ) { state = states::waiting; } else if( pow( target_x - x, 2 ) + pow( target_y - y, 2 ) < moveSpeed * moveSpeed ) { float radians = atan2( target_y - y, target_x - x ); x = target_x; y = target_y; angle = radians * 180.0f / PI; } else { float radians = atan2( target_y - y, target_x - x ); x += moveSpeed * cos( radians ); y += moveSpeed * sin( radians ); angle = radians * 180.0f / PI; } } else if( state == states::goToGameObject ) { if( pow( target->x - x, 2 ) + pow( target->y - y, 2 ) > 2.0f * range * range ) { float radians = atan2( target->y - y, target->x - x ); x += moveSpeed * cos( radians ); y += moveSpeed * sin( radians ); angle = radians * 180.0f / PI; } } shape->setPosition( x, y ); rangeShape->setPosition( x, y ); if( isSelected == true ) shape->setFillColor( sf::Color( 128.0f, 48.0f, 48.0f ) ); else shape->setFillColor( sf::Color( 128.0f, 128.0f, 128.0f ) ); }
void Villager::render( sf::RenderWindow * window ) { window->draw( * rangeShape ); window->draw( * shape ); }
|
|
pekfos |
» 2024-02-11 19:37:20 Co oznaczają takie błędy zazwyczaj ?? Że w komunikacie o nieudanym budowaniu potwierdziłeś że chcesz uruchomić stary build, a takiego nie ma. Tak na marginesie, treść tego okna możesz skopiować przez ctrl+c. To nie jest komunikat błędu jaki miałeś podać. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-02-11 19:59:22 no właśnie nie miałem żadnego inngo błędu. Ale problem już rozwiązany. |
|
« 1 » |