Hi people,
I don't know for sure, if it's even a "window" related problem. If not, than you can freely move this thread to the right area.
It's about an issue, where sprites can only be created only inside the start screen, but if I move the view to other areas of the map, than it is not possible to create sprites there.
I've a suspicion that it's related to the coordinates, that are relative to the window.
In the tutorials I only see the cases, where you can get the relative mouse position in relation to the desktop (1) or in relation to the window (2). But how to get the "really" absolute position. I couln't find anything about it by searching the web and forum. I've only seen code for the both cases from above and/or completely outdated code. Any help is welcome :-)
I think it's this line, that is causing the problem:
newSprite.setPosition(sf::Mouse::getPosition(mMainWindow).x,sf::Mouse::getPosition(mMainWindow).y);
I've tried to even set this in relation to the my maprect or the boundrect, but it did't work.
The whole code:
#include <SFML/Graphics.hpp>
#include <iostream>
#include <list>
int main()
{
sf::RectangleShape maprect;
maprect.setSize(sf::Vector2f(1500, 400));
maprect.setFillColor(sf::Color(0,00,255,255));
maprect.setPosition(0, 0);
sf::Sprite newSprite;
sf::FloatRect mapbound = maprect.getGlobalBounds();
sf::RenderWindow mMainWindow(sf::VideoMode(500, 400), "Map");
mMainWindow.setFramerateLimit(60);
sf::Texture unittexture;
unittexture.loadFromFile("warrior.png");
std::list<sf::Sprite> EnemyList;
std::list<sf::Sprite>::iterator EnemyIt;
sf::View view(sf::Vector2f(250, 200), sf::Vector2f(500, 400)); // center and size
while (mMainWindow.isOpen())
{
sf::Event event;
while (mMainWindow.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
mMainWindow.close();
}
if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Right))
{
view.move(+150, 0);
}
if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Left))
{
view.move(-150, 0);
}
if(event.type == sf::Event::MouseButtonPressed)
if(event.mouseButton.button == sf::Mouse::Left)
if (maprect.getGlobalBounds().contains(mMainWindow.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y))))
{
newSprite.setTexture(unittexture);
newSprite.setPosition(sf::Mouse::getPosition(mMainWindow).x,sf::Mouse::getPosition(mMainWindow).y);
EnemyList.push_back(newSprite);
std::cout << "Mouse Pos" << sf::Mouse::getPosition(mMainWindow).x << ", " << sf::Mouse::getPosition(mMainWindow).y << std::endl; // only relative to window
}
}
mMainWindow.draw(maprect);
mMainWindow.setView(view);
for(EnemyIt = EnemyList.begin();EnemyIt != EnemyList.end();EnemyIt++)
{
mMainWindow.draw(*EnemyIt);
}
mMainWindow.display();
mMainWindow.clear(sf::Color(0, 200, 0, 255));
}
return 0;
}
A few random comments - not related to your problem since you already solved that, just some things I wanted to comment on:
#include <SFML/Graphics.hpp>
#include <iostream>
Why include "iostream"? I don't see any uses.
sf::Texture unittexture;
unittexture.loadFromFile("warrior.png");
A little error handling probably wouldn't hurt.
if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Right))
{
view.move(+150, 0);
}
if((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Left))
{
view.move(-150, 0);
}
if(event.type == sf::Event::MouseButtonPressed)
if(event.mouseButton.button == sf::Mouse::Left)
Not that it really matters from a performance perspective but it still seems bizare to me that apparently you expect that an sf::Event can be multiple types at once. Why don't you use
if (event.type == foo) { ... } else if (event.type == bar) { ... }
?
Ohh and some consistent indenting probably wouldn't hurt either (check out ClangFormat (http://clang.llvm.org/docs/ClangFormat.html).
for(EnemyIt = EnemyList.begin();EnemyIt != EnemyList.end();EnemyIt++)
{
mMainWindow.draw(*EnemyIt);
}
Why not simply for (auto& enemy : EnemyList) { mMainWindow.draw(enemy); }
?
And if you insist on using C++03 style code, then at least use "++EnemyIt" rather than "EnemyIt++" - the prefix operator is never slower than the postfix one (but potentially faster), so always prefer to use prefix unless you need postfix.
Can someone explain to me why this doesn't cause a green screen:
mMainWindow.display();
mMainWindow.clear(sf::Color(0, 200, 0, 255));
I was surprised when I tried it in my own code and everything just looked normal. I would expect it to just.. clear the screen.
for (auto& unitsprite: EnemyList) { mMainWindow.draw(unitsprite); }
As we know it doesn't work with "enemy". But what to choose instead for replacement? I thought "unitsprite" was an element of the container.Btw: .I'm using VS 2010.
I'm using VS 2010.
Visual Studio 2010 does not support the range-based for loop.
You have to use iterators, or AURORA_FOREACH (http://www.bromeon.ch/libraries/aurora/v1.0/doc/group___tools.html#gaa96508df6697039877c7508f2c98a539), which emulates range-based for:
AURORA_FOREACH(sf::Sprite& s, EnemyList)
{
...
}
mMainWindow.display();
mMainWindow.clear(sf::Color(0, 200, 0, 255));
I have to ask: why are you using display() before clear()?