Thursday, February 27, 2014

Project Aurora, post 6, (Blog Assignment 3) Light / Fog of war around the player

So the feature I have been working on this week is the light effect for our light bulb/Fishing rod that light up an area around the player.

This was something I never done before so first I broke down the problem to the basics.
I need a black filter to make everything on screen black and I need to be able to cut through it somehow to show what's under it.

So I draw out the filter as a sprite that covers the whole screen, Done!
Then I read up on SFML to see if there was some information there abouthow to cut through other sprites and I found some people with similar problems and they had solved it in many different ways. One guy had a flashlight solution that seemed simple enough so I went ahead with trying to implement some of what he done into our game.  The reason I went with his example is because it was fairly easy to understand and wouldn't take a lot of time to code.

He used something called sf::RenderTexture. With it you can "draw" stuff without showing it on the screen. like a secret drawing. If you give that drawn stuff to a sprite you can then draw the sprite out on screen using our normal DrawManager..

So first I need a circle that will be the ring of light that cuts through the darkness.
I don't want a clear cut. I want you to see most in the middle and then it gets darker towards the edges of the circle. So when I created the circle I draw it out on another of these sf::RenderTextures one circle after another, each new circle smaller and with different Alpha value than the previous circle. With this way I created the layered circle I wanted.

I then draw this layered circle on to the drawing / sf::RenderTexture that holds the black filter. After that the black filter sprite gets that sf::RenderTexture/secret drawing loaded into it and is then drawn out on the window.

GetFilterTexture()->clear();
if(p_GameObjMgr->m_pxPlayer->GetLightSource()->GetLightStatus() == true )
{
GetFilterTexture()->draw(*p_GameObjMgr->m_pxPlayer->GetLightSource()->GetLightCircle(), sf::BlendNone );
}
GetFilterTexture()->display();

In this code example I clear my secret drawing. draw out my layered circle and the "save" that.
The "GetFilterTexture()->display();"  don't draw it out on screen but only draw it out on the texture surface.
See it as saving your picture or something. Drawing it out on the screeen is done later in the code.


As you can see on the screenshot the other fish has a light around them as well. That's only for testing at the moment and work in progress, I want to be able to merge two light circles if they overlap for other game features that will let us light up some areas of the game world.

This feature was easy enough to understand but I bumped into so many problems adapting this code into our game due to much code we have is hard coded with numeric limits. And with that there was a problem when moving around on the screen because the world limits was hard coded this way and so was some starting positions and sizes of the player and whatnot. The black filter was the easiest to add to the game but the hardest to understand( because of how the camera is handled).

The black filter can be made really big to cover the whole world or just follow the camera. I chose the solution making it big as the screen and follow the camera because that's more dynamic and can be used if the game world is made bigger or smaller. With my solution we don't have to resize the filter all the time. It does that automatic after the screen resolution.
Since all the problems I had was because of the camera and how moving around works in our game I will cover that in another post about the camera and not go deeper into those problems here.


2 comments:

  1. Hello Georgios!

    I am confused by the sf::RenderTexture and what you call ”a secret drawing”. Is it just a normal texture that is set to a sprite, or is it something that can lower the opacity of another texture? I am especially confused by the sixth paragraph, as you seem to call the black filter a drawing and then you speak of the secret drawing, but both are of the sf::RenderTexture type. Is the black filter sprite the secret drawing?

    You could also explain why you draw the circles on the texture surface and what the texture surface is. Also, why you choose to draw the circles out on the screen later in the code and not where you draw them in the texture surface. Both the texture surface and what you later write in the post, that your code is ‘hard coded’, are both things that could be explained if you want readers that do not know much about programming to understand.

    When code is given as an example in a post it could be presented in a picture instead, so that it is different from the other text and stands out. Otherwise, you could simply describe the code without showing it, as it would make the reading easier.

    The filter could be dynamic when covering the play area. If your play area got its size from a .txt file and the black filter got its size from the same file, it would be easy to modify. Also, this would give you the possibility to hide all the objects which are not inside of the visible light, allowing you to only draw the ones that are inside the visible light and just update the ones that are hidden. This could save some performance for your project.

    Good luck!
    Nicolina

    P.S. I really like the structure in your latest blog post, I understand it all very well!

    ReplyDelete
  2. Thanks for your reply.
    A RenderTexure is like a combination of a RenderWindow and a Texture. So instead of drawing something to the window you draw it to the RenderTexture and then a sprite can get the content of the RenderTexture like it does from a normal Texture. This way I can manipulate the RenderTexture every iteration of the game loop without showing it to anyone. Something that happens in the background....thats what I mean by my secret drawing. So first I draw many circles with different opacity every iteration to create the gradient using a RenderTexture. I save that to a circle shape instead of a sprite. So then in I draw this circle shape with opacity to the RenderTexture that only have a black background to give the effect that you see whats under the black texture and then give that to a sprite that sprite is what I use to draw out everything from the RenderTexture to the RenderWindow in the main game loop. make sense? hard to explain this stuff.

    I have been thinking of adding a black filter to the whole game world like you mention but I'm not sure how that will work with the RenderTexture. I might adjust this little bit this week.
    I also usually show code example with a picture but I got lazy this time. I will do it the following times though :-)

    Thanks for your input. I liked it. feel free to comment even when it's not an assignment.

    ReplyDelete