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 - SFMLNewGuy

Pages: [1] 2
1
Graphics / Understanding how to create X type of Shader?
« on: January 04, 2022, 03:48:08 am »
I just had a quick question? How do people typically figure out different types of shader effects (2D)? Say you want an explosion, or a wind effect, or a fountain? How do people figure this out? Do they just find out the formulas that emulate X type of effect?

Is there a general place where you can find templates of just about anything you can think of? Like a plug-in-play almost where you can fiddle with the variables?

Thanks.

2
Graphics / Vertex Array shapes
« on: March 31, 2021, 02:32:02 pm »
Hello,

As of right now, I'm using Rectangles as a Tile Map as textures aren't of importance right now. It was a simple transparent fillColor, 1.f outline, sf::White outline color. So I'm trying to use VertexArray without textures (sf::Quad). Everything was fine until I realized I don't think colors work like that now.

So would I add an extra 4 lines over the current square to create an outline? Perhaps, just draw the same quad coordinates as lines? I'm just making sure there isn't an easier way.

Thanks

3
Graphics / sf::ConvexShape and sf::Mouse
« on: December 21, 2020, 09:20:00 pm »
Hello,

Hope you all are doing well and getting ready for the holidays. I had a quick question regarding sf::ConvexShape.

sf::Vector2f startPos{ 0,0 };
        sf::ConvexShape shape{ 3 };
        shape.setPoint(0, { 100,0 });
        shape.setPoint(1, { 100,100 });
        shape.setPoint(2, startPos);

        shape.setFillColor(sf::Color::Transparent);
        shape.setOutlineThickness(5.f);
        shape.setOutlineColor({ 120,0,0 });
        shape.setOrigin(150, 150);
        shape.setPosition(640, 384);

and in update:
auto mousePos = sf::Mouse::getPosition(window);
if(clicked)
        shape.setPoint(2, sf::Vector2f(mousePos));
 

Now all I'm trying to do is have point 2 follow the mouse position. The mouse position seems way off though. I'm not using a view, it's just a barebone project. I've tried sf::Mouse::getPosition(window), I've tried using mapPixelToCoords(sf::Mouse::getPosition(window)). But mapCoordsToPixel has got me the most accurate results, yet still it's off.

Anyone see what my problem could be? I'm trying to setup a little sandbox to really get familiar and have a good understanding with cos/sin.

Thanks!

4
General / Moving a point around a falling circle
« on: December 14, 2020, 10:37:57 am »
Hello,

This is where my lack of knowledge of math affects me the most. So I have a regular circle that appears where you click the mouse and begins to fall using basic velocity and acceleration.

I have a line created in the middle of the circle to represent the angle the circle is falling. I can't seem to get the last point to rotate around the circle. At the moment I'm just trying to have it follow the circle's path just in general.

circle.setPosition(m_position.x - fOffsetX, m_position.y - fOffsetY);
circle.setRadius(radius);
circle.setOutlineThickness(0.5f);
circle.setOutlineColor(sf::Color::White);
circle.setFillColor(sf::Color::Transparent);
float angle = (atan2(circle.getPosition().y ,   circle.getPosition().x ) * 180) / 3.141;
circle.rotate(angle);

sf::Vector2f l1{ circle.getPosition().x + circle.getRadius() , circle.getPosition().y + circle.getRadius() };
sf::Vector2f l2{ circle.getPosition().x + circle.getRadius() * 2 , circle.getPosition().y + circle.getRadius() };

drawLine(l1, l2, sf::Color Yellow)
 

Without telling you every single cosf and sinf formula I configured (aka probably made up) for 'l2' can anyone just tell me off the top of their head how I would accomplish this? Perhaps explaining quickly why would be awesome.

Thanks, everyone have a great week and be safe.

5
Graphics / Texture loadFromFile every frame.
« on: December 04, 2020, 10:03:12 pm »
Hello,

So I'm getting more and more familiar with sf::RenderTexture. It has REALLY helped with this current project since it requires drawing millions of pixels. I finally got it to run smooth switching to it. What I am concerned about is the texture loading the sf::image being drawn to every frame.

It's running great, as I said, but I'm just wondering if this is 'okay' to do and if not, what would be the appropriate solution? Is loading from the image 'okay', but loading up a new texture from a file different? I'm just curious about the future and if I had more stuff going on it would cause problems.

Thanks

void Worms_Part1::onDraw() {

        for (int y = worldMin.y; y <= worldMax.y; ++y) {
                for (int x = worldMin.x; x <= worldMax.x; ++x) {
                        const sf::Vector2i p(x, y);
                        if (m_map.isInBounds(p)) {

                                m_image.setPixel(x, y, m_map(p).isLand ? sf::Color(58, 110, 45) : sf::Color(45, 198, 198));
                        }
                }
        }

        m_renderTexture.clear();
       
        m_texture.loadFromImage(m_image);
        m_renderTexture.draw(sf::Sprite(m_texture));
        m_renderTexture.display();
       
        m_renderSprite.setTexture(m_renderTexture.getTexture());
        window.draw(m_renderSprite);
}

6
Graphics / RenderTexture and editting pixels Help
« on: November 22, 2020, 12:37:32 am »
Hello,

So I've been translating projects from a great YouTuber named Javidx9, to SFML. This project
"Line Of Sight" is the project I'm translating to SFML. At the end of the video, he uses a light_cast.png sprite (cool effect) that follows the mouse, and pixels are used to put the shadow over it.

He defines the variables like this (directly from the source), and this has been the most difficult part figuring out what is a sf::Image, sf::Sprite, sf::Texture, sf::RenderTexture.

olc::Sprite *sprLightCast;
olc::Sprite *buffLightRay;
olc::Sprite *buffLightTex;

On initialization:
sprLightCast = new olc::Sprite("light_cast.png");

// Create some screen-sized off-screen buffers for lighting effect
buffLightTex = new olc::Sprite(ScreenWidth(), ScreenHeight());
buffLightRay = new olc::Sprite(ScreenWidth(), ScreenHeight());
return true;

On userUpdate, which also draws. https://github.com/OneLoneCoder/olcPixelGameEngine/blob/master/Videos/OneLoneCoder_PGE_ShadowCasting2D.cpp#L434   (lines 434 to 444)
         
...
// Clear offscreen buffer for sprite
SetDrawTarget(buffLightTex);
Clear(olc::BLACK);

// Draw "Radial Light" sprite to offscreen buffer, centered around
// source location (the mouse coordinates, buffer is 512x512)
DrawSprite(fSourceX - 255, fSourceY - 255, sprLightCast);

// Clear offsecreen buffer for rays
SetDrawTarget(buffLightRay);
Clear(olc::BLANK);

On userUpdate, which also draws. https://github.com/OneLoneCoder/olcPixelGameEngine/blob/master/Videos/OneLoneCoder_PGE_ShadowCasting2D.cpp#L473 (473-477)
        ...
// Wherever rays exist in ray sprite, copy over radial light sprite pixels
SetDrawTarget(nullptr);
for (int x = 0; x < ScreenWidth(); x++)
        for (int y = 0; y < ScreenHeight(); y++)
                if (buffLightRay->GetPixel(x, y).r > 0)
                        Draw(x, y, buffLightTex->GetPixel(x, y));

So defining these variables correctly has been my problem. It looks like buffLightRay would be a sf::Image and buffLightText, but I'm getting hung up on the last portion where I need to change the pixel. I believe his draw() function is drawing a single pixel, which I have an equivalent function. The reason I thought I needed a sf::RenderTexture was that he mentioned an offscreen drawing. But, I don't think I need that?

Hope that makes sense, thank you have a great day.

7
Graphics / Little help with 'getPixelPtr()'
« on: October 13, 2020, 09:14:30 am »
Hello everyone,

According the the SFML documents it says

getPixelPtr() -
The returned value points to an array of RGBA pixels made of 8 bits integers components. The size of the array is width * height * 4 (getSize().x * getSize().y * 4). Warning: the returned pointer may become invalid if you modify the image, so you should never store it for too long. If the image is empty, a null pointer is returned.

So I'm interested how this works and if someone can give a bare minimum example? I find this all very interesting, especially how you can load a raw png file for example.

At the moment I am doing some raycasting and trying to figure out a way to make it more efficient because it's a bit slow (from the transfer to RGBA from ARGB) and I was wondering if this would be something to look too? When I am setting a pixel color I'm doing:

(loop rays)
(drawCeiling)
(calculate offset)
(loop wallTop to wallBottom)
        auto texelColor = images[textureNum]->getPixel(textureOffsetX,textureOffsetY)
         drawPixels(x,y,texelColor)   // overloaded for sf::Uint32 and sf::Color
(draw floor)

----
        void drawPixel(int x, int y, sf::Uint32 color) {
                // The example I was learning from used ARGB so a nice gentleman gave me the convert
                const sf::Uint32 rgbaPixel =
                     ((color & 0xff000000) >> 24) | ((color & 0x00ffffff) << 8);        // or to an RGBA uint32:

                colorBuffer->setPixel(x,y,sf::Color(rgbaPixel));
        }
        void drawPixel(int x, int y, sf::Color color) {
                colorBuffer->setPixel(x, y, color);
        }
 
How would I do something simular using the Ptr function and I know it returns Uint8's, but the image it self is created 64x64 so I wouldn't multiple by 4 right?

Thanks, be safe and take care everyone.

8
Graphics / Creating ColorBuffer with Pixel Data (transcribing some SDL)
« on: October 04, 2020, 09:06:30 am »
Hello,

I was hoping someone could help me out with this bit of code and its SDL equivalent? I'm learning about RayCasting, unfortunately, it's in SDL and this part hasn't been as easy as I thought it would be. I'll show the basic code and what I did to emulate it in SFML. Also, he did the format as ARGB8888 is that going to be a problem and can I convert that for SFML? Because I've always thought SFML took it as RGBA.

const int TILE_SIZE 64;
constexpr int MAP_NUM_ROWS = 13;
constexpr int MAP_NUM_COLS = 20;
#define WINDOW_WIDTH  (MAP_NUM_COLS * TILE_SIZE)
#define WINDOW_HEIGHT (MAP_NUM_ROWS * TILE_SIZE)

// SDL CODE                                   //  SFML CODE
// globals
Uint32* = colorBuffer = NULL;         //  sf::Uint8* colorBuffer = nullptr;
SDL_Texture* colorBufferTexture;    // sf::Texture* colorBufferTexture = nullptr;

// init()
colorBuffer =
(Uint32*)malloc(sizeof(Uint32) * WINDOW_WIDTH * WINDOW_HEIGHT);
 colorBufferTexture = SDL_CreateTexture(
        renderer,
        SDL_PIXELFORMAT_ARGB8888,
        SDL_TEXTUREACCESS_STREAMING,
        WINDOW_WIDTH,
        WINDOW_HEIGHT
    );

/*  SFML
colorBuffer = new sf::Uint8[WINDOW_WIDTH * WINDOW_HEIGHT * 4];
colorBufferTexture = new sf::Texture();
colorBufferTexture.create(WINDOW_WIDTH, WINDOW_HEIGHT);
*/


// simple functions in class
void clearColorBuffer(Uint32 color) {
    for (int x = 0; x < WINDOW_WIDTH; x++)
        for (int y = 0; y < WINDOW_HEIGHT; y++)
            colorBuffer[(WINDOW_WIDTH * y) + x] = color;
}

/* SFML
        void clearColorBuffer(sf::Uint8 color) {
                for (int x = 0; x < WINDOW_WIDTH; ++x) {
                        for (int y = 0; y < WINDOW_HEIGHT; ++y) {
                                 /* I thought the 1D code should be MapWidth * X + Y here instead the way the loop is
                                    constructed. Guess not. because both ways give me an write access error
                                    "color = 48 '0'
                                     colorBUffer = 0x0a9ed088 "0yyyyyyyyy uuG'"  0yy-uuG has little ' on top of it
                                    "
                                colorBuffer[(WINDOW_WIDTH * y) + x] = color;   // tried putting * 4 in there as well
                        }
                }
        }
*/


void renderColorBuffer() {
    SDL_UpdateTexture(
        colorBufferTexture,
        NULL,
        colorBuffer,
        (int)(WINDOW_WIDTH * sizeof(Uint32))
    );
    SDL_RenderCopy(renderer, colorBufferTexture, NULL, NULL);
}

/* SFML
void renderColorBuffer() {     
                colorBufferTexture->update(colorBuffer);
                const sf::Sprite sprite(*colorBufferTexture);
                window.draw(sprite);
        }

*/


void draw()
        {
                window.clear();

                clearColorBuffer(0xFF00EE30); // I believe in SFML I'm suppose to make this 0x00EE30FF
                renderColorBuffer();

                // display mini-map
                renderMap();
                renderRays();
                renderPlayer();

                window.display();
        }

 

Any help would be appreciated. I'm shutting down for the night and will take a crack tomorrow. This was just a "see if it's working thus far" run before moving further and I'm putting it on hold until I get this down correctly. The example down the road involves using something called 'uPNG' which is why I want to get at least feeding it the correct data correctly. My hunch is how he is using the Uin32 and I can't cast a Uint32 to a Uint8, which is why I've used sf::Uint8 since update() takes a pointer to sf::Uint8 data. But I've been all sorts of wrong during this example.  :-X

I hope this makes sense. Thank you and you all be safe now!

9
General / Cartesian to Polar
« on: August 19, 2020, 08:20:26 pm »
So I've always been curious about this and I was hoping someone could help me figure out what's wrong.

sf::Vector2u WindowSize{1280, 768};
sf::RectangleShape shape1{{64.f,64.f}}, shape2{{64.f,64.f}};
sf::Vector2f cart{0.f,0.f};
float scaleFactor = 1.f;
shape1.setscale(scaleFactor,scaleFactor); shape2.setscale(scaleFactor,scaleFactor);
sf::Vector2f polar{}, screen{};

while(window.open()) ...
...
screen = {(cart.x + (WINDOW_SIZE.x / 2.f)) / zoomF,
                ((WINDOW_SIZE.y / 2.f) + cart.y) / zoomF };
polar   = {(cart.x + (WINDOW_SIZE.x / 2.f)) * zoomF,
                ((WINDOW_SIZE.x / 2.f) - cart.y) * zoomF };

... up down left right        cart.x - or + = 100; cart.y - or + = 100
... num1 num2                scaleFactor + or - 0.1 and shape.setScale(scaleFactor, scaleFactor);

shape1.setPosition(polar); shape2.setPosition(cart);
draw(shape1 and shape2)
 

So I'm tracking each shapes position and I'm wondering why shape1's screen coordinates isn't being shown as (0,0)? At cartesian coordinates (0,0) it shows (480,480)  and screen coordinates (496.802, 397.442). Also when I increase the scale how come it increases off the screen at 2.f and then as you decrease continues to get bigger than shrinks down. Something with the scale isn't correct and I'm wonder if I am setting the scale correctly.

Thanks

EDIT: Also increasing the scale moves it in very unpredictable ways.

10
General / Simple math
« on: August 07, 2020, 12:16:52 am »
Hello,

I'm so rusty with math, it has been my downfall learning how to program. I honestly need to take a course again and I have something called Khan to check out.

With that said, I just have a simple question regarding this formula

A + B = ||A||||B||           

Do I add or multiply the magnitude of A and B. I'm having one hell of a time finding clarity to this? I'd assume multiply, but from the examples I see, it looks like you use addition.

Any help, sorry if this is the wrong place to ask. I'm just kind of stuck on this.

EDIT: And if someone could explain why SFML used degrees instead of radians I would appreciate it. Thanks

11
General discussions / Thor and Animation
« on: July 31, 2020, 04:40:18 am »
Hello,

So I'm trying to use thor and things aren't going as smoothly as I thought they would. At the moment I have an isometric sprite sheet and I'm just trying to watch it animate the walk directions with W A S D and the diagonals of the keys. It must have something to do with the "queue" because it seems like a "lag" to the next animation and sometimes it never gets called even. I might be doing something wrong, but a lot of the functions in the tutorial aren't there. Such as

animator.playAnimation("walk");
animator.stopAnimation();
animator.isPlayingAnimation()

#include <Thor/Animations.hpp>
#include <Thor/Input.hpp>
#include <SFML/Graphics.hpp>
const int Sprite_Width = 160;
const int Sprite_Height = 160;

// Adds a range of frames, assuming they are aligned as rectangles in the texture.
// animation:      FrameAnimation to modify
// x:              Column index of the texture rectangle
// [yFirst,yLast]: Bounds for row indices (if yLast < yFirst, add frames in reverse order)
// duration:       Relative duration of current frame (1 by default)
void addFrames(thor::FrameAnimation& animation, int x, int yFirst, int yLast, float duration = 1.f) {
        const int step = (yFirst < yLast) ? +1 : -1;
        yLast += step; // so yLast is excluded in the range

        for (int y = yFirst; y != yLast; y += step)
                animation.addFrame(duration, sf::IntRect(Sprite_Width * x, 160 * y, Sprite_Width, 160));
}

// Plays an animation, and updates the text correspondingly
// animator:    Thor animator to play the animation
// animationId: Name of the animation to play
// restart:     true if the queued animations are discarded, false if the new animation is enqueued at the end
// display:     SFML text that displays the current animation
void playAnimation(thor::Animator<sf::Sprite, std::string>& animator, const std::string& animationId, bool restart, sf::Text& display) {
        // Function to call before animation is played
        auto onStart = [&display, animationId]() {
                display.setString(animationId);
        };
        restart = false;
        // Function to call after animation is played
        auto onFinish = [&display]() {
                display.setString("(idle)");
        };

        // Enqueue animation and callbacks -- restart determines whether queue is reset
        (restart ? animator.play() : animator.queue())
                << thor::Playback::notify(onStart)
                << animationId
                << thor::Playback::notify(onFinish);
}

int main() {
        sf::RenderWindow window(sf::VideoMode(1280, 768), "Thor Animation");
        window.setVerticalSyncEnabled(true);
        window.setKeyRepeatEnabled(false);

        sf::Font font;
        if (!font.loadFromFile("Media/sansation.ttf"))
                return 1;


        sf::Text animationText("(idle)", font, 14u);
        animationText.setPosition(100.f, 150.f);
        animationText.setFillColor(sf::Color(250, 215, 11));

        // Create texture based on sf::Image
        sf::Texture texture;
        if (!texture.loadFromFile("Media/Sprite_1.png"))
                return 1;

        // Create sprite which is animated
        sf::Sprite sprite(texture);
        sprite.setPosition(100.f, 100.f);

        // Define walk animation
        thor::FrameAnimation walkDown;
        for(auto i = 0; i < 8; i++)
                addFrames(walkDown, i, 0, 0);          
        thor::FrameAnimation walkLeft;
        for (auto i = 8; i < 16; i++)
                addFrames(walkLeft, i, 0, 0);          
        thor::FrameAnimation walkRight;
        for (auto i = 16; i < 24; i++)
                addFrames(walkRight, i, 0, 0);                 
        thor::FrameAnimation walkUp;
        for (auto i = 0; i < 8; i++)
                addFrames(walkUp, i, 1,1 );                    

        thor::FrameAnimation walkDownLeft;
        for (auto i = 8; i < 16; i++)
                addFrames(walkDownLeft, i, 1, 1);              
        thor::FrameAnimation walkUpLeft;
        for (auto i = 16; i < 24; i++)
                addFrames(walkUpLeft, i, 1, 1);        
         thor::FrameAnimation walkDownRight;
        for (auto i = 0; i < 8; i++)
                addFrames(walkDownRight, i, 2, 2);                     
         thor::FrameAnimation walkUpRight;
        for (auto i = 8; i < 16; i++)
                addFrames(walkUpRight, i, 2, 2);               
       

        // Register animations with their corresponding durations
        thor::AnimationMap<sf::Sprite, std::string> animations;
        animations.addAnimation("walkDown", walkDown, sf::seconds(1.f));
        animations.addAnimation("walkLeft", walkLeft, sf::seconds(1.f));
        animations.addAnimation("walkUp", walkUp, sf::seconds(1.f));
        animations.addAnimation("walkRight", walkRight, sf::seconds(1.f));
        animations.addAnimation("walkDownLeft", walkDownLeft, sf::seconds(1.f));
        animations.addAnimation("walkUpLeft", walkUpLeft, sf::seconds(1.f));
        animations.addAnimation("walkDownRight", walkDownRight, sf::seconds(1.f));
        animations.addAnimation("walkUpRight", walkUpRight, sf::seconds(1.f));
        // Create animator referring to this map, and play 'stand' animation to bring the sprite into an initial state
        thor::Animator<sf::Sprite, std::string> animator(animations);
        animator.play() << "walkDownLeft";
       
        // Create clock to measure frame time
        sf::Clock frameClock;

        thor::ActionMap<std::string> keyMap;

        thor::Action w(sf::Keyboard::W, thor::Action::Hold);
        thor::Action a(sf::Keyboard::A, thor::Action::Hold);
        thor::Action s(sf::Keyboard::S, thor::Action::Hold);
        thor::Action d(sf::Keyboard::D, thor::Action::Hold);
        keyMap["Down"] = s;
        keyMap["Up"] = w;
        keyMap["Left"] = a;
        keyMap["Right"] = d;

        thor::Action sa = s && a;
        thor::Action wa = w && a;
        thor::Action sd = s && d;
        thor::Action wd = w && d;
        keyMap["DownLeft"] = sa;
        keyMap["UpLeft"] = wa;
        keyMap["DownRight"] = sd;
        keyMap["UpRight"] = wd;

        thor::Action esc(sf::Keyboard::Escape, thor::Action::PressOnce);
        thor::Action stop(sf::Keyboard::Space, thor::Action::PressOnce);
        keyMap["quit"] = esc;
        keyMap["Stop"] = stop;

        // Main loop
        while (window.isOpen()) {
                // Handle events
                sf::Event event;
                while (window.pollEvent(event)) {

                        // React to different action types
                        if (keyMap.isActive("quit") || event.type == sf::Event::Closed)
                        {
                                window.close();
                                return 0;
                        }

                }
                        // Poll the window for new events, update actions
                        keyMap.update(window);

                if (keyMap.isActive("DownLeft")) {
                        animationText.setString("(Walk Down-Left)");
                        playAnimation(animator, "walkDownLeft", event.key.code, animationText);
                }
                else if (keyMap.isActive("UpLeft")) {
                        animationText.setString("(Walk Up-Left)");
                        playAnimation(animator, "walkUpLeft", event.key.code, animationText);
                }
                else if (keyMap.isActive("DownRight")) {
                        animationText.setString("(Walk Down-Right)");
                        playAnimation(animator, "walkDownRight", event.key.code, animationText);
                }
                else if (keyMap.isActive("UpRight")) {
                        animationText.setString("(Walk Down-Right)");
                        playAnimation(animator, "walkUpRight", event.key.code, animationText);
                }
                else if (keyMap.isActive("Down")) {
                        animationText.setString("(Walk Down)");
                        playAnimation(animator, "walkDown", event.key.code, animationText);
                }
                else if (keyMap.isActive("Left")) {
                        animationText.setString("Walk Left");
                        playAnimation(animator, "walkLeft", event.key.code, animationText);
                }
                else if (keyMap.isActive("Up")) {
                        animationText.setString("Walk Up");
                        playAnimation(animator, "walkUp", event.key.code, animationText);
                }
                else if (keyMap.isActive("Right")) {
                        animationText.setString("Walk Right");
                        playAnimation(animator, "walkRight", event.key.code, animationText);
                }
                else {
                        animator.stop();
                }
       
       
                // Update animator and apply current animation state to the sprite
                animator.update(frameClock.restart());
                animator.animate(sprite);

                // Draw everything
                window.clear(sf::Color(50, 50, 50));
                window.draw(animationText);
                window.draw(sprite);
                window.display();
        }
}

 


12
Graphics / VertexArray Isometric
« on: June 28, 2020, 12:54:20 am »
Hello,

I don't know why I can't find information on this anywhere. But using the example tutorial on displaying tiles with VertexArray (simple square) how would you set up an outline of an isometric tile? I have a nice looking square texture that I'd like to assign to an isometric outline. It should paste it on the isometric tile correct?

   
                 // define its 4 corners (from tutorial page) how to make a correct isometric tile
                quad[0].position = sf::Vector2f(i * tileSize.x, j * tileSize.y);
                quad[1].position = sf::Vector2f((i + 1) * tileSize.x, j * tileSize.y);
                quad[2].position = sf::Vector2f((i + 1) * tileSize.x, (j + 1) * tileSize.y);
                quad[3].position = sf::Vector2f(i * tileSize.x, (j + 1) * tileSize.y);
 

Also, at what point does using sf::VertexArray over sf::sprite really shows noticeable differences?

Thanks

13
General discussions / SFML GameDevelopment LoadingState
« on: May 31, 2020, 08:15:30 pm »
Hello,

So I just had some help on a super barebone example on a loading state using a thread. I'm reading SFML Game Development still and I've come to a halt to try to understand how they incorporate the loading state so that it is actually reading the files instead of the mock loading they do.

I could just do what I learned in my previous thread, but I'd like to learn how to incorporate it using the book's design. The loading state is called when you click "Play" from the main menu. I'm just trying to understand when and where I would pass the fonts/texture data into loading and where?

Any help would be greatly appreciated. Here is the basics of what it offers.

#include "ParallelTask.h"


ParallelTask::ParallelTask()
: m_thread(&ParallelTask::runTask, this)
, m_finished(false)
{
}

void ParallelTask::execute()
{
        m_finished = false;
        m_elapsedTime.restart();
        m_thread.launch();
}

bool ParallelTask::isFinished()
{
        sf::Lock lock(m_mutex);
        return m_finished;
}

float ParallelTask::getCompletion()
{
        sf::Lock lock(m_mutex);

        // 100% at 10 seconds of elapsed time
        return m_elapsedTime.getElapsedTime().asSeconds() / 10.f;
}

void ParallelTask::runTask()
{
        // Dummy task - stall 10 seconds
        bool ended = false;
        while (!ended)
        {
                sf::Lock lock(m_mutex); // Protect the clock
                if (m_elapsedTime.getElapsedTime().asSeconds() >= 10.f)
                        ended = true;
        }

        { // mFinished may be accessed from multiple threads, protect it
                sf::Lock lock(m_mutex);
                m_finished = true;
        }      
}

#include "LoadingState.h"
#include "Utils/Helpers.h"
#include"ResourceHolder.h"

#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/View.hpp>


LoadingState::LoadingState(StateStack& stack, Context context)
: State(stack, context)
{
        sf::RenderWindow& window = *getContext().window;
        sf::Font& font = context.fonts->get(Fonts::Sansation);
        sf::Vector2f viewSize = window.getView().getSize();

        m_loadingText.setFont(font);
        m_loadingText.setString("Loading Resources");
        Helpers::position::centerOrigin(m_loadingText);
        m_loadingText.setPosition(viewSize.x / 2.f, viewSize.y / 2.f + 50.f);

        m_progressBarBackground.setFillColor(sf::Color::White);
        m_progressBarBackground.setSize(sf::Vector2f(viewSize.x - 20, 10));
        m_progressBarBackground.setPosition(10, m_loadingText.getPosition().y + 40);

        m_progressBar.setFillColor(sf::Color(32,170,14));
        m_progressBar.setSize(sf::Vector2f(200, 10));
        m_progressBar.setPosition(10, m_loadingText.getPosition().y + 40);

        setCompletion(0.f);

        m_loadingTask.execute();
}


bool LoadingState::handleEvent(const sf::Event& event) {
        return true;
}

bool LoadingState::update(sf::Time) {
        // Update the progress bar from the remote task or finish it
        if (m_loadingTask.isFinished()) {
                requestStackPop();
                requestStackPush(States::Game);
        }
        else {
                setCompletion(m_loadingTask.getCompletion());
        }
        return true;
}

void LoadingState::draw()
{
        sf::RenderWindow& window = *getContext().window;

        window.setView(window.getDefaultView());

        window.draw(m_loadingText);
        window.draw(m_progressBarBackground);
        window.draw(m_progressBar);
}


void LoadingState::setCompletion(float percent)
{
        if (percent > 1.f) // clamp
                percent = 1.f;

        m_progressBar.setSize(sf::Vector2f(m_progressBarBackground.getSize().x * percent, m_progressBar.getSize().y));
}
 

The previous thread (as in my post) a fine gentleman helped me learned how to accomplish a loading screen like this (was a barebone main.cpp example)

THIS IS NOT PART OF THE BOOK CODE, BUT AN EXAMPLE BEFORE LOOKING AT BOOK CODE
// Still in main thread
std::vector<std::shared_ptr<Tile>> tilesVector;
tilesVector.reserve(Map_Height * Map_Width); // This creates the tiles with default constructor ( Tile() )

std::atomic<bool> done(false);

// Create thread to execute the bellow code while main thread continues normal execution
std::thread t([&done, &tilesVector] {
// Tile creation IS the heavy duty work
for(auto y = 0; y < Map_Height; ++y)
{
    for (auto x = 0; x < Map_Width; ++x)
    {
       Tile * tile = tilesVector[y * Map_Width + x].get(); // Get a pointer to tile to change its attributes
       tile->spr.setSize(TILE_SIZE);
       tile->spr.setFillColor({ 0,255,0,15 });
       tile->spr.setOutlineColor(sf::Color::White);
       tile->spr.setOutlineThickness(1.f);
       tile->spr.setPosition(x * TILE_SIZE.x, y * TILE_SIZE.y);
       tile->spr.setOrigin(TILE_SIZE.x / 2.f, TILE_SIZE.y / 2.f);

       if (y >= 240 && y <= 260 && x >= 240 && x <= 260)
       {
             tile->spr.setFillColor({ 200,25,22 });
       }
                               
       // tiles.emplace_back(std::move(tile)); This line no longer needed, we already have our tile vector
    }
}

// After building the tiles we set variable to true to signal that our work
// (tile creation) on this separate thread is done.
done = true;

});

Thank you, and have a nice day.

14
General discussions / sf::Thread (Loading Demo)
« on: May 21, 2020, 06:44:15 pm »
Hello,

So I'm messing with another concept, threads. I was trying to follow the SFML tutorial on threads, but it's not doing what I thought it would. I have no experience dealing with threads and just know roughly what Mutex and a Thread are.

I have this demo of a 500x500 tilemap of rectangles. And my original concept was finding ways to do tile culling. I solved, but I still get the white window until it loads everything up, then it runs perfectly. So I thought this would be a good time to try out threads and see if I can display a "Loading" sf::Text until it has gathered all the sprites up.

Also, I tried to use std::bind when initializing the thread, but it doesn't work because it is a deleted function. I'm using msvc19. But I got it to work with a lambda, but the results were the same. I put a comment giving the error when I try the std::bind and when I use the lambda. I

Quote
/*Failed to activate the window's context Failed to activate OpenGL context: The requested resource is in use.*/

So I'm assuming it obviously is trying to access data that's being used? ...Right ???? Any help would be appreciated, have a nice day!

#include <SFML/Graphics.hpp>
#include <iostream>
#include <functional>

sf::Vector2u WINDOW_SIZE{1400,900};
constexpr unsigned TPS = 60; //ticks per seconds
const sf::Time     timePerUpdate = sf::seconds(1.0f / float(TPS));
sf::Vector2f TILE_SIZE{64.f,64.f};

struct Tile
{
        sf::RectangleShape spr;
};


void loadingText(sf::RenderWindow& window, sf::Font& font, const std::string& text) {
        sf::Text loadText{ text,font,25 };
        loadText.setPosition((float)window.getSize().x / 2.f, (float)window.getSize().y / 2.f);
        loadText.setFillColor(sf::Color{ 88,225,0 });
        loadText.setOutlineThickness(1.f);
        loadText.setStyle(sf::Text::Style::Underlined | sf::Text::Style::Bold);
        window.draw(loadText);
}


int main() {
        sf::RenderWindow window{ sf::VideoMode{WINDOW_SIZE.x,WINDOW_SIZE.y},"" };
        //      window.setFramerateLimit(60);
        window.setPosition(sf::Vector2i{ window.getPosition().x,0 });

        bool lostFocus = false;
        sf::Clock clock;
        auto lastTime = sf::Time::Zero;
        auto lag = sf::Time::Zero;
        auto dt = 0.f;
        unsigned ticks = 0;
        auto view = window.getDefaultView();

        sf::Font font;
        if (!font.loadFromFile("fonts/arial.ttf"))
                std::cout << "Failed to load arial.ttf\n";


        sf::Thread thread([&]() {
                loadingText(window, font, "Loading");
                });
        /*Failed to activate the window's context Failed to activate OpenGL context: The requested resource is in use.*/
        thread.launch();

//***sf::Thread thread(std::bind(&loadingText, window, font, "Loading...")); *** (Doesn't Work)

/*Severity      Code    Description     Project File    Line    Suppression State
Error   C2280   'std::_Binder<std::_Unforced,void (__cdecl *)(sf::RenderWindow &,sf::Font &,
const std::string &),
sf::RenderWindow &,sf::Font &,
const char (&)[11]>::_Binder(const std::_Binder<std::_Unforced,void (__cdecl *)(sf::RenderWindow &,
sf::Font &,
const std::string &),
sf::RenderWindow &,sf::Font &,
const char (&)[11]> &)'
: attempting to reference a deleted function    E:\Libaries\SFML\include\SFML\System\Thread.inl 70
*/


        constexpr int Map_Width = 500;
        constexpr int Map_Height = 500;
        std::vector<Tile> tiles;

        sf::RectangleShape camera{ TILE_SIZE };
        camera.setFillColor({ 255,255,255,100 });
        camera.setOutlineThickness(1.f);
        camera.setOutlineColor(sf::Color::White);

        for(auto y = 0; y < Map_Height; ++y)
                for (auto x = 0; x < Map_Width; ++x) {

                        auto tile = new Tile;
                        tile->spr.setSize(TILE_SIZE);
                        tile->spr.setFillColor({ 0,255,0,15 });
                        tile->spr.setOutlineColor(sf::Color::White);
                        tile->spr.setOutlineThickness(1.f);
                        tile->spr.setPosition(x * TILE_SIZE.x, y * TILE_SIZE.y);

                        if (y >= 240 && y <= 260 && x >= 240 && y <= 260)
                                tile->spr.setFillColor({ 200,25,22 });

                        tiles.emplace_back(*tile);
                }

        view.setCenter(Map_Width / 2.f * TILE_SIZE.x, Map_Height / 2.f * TILE_SIZE.y);
        while (window.isOpen()) {

        auto time = clock.getElapsedTime();
        auto elapsed = time - lastTime;
        lastTime = time;
        lag += elapsed;

        //Fixed time update
        while (lag >= timePerUpdate)
        {
            ticks++;
            lag -= timePerUpdate;
            //x fixedUpdate(elapsed);
        }

                        sf::Event event{};
                        while (window.pollEvent(event)) {
                                if (event.type == sf::Event::Closed ||
                                    event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
                                        window.close();
                                if (event.type == sf::Event::KeyPressed) {
                                        switch (event.key.code) {
                                                case sf::Keyboard::Enter: std::cout << "Enter Pressed\n"; break;
                                                case sf::Keyboard::Space: std::cout << "Space Pressed\n"; break;
                                                default: break;
                                        }
                                }
                                if (event.type == sf::Event::Resized) {
                                        // update the view to the new size of the window
                                        view.setSize(static_cast<float>(event.size.width),
                                                           static_cast<float>(event.size.height));
                                }
                                if (event.type == sf::Event::LostFocus)     { lostFocus = true; }
                                if (event.type == sf::Event::GainedFocus) { lostFocus = false; }
                        }

                        if (!lostFocus) {
                                auto mousePos = sf::Mouse::getPosition(window);
                                auto mouseWorldPos = window.mapPixelToCoords(mousePos, view);

                                window.setTitle("Mouse Position: (" + std::to_string(int(mouseWorldPos.x / 64.f)) + ", " +
                                        std::to_string(int(mouseWorldPos.y / 64.f)) + ")");

                                if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
                                        if (mouseWorldPos.x >= 0 && mouseWorldPos.y >= 0 &&
                                                mouseWorldPos.x < WINDOW_SIZE.x &&
                                                mouseWorldPos.y < WINDOW_SIZE.y) {
                                        }
                                }

                                //! ** INPUT SECTION **
                                if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {
                                        view.move(0, -100 * elapsed.asSeconds());
                                }
                                if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {
                                        view.move( -100 * elapsed.asSeconds(),0);

                                }
                                if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {
                                        view.move(0, 100 * elapsed.asSeconds());

                                }
                                if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {
                                        view.move(100 * elapsed.asSeconds(), 0);

                                }

                                //! ** UPDATE SECTION**                
                                window.setView(view);
                        }

               
                        //! ** DRAW SECTION **
                        window.clear();

                        camera.setPosition(view.getCenter());

                        int cam_posX = camera.getPosition().x;
                        int cam_posY = camera.getPosition().y;
                        cam_posX /= TILE_SIZE.x;
                        cam_posY /= TILE_SIZE.y;
                        int minMaxWidth = 12;
                        int minMaxHeight = 12;

                        //std::cout << "Camera: " << camera.getPosition().x << ", " << camera.getPosition().y << "\n";
                        //std::cout << "View: " << view.getCenter().x << ", " << view.getCenter().y << "\n";
                        //std::cout << "posX: " << posX << "\n";
                        //std::cout << "posY: " << posY << "\n";
                        for (auto y = cam_posY - minMaxHeight < 0 ? 0 : cam_posY - minMaxHeight;
                                      y <= cam_posY + minMaxHeight && y < WINDOW_SIZE.y; y++) {
                                for (auto x = cam_posX - minMaxWidth < 0 ? 0 : cam_posX - minMaxWidth;
                                              x <= cam_posX + minMaxWidth && x < WINDOW_SIZE.x; x++) {
                                        window.draw(tiles[y * Map_Width + x].spr);
                                }
                        }
                        window.draw(camera);

                        window.setView(window.getDefaultView());               
                        window.display();
                }
       
        return EXIT_SUCCESS;
}




15
General / Rotating Tiles and keeping the player within Tile
« on: May 12, 2020, 12:51:31 am »
Hello,

This is just a concept I'm trying to understand, I got curious about :-X. I have basic sf::RectangleShape's in a Tile struct and just being displayed 50 by 50 with a 64x64 tile size. I have a 32x32 rectangle shape considered the player that you can move around with the WASD keys.

With Q and E I have a backward and forward rotation of all tiles by -5 and 5. How exactly could I maintain keeping the player within the same tile? So essentially, moving by the rotation of the tiles? I thought I could just grab the position of the tile the player is on and rotate him the same amount. But that doesn't seem to work.

Thanks

Pages: [1] 2
anything