# Select multiple images vector sfml

This topic is 2600 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello
I have this code where if you have 10 gold and press on the game screen a tower will be drawn in that position. Now i want to be able to click on each tower to do a specific task.
for example if you click on one of the towers the word "coco" will be printed on the screen. now my problem is that i can only click on the last tower that was create and it will display "coco". If i click on any other tower the word "coco" doesn't print out, only if i click on the last tower that was create the word "coco" get print out.

can you guys please help me out. I'm new to the whole victor thing and i'm still trying to understand how it works.

this is the part of code where if you click on the tower prints out "coco"
 void tower::MouseEventReleased(sf::Event &Event) { for(int ButtonX=ImageX; ButtonX<=ImageX + ImageSizeX; ButtonX++) { for(int ButtonY=ImageY; ButtonY<=ImageY + ImageSizeY; ButtonY++) { if(MouseX==ButtonX && MouseY==ButtonY && Event.Type == sf::Event::MouseButtonPressed && Event.MouseButton.Button == sf::Mouse::Left) { std::cout<<"coco"; } } } } 

tower.cpp
 #include "tower.h" #include "economy.h" economy eco; tower::tower(float x, float y) { Position = sf::Vector2f(x,y); TowerImage.LoadFromFile("hero.png"); } tower::~tower(void) { } void tower::init(sf::RenderWindow &window) { TowerSprite.SetImage(TowerImage); MouseX = window.GetInput().GetMouseX(); MouseY = window.GetInput().GetMouseY(); for(int i = 0; i <TowerVector.size(); i++) { ImageX = TowerVector->Position.x; ImageY = TowerVector->Position.y; } ImageSizeX = TowerSprite.GetSize().x; ImageSizeY = TowerSprite.GetSize().y; } void tower::addtower() { TowerVector.push_back(new tower(MouseX, MouseY)); } void tower::eventhandle(sf::Event Event) { int getamount=eco.getamount(); if(Event.Type == sf::Event::KeyPressed && Event.Key.Code== sf::Key::F) eco.deposet(1); if(getamount>=10) { if(Event.Type == sf::Event::MouseButtonReleased && Event.MouseButton.Button == sf::Mouse::Left) { tower::addtower(); eco.widthdraw(10); } } } void tower::drawtower(sf::RenderWindow &window) { for(int i = 0; i <TowerVector.size(); i++) { // Set position to current tile, and draw it TowerSprite.SetPosition(TowerVector->Position.x, TowerVector->Position.y); window.Draw(TowerSprite); } eco.DisplayMoney(window); } void tower::MouseEventReleased(sf::Event &Event) { for(int ButtonX=ImageX; ButtonX<=ImageX + ImageSizeX; ButtonX++) { for(int ButtonY=ImageY; ButtonY<=ImageY + ImageSizeY; ButtonY++) { if(MouseX==ButtonX && MouseY==ButtonY && Event.Type == sf::Event::MouseButtonPressed && Event.MouseButton.Button == sf::Mouse::Left) { std::cout<<"coco"; } } } } 

tower.h
 #include <SFML\Graphics.hpp> #include <iostream> class tower { public: tower(float x, float y); ~tower(void); void init(sf::RenderWindow &window); void addtower(); void eventhandle(sf::Event Event); void MouseEventReleased(sf::Event &Event); void drawtower(sf::RenderWindow &window); private: sf::Vector2f Position; std::vector<tower*> TowerVector; float MouseX, MouseY; int dmg,cost,defence,getamount; bool DestroyTower; sf::Image TowerImage; sf::Sprite TowerSprite; int ImageX, ImageY, ImageSizeX, ImageSizeY; }; 

##### Share on other sites
There's something thing odd about your code. Not necessarily 'wrong', just odd.

Why does your Tower contain lists of Towers? Does your towers have child towers or something?
Your class is simultaneously trying to do two different things:
1) It's trying to be a tower (good!)
2) It's trying to manage all your towers (???)

Separate the second task into it's own class, and it'll simplify what you are doing. Create a class that manages your vector of towers for you, because it seems to be confusing what you are trying to do.

Random side-note: Your destructor doesn't need to have (void) as a parameter... it's implicit.
Your vector of towers is called 'TowerVector'. That's a bad name, because although it describes what the object is (which we already know what it is) it doesn't describe what it does. Variables names should describe their own purpose, not their own type. Likewise, 'TowerImage' and 'TowerSprite' could just be named 'Image' and 'Sprite'. We already know it belongs to Tower because it's in the Tower class.

By the way, with SFML you don't need to keep track of the image's size or position. sf::Sprite does that for you. Which is actually your problem. You are using too many different ways of keeping track of the tower's position, that when you are clicking, you are checking the wrong one.

Use sf::Sprite's position for the position of your tower, and use it for checking in 'MouseEventReleased()' if that's where you clicked or not. Get rid of ImageX, ImageY, ImageSizeX, and ImageSizeY entirely, and your program will be alot closer to working properly (though it wont be entirely there yet). Replace ImageX with Sprite::GetPosition().x, and replace ImageSizeX with (Sprite::GetPosition().x + Sprite::GetSize().x), and so on.

[font=arial, verdana, tahoma, sans-serif][size=2]

can you guys please help me out. I'm new to the whole victor thing and i'm still trying to understand how it works.

Note that 'sf::Vector2f' and 'std::vector' are both called 'vectors' but they are entirely different things. (They both are named after a mathematical thing called a 'vector', but they are named after it for different reasons and different purposes).

std::vector is simply a regular C++ array, but that's re-sizable. If you don't know what a regular array is, or are still confused, just ask and we'd be happy to explain it. [/font]

##### Share on other sites

There's something thing odd about your code. Not necessarily 'wrong', just odd.

Why does your Tower contain lists of Towers? Does your towers have child towers or something?
Your class is simultaneously trying to do two different things:
1) It's trying to be a tower (good!)
2) It's trying to manage all your towers (???)

Separate the second task into it's own class, and it'll simplify what you are doing. Create a class that manages your vector of towers for you, because it seems to be confusing what you are trying to do.

Random side-note: Your destructor doesn't need to have (void) as a parameter... it's implicit.
Your vector of towers is called 'TowerVector'. That's a bad name, because although it describes what the object is (which we already know what it is) it doesn't describe what it does. Variables names should describe their own purpose, not their own type. Likewise, 'TowerImage' and 'TowerSprite' could just be named 'Image' and 'Sprite'. We already know it belongs to Tower because it's in the Tower class.

By the way, with SFML you don't need to keep track of the image's size or position. sf::Sprite does that for you. Which is actually your problem. You are using too many different ways of keeping track of the tower's position, that when you are clicking, you are checking the wrong one.

Use sf::Sprite's position for the position of your tower, and use it for checking in 'MouseEventReleased()' if that's where you clicked or not. Get rid of ImageX, ImageY, ImageSizeX, and ImageSizeY entirely, and your program will be alot closer to working properly (though it wont be entirely there yet). Replace ImageX with Sprite::GetPosition().x, and replace ImageSizeX with (Sprite::GetPosition().x + Sprite::GetSize().x), and so on.

[font="arial, verdana, tahoma, sans-serif"][quote name='FantasyVI' timestamp='1319729028' post='4877579']
can you guys please help me out. I'm new to the whole victor thing and i'm still trying to understand how it works.

Note that 'sf::Vector2f' and 'std::vector' are both called 'vectors' but they are entirely different things. (They both are named after a mathematical thing called a 'vector', but they are named after it for different reasons and different purposes).

std::vector is simply a regular C++ array, but that's re-sizable. If you don't know what a regular array is, or are still confused, just ask and we'd be happy to explain it. [/font]
[/quote]

ok so what I'm trying to do is make a game like Tower Defence, where if you have enough money you build towers and upgrade them. But the problem is i don't know how to keep track of each tower, and i dont know how to give each one of them its own health - magic - power ups, etc...
keeping track of one tower is very very easy but i don't know how to keep track of all the towers.
can you tell me a way to keep track of every tower?

thank you very much for your help

##### Share on other sites
Well, you're on the right track already, you just need to change things slightly.

Think of this: Each 'Tower' class should manage exactly one tower. It should do everything necessary for that tower to exist in your game; having health, being able to attack, etc...
Right now, your Tower class is trying to manage every tower in the game, and that's what's causing you confusion. You need a different class to manage all your towers, and just let your Tower class manage itself.

Basic idea of a Tower class: (It only handles itself)
 struct TowerStats { TowerStats(std::string imageFile, int damage, int defence, int firingDelay, int cost, int refundAmount); std::string imageFile; int damage, defence; float firingDelay; // (1.0 = fire once a second, 0.5 = fire twice a second, etc...) int cost, refundAmount; } class Tower { public: Tower(sf::Vector2f position, TowerStats stats); ~Tower(); //Checks if the position is within the tower, returns true if it is. bool IsWithin(sf::Vector2f position); //Returns the tower's stats. const TowerStats &GetStats(); void Click(); void Draw(sf::RenderWindow &window); private: sf::Image Image; sf::Sprite Sprite; TowerStats stats; };

Then you can have another class that handles Towers getting built, and manages them also. You only need one TowerManager.
#include "Tower.h" enum TowerType {BasicTower = 0, DifferentTower, AnotherTower} class TowerManager { public: TowerManager(); ~TowerManager(); //Loads the tower types from file and loads them into 'TowerTypes' vector. void LoadTowerTypes(); //Returns the cost of a tower type. int CostToBuild(TowerType type); //Tries to build a tower of type 'type', at position. void BuildTowerAt(sf::Vector2f position, TowerType type); //Tries to destroy a tower at 'position'. If a tower does exist, it returns the amount of money to refund (otherwise returns 0 if no tower exists). int RefundTowerAt(sf::Vector2f position); //Tries to damage a tower at 'position' with 'damage' amount of damage. void DamageTowerAt(sf::Vector2f position); //Returns true if there is a tower at 'position'. bool TowerExistsAt(sf::Vector2f position); //Gets the tower at 'position' and returns it. If a tower doesn't exist there, returns NULL. Tower *GetTowerAt(sf::Vector2f position); //Draws every tower. void DrawAllTowers(sf::RenderWindow &window); private: std::vector <Tower*> Towers; std::vector <TowerStats> TowerTypes; }

Most of the functions above are relatively easy to implement, but I'll implement the difficult ones real quick:
//Tries to build a tower of type 'type', at position. void TowerManager::BuildTowerAt(sf::Vector2f position, TowerType type) { //Make sure this is a valid type. if(type > TowerTypes.size()) { //Error message goes here. return; } //Make sure another tower doesn't already exist there. if(TowerExistsAt(position) == false) { Towers.push_back(new Tower(position, TowerTypes[type])); } } //Gets the tower at 'position' and returns it. If a tower doesn't exist there, returns NULL. Tower *TowerManager::GetTowerAt(sf::Vector2f position) { for(int index = 0; index < Towers.size(); index++) { Tower *towerToCheck = Towers[index]; if(tower->isWithin(position)) { //Found a tower! return towerToCheck; } } //Didn't find a tower! return NULL; } //Draws every tower. void TowerManager::DrawAllTowers(sf::RenderWindow &window) { for(int index = 0; index < Towers.size(); index++) { Towers[index].Draw(window); } }

Any questions, feel free to ask.

1. 1
2. 2
3. 3
Rutin
25
4. 4
5. 5
khawk
14

• 11
• 11
• 23
• 10
• 9
• ### Forum Statistics

• Total Topics
633649
• Total Posts
3013117
×