1. CSE 380 C++ Boot Camp
Part 2/2
You
You
C++
C++
Subtle and
Subtle and
annoying things
annoying things
2. Now what?
●
Last week: The language
●
This week: The tools
●
Compiling and linking code
●
Box2D, specifically
●
You will be using it for your course project
●
Splitting classes into headers and source files
●
What that means and why you must do it
●
Overview of popular C++ libraries and tools
●
Tips about the course
3. Static vs. Dynamic Libraries
.a or .lib extension
(varies by compiler)
Resolved at link-time and
included in the binary
Must recompile to update
the library
Unused or duplicated
library code can be
removed
.dylib, .dll, or .so
extension (varies by OS)
Resolved at run-time and
included in program
directory or system folders
Can swap out different
versions at will
Only loaded to RAM once
if multiple programs use
the same dynamic library
at the same time
5. Symbol Tables
moe.obj
moe.obj
Have: stooges::slap
Have: std::vector<float>
Seeking: stooges::poke
Seeking: std::sin
Multiple gaps seeking one symbol: Perfectly normal
Multiple tabs declaring one symbol: multiple definition of
symbol symbol_name
Gap without a tab filling it: unresolved external symbol
symbol_name
Tab not assigned to a gap: Unused symbol (can be stripped)
7. Installing Box2D
I assume you've downloaded Visual Studio already
Download Box2D now
– And 7-Zip to open the archive
Extract the Box2D_v2.3.0/Box2D folder to wherever you want to keep
your libraries
I use C:/Users/<name>/Libraries
All of your libraries should go
here (with a folder for each)
Does this
contain these?
8. Compiling Box2D
Projects contain related code
Solutions contain related projects
Open Build/vs2012/Box2D.sln
#include that
in your game
For testing
and demos
Right-click Box2D → Build
You just built a static library!
9. Compiling Box2D
Do the same with Testbed
Note that its dependencies are compiled
See Solution 'Box2D' → Properties → Project Dependencies
Testbed → Debug → Start New Instance
Play around with this over the weekend
10. What did you just build?
Box2D → Properties
The most
important
stuff
Change options depending on build type and platform
Macros have different values
depending on config or build
environment
11. Release Builds
Run the Testbed, go to Tiles demo, tick the Profile box
Look at step [ave] (max); note these numbers
previous [average] (longest time) for one physics step in milliseconds
Do it again in Release mode
WOW!
Debug build Release build
12. Creating a Solution
Your solution will have multiple projects
Your game + any supporting libraries
File → New → New Project
Create a new solution
13. Let's Compile Something
Source Files → Add New Item → C++ File
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;
using std::system;
int main() {
cout << "Hello world!" << endl;
system("PAUSE");
}
14. Headers and Classes
Declare classes, global functions, etc. in header files
(.hpp extension)
Define them in a corresponding source file (.cpp
extension)
Exception: templated classes, functions, or methods
must be defined in headers
15. Headers and Classes
Reduces the number of files to build
Header changes? All .cpp files that use it
must be recompiled
Source changes? Only that file must be
recompiled
Prevent linker errors, too
16. You Should See These
// Vector2.hpp
#pragma once
class Vector2
{
public:
Vector2();
~Vector2();
};
// Vector2.cpp
#include "Vector2.hpp"
Vector2::Vector2()
{
}
Vector2::~Vector2()
{
}
Provides symbols Provides code
17. More (.hpp)
// Vector2.hpp
#pragma once
namespace cse380 {
class Vector2
{
public:
Vector2();
Vector2(const float, const float);
// Can omit names in declaration
float x, y;
Vector2& operator+=(const Vector2&);
Vector2& operator*=(const float);
};
Vector2 operator+(const Vector2&, const Vector2&);
Vector2 operator*(const Vector2&, const float);
}
21. Now Add a Conversion Operator
// Vector2.hpp
#pragma once
#include
#include "Vector3.hpp"
"Vector3.hpp"
namespace cse380 {
class Vector2
{
public:
// Omitted for brevity
explicit
explicit operator
operator Vector3
Vector3()
() const
const;
;
};
// Omitted for brevity
}
// Vector2.cpp
#include "Vector2.hpp"
namespace cse380 {
// Omitted for brevity
Vector2
Vector2::
::operator
operator cse380::
cse380::Vector3
Vector3()
() const
const {
{
return
return Vector3
Vector3(
(this
this->x,
->x, this
this->y, 0);
->y, 0);
}
}
// Omitted for brevity
}
You just tried a circular #include!
Won't compile; incomplete type
22. What to Do
// Vector2.hpp
#pragma once
#include "Vector3.hpp"
namespace cse380 {
class
class Vector3
Vector3;
;
// Omitted for brevity
}
// Vector3.hpp
#pragma once
#include "Vector2.hpp"
namespace cse380 {
class
class Vector2
Vector2;
;
// Omitted for brevity
}
// Vector3.cpp
#include "Vector3.hpp"
#include
#include "Vector2.hpp"
"Vector2.hpp"
namespace cse380 {
// Omitted for brevity
}
// Vector2.cpp
#include "Vector2.hpp"
#include
#include "Vector3.hpp"
"Vector3.hpp"
namespace cse380 {
// Omitted for brevity
}
Forward-declare a class when you only need its name
This is why we split classes into .hpp/.cpp
#include its header when you need anything else (including sizeof)
i.e. in dependent .cpp files or templates in headers
Two classes can't be members of each other
Raw pointers (not smart pointers) to each other okay
24. #pragma once
Include at the top of each .hpp
Otherwise the same class is effectively
defined multiple times
#include "Vector2.hpp"
#pragma once
// Contents of Vector2.hpp
<nothing>
First time this file
was #included?
Yes
No
25. With
#pragma once
Without
#pragma once
#pragma once
// France.hpp
// Spain.hpp
#include "France.hpp"
// Before
#include "France.hpp"
#include "Spain.hpp"
int main() {
// Etc.
}
// France.hpp
#pragma once
// Spain.hpp
#pragma once
#include "France.hpp"
// Hooray!
// France.hpp
// Spain.hpp
int main() {
// It works!
}
// Uh-oh
// France.hpp
// Spain.hpp
// France.hpp
int main() {
// Multiple
// definition error
}
26. Library/Include Install
Conventions
Linux
●
/usr/include and /usr/lib for
package managers
●
/usr/local/include and
/usr/local/lib for everything
else
Mac
●
/Library/Frameworks
Project-Specific
●
Enforce a location
●
“Use your home folder”
●
Include in your source tree
●
Recommended for this course
●
Submodules
Windows
●
None
●
God help you
28. Importing Box2D
●
Still gotta add the include/library paths
●
Project → VC++ Directories
●
If you and your team aren't consistent, you
will lose lots of sleep
The important stuff
29. Importing Box2D
●
Add <RootBox2DDir>Box2D
to includes
●
Change your main to this:
Expands to these
Nice and easy
Filter by macro name
#include <iostream>
#include <cstdlib>
#include
#include "Vector2.hpp"
"Vector2.hpp"
#include
#include "Vector3.hpp"
"Vector3.hpp"
#include
#include <Box2DBox2D.h>
<Box2DBox2D.h>
using std::cout;
using std::endl;
using std::system;
using
using namespace
namespace cse380;
cse380;
int main() {
b2World
b2World world(b2Vec2_zero);
world(b2Vec2_zero);
Vector2
Vector2 a(2, 3);
a(2, 3);
Vector3
Vector3 b;
b;
cout << "Hello world!" << endl;
system("PAUSE");
}
// Not done yet; you'll get a linker error!
40. UPX
Compress executables and
libraries
Output automatically
decompresses when run
Output may trigger virus
scanners
– They hate self-modifying code
Compressed DLLs cannot
be shared between
programs
41. Visual Studio Tips
Don't be afraid to customize it
Most of today's lessons are not specific to it
You can define tasks to run upon a
successful build (e.g. zipping up the
game/assets, copying over any DLLs, etc.)
42. Box2D Tips
Box2D has a lot of classes; most of these are only used
internally
I'll make a list of classes to care about later
There is an abstract b2Draw class you can extend for
drawing bodies, joints, etc.
USE IT USE IT USE IT USE IT USE IT
Don't use pixels as world units; pick a size (e.g. 64px = 1
meter) and use that
Otherwise it's hard to reason about world design