-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce GameObjects and Components. #3
Conversation
/// A component by itself has no meaning, and is useful to describe properties or attributes | ||
/// of a `wex::GameObject`. | ||
/// Extend this class to use custom components. | ||
struct Component { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Convention is to have such things be class
es, struct
s don't usually have virtual semantics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My reasoning was this is more of a C-style "bag of data", rather than mutable state + mutating functions. So I went with a struct here. is that okay?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, just letting you know what to expect elsewhere
T* give(Args&&... args) { | ||
auto compPtr = std::make_unique<T>(std::forward<Args>(args)...); | ||
mComponents.push_back(std::move(compPtr)); | ||
return reinterpret_cast<T*>(mComponents.back().get()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static_cast
pls! reinterpret will cast anything without care, we mostly restrict it to primitives only.
include/wex/presets/GameObject.hpp
Outdated
virtual void onUpdate([[maybe_unused]] double dt) {} | ||
|
||
template <typename T> | ||
T* get() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be a const
member function (don't need non const overload, because pointer isn't const)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aaah, great catch!
include/wex/presets/GameObject.hpp
Outdated
/// TODO: optimize this O(n) lookup | ||
for (auto const& compPtr : mComponents) { | ||
auto comp = dynamic_cast<T*>(compPtr.get()); | ||
if (comp != nullptr) return reinterpret_cast<T*>(comp); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pls no reinterpret_cast
😭
Here you can just return comp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol, alright. Why is reinterpret_case bad?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's basically (foo)bar
: there are no checks whatsoever, and unlike in C, materializing an object (or a pointer to one) that was never created before is UB in C++.
src/main.cpp
Outdated
template <typename T> | ||
struct Shape : wex::Component { | ||
T shape; | ||
Shape(T&& shape_) : shape(shape_) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rvalue
that's not moved? sus...
void onUpdate(double) override { | ||
sf::Vector2f const& vel = this->get<wex::CVelocity>()->vel; | ||
auto& shape = this->get<CCircleShape>()->shape; | ||
shape.setPosition(shape.getPosition() + vel); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing * dt
for framerate independence.
src/main.cpp
Outdated
} | ||
|
||
void draw() override { | ||
g->draw(mCircle); | ||
g->draw(ball.get<CCircleShape>()->shape); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not delegate to ball
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Small comment: while double dt
is fine, it doesn't convey the units, a chrono::duration<float, R>
instead will be a zero overhead unit safe wrapper.
A
GameObject
is a wrapper around astd::vector
of Components, along with anonUpdate
method.Current app is a circle that slowly moves from the topleft to the bottom right of the screen.
Eventually this will become the ball in
pong
.Files added:
include/wex/presets/GameObject.hpp
include/wex/presets/Component.hpp