-
Hey Guys!
I love the SFML Game Dev Guide a lot. Also when it comes a bit tricky thinking over from C++ to C# -but until now I managed it with your help and google.
Sadly nothing runs perfect in coding anyway and therefore I'm in front of a new wall which I can't climb with my novice knowledge.
I now arrived at SceneNodes - a topic I really am interested in. But as it goes - C++ knocks me out and I don't know what the book is talking about:
class SceneNode
{
public:
typedef std::unique_ptr<SceneNode> Ptr;
public:
SceneNode();
private:
std::vector<Ptr> mChildren;
SceneNode* mParent;
};
I have no idea how to convert this anyhow into C# - The main problem is that I dont get the semantics with these pointers here good enough. If I would understand it right away I might be able to do it in C#. But I just don't get what they suppose to manage here :D
-
I'm sure a much more thorough answer will arrive shortly from someone much more knowledgeable than me, but:
C# is a garbage-collected language. So most memory management problems and solutions in C++ simply won't have an analogue. If you ignore everything to do with memory management, then std::unique_ptr is essentially no different from a regular pointer, so you can get away with pretending that that class isn't even there and just focus on the important conceptual part, namely: A SceneNode has pointers to other SceneNodes, one of them is its parent, and the others are its children.
-
class SceneNode
{ private List
<SceneNode
> mChildren
; private SceneNode mParent
; public SceneNode
() { mChildren
= new List
<SceneNode
>(); mParent
= new SceneNode
(); } public void AttachChild
(SceneNode child
) { child
.mParent = this; mChildren
.Add(child
); } public SceneNode DetachChild
(SceneNode child
) { child
.mParent = null; mChildren
.Remove(child
); return child
; } }
Thats how I solved it... does it fit to the needs? I think yes - just courios what you say
So u know about the methods I added I quote the books descriptions:
Node insertion and removal
Now we write an interface to insert or remove child nodes into or from a scene node.
We do this by adding the following two functions:
void SceneNode::attachChild(Ptr child)
{
child->mParent = this;
mChildren.push_back(std::move(child));
}
SceneNode::Ptr SceneNode::detachChild(const SceneNode& node)
{
auto found = std::find_if(mChildren.begin(), mChildren.end(),
[&] (Ptr& p) -> bool { return p.get() == &node; });
assert(found != mChildren.end());
Ptr result = std::move(*found);
result->mParent = nullptr;
mChildren.erase(found);
return result;
}
-
That looks correct to me. Hopefully someone who actually knows C# and is familiar with the book's code will show up to confirm that.
-
For you guys who are bored ;)
I have a next issue going on under the Topic: Making scene nodes drawable
The issue is - like I've read not an unusual one - that there isn't an easy way to override Draw(x,y) of the Drawable Interface in SFML.NET because it's not virtual. I'm gonna lurk for the solution to get straight with the C++ solution anyhow. Mybe you guys can throw in some informations already to this issue !
Updates will follow...
Greets Charlie
-
That looks correct to me. Hopefully someone who actually knows C# and is familiar with the book's code will show up to confirm that.
I bet sb. will 8)
-
SceneNode result = mChildren[mChildren.IndexOf(child)];
This line is pretty much useless, "result" is "child", obviously.
The issue is - like I've read not an unusual one - that there isn't an easy way to override Draw(x,y) of the Drawable Interface in SFML.NET because it's not virtual.
It is. Drawable is an interface in SFML.Net.
-
SceneNode result = mChildren[mChildren.IndexOf(child)];
This line is pretty much useless, "result" is "child", obviously.
The issue is - like I've read not an unusual one - that there isn't an easy way to override Draw(x,y) of the Drawable Interface in SFML.NET because it's not virtual.
It is. Drawable is an interface in SFML.Net.
Ha...yea you're right...mixed up minds with this C++ to C# transfers ::)
-
It's me again - came a lot further and broke through SceneNodes pretty well!
sf::Vector2f SceneNode::getWorldPosition() const
{
return getWorldTransform() * sf::Vector2f();
}
Here it's not clear for me how I can reach something like sf::Vector2f in .NET since Vector2f is only a struct type.
-
And? What prevents you from multiplying a transform with a vector?
Please don't ask every minor thing. Have a look at the SFML.NET documentation and try to understand the classes and their functionality. Consult the source code in case of doubt.
By the way, other people might already have ported the book or parts of it to C#, you could see if you find something.
-
Meh sorry for asking so much - It's just I'm working fulltime on it and therefor questions arise pretty continuesly.
public Transform GetWorldPosition
() { return GetWorldTransform
() * new Vector2f
(0
.0f, 0
.0f
); }
Error 3 an implicit conversion of type 'SFML.System.Vector2f' into 'SFML.Graphics.Transform' is not possible. C:\Users\FalkeXY\Desktop\SFML_Game_Dev\Game\SceneNode.cs 71 20 Tutorial_Game
And? What prevents you from multiplying a transform with a vector?
That's what actually prevents me from it
-
And don't get me wrong that I didn't tried everything I know or googled for it already. I spend some time searching for the solution. But since this forum is the only reliable source for asking I have no other choice than asking here. Waiting for nothing isn't really an option if we all are honest.
-
Your code is ok, you just have the return type of GetWorldPosition() wrong.
-
Okay, that was not clear from your previous post. Please provide always details and what you've tried already when asking.
The Transform class contains an overloaded operator for Vector2f, see here (https://github.com/SFML/SFML.Net/blob/master/src/Graphics/Transform.cs#L266-L269). Are you using an older version? One alternative is calling TransformPoint() directly.
-
Your code is ok, you just have the return type of GetWorldPosition() wrong.
Ah dang...bad bugsearch from my side here sorry guys...what a silly mistake.
I will take the tip with the C# conversion of the tutorial book with me now so I don't need to bugger you that often.
greets
-
As indicated above, there's an existing C# port (http://en.sfml-dev.org/forums/index.php?topic=15981.0). Even if you do yours for learning purposes, looking at existing source code would solve many of your problems immediately.
Thus... always search a bit ;)
-
Hey Bros!
Asking Time again :P Just want to check if this would be redundant or not.
class CommandQueue
{
Queue<Command> queue;
public bool isEmpty()
{
return queue.Count == 0;
}
public void Push(Command command)
{
queue.Enqueue(command);
}
public Command Pop()
{
return queue.Dequeue();
}
}
In this class I forward every method with the method of the Queue<T> object. Why can't I just declare Queue<T> public and access their methods like: CommandQueue.queue.Enqueue(command)
Is it just that it looks nicer with CommandQueue.Push(command)
There just a design thingie?
-
Encapsulation. In C++, nobody needs access to the size or back element of std::queue, so only the required operations are provided. The implementation could be exchanged without affecting the interface. Also, it makes it possible to forward-declare the CommandQueue (not relevant in C#).
-
Hey Guys - new issue here. Since the C# Port guy made things a bit different I can't rely of his code.
Actually it's not a syntax issue more a semantic one.
struct AircraftMover
{
AircraftMover(float vx, float vy)
: velocity(vx, vy)
{
}
void operator() (SceneNode& node, sf::Time) const
{
Aircraft& aircraft = static_cast<Aircraft&>(node);
aircraft.accelerate(velocity);
}
sf::Vector2f velocity;
};
That's the code in the book. Please focus on the fact that the method operator() here receives these usual parameters of type SceneNode and Time.
After that there is a definition for HandlePlayerRealtimeInput:
void Player::handleRealtimeInput(CommandQueue& commands)
{
const float playerSpeed = 30.f;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
Command moveLeft;
moveLeft.category = Category::PlayerAircraft;
moveLeft.action = derivedAction<Aircraft>(
AircraftMover(-playerSpeed, 0.f));
commands.push(moveLeft);
}
}
Here you can see that the Commad object moveLeft within its function pointer action (if it isnt a function pointer nvm - thats not the point here I think) receives AircraftMover() (which is the constructor as I can see that far)
Now...since the operator() method of AircraftMover isn't called explicit I'm sure that it's called within the AircraftMover Constructor. (Be sure that I'm not hip with C++ therefore I have to estimate what happens and relate it to C# designs).
That are all things which I could handle with C#.
The big BUT here is...
How can the operator() method of AircraftMover receive any references to SceneNode and Time ? Since the AircraftMover Constructor isn't receiving any of these (only float_x and float_y parameters). Neither there is any inheritance to something which contains a SceneNode nor Time.
I really browsed the C# Port and ascending pages of the Tutorial Book - but couldn't find any explaination what is happening there.
Besides that problem I really miss the definition of the HandleEvent Method of the Player class. Only the HandlePlayerRealtimeInput receives a defintion with the implemenation of the Command class etc. as you can see above. Would be nice to have some clear code on that method aswell (Again - the C# Port has another approach on that problem - therefore I can't take it for this here)
I hope I won't waste your time on this - but I'm very motivated to complete this tutorial with all dents and stones which may occur. Since I'm a beginner coder I need your help often. But HEY - I learned a lot here and with the book - so you can be sure my question activity will lower and answer posts will raise ;)
greets Charlie
-
Browsing through this (https://github.com/SFML/SFML-Game-Development-Book)
Now...since the operator() method of AircraftMover isn't called explicit I'm sure that it's called within the AircraftMover Constructor. (Be sure that I'm not hip with C++ therefore I have to estimate what happens and relate it to C# designs).
...
How can the operator() method of AircraftMover receive any references to SceneNode and Time ? Since the AircraftMover Constructor isn't receiving any of these (only float_x and float_y parameters). Neither there is any inheritance to something which contains a SceneNode nor Time.
No, operator() is an operator overload. In this case it overloads call operation. You can also overload typical operations such as add or substract. Operator()-method is executed when you call aircraftmover instance. In the link I posted it's located in SceneNode-class.
void SceneNode::onCommand(const Command& command, sf::Time dt)
{
// Command current node, if category matches
if (command.category & getCategory())
command.action(*this, dt);
// Command children
FOREACH(Ptr& child, mChildren)
child->onCommand(command, dt);
}
SceneNode and time are also passed to parameters there as you can see.
You can't overload call operator in C# so you'll have to handle that in a different way.
Here's a list of overloadable operators in C# http://msdn.microsoft.com/en-us/library/8edha89s.aspx
-
Now...since the operator() method of AircraftMover isn't called explicit I'm sure that it's called within the AircraftMover Constructor.
No. You see the constructor's definition right above, and there is no operator() call. The function object is invoked later, to apply functions to scene nodes. The whole point of storing functions in std::function is to not invoke them directly, but in a deferred way as a callback.
In C#, the equivalent would be delegates -- or simply interfaces that are implemented. For the interface approach, consult the C# port (https://github.com/dejangeci/WarfareUnleashed/blob/master/Projects/Ch06_Menus/Player.cs#L8-L21).
Besides that problem I really miss the definition of the HandleEvent Method of the Player class.
In C++, it's here (https://github.com/SFML/SFML-Game-Development-Book/blob/master/10_Network/Source/Player.cpp#L81-L122).
-
Thank you guys very much! Now I get the problem here much better. Well might be a bit tricky to receive the same solution as being able to overload the call operator. Thanks for the Laurent Link to see the Dev Books Codes more clearly - missed that completly it seems.
:-*
-
Well might be a bit tricky to receive the same solution as being able to overload the call operator.
I mentioned two alternatives in C#, so why would you want to do that?
-
Well might be a bit tricky to receive the same solution as being able to overload the call operator.
I mentioned two alternatives in C#, so why would you want to do that?
You misunderstood me here - I read your alternatives and will use them for that solution here - Still it will be tricky because I'm no Pro :D
-
Nobody was born a pro, you need to invest some time into learning C# ;)
-
Nobody was born a pro, you need to invest some time into learning C# ;)
I'm on it at fullspeed chief ;) - being an Airborne Ranger and spending all my freetime for coding <3
BTW thats my solution which pretty much fits very well:
class AircraftMover
{ private Vector2f velocity
; public AircraftMover
(float x,
float y
) { velocity
= new Vector2f
(x, y
); } public void Execute
(SceneNode node, Time dt
) { ((Aircraft
)node
).SetVelocity(((Aircraft
)node
).GetVelocity() + velocity
); } }
Note: Keeping the Downcast up still...for now.
public void HandleRealTimeInput
(CommandQueue commands
) { const float playerSpeed
= 30
.0f
; if(Keyboard
.IsKeyPressed(Keyboard
.Key.Left)) { Command moveLeft
= new Command
(); moveLeft
.SetCategory(Category
.PlayerAircraft); moveLeft
.action = new AircraftMover
(-playerSpeed, 0
.0f
).Execute; } }
I made action a delegate already from the beginning because I kinda thought it might fit. Cool thing that I can define the AircraftMover class and directly through the DOT operator access its method - in fact made it flush in one row *proud of me*
-
The C++ Book code tells me to use Transformable::move() therefore I found Transformable.Translate which receives a Vector2f. I check if the code for Pressing "Left" as Userinput reaches the mVelocity there and it does - mVelocity is being changed.
Still no change on the sprites on execution - trying to locate the bug. Kinda think that the Translate Method isn't working as intended.
class Entity
: SceneNode
{ Vector2f mVelocity
; public Vector2f GetVelocity
() { return mVelocity
; } public void SetVelocity
(float x,
float y
) { mVelocity
= new Vector2f
(x, y
); } public void SetVelocity
(Vector2f velocity
) { mVelocity
= velocity
; } protected override void UpdateCurrent
(Time dt
) { Transform
.Translate(mVelocity
* dt
.AsSeconds()); } }
Alternatively using:
Position += mVelocity * dt.AsSeconds();
Is working just that you know - but I would like to use Translate :/
-
You can't use Transform.Translate. Transform is a read-only member, it's just that C# provides nothing to enforce this, unlike C++.
The equivalent to entity.move(v) is entity.Position += v.
-
You can't use Transform.Translate. Transform is a read-only member, it's just that C# provides nothing to enforce this, unlike C++.
The equivalent to entity.move(v) is entity.Position += v.
If its a read only member how come its defined that way in the .dll :
public void Translate(Vector2f offset);
public void Translate(float x, float y);
Accepting two overloads as a method and returning void? doesn't sound more me as something that only can be read :/ - mybe I misundestand read only a bit here
-
The Transform class itself is not read-only. What I said is that the Transform member of Transformable is read-only.
// you can do this
Transform t1 = new Transform();
t1.Translate(10, 20);
// ... but not this
Transformable t2 = new Transformable();
t2.Transform.Translate(10, 20);