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.


Messages - starkhorn

Pages: [1] 2 3 4
1
Graphics / Re: shape texture and fill Colour
« on: August 07, 2016, 11:41:39 pm »
ok thanks. I think I will just add the background colour I want via a layer in GIMP. :)

2
Graphics / shape texture and fill Colour
« on: August 04, 2016, 12:26:20 am »
Hi Folks,

So I setup a shape and put in a fill color. I then set a texture to the shape which has a transparent background. What I was expecting was that the fill color would remain as the background color of that shape and the texture would sit on top of the back ground color. However that doesn't seem to be correct?

However instead, the background is black as I am using the default window.clear().

Basically how can I set the background colour of a shape so it remains whilst having a texture (with a transparent background) applied. Also when I remove the setTexture statement, the fillColour is visible.

Here is a fully working example so should be possible to copy/paste.

class header file
#include <math.h>

using namespace std;


class hexgrid : public sf::Drawable
{
        public:
                hexgrid(sf::RenderWindow& window);
                ~hexgrid();

                void draw(sf::RenderTarget& target, sf::RenderStates states) const;

        private:
                std::vector<sf::CircleShape> hexaGrid;
                sf::Texture hexTexture;
};
 

class cpp file
#include "hexgrid.h"

hexgrid::hexgrid(sf::RenderWindow& window)
{
        sf::CircleShape hexagon;
        hexagon.setPointCount(6);
        hexagon.setRadius(40);
        hexagon.setFillColor(sf::Color(225, 247, 164));
        hexagon.setOutlineThickness(-1.5);
        hexagon.setOutlineColor(sf::Color::Black);
       
        if (!hexTexture.loadFromFile("E:\\downloads\\grassland.png"))
        {
                std::cout << "Failed to load hex texture image!" << std::endl;
        }

        hexagon.setTexture(&hexTexture);

        float xpos = 0, ypos = 0;
        hexagon.setPosition(xpos, ypos);
        hexaGrid.push_back(hexagon);
}

hexgrid::~hexgrid()
{

}

void hexgrid::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
        std::vector<sf::CircleShape>::const_iterator hexit;

        for (hexit = hexaGrid.begin(); hexit != hexaGrid.end(); ++hexit)
        {
                target.draw(*hexit, states);
        }
}
 

and my main

#include <iostream>
#include <SFML/Graphics.hpp>
#include "hexgrid.h"

int main()
{
        sf::ContextSettings settings;
        settings.antialiasingLevel = 8;

        sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Hexgrid Example", sf::Style::Default, settings);

        hexgrid grid(window);
               
        sf::Event e;
        bool running = true;
        while (running)
        {
                while (window.pollEvent(e))
                {
                        if (e.type == sf::Event::Closed)
                        {
                                window.close();
                                return 0;
                        }
                }
                window.clear();
                window.draw(grid);
                window.display();
               
        }
        return 0;
}
 

3
Graphics / Re: overlapping circle shapes
« on: July 29, 2016, 12:44:31 am »
Ok thanks Hapax, the Plinth lib works perfectly. I am currently stepping through the methods now to try to understand the CCW method.....as you can probably tell geometry was never my strong point. :)

Thanks again.

4
Graphics / Re: overlapping circle shapes
« on: July 28, 2016, 10:12:17 pm »
However, you don't need those points to calculate if a line crosses another.

Oh ok, I guess that is what I am trying to achieve then. I just assumed to implement ray casting algorithm that I would need to know the pixels of the edge of the polygon.

By the way, if you were using my Plinth library, this would be a lot simpler; it has functions for calculating if lines cross and for calculating if a point is inside a polygon ;)

Oh wow, ok - I obviously had no idea about this library. I will download and check it out.

5
Graphics / Re: overlapping circle shapes
« on: July 28, 2016, 02:28:11 am »
Are you splitting an edge into multiple points? You only need two points (which you can get from the circle) to define a line and you use this line to see if the testing line crosses that line.

No the edges are not split into multiple points. Yeah I am going through the output of sf::CircleShape->getPoint method to get points of the hexagon. (see below)

I get the points that are next to each other and work out the angle and distance between those two points.

My question/problem is I don't know how to get all of the x,y co-ordinates of the line/edge between those two points. So how can I determine the edge between those two points when I have the distance and angle?


bool hexgrid::isMouseWithinHexagon(sf::CircleShape *hexPtr, sf::Vector2f passed_mousePos)
{
    bool returnVal = true;
    sf::Vector2f point, nextPoint;
    const sf::Transform transformedVals = hexPtr->getTransform();
    float angle = 0;
   
    for (int i = 0; i < hexPtr->getPointCount(); i++)
    {
        point = transformedVals.transformPoint(hexPtr->getPoint(i));
       
        if (i + 1 < hexPtr->getPointCount())
        {
            nextPoint = transformedVals.transformPoint(hexPtr->getPoint(i + 1));
        }
        else
        {
            nextPoint = transformedVals.transformPoint(hexPtr->getPoint(0));
        }      
       
        angle = atan2(point.y - nextPoint.y, point.x - nextPoint.x);
        angle = (angle * 180) / PI;
    }

    return returnVal;
}

 

It might be worth considering specific hexagon detection algorithms. One of those being splitting the hexagon into triangles as they're pretty easy to test if a point is inside it.

Hmm ok, won't I have the same issue? how to determine the edge of the sf::CircleShape that has 3 points ?

Oh ok, I see what you mean, I guess I should have googled more before replying. :) So I will try to to do something like the below link to calc the area of the triangle?

http://www.geeksforgeeks.org/check-whether-a-given-point-lies-inside-a-triangle-or-not/

6
Graphics / Re: overlapping circle shapes
« on: July 28, 2016, 01:04:08 am »
Are you testing to see if a point is inside a circle, not a hexagon? Testing a circle is incredibly simple: test the distance between the point and the circle's centre - if that distance is greater than the circle's radius, it's outside.

I am trying to test if the point is inside a hexagon. So code from first post you see I have a sf::CircleShape defined with 6 points.

sf::CircleShape hexagon;
....
....
....
hexagon.setPointCount(6);
 

7
Graphics / Re: overlapping circle shapes
« on: July 28, 2016, 12:27:05 am »
Implement your own "point in hexagon" test. There are two common ways of finding if a point is inside a convex polygon, you should easily find them with Google ;)

Ok thanks. I see the easiest one is the ray casting algorithm, i.e. check how many times a straight line from that point intersects the polygon's edge.

And there is the first stumbling block that I hit, how can I determine the edges of a sf::Circleshape? I am assuming there is no getEdges method in sf::circleshape or even getAllPixels method? (I could not see anything in documentation).

I've gone through each point of the shape and worked out the angle between each connecting point as below.

However I am confused as to how I then determine all of the the points along the edge. Without being able to determine that then I do not see how I can implement a ray casting algorithm

bool hexgrid::isMouseWithinHexagon(sf::CircleShape *hexPtr, sf::Vector2f passed_mousePos)
{
        bool returnVal = true;
        sf::Vector2f point, nextPoint;
        const sf::Transform transformedVals = hexPtr->getTransform();
        float angle = 0;
       
        for (int i = 0; i < hexPtr->getPointCount(); i++)
        {
                point = transformedVals.transformPoint(hexPtr->getPoint(i));
               
                if (i + 1 < hexPtr->getPointCount())
                {
                        nextPoint = transformedVals.transformPoint(hexPtr->getPoint(i + 1));
                }
                else
                {
                        nextPoint = transformedVals.transformPoint(hexPtr->getPoint(0));
                }              
               
                angle = atan2(point.y - nextPoint.y, point.x - nextPoint.x);
                angle = (angle * 180) / PI;    
        }

        return returnVal;
}
 

8
Graphics / [SOLVED] overlapping circle shapes
« on: July 14, 2016, 05:15:46 am »
Hi Folks,

I am trying to setup a hexGrid type game and I am currently playing with different ways to do it.
Right now I got a simple class which has a sf::CircleShape that has 6 points to make it a Hexagon. I also have a vector of the sf::CircleShape for the grid.

Now I got the grid drawing fine and I am now trying to detect the hex that the mouse is in. I've written a simple method that is called each time the mouse is moved. It basically checks the globalBounds of each sf::Circleshape to see if the mouse position is contained within that circleShape. If yes then it changes the fillColour of the sf::Circleshape.

Now this is working ok, except when the mouse is hovering near the edge of some grids, then both get highlighted white, i.e. the mouse is within both circleshapes.

Is this because there is a bounding box around the sf::CircleShape which is larger that the displayed shape? Is there a way to resolve this?

I have put down a full working example that should be able to be compile and run on it's own.

hexGrid.h
#ifndef HEXGRID_HPP
#define HEXGRID_HPP

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

using namespace std;

class hexgrid : public sf::Drawable
{
        public:
                hexgrid(sf::RenderWindow& window);
                ~hexgrid();

                void draw(sf::RenderTarget& target, sf::RenderStates states) const;

                bool chkHexGridWithMousePos(sf::Vector2f passed_mousePos);
                bool isMouseContainsHexagaon(sf::CircleShape *hexPtr, sf::Vector2f passed_mousePos);

                enum hexStyle
                {
                        translucent,
                        colorful,
                        green,
                        cyan
                };

        private:
                sf::CircleShape hexagon;
                std::vector<sf::CircleShape> hexaGrid;
};


#endif // HEXGRID_HPP
 

hexGrid.cpp
#include "hexgrid.h"

hexgrid::hexgrid(sf::RenderWindow& window)
{
        //set up background elements
        hexagon.setRadius(window.getSize().x / 16.f);
        hexagon.setPointCount(6);
        hexagon.setFillColor(sf::Color(150, 50, 250));
        hexagon.setOutlineThickness(2);
        hexagon.setOutlineColor(sf::Color(250, 150, 100));
        hexagon.setOrigin(hexagon.getGlobalBounds().width / 2.f, hexagon.getGlobalBounds().height / 2.f);

        std::vector<sf::ConvexShape>::iterator hexit;
        float xpos = 0, ypos = 0;

        for (int y = 0; y < 12; y++)
        {
                if (y == 0)
                {
                        ypos = y * hexagon.getGlobalBounds().height;
                }
                else
                {
                        ypos = ypos + (hexagon.getGlobalBounds().height - (hexagon.getGlobalBounds().height * 0.25f));
                }

                for (int x = 0; x < 12; x++)
                {
                        if (y % 2 == 0)
                        {
                                xpos = x * hexagon.getGlobalBounds().width;
                        }
                        else
                        {
                                xpos = (x * hexagon.getGlobalBounds().width) + (hexagon.getGlobalBounds().width * 0.5f);
                        }
                        hexagon.setPosition(xpos, ypos);
                        hexaGrid.push_back(hexagon);
                }
        }
}

hexgrid::~hexgrid()
{

}

void hexgrid::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
        std::vector<sf::CircleShape>::const_iterator hexit;
        for (hexit = hexaGrid.begin(); hexit != hexaGrid.end(); ++hexit)
        {
                target.draw(*hexit, states);
        }
}

bool hexgrid::chkHexGridWithMousePos(sf::Vector2f passed_mousePos)
{
        bool returnVal = false;
       
        for (int i = 0; i < hexaGrid.size(); i++)
        {
                if (isMouseContainsHexagaon(&hexaGrid[i], passed_mousePos))
                {
                        returnVal = true;
                }
        }

        return returnVal;
}

bool hexgrid::isMouseContainsHexagaon(sf::CircleShape *hexPtr, sf::Vector2f passed_mousePos)
{
        if (hexPtr->getGlobalBounds().contains(passed_mousePos))
        {
                hexPtr->setFillColor(sf::Color(255, 255, 255));
                return true;
        }
        else
        {
                hexPtr->setFillColor(sf::Color(150, 50, 250));
                return false;
        }
}
 

main
#include <iostream>
#include <SFML/Graphics.hpp>
#include "hexgrid.h"

int main()
{
        sf::ContextSettings settings;
        settings.antialiasingLevel = 8;

        sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Hexgrid Example", sf::Style::Default, settings);

        hexgrid grid(window);
               
        sf::Event e;
        bool running = true;
        while (running)
        {
                while (window.pollEvent(e))
                {
                        if (e.type == sf::Event::Closed)
                        {
                                window.close();
                                return 0;
                        }

                        if (e.type == sf::Event::MouseMoved)
                        {
                               
                                grid.chkHexGridWithMousePos(sf::Vector2f(e.mouseMove.x, e.mouseMove.y));
                        }
                }
                window.clear();
                window.draw(grid);
                window.display();
               
        }
        return 0;
}
 

9
Graphics / Re: Doing a drag and drop method
« on: June 15, 2016, 11:02:29 pm »
Is the sleep there to ensure that the button is held rather than just clicked?

Yes that is exactly why the sleep is there. Basically if the left pressed event is triggered then I want to know if the user is still holding the left button. If I don't have that sleep in there then it takes left clicks as dragging attempts and moves the sprite when I just trying to left-click on the sprite.

I don't think I fully understand the timing method that you are describing. Are you able to clarify how the timer would work?

I did make an attempt as below, but it always seemed to be saying the user was dragging, even during a left-click.

So in my class I defined a gameClock

sf::Clock gameClock;
 

Then at the beginning of the event loop, I have this to check if the left button is pressed and if the gameclock elapsed time is > 100 milliseconds. If not then restart the game clock

                        if (sf::Mouse::isButtonPressed(sf::Mouse::Left) && gameClock.getElapsedTime().asMilliseconds() >= 100)
                        {
                                cout << "gameClock.getElapsedTime().asMilliseconds() = " << gameClock.getElapsedTime().asMilliseconds() << "\n";
                                cout << "setting isdragging to true\n";
                                isDragging = true;
                        }
                        else
                        {
                                gameClock.restart();
                        }
 

Now I am not entirely sure if this what you meant as to having a timer?

Then in my events I have more or less the same thing, except no sleep or isButton pressed check anymore.

                        if (event.type == sf::Event::MouseButtonPressed)
                        {
                                //if left button pressed
                                if (event.mouseButton.button == sf::Mouse::Left)
                                {
                                        cout << "left pressed \n";
                                        if (isDragging)
                                        {
                                                //Here I check if mouse was within the bounds of the sprite and if so then do the dragging updates.
                                        }
                                        else if (!isDragging)
                                        {
                                                //Do the stuff I want to do when user is not trying to do a drag and drop
                                        }
                                }
                        }
 

10
Graphics / Doing a drag and drop method
« on: June 14, 2016, 11:28:02 pm »
Hi Folks,

I am trying to implement method that can detect whether a user is holding down the left mouse button, thus indicating that the user is dragging a sprite.

In my event loop, I have this - note some is pseudo code. Basically I am sleeping the program for 100 milliseconds after the a sf::Mouse::Left event is detected. If the mouse is still pressed then I say the user is attempt to drag an icon.

I cannot assume that just having a sf::Mouse::Left indicates that the user is dragging an icon as he could just be left clicking the sprite to select it. If I did then it starts dragging/dropping icons when the user is just trying to select them.

It just seems a bit of an inefficient way to detect whether a user is dragging by adding a sleep. Is there a more efficient method to implement drag/drop, whilst at the same time support left clicking


                        if (event.type == sf::Event::MouseButtonPressed)
                        {
                                //if left button pressed
                                if (event.mouseButton.button == sf::Mouse::Left)
                                {
                                        cout << "left pressed \n";
                                        sf::sleep(sf::milliseconds(100));
                                        if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
                                        {
                                                isDragging = true;
                                                cout << "left pressed and isDragging \n";
                                               
                                                //Here I check if mouse was within the bounds of the sprite and do what I need to do
                                        }
                                }
                        }

 

11
Audio / Re: Sounds stop playing too early when using std::vector
« on: June 13, 2016, 02:48:54 am »
Ok so I tried changing from a std::vector to a std::queue and this seems to have resolved the issue.

So my remove method is now

void soundsList::removeStoppedSounds()
{
        for (int i = 0; i < soundVtr.size(); i++)
        {
                if (!isSoundPlaying(&soundVtr.front()))
                {
                        //soundVtr.erase(soundVtr.begin() + i);
                        soundVtr.pop();
                        cout << "erased sound at front of queue " << i << "\n";
                        //i--;
                }
        }
}
 

I am assuming std::vector is doing something different when doing a erase than when a std::queue is doing a pop?

12
Audio / Sounds stop playing too early when using std::vector
« on: June 13, 2016, 02:35:53 am »
Hi Folks,

So I am using sf::Sound for the first time and I am having a bit of trouble where sounds seem to stop playing before the entire wav file has finished playing.

What I have is:

- A std::vector of sf::Sound in my private section of my class.

vector<sf::Sound> soundVtr;
 

- When I play a sound I simply push_back a new sf::Sound to this std::vector

soundVtr.push_back(sf::Sound(*passed_SoundBuffer));
 

- During each game tick/loop, I call the below removeStoppedSounds() which goes through the std::vector of the sf::Sounds to check the status. If the status is sf::SoundSource::Stopped

However as stated, when I call the removeStoppedSounds() during the gameloop, I find that sounds don't finish, i.e. a 2 second wav file gets stopped withing a few milliseconds.

If I comment out the call to removeStoppedSounds() then it plays until the end. So I am assuming this method is something removing the sf::Sound before it can be played until the end of the wav file.

So is this something to do with using std::vector? If yes, then how I can store sf::sounds so that they can be played until the end of the wav file?

Or something to do with sf::Sound::getStatus()?

bool soundsList::isSoundPlaying(sf::Sound *passed_Sound)
{
        if (passed_Sound->getStatus() == sf::SoundSource::Stopped)
        {
                //cout << "stopped playing\n";
                return false;
        }
        else
        {
                cout << "still playing\n";
                return true;
        }
}


void soundsList::removeStoppedSounds()
{
        for (int i = 0; i < soundVtr.size(); i++)
        {
                if (!isSoundPlaying(&soundVtr[i]))
                {
                        soundVtr.erase(soundVtr.begin() + i);
                        cout << "erased sound at index " << i << "\n";
                        //i--;
                }
        }
}
 

13
Graphics / Re: update texture from a sf::image
« on: April 21, 2016, 10:38:37 pm »
What exactly are you doing with the sf::Image? Do you really have to go the slow way via sf::Image? Can't it be done with an sf::RenderTexture or a shader?

So as per the below thread, I have a map of europe where each region has a unique RGB value. That way when a user click on a pixel, I can check the colour of the SF::Image to determine exactly which region he has clicked on.

http://en.sfml-dev.org/forums/index.php?topic=19942.msg143704#msg143704

Now what I am also trying to add, is that when a user clicks on a region, the pixels that the user clicked on and the neighbouring regions pixels are all highlighted. (The idea being to show the user what regions he/she can move their army).

So I use the setImagePixelColour method that I put in my first post to do that - I'm unsure if there are faster ways to achieve the same effect? I have zero experience of shaders so I've honestly no idea if this can be
done via a shader - sorry.

As side note: Use references and not pointers to pass around objects (see my code above).

Oh ok, sry I'm going to go off tangent a little but is there is a reason? Sorry I am still new to programming in general so learning as I go. I googled and found some interesting answers but is there a reason specific to SFML that I should know about?

14
Graphics / update texture from a sf::image
« on: April 21, 2016, 03:37:41 am »
Hi Folks,

So I have a sf::Image that I update. The image is quite large 5680 X 4178, so when I update the sf::Image, I ensure to pass in the sf::IntRect of the area that I am working on - see below. This works fine for my needs and it is pretty fast to update the IntRect area. (0.047 secs).

//set Pixel colour for all pixels in regionIntRect that match colourToCheck
void drawEngine::setImagePixelColour(sf::Image *passed_Image, sf::Color colourToCheck, sf::Color colourToSet, sf::IntRect regionIntRect)
{
        for (int y = regionIntRect.top; y < (regionIntRect.height + regionIntRect.top); y++)
        {
                for (int x = regionIntRect.left; x < (regionIntRect.width + regionIntRect.left); x++)
                {
                        if (passed_Image->getPixel(x, y) == colourToCheck)
                        {
                                passed_Image->setPixel(x, y, colourToSet);
                        }
                }
        }
}
 

However I am finding that update texture command is a bit slower. (0.27 secs) to run the below. Now I know the sf::Texture update method is having to load into the graphics memory so it will always be slower.

(regionLandHighlightTexture is the sf::Texture and landHighlightImageToDisplay is the sf::Image that I modified via the above method.)

regionLandHighlightTexture.update(landHighlightImageToDisplay);
 

Now I know the sf::Texture update method is having to load into the graphics memory so it will always be slower. I was wondering if there was a way to make to the update faster.

Basically I know the area of the texture that needs updating from the IntRect that I modified. However when I check the update methods, I don't see one where I can pass in an IntRect, i.e. only update this portion. I do see this method which is very similiar.

(What does "x   X offset in the texture where to copy the source image" mean in regards to this method?)

void    update (const Uint8 *pixels, unsigned int width, unsigned int height, unsigned int x, unsigned int y)

However I don't understand how I can get an array of pixels from my sf::Image using the sf::IntRect that I modified. I don't see any method that can pull out an array of pixels using sf::IntRect as part of the sf::Image class. I do see the below method but I don't really understand what it is doing. It seems to be pulling out the entire sf::Image pixel array? Whereas I only want a small portion of the sf::Image pixel array.

const Uint8 *    getPixelsPtr () const

15
Graphics / Re: Highlight sprite when selected
« on: April 14, 2016, 03:24:26 am »
Hi Folks,

Yeah ok doing a 2nd image with the outline is fairly straight-forward. However that is just a static image. How can I make that outline image appearing like it is flashing?

Pages: [1] 2 3 4