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

Pages: [1] 2 3 ... 12
1
SFML projects / [Steam Release] Open Hexagon
« on: July 18, 2020, 02:11:30 am »
Hello folks!

I've recently released my first complete game (powered by SFML) on Steam, Open Hexagon:
https://store.steampowered.com/app/1358090/Open_Hexagon/

Quote
Open Hexagon is a fast-paced and adrenaline-inducing paced arcade experience by Vittorio Romeo. Designed for moddability and custom level creation.

https://www.youtube.com/watch?v=TlSJZlQrVJ4

While it might look like just a clone of Super Hexagon on the surface, it is far from that. Other than brand new gameplay features such as a 180° swap and curving walls, Open Hexagon was completely designed with modding and customization in mind.

Users can create custom levels using Lua scripts, and I have seen some fans creating some absolutely mind-blowing levels that push the engine to its boundaries. I've also had fans thank me for getting them into programming, and that has been an amazing feeling.

The history of this game is quite interesting. It started as a clone of Super Hexagon about 7 years ago, and it was one of my first C++ projects. Over time it developed a community of fans who started creating amazing custom levels, and enjoyed competing with each other for the highest scores. I've worked on the game for a few years in the past, adding features that distinguish it from the original, and making it more and more unique.

After a long hiatus, I've returned to the community and I have started working on Open Hexagon again. The last few months' efforts resulted in a Steam release, with many improvements and new features.

Despite the Steam release, Open Hexagon is still available for free as open-source (and always will be): https://github.com/SuperV1234/SSVOpenHexagon/

Hope you enjoy the game, and let me know if you have any question! ❤️

2
Great talk. Thank you.

Interestingly I have an ECS implementation which is very close to yours and was developed completely independently [1]. Same emphasis on compile time configuration (C++1y FTW). The bitset with tags at the end, the components meta list and the concept of signature, everything is here. For that latter I don't request the user to declare his signatures prior using them (I use Eric Niebler's tiny meta library). Yet we both pass lambda with expanding auto& arguments matching the components. Awesome.

My tuple of vectors of components data are "compressed". Random access requires an extra level of indirection through a lookup table (handle ID+counter). Initially I thought it was a good idea which allowed me to loop through valid components data without encountering "holes" but it prevents me from looping over more than one vector at the same time because indexes don't necessarily belong to the same entity (compression might reorder slots in one vector but not the others).

Also I should definitely use std::get<T> rather than std::get<size_t> for tuple element access. It simplify things greatly ;)

[1] I'm by no mean a game developer but got interested in ECS after reading stuff about DOD. I don't remember having watched your video but I for sure read lots of articles on the net. The compile-time approach (meta list of components) without some kind of static counters or typeid doesn't seem common at all.

Thanks for the feedback, glad you enjoyed the talk!

It's really cool to see that someone else had a similar idea - I think heavily using compile-time computation to define ECS architectures is valuable and I'll continue to explore it further in the future.

There is another C++14 developer who built something interesting as well:
http://maikklein.github.io/2016/01/14/Entity-Component-System/

Is your implementation available online? If not, consider putting it on GitHub - I would be happy to see it and learn from it.

3
Sounds very interesting and I will definitely watch full video later, but the first thing I've noticed while looking at the source code on github is that it is barely readable. 1k+ line of source code in file p7.cpp, not to mention a lot of files in Other folder with nonintuitive structure and contents. It would be much better to have separate file (possibly with header/source separation) for each class and without any other files that just include other files without having any additional code in them.

All the code segments were written for the talk - they're supposed to be shown one after another, explaining the additions/removals/changes from the previous code segment. They were made with the idea of a "step-by-step" live talk in mind, so I understand that they might not be well suited to reading. Sorry about that!

Regarding the code in the "Other/" folder - that's code that has been included mostly to get utility functions out of it. There's also an outdated ECS library prototypical implementation - my intention was to show some of the ideas present in the library but not in the live code segments if I had enough time during my session... but I actually ran out of time  :-\

So, yeah, the material was created with the live talk in mind.
However, if you'd appreciate me to explain anything regarding the code or the talk, don't hesitate to ask :)

4
Hello SFML community.

Like last year, I attended the truly excellent CppCon 2015 conference (Bellevue, WA) and presented two talks.

The video of my first talk, which is heavily oriented towards game development, is now available on the conference’s official YouTube channel:

http://www.youtube.com/watch?v=NTWSeQtHZ9M

The talk shows the audience how to write a simple yet powerful C++14 component-based entity system, from scratch.

I use SFML for window/input management and to render simple 2D graphics.

Modern C++ features and idioms are used.
I’ve tried to make the implementation as cache-friendly and data-oriented as possible while maintaining a reasonable level of simplicity.

It is not an AAA framework, but I think I’ve managed to write a small powerful system that shows the benefits and ideas behind a data-oriented ECS.

Choices I’ve made:

  • Components are logic-less. (They are simple structs.)
  • Entities are implicit. (The Entity class is just an ID with some metadata.)
  • Components are stored in separate, contiguous arrays. (Every component type has its own array.)
  • Systems are implicit. (Entities are matched using “signatures”.)
  • Entity metadata is sorted in memory for efficient iteration. Component data is not sorted or “compressed”. (Think about the storage as a relational table, where the columns are the entities and the rows are the component types.)

There are many open-ended questions and possible improvements of this implementation - my goal was showing people how beneficial and convenient a more data-oriented and component-based approach is, and how C++14 makes coding such a system extremely satisfying (thanks to its modern features and cost-free abstractions.)

I’m very open to feedback and would love to hear what you think.
Hope you find the video interesting!

You can find all the material (slides and code) on my GitHub repository:
https://github.com/SuperV1234/cppcon2015

5
I don't really understand what the purpose of those texture and layer handles is.

According to the comments "Textures must be bound in advance for maximum performance. (No associative lookups!)". Why is this necessary? You end up passing the texture reference to .draw() as a sf::RenderState anyway, so you might as well let the user simply construct the texture themselves and just pass it on to SFML when the time comes. This also doesn't require any associative lookups.

Also, why do we need handles for layers? All layers are meant to do is specify an order in which the buckets of draw calls are actually dispatched. Simply storing a numerical value would suffice if you ask me.

The design of this sprite batch allows it to be quickly integrated in projects using `sf::Sprite` without any batching.

Whenever you bind a texture to the batch manager, you get an unique integer (starting from 0) identifying that texture.

Whenever you create a layer in the batch manager, the layer automatically creates contiguous data structures (`std::vector` instances, for now) for every bound texture.

When you want to draw a Batch::Sprite on a specific layer, having the sprite know the ID of the texture it has and the ID of the layer it needs to be drawn onto results in some contiguous memory direct access lookups and 4 `sf::Vertex` emplacements.

The user can simply store a Batch::Sprite instance in its game entity class (or replace `sf::Sprite` instances), and can fire-and-forget multiple Batch::Sprite draw calls - the batch manager, thanks to the unique IDs of textures and layers, will deal with minimizing draw calls.

The code for the sprite batch is here (still very primitive), but I hope it clarifies the idea:
https://github.com/SuperV1234/Experiments/blob/master/Random/batching.cpp

When you call `Batch::Sprite::draw()` you're just asking the manager to "enqueue" the sprite in the right layer, in the right vertices container for its texture.



As stated above, I don't think they are even necessary. Just let the user use their own sf::Textures as usual and specify numerical values instead of layer handles.

The user manages the lifetime of their own `sf::Textures`. Binding them to the Batch::Manager is pure convenience - having an handle object that refers to that texture that can be used in Batch::Sprites allows the user to not having to specify the wanted texture during the draw call.

I'm trying to make the system as easy as possible to substitute to existing `sf::Sprite`-based code.

The idea behind layers is that the user does not care about the drawing order of sprites in the same layer - but that may not be realistic.
One thing I'm considering to add, is another layer type, where instead of having separate buffers for every texture, there is an unique buffer where vertices are sorted inside the same buffer by an user-specified Z-order.

If the user requires more fine-tuning with it's Z-order, that type of layer can be used, but it will definitely result in more draw calls.



Better batching.

In terms of OpenGL draw calls, yes, they do get reduced, but only in optimal scenarios. Since you don't re-order the sprites in order to minimize state changes, a user specifying their sprites in a really disadvantageous way will not benefit at all from your batching. In fact, it will even add additional overhead in that case.

Where your batcher does save time is within the sf::RenderTarget methods. When batching does work, less time is spent in there and potentially on the GPU since you pre-transform vertices (this leads to more optimistic paths being taken when the GPU realizes it doesn't have to do anything). However, in exchange for reducing the time spent in those locations, we need to consider the extra time that will be spent in your batcher. From your example, it seems like it will scale linearly with the number of sprites that you actually intend to draw with it since you seem to have to reconstruct the draw queue again every frame. I just don't see the advantage your class is supposed to provide over "manual batching" via sf::VertexArray.

Have you run any performance tests using your batcher? Where does it save time? On the GPU, in the driver or in the application?

The current state of the batcher is a start, but there is still much more to do in order to be useful in real world scenarios if you ask me. When writing my own batchers (similar to how I designed the SFGUI renderers) I like to measure the amount of draw calls that are actually issued to OpenGL in total every frame. I estimate that for a typical 2D SFML application that doesn't make too much use of shaders, it can easily be dropped below 10 in total per frame. This of course requires more advanced techniques such as texture atlasing, but that is what a batcher is there for...

Having only minimally used OpenGL without SFML, I do not really have a lot of experience/knowledge on the subject. Maybe I'm approaching this in the wrong way...

You're correct when you say that "it will scale linearly with the number of sprites". I am re-creating the draw queue every frame.

But I was under the impression that calling `sf::Sprite::draw()` does actually execute an OpenGL draw call.

Drawing 10000 `sf::Sprite` instances with the same texture would result in 10000 OpenGL draw calls.
Drawing 10000 `Batch::Sprite` instances with the same texture would result in a single OpenGL draw call.

The advantage of my system, over `sf::VertexArray`, is pure convenience - binding textures and layers to the manager, and having `Batch::Sprite` instances store their texture ID and layer ID, allows the user to "think in terms of `sf::Sprite`" and still get some performance benefits from automatic batching.

6
General discussions / Simple SpriteBatch desired interface/features
« on: June 03, 2015, 03:48:22 pm »
I'm working on a simple SpriteBatch class with the goal of automatically reducing the number of draw calls.

It currently supports layering and texture binding.
The interface looks like this, so far:

// ...load some textures and store them somewhere,
// then create some const references to them.
const auto& txApple(someAssetManager.get(...));
const auto& txBanana(someAssetManager.get(...));
const auto& txOrange(someAssetManager.get(...));
const auto& txSky(someAssetManager.get(...));



// Create a batch sprite manager.
// This would ideally go in your `Game` class or
// in your rendering system instance.
Batch::Manager bm;



// Bind the textures to the batch manager.
// Textures must be bound in advance for maximum
// performance. (No associative lookups!)
// Binding returns an handle-like object.
auto bthApple(bm.bind(txApple));
auto bthBanana(bm.bind(txBanana));
auto bthOrange(bm.bind(txOrange));
auto bthSky(bm.bind(txOrange));



// Create some layers to manage Z-ordering.
// Layer creation returns handle-like objects.
auto btlBackground(bm.createLayer(0));
auto btlForeground(bm.createLayer(1));



// To draw stuff, use `Batch::Sprite` instances.
// They have a similar interface to `sf::Sprite`,
// but require a layer handle and a texture handle.
std::vector<Batch::Sprite> sprites;

for(auto i(0u); i < 10000; ++i)
{
    // Make 10000 apple sprites.
    sprites.emplace_back(btlForeground, txApple);

    // Make 10000 banana sprites.
    sprites.emplace_back(btlForeground, txBanana);

    // Make 10000 orange sprites.
    sprites.emplace_back(btlForeground, txOrange);
}

// Make 1 sky sprite, in the background layer.
sprites.emplace_back(btlBackground, txSky);



// In the game loop, you need to clear, fill and
// render the batch manager.
while(true)
{
    // ...stuff...

    bm.clear();
    for(const auto& s : sprites) bm.enqueue(s);
    bm.drawOn(someRenderTarget);

    // ...stuff...
}

// The `bm.drawOn(someRenderTarget);` call
// will result in 4 draw calls, implemented with
// 4 different vertices arrays.

  • Could the API/interface be improved?
  • Is layering sufficient for Z-ordering needs?
  • Is the ownership model of textures/layers fine?
  • What other features would you expect from a sprite batch?

7
I've published two new video tutorials on my YouTube channel.
The videos introduce a new series: "Dive into C++14".

Like the previous series, dedicated to the C++11 standard, "Dive into C++14" will show the convenience and power of the latest standard (C++14) through videos regarding various topics.

The format of the videos is what makes "Dive into C++11" and "Dive into C++14" different from other tutorials: well-commented and well-formatted independently compilable chronologically sequential code segments will show the audience the thought process behind writing modern C++14 code.

The first two videos are not really related to game development, but I find myself using the features/patterns described in them a lot for my game projects, so I hope they're not out-of-scope for the SFML forum.



* Dive into C++14 - [1] - Introduction to C++14 core language features

http://www.youtube.com/watch?v=WZYKzCsACiw

The first video is a brief introduction to some of my favorite new C++14 core language features.
It covers the following topics, using code examples:
    * Function return type deduction.
    * `decltype(auto)`.
    * Relaxed constexpr restrictions.
    * Variable templates.
    * Generic lambdas.

   The target audience is newcomers to the C++14 standard who already have some experience with C++11.



* Dive into C++14 - [2] - `for_each_argument` explained and expanded

http://www.youtube.com/watch?v=Za92Tz_g0zQ

The second video covers a very interesting code snippet originally posted on Twitter by Sean Parent: `for_each_argument`.
It shows and explains the usage of C++14 compile-time integer sequences, and analyzes a very interesting iterative implementation of an alternative version of Sean's function that takes the desired arity as a template parameter.

This tutorial video is a reviewed and improved version of my C++Now 2015 lightning talk ("`for_each_arg` explained and expanded").

Some possible use cases for the implemented functions are also shown and analyzed:
    * `make_vector(...)`
    * `forTuple` - iteration over tuple elements
    * `make_unordered_map(...)`

The target audience is people with knowledge of C++11 features and some C++14 experience.



I greatly appreciate comments and criticism, and ideas for future videos/tutorials.

Feel free to fork/analyze/improve the source code at:
https://github.com/SuperV1234/Tutorials

You can find previous episodes here:
https://www.youtube.com/playlist?list=PLTEcWGdSiQenl4YRPvSqW7UPC6SiGNN7e

8
Hi Vittorio,
thanks for the videos. Really enjoying folloing them  ;)

Thank you!



Update: I've finished writing the source code for part 4 of the tutorial.
Since I'll be busy this week it will take a while before I start recording.

The source code is available here. If anyone is not currently busy, I'd really like to hear some feedback on the code before I start recording, so that the quality of the final video could improve. Thanks!
This one. Sorry, I must have clicked on the wrong page.

Whoops - you're right. I've moved stuff around in the repository.
You can find "4_SmartPtrs" here:
https://github.com/SuperV1234/Tutorials/tree/master/DiveIntoC%2B%2B11

9
The link doesn't seem to work. It comes up with a 404 this is not the page you are looking for.

What link?

10
Thanks everyone for the feedback!

1) In Episode 2 (about Frametime and FPS) is there a benefit using std::chrono instead of sf::Time? I am researching about Game Loop and Game Time and I am still trying to find the best approach. BTW I really liked the Fixed time slice approach.

I don't think there is a particular benefit - I was trying to be as standard-compliant as possible and use modern STL features.



2) Based on Episode 5 (Game entity management basics) I wanted to make a space invaders clone.
I expanded the p9.cpp and created my game. The problem is that I haven't figured out how to create Entities in real time. For example when player presses the space bar, a bullets gets fired from player ship. (Maybe I need to brush up my C++ skills  :-[)

Create a function similar to `createBrick` and call it during your game loop - you can do it after spacebar is pressed, for example.



  • Base classes that aren't instantiated should be abstract, corresponding virtual member functions pure.
Classes that derive from abstract classes explicitly require to define the base class's abstract methods.
In my design, components can often have an empty `draw` or `update` implementation - forcing the derived type to implement an empty version of those methods is not something I want to do.



  • You could show std::make_unique() (C++14). emplace_back() with raw new
    is not exception-safe, leading to possible memory leaks. In general, I would avoid new where possible -- especially if you wrap the pointer in a smart pointer anyway.
This is correct - the `new` keyword should never be used (unless we're using "placement new").
Unfortunately the video is targeting the C++11 standard, so I can't use `std::make_unique` in it.



  • Calling a parameter mArgs is rather unusual; the "m" prefix is commonly used for members.
I've received the same feedback on my naming conventions before, and you're probably right - "m" could seem an abbreviation for "member".
The truth is that I'm really really used to this naming convention so it would take a lot of time and "find-replace regexes" to change it - I'll think about it.


  • You use both abs() and std::abs(), the latter is correct.
Correct, will fix this as well in the GitHub code.

11
General discussions / Re: static analysis of SFML
« on: April 11, 2015, 10:15:28 pm »
Could you post the complete log?

12
It will certainly work, but it seems unnecessarily inefficient and complex.

`std::typeid` and an `std::unordered_map` have a significant runtime overhead. Also, you cannot use `noexcept` to allow even more aggressive compiler optimizations.

I don't think it can get much faster than a bitset lookup for component availability checks and a direct array access to retrieve a component of a specific type.

A possibly even more efficient version could use a variadic list of component types passed in the manager (which would be a template class) so that appropriate data structures and unique IDs could be generated at compile-time. But I don't think it would be much faster than the implementation I show in the video.

I'm also a little perplexed by the use of `std::list` (which is highly not recommended by Bjarne itself, because of its cache unfriendliness), `std::weak_ptr` (wouldn't a raw pointer do the trick here?) and `std::function`, which, again, has some runtime overhead.

Instead of passing an `std::function` to `EntityManager::ForEach` you can simply add and use a template parameter for the passed function type, which will have no runtime overhead.

Your design and implementation is probably fine for any kind of game that has a small amount of entities... but I really like to make my life harder by trying to squeeze every last bit of performance in my code.
It feels rewarding and I always learn unexpected things about efficient code :)

13
Hello everyone! I've just finished uploading the latest episode of "Dive into C++11".

http://www.youtube.com/watch?v=QAmtgvwHInM

In this episode we'll see various ways of implementing entity management in your games, starting with a very simple "one vector per object type" approach. We'll consider a "polymorphic inheritance tree" approach as well, and finish the video by re-implementing our Arkanoid clone with a simple but effective component-based design.

The goal of the episode is showing the thought process behind the design and improvement of an entity management system.

The intended audience for this tutorial/screencast are people who have some experience with C++ in general, and who watched the previous episodes. This episode also teaches the basics of polymorphism and component-based design.

Hope you'll find the video interesting!
I greatly appreciate comments and criticism, and ideas for future videos/tutorials.

14
General discussions / Re: C#/C++ comparison
« on: March 06, 2015, 11:46:46 pm »
That's true, sorry if it sounded like I was attacking you.
But it looks like you're trying to say (even if this is not your intention): "Aha! I finally proved that C++ is not faster than C#!" ... without even posting the code of your benchmarks.

I should have chosen better words.
Anyway, could you post the code of your benchmarks?

15
Check out my tutorial series:
https://www.youtube.com/watch?v=_4K3tsKa1Uc

I strive to use modern C++11/C++14 features and write idiomatic, safe and efficient code.

Quote
This is my first attempt at a complete C++11 game development tutorial.

In about 40 minutes we will create an arkanoid/breakout clone from scratch, using the Standard Library and SFML 2.1, an amazing easy-to-use library that handles GFX, SFX and input.

The video tutorial was extremely well received by the C++ community.
I even transformed it into a 60 minutes talk that I gave at CppCon 2014, in Bellevue:
https://www.youtube.com/watch?v=TC9zhufV_Z8

The CppCon 2014 video has some additional slides and diagrams that may help you even more.

Hope you find it useful!


Pages: [1] 2 3 ... 12
anything