Difference between revisions of "Intermediate C++ Game Programming Tutorial 25"
(→See also) |
(→Tutorial 25 - Solution) |
||
(11 intermediate revisions by the same user not shown) | |||
Line 186: | Line 186: | ||
:* To point to an actual member function, use <code>pFooFunc = &Foo::SomeMemberFunction;</code> | :* To point to an actual member function, use <code>pFooFunc = &Foo::SomeMemberFunction;</code> | ||
::-(Note: 'Address of' operator <code>&</code> is required here) | ::-(Note: 'Address of' operator <code>&</code> is required here) | ||
− | :* To call it, you can use it on a class instance | + | :* To call it, you can use it on a class instance foo <code>(foo.*pFooFunc)(3);</code> |
− | :* If you have a pointer to a class instance <code>Foo* pF = & | + | :* If you have a pointer to a class instance <code>Foo* pF = &foo;</code>, the syntax to invoke through the function pointer is: <code>(pF->*pFooFunc)(3);</code> |
:* This syntax is obviously not preferable, just good to know it exists | :* This syntax is obviously not preferable, just good to know it exists | ||
</div> | </div> | ||
Line 200: | Line 200: | ||
<div class="mw-collapsible-content"> | <div class="mw-collapsible-content"> | ||
:* Works as a sort of adaptor for functions; it allows you to bind values to input parameters | :* Works as a sort of adaptor for functions; it allows you to bind values to input parameters | ||
− | :* For instance say you have some free | + | :* For instance say you have some free function <code>int Foo(int x)</code> |
:* <code>std::bind(Foo,69)</code> defines a new function that calls <code>Foo</code> with the value 69. That new function will now take zero parameters: it essentially changes the signature | :* <code>std::bind(Foo,69)</code> defines a new function that calls <code>Foo</code> with the value 69. That new function will now take zero parameters: it essentially changes the signature | ||
:* Useful if you want to map functors that have more input parameters than your map definition; we can adapt a function that normally would not fit in our function containers so that it fits | :* Useful if you want to map functors that have more input parameters than your map definition; we can adapt a function that normally would not fit in our function containers so that it fits | ||
Line 243: | Line 243: | ||
auto g = [](int x) { return Thing(x,5); }; | auto g = [](int x) { return Thing(x,5); }; | ||
g(10); // returns 25 | g(10); // returns 25 | ||
+ | </syntaxhighlight> | ||
+ | :* Or, to bind a call to a member function of an objeect of class Foo with a Lambda (myfoo is an instance): | ||
+ | ::<syntaxhighlight lang="cpp" line> | ||
+ | std::function<void()> f; | ||
+ | f = [&myfoo](){myfoo.DoublePlus(69);}; | ||
+ | f(); | ||
+ | </syntaxhighlight> | ||
+ | :* You don't stricly need to bind a lambda through <code>std::function</code>, you could also assign a lambda to a normal function pointer (with matching signature), but then you cannot use capture variables | ||
+ | </div> | ||
+ | * Operator function objects [https://youtu.be/4EZVTNHmojc?t=14m55s 14:55] | ||
+ | <div class="mw-collapsible-content"> | ||
+ | :* Useful when dealing with algorithms instead of writing your own custom predicates | ||
+ | :* Examples: <code>equal_to</code>, <code>modulus</code>, etc. | ||
+ | </div> | ||
+ | * Making a function pointer to a static member function [https://youtu.be/4EZVTNHmojc?t=16m30s 16:30] | ||
+ | <div class="mw-collapsible-content"> | ||
+ | :* This is easier to do than in case of normal member functions, because static member functions do not operate to any specific instance of a class | ||
+ | :* So, say you have a static member function <code>static int DoStatic( int y )</code> inside you Foo class: | ||
+ | ::<syntaxhighlight lang="cpp" line> | ||
+ | int(*pStaticFunc)(int) = &Foo::DoStatic; // & is optional here | ||
+ | std::cout << pStaticFunc(2); // same as: | ||
+ | std::cout << (*pStaticFunc)(2); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</div> | </div> | ||
− | |||
</div> | </div> | ||
=== [https://youtu.be/Vh2JW5MHJX0 Tutorial 25 - Solution] === | === [https://youtu.be/Vh2JW5MHJX0 Tutorial 25 - Solution] === | ||
<div class="mw-collapsible mw-collapsed"><br /> | <div class="mw-collapsible mw-collapsed"><br /> | ||
− | * A look at <code>world.step( dt,8,3 );<code> in <Game::UpdateModel()</code> [https://youtu.be/Vh2JW5MHJX0?t=28m39s 28:39] | + | * A look at <code>world.step( dt,8,3 );</code> in <code>Game::UpdateModel()</code> [https://youtu.be/Vh2JW5MHJX0?t=28m39s 28:39] |
* Solution to 1st part: destroy boxes of same color when they collide [https://youtu.be/Vh2JW5MHJX0?t=33m50s 33:50] | * Solution to 1st part: destroy boxes of same color when they collide [https://youtu.be/Vh2JW5MHJX0?t=33m50s 33:50] | ||
<div class="mw-collapsible-content"> | <div class="mw-collapsible-content"> | ||
Line 308: | Line 329: | ||
* [[Intermediate C++ Game Programming Series]] | * [[Intermediate C++ Game Programming Series]] | ||
* Chili [https://youtu.be/lj9niRFCVGc grabbing a package using vcpkg] (note, SFML is not relevant for this tutorial, it's Box2D you want to grab) | * Chili [https://youtu.be/lj9niRFCVGc grabbing a package using vcpkg] (note, SFML is not relevant for this tutorial, it's Box2D you want to grab) | ||
+ | * Chili [https://youtu.be/XywXJD8khHg grabbing a package using NuGet] |
Latest revision as of 07:07, 9 March 2020
Function pointers allow you to store and change what function is to be called dynamically at runtime. Combine that with containers to have collections of actions/behaviors that can be selected from, and then jam in the power std::function
to allow you to wrap up pretty much any kind of callable thing and bring them together in one container. Groovy.
Contents
[hide]Topics Covered
- Function pointers
- Functionoids
-
std::function
Bonus Video
- Pointers to member functions
- std::bind
- std::mem_fn
- std::reference_wrapper (a little)
- Pointer to static member function (it's the same as for normal funcy bois)
- You can use normal func pointers for lambdas if they do not capture anything
Video Timestamp Index
Tutorial 25 - Function Pointers
- How to switch on a string? (execute some code based on the string passed to the switch): using Functionoids 0:15
- Introducing Function Pointers 5:13
- Using Function Pointers with a map 7:27
- Alternative route: use
std::function<>
in order to map to lambda functions 9:33
- Example: making a single string switch class 13:01
- Homework assignment: time to face the music 20:06
Tutorial 25 - Bonus
- Pointers to a member function of a class/struct 0:07
- Defining
std::function
to hold a pointer to a member function 3:30
-
std::bind
from the Utilities library adapts function signatures <functional>5:57
- Reference wrappers
std::reference_wrapper
10:20
-
mem_fn
creates a function object out of a pointer to a member 12:12
- Lambda functions can bind much more elegantly 12:36
- Operator function objects 14:55
- Making a function pointer to a static member function 16:30
Tutorial 25 - Solution
- A look at
world.step( dt,8,3 );
inGame::UpdateModel()
28:39 - Solution to 1st part: destroy boxes of same color when they collide 33:50
- Solution to 2nd part: pattern matching 42:20
Homework Assignment
This homework might wreck your butthole a little, but hopefully not too badly. Anyways, you get the code from the repo, you try and get it to build. The project requires Box2D, but the repo doesn't have it included so you're gonna need to wrangle it yourself. The easiest way to accomplish this is to pull in dependencies into your system with vcpkg. Some of you are probably going to run into some speed bumps at this point getting vcpkg to work on your system, but I recommend powering through and not giving the fuck up, because vcpkg is immensely useful for adding amazing libraries to your projects easily. If you search YouTube, you'll find a video of me showing how to install vcpkg and use it to grab SFML, so that might be a good starting point.
After you get that shit working, the party has just started. Then you need to figure out how the codebase actually works. Use all the tools at your disposal (debugger, Google, Box2D documentation, etc.), and don't get bogged down in unimportant distractions (you don't need to know how the triangle rendering pipeline works to understand the general simulation system, for example).
The actual tasks are, as laid out in the video:
- Implement destruction of boxes when two boxes with the same color trait hit each other
- Implement a box splitting mechanic
- Implement a pattern matching collision event manager based on std::unordered_map (this is the main task that ties into Intermediate 25)
- Use the pattern matching system together with box splitting and other effects to define simulation with various action that occur based on what colors of boxes collide with each other.
Chili will hook you up with a solution video that A) explains the starting codebase in some detail and B) goes over the process of implementing all the the above.
The repo: GitHub
See also
- Intermediate C++ Game Programming Series
- Chili grabbing a package using vcpkg (note, SFML is not relevant for this tutorial, it's Box2D you want to grab)
- Chili grabbing a package using NuGet