SFML only allows creating a window of a rectangular(boxy) shape and all other actions are done within it. I am making a Monopoly game and I basically want Monopoly Logo to flash on a screen when the user clicks the executable file and it han’t has to be inside any window(just logo with transparent background).After the logo, the rectangular window then appears. Is there any way to do this?
SFML doesn't have any integrated feature to make window background transparent.
In order to achieve this, you should use some OS specific functions. But this won't work either. If you change window attributes to have a transparent window, SFML will render correctly, but you won't see anything because everything, background and foreground, will be transparent.
What's the solution then? The easiest way to do this is by not having any background, making your logo fit perfectly into your window. Then you only need to remove the title bar and borders, with sf::Style::None.
This is how I reach this:
int main()
{
// First, I load the logo and create an sprite
sf::Texture logo;
if (!logo.loadFromFile("monopoly.png")){
exit(1);
}
sf::Sprite sp;
sp.setTexture(logo);
sp.scale(0.2, 0.2); // My logo is quite big in fact (1st google result btw)
int logoWidth = sp.getGlobalBounds().width;
int logoHeight = sp.getGlobalBounds().height;
// With the logo loaded, I know its size, so i create the window accordingly
sf::RenderWindow window(sf::VideoMode(logoWidth, logoHeight), "SFML", sf::Style::None); // <- Important!! Style=None removes title
// To close splash window by timeout, I just suppose you want something like this, don't you?
sf::Clock timer;
sf::Time time = timer.restart();
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event)){
// event loop is always needed
}
// Window closed by time
time += timer.restart();
if (time >= sf::seconds(2.f)){
window.close();
}
window.clear();
window.draw(sp);
window.display();
}
// Then, reuse the window and do things again
window.create(sf::VideoMode(600, 400), "SFML");
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event)){
}
window.clear();
window.draw(sp);
window.display();
}
return 0;
}
Note that you can re-use your window again just by re-creating with create method.
Results:
and then the other window :
Related
Here is a MWE
#include <SFML/Graphics.hpp>
#include <string>
#include <iostream>
int main(int argc, char *argv)
{
sf::RenderWindow window(sf::VideoMode(200, 200), "Title");
std::string image_filename;
image_filename = "image.png";
sf::Image image;
if(!image.loadFromFile(image_filename))
{
std::cout << "Error: Could not load file " << image_filename << std::endl;
}
sf::Texture texture;
texture.loadFromImage(image);
sf::Sprite sprite;
sprite.setTexture(texture);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(sprite);
window.display();
}
return 0;
}
When starting the application, the window looks like this:
After resizing the window, the window looks like this:
The global and local bounds of the sprite are the same before and after re-sizing.
The behaviour (as seen in the screenshot) is not what I would expect the default behaviour to be.
The number of pixels (width and height) of the window has changed.
The same region of the image/texture/sprite is drawn to the window.
An interpolation algorithm of some kind has been applied to scale the initial window width and height to the resized window width and height.
Maybe that was already really obvious. This behaviour makes sense when designing something like a game**, but it doesn't make sense for the application I am intending to implement.
**
(because the background will "scale" as the window is resized, whereas the rendering resolution would be fixed in advance, likely by a config file)
Before attempting to change the behaviour I want to understand why the behaviour is like this.
Presumably opening a RenderWindow with some initial default resolution (width x height) starts some kind of rendering instance on the GPU with that width and height. Resizing the window on the other hand presumably changes that width and height of the window in the "window system" (window manager, regardless of which OS it is running on) but does not update or change the corresponding width and height on the GPU rendering instance.
Or at least this is my best guess as to what happens.
Is there a way to change this behaviour? Perhaps using something like a SFML RenderWindow is fundamentally the wrong approach to use?
Note: I checked and the "scale" of the sprite does not change during a resize operation. So my assumption would be that the initial window size fixes the resolution of the array of pixels to be rendered and then this is upscaled/downscaled to fit the size of the actual window when drawing pixel data into the display pixel buffer using some kind of interpolation algorithm.
You can add the following event listener to the events loop:
if(event.type == sf::Event::Resized)
{
sf::FloatRect view(0, 0, event.size.width, event.size.height);
window.setView(sf::View(view));
}
This will update the render area to the dimensions of the window every time the window is resized rather than scaling the render area to fit the window.
how can you change the make of a SFML interface?
#include <SFML/Graphics.hpp>
int main()
{
window.create(sf::VideoMode(800, 600), "The Veterans");
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.display();
}
return 0;
}
I want Background to be red.
Now it's black.
If you want to change the background of a SFML window, you have to use sf::RenderWindow::clear with a argument for the color (No argument = Black background). The function call would be:
window.clear(sf::Color::Red);
This "clears" the window with a red color. Place the call right before the window.display().
If you want the window to display something you have to draw it to the screen. Whether that is drawing a shape or an image (or if you are using a RenderWindow, passing a color argument to the clear() method).
Well, I've been watching a tutorial on how to use SFML. I'm currently learning to move a sprite in the screen. Before adding window.clear(); every time I moved the sprite it left like a trail, like if the sprite was a brush. Then the tutorial man said to add window.clear BEFORE window.draw(player);
Could you please explain the logic behind that? Like, the window gets cleared, then draws the character and the displays it. Here is the code:
#include <SFML/Graphics.hpp>
#include <iostream>
int main() {
sf::RenderWindow window(sf::VideoMode(1920, 1080), "Screen", sf::Style::Default);
sf::RectangleShape player(sf::Vector2f(100.0f, 100.0f));
player.setFillColor(sf::Color::Green);
//run as long as the window is open
while (window.isOpen()) {
// check all the window's events that were triggered since the last iteration of the loop
sf::Event evnt;
while (window.pollEvent(evnt)) {
switch (evnt.type) {
case sf::Event::Closed:
window.close();
break;
case sf::Event::Resized:
printf("New window width: %i New window height: %i\n", evnt.size.width, evnt.size.height);
break;
case sf::Event::TextEntered:
if (evnt.text.unicode < 128) {
printf("%c", evnt.text.unicode);
}
}
// "close requested" event: we close the window
if (evnt.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W)){
player.move(0.0f, -0.1f);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A)) {
player.move(-0.1f, 0.0f);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::S)) {
player.move(0.0f, 0.1f);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D)) {
player.move(0.1f, 0.0f);
}
window.clear();
window.draw(player);
window.display();
}
return 0;
}
The logic behind sf::RenderWindow::clear() is actually quite simple. The reason you see a trail behind the sprite without clear is because you redraw the sprite again without getting rid of the old one. Clearing the screen gets rid of anything that was already on the screen, so you end up with a blank canvas to redraw everything on in its updated position. The character, which is your sprite, isn't actually moving, it is constantly getting redrawn in a new position on the window.
Going through the SFML tutorial I tried to write a small code example that slides the window to the right over time, it acted in a way that I didn't expect (the window slid all the way to the bottom). Here's a minimal example that has the window moving despite sticking the exact same coordinates that getPosition spits out into setPosition
#include <SFML/Window.hpp>
#include <SFML/System/Clock.hpp>
#include <SFML/System/Time.hpp>
int main(){
sf::Window window(sf::VideoMode(800,600), "Aydin's Window");
window.setPosition(sf::Vector2i(10, 10));
sf::Clock clock;
while(window.isOpen()){
sf::Event event;
while(window.pollEvent(event)){
if(event.type == sf::Event::Closed)
window.close();
}
sf::Time elapsed = clock.getElapsedTime();
if(elapsed > sf::milliseconds(100)){
sf::Vector2i pos = window.getPosition();
window.setPosition(pos);
clock.restart();
}
}
return 0;
}
One would expect this code to keep the window where it is, but instead it slides to the right and downwards on my machine. I had a friend run the same code. On his machine it slides to the left and upwards. What is going on?
edit: when I create the window without decorations (sf::Style::None) the windows stays where it is. I'm guessing one of getPosition or setPosition is getting offset by the title bar and the other is not.
I'm learning the SFML library at the moment but I'm a little lost on moving the sprite. Here's my main.cpp file:
#include <SFML/Graphics.hpp>
int main()
{
// Create the main window
sf::RenderWindow App(sf::VideoMode(800, 600), "SFML window");
// Load a sprite to display
sf::Texture Image;
if (!Image.LoadFromFile("cb.bmp"))
return EXIT_FAILURE;
sf::Sprite Sprite(Image);
// Define the spead of the sprite
float spriteSpeed = 10.f;
// Start the game loop
while (App.IsOpened())
{
// Process events
sf::Event Event;
while (App.PollEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
App.Close();
if (sf::Keyboard::IsKeyPressed(sf::Keyboard::Up))
Sprite.Move(spriteSpeed * App.GetFrameTime(), 0);
}
// Clear screen
App.Clear();
// Draw the sprite
App.Draw(Sprite);
// Update the window
App.Display();
}
return EXIT_SUCCESS;
}
But I get really slow, inconsistent movements, why isn't the sprite moving steadily around the screen? Also, seeing as how I plan to use the mouse to control the character how will I use the loop to make the character move towards where the user clicks?
You shouldn't be checking if the key is held down in the event loop.
SFML only posts one event when the key is first pressed down, and then another event when the key is released. In this case, your code is only checking if the key is held when an event occurs (such as moving your mouse, clicking, or anything else).
Moving the IsKeyPressed check out of the event loop, preferably below it, should fix the issue.
Making the sprite move towards your mouse is a more complicated issue, better suited for the Game Development StackExchange.