Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[SFML] Zaznaczanie jednostek w grze

Ostatnio zmodyfikowano 2024-02-12 14:23
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
[SFML] Zaznaczanie jednostek w grze
» 2024-02-09 17:05:13
Witam.
Napisałem prosty system zaznaczania i sterowania jednostek.

Left Click - Zaznacz nową jednostkę
Shift + Left Click - Dodaj jednostkę do zaznaczonych
Right Click - Wyznacz cel jednostkom

Potrzebuję zrozumieć jak wyznaczyć "obszar zaznaczenia", który zaznaczy kilka jednostek jednocześnie.

kod poniżej ...

Villager.hpp
C/C++
#ifndef Villager_hpp
#define Villager_hpp

#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;

class Villager
{
public:
   
string name;
   
float x, y, radius;
   
sf::CircleShape * shape;
   
bool isSelected;
   
   
float speed;
   
   
bool goToTarget;
   
float target_x, target_y;
   
   
Villager( string, float, float, float );
   
~Villager();
   
bool collisionWithPoint( float, float );
   
void update();
   
void render( sf::RenderWindow * );
   
};

#endif

Villager.cpp
C/C++
#include "Villager.hpp"

Villager::Villager( string name, float x, float y, float radius )
{
   
this->name = name;
   
this->x = x;
   
this->y = y;
   
this->radius = radius;
   
   
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 ) );
   
   
speed = 1.0f;
   
   
isSelected = false;
   
   
goToTarget = false;
   
target_x = target_y = 0;
   
}

Villager::~Villager()
{
   
}

bool Villager::collisionWithPoint( float px, float py )
{
   
if( pow( px - x, 2 ) + pow( py - y, 2 ) < radius * radius )
       
 return true;
   
else
       
 return false;
   
}

void Villager::update()
{
   
if( goToTarget == true )
   
{
       
if( target_x == x && target_y == y )
       
{
           
goToTarget = false;
       
}
       
else if( pow( target_x - x, 2 ) + pow( target_y - y, 2 ) < speed * speed )
       
{
           
x = target_x;
           
y = target_y;
       
}
       
else
       
{
           
float radians = atan2( target_y - y, target_x - x );
           
x += speed * cos( radians );
           
y += speed * sin( radians );
       
}
       
       
    }
   
   
// Shape
   
shape->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( * shape );
}

main
C/C++
#include <iostream>
#include <vector>

#include <SFML/Graphics.hpp>
using namespace std;

#include "villager.hpp"

sf::RenderWindow * window;

std::vector < Villager * > villagers;
std::vector < Villager * > selectedVillagers;

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;
       
}
       
       
// adding selected villagers to "selectedVillagers list"
       
if( v->isSelected )
           
 selectedVillagers.push_back( v );
       
   
}
   
   
cout << "click [" << x << ", " << y << "]\n";
}

void setTargetForVillagers( float x, float y )
{
   
for( auto & sv: selectedVillagers )
   
{
       
sv->goToTarget = true;
       
sv->target_x = x;
       
sv->target_y = y;
   
}
}

void updateVillagers()
{
   
for( auto & v: villagers )
       
 v->update();
   
}

void renderVillagers( sf::RenderWindow * window )
{
   
for( auto & v: villagers )
       
 v->render( window );
   
}



int main()
{
   
window = new sf::RenderWindow( sf::VideoMode( 720, 480 ), "village" );
   
window->setFramerateLimit( 60 );
   
   
villagers.clear();
   
villagers.push_back( new Villager( "Odyn", 100, 100, 16 ) );
   
villagers.push_back( new Villager( "Uruk", 200, 100, 16 ) );
   
villagers.push_back( new Villager( "Har", 200, 300, 16 ) );
   
villagers.push_back( new Villager( "Zahn", 150, 250, 16 ) );
   
   
selectedVillagers.clear();
   
   
while( window->isOpen() )
   
{
       
// GET EVENTS
       
sf::Event ev;
       
while( window->pollEvent( ev ) )
       
{
           
sf::Vector2i mousePosition = sf::Mouse::getPosition( * window );
           
           
if( ev.type == sf::Event::Closed )
               
 window->close();
           
           
if( // Left Shift + Left Click
           
sf::Keyboard::isKeyPressed( sf::Keyboard::LShift ) &&
           
ev.type == sf::Event::MouseButtonPressed && sf::Mouse::isButtonPressed( sf::Mouse::Left ) )
           
{
               
selectVillagers( mousePosition.x, mousePosition.y );
           
}
           
else if( // Left Click
           
ev.type == sf::Event::MouseButtonPressed && sf::Mouse::isButtonPressed( sf::Mouse::Left ) )
           
{
               
deselectVillagers();
               
selectVillagers( mousePosition.x, mousePosition.y );
           
}
           
else if( // Right Click
           
ev.type == sf::Event::MouseButtonPressed && sf::Mouse::isButtonPressed( sf::Mouse::Right ) )
           
{
               
setTargetForVillagers( mousePosition.x, mousePosition.y );
           
}
        }
// events
       
        // update
       
updateVillagers();
       
       
// render
       
window->clear( sf::Color( 48.0f, 128.0f, 48.0f ) );
       
renderVillagers( window );
       
window->display();
   
}
   
return 0;
}
P-180695
tBane
Temat założony przez niniejszego użytkownika
» 2024-02-09 19:44:55
Postanowiłem zrobić inaczej.
Zrezygnowałem z pojedynczego zaznaczenia na rzecz obszarowego, gdyż zaznaczenie pojedyncze to zaznaczenie obszarowe 1x1. (Jeśli się mylę naprostujcie mnie).

Prawie działa, nie rozumiem tylko dlaczego obszar jest nieporawnie generowany :-/

main.cpp
C/C++
#include <iostream>
#include <vector>

#include <SFML/Graphics.hpp>
using namespace std;

#include "villager.hpp"

sf::RenderWindow * window;

std::vector < Villager * > villagers;
std::vector < Villager * > selectedVillagers;

bool cursor_press;
float cursor_start_x, cursor_start_y;
float cursor_end_x, cursor_end_y;
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;
       
}
       
       
// adding selected villagers to "selectedVillagers list"
       
if( v->isSelected )
           
 selectedVillagers.push_back( v );
       
   
}
   
   
cout << "click [" << x << ", " << y << "]\n";
}

void selectVillagers( float x, float y, float width, float height )
{
   
for( auto & v: villagers )
   
{
       
if( v->collisionWithRectangle( x, y, width, height ) )
           
 v->isSelected = true;
       
       
// adding selected villagers to "selectedVillagers list"
       
if( v->isSelected )
           
 selectedVillagers.push_back( v );
       
   
}
}

void setTargetForVillagers( float x, float y )
{
   
for( auto & sv: selectedVillagers )
   
{
       
sv->goToTarget = true;
       
sv->target_x = x;
       
sv->target_y = y;
   
}
}

void updateVillagers()
{
   
for( auto & v: villagers )
       
 v->update();
   
}

void renderVillagers( sf::RenderWindow * window )
{
   
for( auto & v: villagers )
       
 v->render( window );
   
}



int main()
{
   
window = new sf::RenderWindow( sf::VideoMode( 720, 480 ), "village" );
   
window->setFramerateLimit( 60 );
   
   
villagers.clear();
   
villagers.push_back( new Villager( "Odyn", 100, 100, 16 ) );
   
villagers.push_back( new Villager( "Uruk", 200, 100, 16 ) );
   
villagers.push_back( new Villager( "Har", 200, 300, 16 ) );
   
villagers.push_back( new Villager( "Zahn", 150, 250, 16 ) );
   
   
selectedVillagers.clear();
   
   
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;
   
dragArea = new sf::RectangleShape();
   
dragArea->setFillColor( sf::Color( 48.0f, 48.0f, 128.0f, 128.0f ) );
   
   
while( window->isOpen() )
   
{
       
// EVENTS
       
sf::Event ev;
       
while( window->pollEvent( ev ) )
       
{
           
           
if( ev.type == sf::Event::Closed )
               
 window->close();
           
           
if( sf::Mouse::isButtonPressed( sf::Mouse::Left ) )
           
{
               
if( cursor_press == false )
               
{
                   
// Left Click
                   
cout << "click";
                   
cursor_end_x = cursor_start_x = sf::Mouse::getPosition( * window ).x;
                   
cursor_end_y = cursor_start_y = sf::Mouse::getPosition( * window ).y;
                   
cursor_press = true;
                   
deselectVillagers();
                   
selectVillagers( cursor_start_x, cursor_start_y );
               
}
               
else
               
{
                   
// Left Pressed
                   
cout << "press";
                   
cursor_end_x = sf::Mouse::getPosition( * window ).x;
                   
cursor_end_y = sf::Mouse::getPosition( * window ).y;
                   
                   
float x =( cursor_end_x + cursor_start_x ) / 2.0f;
                   
float y =( cursor_end_y + cursor_start_y ) / 2.0f;
                   
float w = cursor_end_x - cursor_start_x;
                   
float h = cursor_end_y - cursor_start_y;
                   
deselectVillagers();
                   
selectVillagers( x, y, w, h );
               
}
               
            }
           
           
if( cursor_press == true && !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;
               
cursor_press = false;
           
}
           
           
if( sf::Mouse::isButtonPressed( sf::Mouse::Right ) )
           
{
               
setTargetForVillagers(
               
sf::Mouse::getPosition( * window ).x,
               
sf::Mouse::getPosition( * window ).y
                );
           
}
           
           
        }
// events
       
        // UPDATES
       
updateVillagers();
       
dragArea->setPosition( cursor_start_x, cursor_start_y );
       
dragArea->setSize( sf::Vector2f( cursor_end_x - cursor_start_x, cursor_end_y - cursor_start_y ) );
       
       
// RENDERS
       
window->clear( sf::Color( 48.0f, 128.0f, 48.0f ) );
       
renderVillagers( window );
       
window->draw( * dragArea );
       
window->display();
   
}
   
return 0;
}

Villager.hpp
C/C++
#ifndef Villager_hpp
#define Villager_hpp

#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;

class Villager
{
public:
   
string name;
   
float x, y, radius;
   
sf::CircleShape * shape;
   
bool isSelected;
   
   
float speed;
   
   
bool goToTarget;
   
float target_x, target_y;
   
   
sf::CircleShape * collisioner;
   
float xx, yy; // TO-DO
   
   
Villager( string, float, float, float );
   
~Villager();
   
bool collisionWithPoint( float, float );
   
bool collisionWithRectangle( float, float, float, float );
   
void update();
   
void render( sf::RenderWindow * );
   
};

#endif

Villager.cpp
C/C++
#include "Villager.hpp"

Villager::Villager( string name, float x, float y, float radius )
{
   
this->name = name;
   
this->x = x;
   
this->y = y;
   
this->radius = radius;
   
   
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 ) );
   
   
speed = 1.0f;
   
   
collisioner = new sf::CircleShape( 4.0f );
   
collisioner->setOrigin( 4.0f, 4.0f );
   
   
isSelected = false;
   
   
goToTarget = false;
   
target_x = target_y = 0;
   
   
   
}

Villager::~Villager()
{
   
}

bool Villager::collisionWithPoint( float px, float py )
{
   
float radians = atan2( py - y, px - x );
   
xx = x + radius * cos( radians );
   
yy = y + radius * sin( radians );
   
   
if( pow( px - x, 2 ) + pow( py - y, 2 ) < radius * radius )
       
 return true;
   
else
       
 return false;
   
}

bool Villager::collisionWithRectangle( float rx, float ry, float rwidth, float rheight )
{
   
float radians = atan2( ry - y, rx - x );
   
xx = x + radius * cos( radians );
   
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( goToTarget == true )
   
{
       
if( target_x == x && target_y == y )
       
{
           
goToTarget = false;
       
}
       
else if( pow( target_x - x, 2 ) + pow( target_y - y, 2 ) < speed * speed )
       
{
           
x = target_x;
           
y = target_y;
       
}
       
else
       
{
           
float radians = atan2( target_y - y, target_x - x );
           
x += speed * cos( radians );
           
y += speed * sin( radians );
       
}
       
       
    }
   
   
// Shape
   
shape->setPosition( x, y );
   
collisioner->setPosition( xx, yy );
   
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( * shape );
   
window->draw( * collisioner );
}
P-180696
pekfos
» 2024-02-09 20:32:08
Nie powinieneś mieszać sf::Mouse ze zdarzeniami. Zdarzenie naciśnięcia myszki mówi jaka była pozycja i przycisk.
https://www.sfml-dev.org/documentation/2.6.1/structsf_1_1Event_1_1MouseButtonEvent.php

Co do problemu, to nawet nie wiem jaki jest problem. Podałeś tylko kod.
P-180698
tBane
Temat założony przez niniejszego użytkownika
» 2024-02-09 20:34:26
Potrzebuje w grze zaimplementować system sterowania jednostkami. Taki jak w typowej grze RTS.


Prawie działa, nie rozumiem tylko dlaczego obszar jest niepoprawnie generowany :-/
Gdy zaznaczamy obszar z prawego dolnego punktu w lewo do góryy to obszar zaznaczenia się "minimalizuje"
P-180699
pekfos
» 2024-02-10 13:40:32
W sensie ma ujemny rozmiar? Jak chcesz mieć lewy górny róg jako start, powinieneś brać mniejsze współrzędne jako początek.
P-180704
tBane
Temat założony przez niniejszego użytkownika
» 2024-02-10 13:55:03
udało mi się rozwiązać problem. Dodałem dodatkowe zmienne do przechowywania pozycji. Nadal nie rozumiem gdzie miałem błąd ale teraz przynajmniej działa.

Wrzucam kod może kiedyś się to komuś przyda.

sterowanie
Left Click - Zaznacz nową jednostkę
LShift + Left Click - Dodaj/Usuń jednostkę z wybranych
Right Click - Wyznacz cel jednostkom
Zaznacz Obszar - Wybierz jednostki

main.cpp
C/C++
#include <iostream>
#include <vector>


#include <SFML/Graphics.hpp>
using namespace std;

#include "villager.hpp"

sf::RenderWindow * window;

std::vector < Tree * > trees;
std::vector < Villager * > villagers;
std::vector < Villager * > selectedVillagers;



bool cursor_press;
float cursor_start_x, cursor_start_y, cursor_end_x, cursor_end_y; // positions of cursor
float select_x1, select_x2, select_y1, select_y2; // using to dragArea shape
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;
       
}
       
       
// adding selected villagers to "selectedVillagers list"
       
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;
       
       
// adding selected villagers to "selectedVillagers list"
       
if( v->isSelected )
           
 selectedVillagers.push_back( v );
       
   
}
}

void setTargetForVillagers( float x, float y )
{
   
for( auto & sv: selectedVillagers )
   
{
       
sv->goToTarget = true;
       
sv->target_x = x;
       
sv->target_y = y;
   
}
}

void updateVillagers()
{
   
// odpychanie sie
   
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 )
       
{
           
// wzór na odpychanie się obiektów
            // sf::Vector2f v = (v1 - v2) * (v1->radius + v2->radius - d) / (d * 2);
           
           
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 renderTrees( sf::RenderWindow * window )
{
   
for( auto & t: trees )
       
 t->render( window );
   
}

int main()
{
   
window = new sf::RenderWindow( sf::VideoMode( 720, 480 ), "village" );
   
window->setFramerateLimit( 60 );
   
   
trees.clear();
   
villagers.clear();
   
selectedVillagers.clear();
   
   
// add trees
    /*
 trees.push_back(new Nature(100, 120, 32));
 trees.push_back(new Nature(240, 180, 32));
 trees.push_back(new Nature(100, 120, 32));
 trees.push_back(new Nature(100, 120, 32));
 */
   
    // add units
   
villagers.push_back( new Villager( "Odyn", 100, 100, 16 ) );
   
villagers.push_back( new Villager( "Uruk", 200, 100, 16 ) );
   
villagers.push_back( new Villager( "Har", 200, 300, 16 ) );
   
villagers.push_back( new Villager( "Zahn", 150, 250, 16 ) );
   
   
   
// cursor and drag area
   
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() )
   
{
       
// EVENTS
       
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 ) )
           
{
               
// LPM
                // Left Pressed
               
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 ) )
           
{
               
// PPM
                // set the target for units
               
               
setTargetForVillagers(
               
sf::Mouse::getPosition( * window ).x,
               
sf::Mouse::getPosition( * window ).y
                );
           
}
           
else if( ev.type == sf::Event::MouseMoved && sf::Mouse::isButtonPressed( sf::Mouse::Left ) )
           
{
               
// select area
               
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 ) );
       
}
       
       
       
// UPDATES
       
updateVillagers();
       
       
       
// RENDERS
       
window->clear( sf::Color( 48.0f, 128.0f, 48.0f ) );
       
renderVillagers( window );
       
renderTrees( window );
       
if( cursor_press )
           
 window->draw( * dragArea );
       
       
window->display();
   
}
   
return 0;
}

Villager.hpp
C/C++
#ifndef Villager_hpp
#define Villager_hpp

#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;

class Villager
{
public:
   
string name;
   
float x, y, radius;
   
float angle;
   
float speed;
   
   
bool isSelected;
   
   
sf::CircleShape * shape;
   
   
bool goToTarget;
   
float target_x, target_y;
   
   
Villager( string, float, float, float );
   
~Villager();
   
bool collisionWithPoint( float, float );
   
bool collisionWithRectangle( float, float, float, float );
   
void update();
   
void render( sf::RenderWindow * );
   
};

#endif

Villager.cpp
C/C++
#include "Villager.hpp"
#define PI 3.14159265358979323846

Villager::Villager( string name, float x, float y, float radius )
{
   
this->name = name;
   
this->x = x;
   
this->y = y;
   
this->radius = radius;
   
   
this->angle = 0.0f;
   
this->speed = 1.0f;
   
   
isSelected = false;
   
   
// shape of villager
   
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 ) );
   
   
goToTarget = false;
   
target_x = target_y = 0;
   
   
   
}

Villager::~Villager()
{
   
}

bool Villager::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 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( goToTarget == true )
   
{
       
if( target_x == x && target_y == y )
       
{
           
goToTarget = false;
       
}
       
else if( pow( target_x - x, 2 ) + pow( target_y - y, 2 ) < speed * speed )
       
{
           
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 += speed * cos( radians );
           
y += speed * sin( radians );
           
           
angle = radians * 180.0f / PI;
       
}
       
    }
   
   
// Shape
   
shape->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( * shape );
}
P-180706
tBane
Temat założony przez niniejszego użytkownika
» 2024-02-12 14:23:02
logika trochę kuleje, ale program się kompiluje.
P-180743
« 1 »
  Strona 1 z 1