如何在(D)SFML中自动同步自定义Drawable与Shape的变换属性?
How to Automatically Sync Transformable Properties with Your Custom Drawable in D + SFML
Great question—let's fix that manual position syncing and align your code with SFML's design patterns properly.
First, let's break down why your current approach (body.position = this.position;) isn't ideal:
- It only syncs position, ignoring other critical transform properties like scale, rotation, and origin. If you later call
animal.setScale(2,2)oranimal.setRotation(45), yourbodyshape won't reflect those changes unless you add more manual sync lines. - Modifying the
body's state inside thedrawmethod is bad practice—drawshould be a pure rendering operation, not a state-modifying one, which can lead to inconsistencies or thread-safety issues.
The Correct Approach: Use RenderStates to Pass Transformations
SFML's Transformable interface exists to manage a combined transformation matrix (position + scale + rotation + origin), and RenderStates is how you pass this matrix to child drawables. Instead of syncing individual properties, you'll combine your Animal's transform with the incoming render state and pass that to the body's draw call.
Here's the revised Animal class:
class Animal : Drawable, Transformable { mixin NormalTransformable; Shape body; string name; this(Shape sh, string name) { this.body = sh; this.name = name; } override void draw(RenderTarget target, RenderStates state = RenderStates.Default) { // Combine the incoming render state's transform with our Animal's transform RenderStates combinedState = state; combinedState.transform *= getTransform(); // Draw the body using the combined transformation matrix target.draw(body, combinedState); } }
Why This Works
- Automatic Sync of All Transform Properties:
getTransform()returns a single matrix that encapsulates yourAnimal's position, scale, rotation, and origin. Multiplying this with the incomingstate.transform(which might include parent transformations from the scene) ensures all changes are applied to thebodyautomatically. - Follows SFML's Design: This decouples the transformation logic (handled by
Transformable) from the rendering logic (handled byDrawable), keeping your code clean and aligned with how SFML is intended to be used. - No Manual State Changes: You're no longer modifying the
body's properties during rendering—all transformations are applied via the matrix, which is far more efficient and avoids state inconsistencies.
Extra Tips
- If you've manually set transformations on the
bodyitself (e.g.,body.setPosition(10,10)), the combined transform will stack theAnimal's global transform on top of thebody's local transform. This is usually desired (think of thebody's position as offset relative to theAnimal's origin). - If you want to reset the
body's local transform entirely, you can callbody.setTransform(Transform.Identity)in the constructor—though this is rarely needed since shapes start with an identity transform by default.
内容的提问来源于stack exchange,提问作者eXodiquas
相关产品推荐
相关产品推荐

