Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - thePyro_13

Pages: [1]
1
Feature requests / std::exit()
« on: August 09, 2022, 06:18:08 am »
Currently sfml will cause a crash(MSVC2022) if std::exit is called after using any of the SFML Graphics objects.

In the debugger the crash appears in GLContext.cpp:752 when calling the elements in contextDestroyCallbacks.
This is because std::exit will skip destruction of stack objects, but will still call static global objects destructors.
I think this is during the destructor of the global shared context.

This might be fixed by sticking the static global objects into a static global struct together, so that the callback list won't be destroyed before the shared context. SFML could also register a function to clear the shared context before the static objects are destroyed using std::atexit.

I've moved to using std::quick_exit, but I think it would be worth it to get std::exit working with SFML.

2
General discussions / Dynamic Split Screen
« on: March 12, 2014, 11:27:02 am »
Here's a quick bit of example code on what I call Dynamic Split Screens, this is the effect I first encountered in one of the newer Lego Star Wars games.

I was inspired to give this a shot after reading this post about non axis aligned viewports.
I had already written this post but managed to lose it(I compulsively hit refresh :(). So please tell me if their is anything I missed or should explain in more detail. :(

The goal is to smoothly split and re-merge the two split views based on player locations.
This provides a good middle ground between games that don't use split screens at all(like Super Smash Bro.'s) and games that use static split rectangles, like most console games.

We don't want to split into predefined rectangles, because this can disorient players when their avatar jumps to the opposite side of the screen, we also want to avoid the same problem when re-merging the views.

The solution is to have the two views dynamically generated based on the players relative positions to one another. Also we make sure that the views can cleanly rotate around one other if the players end up circling one another.

This explanation is much worse than my original one, so here's a video showing it off:


Finally, here's the code:
I use SFML for most of the work, and Thor for some vector maths.
The map.png I'm using is just a big image of the world from the original Legend of Zelda.
//===============================================================
// Dynamic Split Screen Example for SFML(http://sfml-dev.org/)
//
// The code in this file was developed by Steven Pilkington.
// More information about this example can be
// found on my blog(http://cyangames.wordpress.com/)
//
// I'm putting this in the public domain, so have fun with it.
//
//                                                                                              Date: 12/03/2014
//===============================================================

#include "SFML/Graphics.hpp"

#include "Thor/Vectors.hpp"

//Set the window resolution.
const int WIDTH = 800;
const int HEIGHT = 600;

//Ditermine if the views should be split based on the difference between both players positions.
bool shouldSplit(sf::Vector2f position1, sf::Vector2f position2);

//Calculate the camera position for the object at position1, moving the camera in the direction of position2.
sf::Vector2f viewPosition(sf::Vector2f position1, sf::Vector2f position2);

int main()
{
        //Create window.
        sf::RenderWindow window;
        window.create(sf::VideoMode(WIDTH, HEIGHT), "Dynamic Split Screen");

        //Create two player sprites.
        sf::Vector2f playerSize(10, 10);
        sf::RectangleShape p1(playerSize), p2(playerSize);

        p1.setFillColor(sf::Color::Blue);
        p2.setFillColor(sf::Color::Red);

        //Multiply our movements by this to control player movement speed.
        const float PLAYERSPEED = .1f;

        //Create background.
        //We're using a big image of the origional Legend of Zelda game world as our background.
        sf::Texture mapTex;
        mapTex.loadFromFile("map.png");
        sf::Sprite map(mapTex);
        //Move the background sprite so that the world origin is somewhere in the middle of the map.
        map.setPosition(-sf::Vector2f(map.getLocalBounds().width / 2.f, map.getLocalBounds().height / 2.f));

        //Create our views.
        //One for each player, player ones view is also used for both players when the views are merged.
        sf::View p1View = window.getView();
        sf::View p2View = window.getView();

        //View movement speed.
        const float VIEWSPEED = .2f;

        //Rendertexture is used to render player twos view of the world.
        sf::RenderTexture p2Tex;
        p2Tex.create(WIDTH, HEIGHT);
        sf::Sprite p2Sprite;

       

        //We use a large rectangle to draw the devider between the two camaras in slit screen mode.
        //We also use this to blend the two views together.
        sf::RectangleShape eraser;
        eraser.setOutlineColor(sf::Color::Black);
        eraser.setFillColor(sf::Color::Transparent);
        eraser.setOutlineThickness(2);
        eraser.setSize(sf::Vector2f(WIDTH*2, HEIGHT*2));

        //Start main loop.
        while(window.isOpen())
        {
                //Handle events.
                sf::Event e;
                if(window.pollEvent(e))
                {
                        if(e.type == sf::Event::Closed)
                                window.close();
                }

                //User controls.
                sf::Vector2f move;
                //Player one input.
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
                        move.y += -1;

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))
                        move.y += 1;

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::A))
                        move.x += -1;

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::D))
                        move.x += 1;

                p1.move(move * PLAYERSPEED);

                //Reset the move vector.
                move = sf::Vector2f();
                //Player two input.
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
                        move.y += -1;

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
                        move.y += 1;

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
                        move.x += -1;

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                        move.x += 1;

                p2.move(move * PLAYERSPEED);

                //Now we need do decide if we split our views.
                bool singleView = true;
                //Ideal position is the location that the camera wants to be in.
                sf::Vector2f idealPos;
       
                if(shouldSplit(p1.getPosition(), p2.getPosition()))
                {                      
                        //We want to split, so we calculate the ideal position for each camera using viewPosition().
                        singleView = false;
                        idealPos = viewPosition(p1.getPosition(), p2.getPosition());
                        p1View.move( (idealPos - p1View.getCenter()) * VIEWSPEED);

                        idealPos = viewPosition(p2.getPosition(), p1.getPosition());
                        p2View.move( (idealPos - p2View.getCenter()) * VIEWSPEED);
                }
                else
                {
                        //If we don't want a split view, then the ideal position is the halfway
                        //point between both players.
                        idealPos = (p1.getPosition() + p2.getPosition()) / 2.f;
                        p1View.move( (idealPos - p1View.getCenter()) * VIEWSPEED);
                        //Set player twos cameras to the same as player ones, this will avoid an jump if the cameras split again
                        //far away from where they last merged.
                        p2View.setCenter(p1View.getCenter());
                }

                //Draw everything from player ones point of view.
                window.clear();
                window.setView(p1View);
                window.draw(map);
                window.draw(p1);
                window.draw(p2);

                //If we're splitting the views then we'll do the same for player twos view.
                if(!singleView)
                {
                        //Draw all our normal stuff from players twos point of view.
                        p2Tex.clear();
                        p2Tex.setView(p2View);
                        p2Tex.draw(map);
                        p2Tex.draw(p1);
                        p2Tex.draw(p2);

                        //Now calculate where to place our rectangle to properly divide the screen.
                        //We start in the centre of the window.
                        eraser.setPosition(window.mapPixelToCoords(sf::Vector2i(WIDTH/2, HEIGHT/2), p2View));
                        //Then we calcuate a vector representing the line that will split the two views.
                        //This line is perpendicular to the line between both players.
                        sf::Vector2f angle = thor::perpendicularVector(p1.getPosition() - p2.getPosition());
                        thor::setLength(angle, static_cast<float>(HEIGHT));
                        //Move the rectangle along this line so that it will stretch across the entire screen.
                        eraser.move(angle);
                        //Rotate the rectangle so that it covers the side of the screen that we want to be blended with player ones view.
                        eraser.setRotation(-(thor::signedAngle(angle, sf::Vector2f(1, 1)) + 135));

                        //Draw the rectangle to our rendertexture using BlendMode None.
                        p2Tex.draw(eraser, sf::BlendMode::BlendNone);
                        p2Tex.display();

                        //Assign the tecture to a sprite.
                        p2Sprite.setTexture(p2Tex.getTexture());
                        //Draw it over the origin so that our rectangle math works out properly.
                        window.setView(window.getDefaultView());
                        //Draw it to the window.
                        window.draw(p2Sprite);
                }

                window.display();
        }


        return EXIT_SUCCESS;
}

bool shouldSplit(sf::Vector2f position1, sf::Vector2f position2)
{
        //If the two positions are more than a half of the average of the screens
        //width and height then we'll split.
        sf::Vector2f dist = position1 - position2;
        if(thor::length(dist) > (WIDTH + HEIGHT) / 4)
                return true;

        return false;
}

sf::Vector2f viewPosition(sf::Vector2f position1, sf::Vector2f position2)
{
        //Our camera position is currently set to keep the player within a circular area of the screen.
        //It would probably be better to convert this to instead keep them within a elliptical area.
        sf::Vector2f out = position1;

        //MAX_DISTANCE will keep position1 on the screen, reguardless of how far away it is from position2.
        const float MAX_DISTANCE = (WIDTH + HEIGHT) / 5;
        //this is the ideal position, the halfway point between both players, the camera will gravitate towards this position
        //so that things meet up nicely when the views merge.
        sf::Vector2f direction = (position2 - position1) / 2.f;

        //Use MAX_DISTANCE to trim our direction vector if it is too long,
        //eg. If it would put position1 off the edge of the screen.
        if(thor::length(direction) > MAX_DISTANCE)
                thor::setLength(direction, MAX_DISTANCE);

        return out + direction;
}

This should work as a good starting point for someone who wants to add this technique to their own project. Theirs are fair bit of cleaning up and improving to do, mostly the player positions should be constrained to an ellipsis rather than a circle, currently the players can end up far too close to the screen edge.

I'll be putting this up on my blog and the SFML wiki as as well, probably tomorrow or the day after.

Criticism welcome(especially when it comes to my maths), If anyone can think of any small features like this that they'd like to see in an example then tell me, I'll give it a shot.

3
Window / Mouse buttons ignore OS settings, bug?
« on: August 27, 2012, 09:54:10 am »
Wasn't sure of a good way to word the title.

On windows 7 x64(and possibly other OS's) the sf::Mouse::isButtonPressed() function doesn't take into account OS settings to flip the left and right mouse buttons.

I have my mouse buttons reversed, so the physical right button, should be registered as a left click. However SFML2 still reports it as a right click.

I did a search and couldn't find any mention of this on the forums or bug tracker.

Minimal example:
Set the OS to reverse mouse settings and press the left mouse button while running the following code. sf::Mouse::isButtonPressed() still returns true, though it should not.
#include <SFML/Window.hpp>

int main()
{
    sf::Window window(sf::VideoMode(800, 600), "My window");

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            //here, isButtonPressed should return false when hitting the physical left button. and the reverse
            //should be true when testing against sf::Mouse::Button::Right
            if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Left))
                window.close();


        }
    }
   

4
SFML projects / DisplayBooth
« on: March 05, 2012, 10:05:12 am »
DisplayBooth is a really simple kiosk application I developed for the Moorabbin Air Museum. It was developed to replace an ageing kiosk whose hardware was failing. The goal was to replicate the program that already existed, but could not run on newer computers(and whose source code had long been lost), since the computer this current program was installed on had died.

DisplayBooth uses SFML and SFMLTheora to draw video files to the screen. All it really does is play the intro file in a loop until someone pushes a button(the physical kiosk has a large button which translates into a mouse press for the computer). When a user interacts with it, it then plays the informational video.

The kiosk is also configurable using an xml file, to add multiple intro videos and associated information videos, and when the button is pressed the program plays the associated informational video for whatever intro video is currently playing.

The source is available here: source via SFMLUploads.org

It requires the indevelopment version of SFML2 and SFMLTheora 1.3 to compile and run.

Edit: It requires TinyXML as well, I knew I had forgotten something.

I'm releasing it free for any use.

I'm pretty much done with it, but I thought I'd show it off, in case anyone was interested.

5
Graphics / Some help with viewports?
« on: November 15, 2011, 10:07:17 am »
I've started playing with views in my current project and have noticed this problem. If I alter the views viewport at all(including (1,1,1,1)) then my window only seems to render the clear() colour. The sprites render fine if I only remove this line.

REDACTED: I can't get Viewports to work anywhere. :(

But I figured I'd post here first. Are their any known bugs related to viewport that could be causing this? Or can anyone provide some pointers on which functions could be effecting the viewport like this.

EDIT:

Ok, so now I've got this:
Code: [Select]
#include "SFML\Graphics.hpp"

int main()
{
sf::RenderWindow window;
window.Create(sf::VideoMode(800,600), "sf::Viewport test");

sf::View view = window.GetView();
view.SetViewport(sf::FloatRect(1, 1, 1, 1));
window.SetView(view); //if I comment out this line I get the expected black window with white circle in the middle

sf::Shape shape = sf::Shape::Circle(sf::Vector2f(window.GetWidth() /2, window.GetHeight() /2), 50, sf::Color::White);

while(window.IsOpened())
{
sf::Event e;
while(window.PollEvent(e))
{
if(e.Type = sf::Event::Closed)
window.Close();
}

window.Clear();
window.Draw(shape);
window.Display();
}

return EXIT_SUCCESS;
}

If I comment out the window.SetView(view); line, then everything works as expected. I'm also able to comment out the SetViewport() line and everything works as-well. I'm using a shape here, but the same problem appears with sprites.

I can't think of anything else I can remove, is this not how view-ports are meant to be used?

Pages: [1]
anything