Rotating a scene to simulate turning wheel

I have a picture of a wheel. I used a paint program to rotate it by % and then save it as a sprite screen to use it in a playanimation sequence (12 images).
But it is not rotating equal because there is a little shift in the wheels position. (looks rather funny).
So I thought it would be better if the scene consists of just this picture and then rotate the scene to simulate rotation of the wheel. Is this possible?
(I guess the axe should be perfectly in the middle of the scene to prevent it from shifting position while rotating).

Yes, that’s exactly the way to go. Just make sure center of the wheel is perfectly at the center of the image.

Use Castle Game Engine: CastleTransform: Class TCastleTransform the example at that page rotates the scene exactly around the Z-axis (that is in your 2D case - as you would expect, along the player’s line of sight / depth of the view unless you are applying additional transformations in parent).

Got it working.
Now I was about to ask how to change rotation direction and speed but already figured it out by changing the pi value.

Location.Props[2].Image.Rotation := Location.Props[2].Image.Rotation + Vector4(0, 0, 0, Pi / -50);
Negative value rotates the image clockwise and decreasing or increasing the value affects speed.

1 Like

Note that if you update the rotation every frame, it’s a good idea to also use SecondsPassed * RotationSpeed where RotationSpeed is in radians. Here, just as you do for movement. Pi / -50 actually stands for this rotation per frame but it doesn’t consider SecondsPassed and may result in something unexpected.

1 Like

Consider this shorthand, when you have established rotation axis and do not want to be changing it but only the angle.

or as a patch - Wish, tutorials, 2D - more and earlier about coordinates transformations. · Issue #370 · castle-engine/castle-engine · GitHub - the patch is a bit obsolete though, as the record member var names were changed later, but the fix is trivial.

Personally i believe it would make your programs safer by clearly documenting developer’s intention and reducing boilerplate.

with Location.Props[2].Image do RotationAngle := RotationAngle + Pi/-50;

Michalis is absolutely against this approach, though.
Yet the good thing about opensource - you can easily have your own branch with any tweaks of your own choice :slight_smile:

Such RotationAngle is a shortcut, and it’s a shortcut with non-obvious meaning to the reader (does it set rotation axis to something hardcoded or leaves it unmodified?).

To be clear, I am not “absolutely against this”. I actually added myself in the past to the engine things that are similar (TCastleTransform.TranslationXY being the close analogy). I just don’t see it as justified enough, for now. I may change my mind in the future, depending on the usage of CGE I’ll observe.

…that is exactly why i called it rotationANGLE to stress that it does NOT change the axis - and it actually looks similar to your exampl with translationXY stressing the only coordinates affected :slight_smile:

Granted, it would make yet more syntax sugar to have it as an advancd record with AngleIncrease or RotateCCW methods - but this way we rush into “record copy modification” trap :slight_smile:

Good day.
I think, my question similar with question from this topic and ask it here.

I plan to smoothly rotate game map with orientation to players point of view, like in road navigator. This is map class:

  { Minimap state }
  TMinimap = class(TUIState)
    MapCanvas: array of TCastleImageTransform;
    constructor CreateMinimap(var Viewport: TCastleViewport; var Point: THero; var GlobalMap: TWorld);
    procedure RedrawMinimap(var Point: THero; var GlobalMap: TWorld);

So i have many map tiles in viewport. Can i work with them like one undivided object (like wheel in this example)?

Or easely use SetView method to 3D camera and change direction?

  Vector3(-11.34, 30.04, 96.07), // position
  Vector3(0.10, -0.49, -0.87), // direction
  Vector3(0.35, 0.83, -0.43), // up (current)
  Vector3(0.00, 1.00, 0.00) // gravity up

@Noscow My advised solution would be to add all your images to a common parent TCastleTransform, and then rotate everything by rotating that single TCastleTransform .

I made a quick demo of in editor, see img-test.castle-user-interface . ParentOfImage is a parent of 9 images. I can rotate all images as a whole by adjusting ParentOfImage.Rotation, like ParentOfImage.Rotation := Vector4(0, 0, 1, 0.75). You can test it in editor, but of course you can do the same arrangement and transformations in code too. (22.0 KB)

Why I advise it? Because it accounts for various options in the future :slight_smile: This way you can still have some things outside of ParentOfImage that will not be rotated.

Alternative solution would be to rotate the camera, you can just rotate Up to rotate camera around. Or you can assign to camera rotation.

Note: If gizmo in editor disappears when testing it, fear not → I just pushed a solution to it, it will be build in a few hours by Jenkins.

1 Like

Thanks, i understand the paradigm.
So, if i add my images from code, i must first add in Viewport.Items one TCastleImageTransform variable and next put my array with map pictures inside them?
I try like this:

  MapCanvas := TCastleImageTransform.Create(FreeAtStop);
  for i := 0 to MinimapWidth - 1 do
    for j := 0 to MinimapHeight-1 do
      MapTiles[TileNumber] := TCastleImageTransform.Create(FreeAtStop);

but i get error:

MinimapUnit.pas(47,22) Error: identifier idents no member “MapCanvas”

It means, compiler is not know this object is already exist?

Oh, i see my mistake, wrong type. I will try again.

But with type of MapCanvas “TCastleTransform” i get same error :pensive:

  1. MapCanvas can (and probably should) be just a TCastleTransform type, not TCastleImageTransform.

    TCastleImageTransform is a descendant of TCastleTransform.

    The TCastleTransform is something that can have children, and it has translation, rotation, scale.

    The TCastleImageTransform is like TCastleTransform but additional it can display an image.

    So in your case, MapCanvas (or ParentOfImages in the example I attached) can be just TCastleTransform. Making it a TCastleImageTransform is allowed but a bit pointless – as you do not plan to set MapCanvas.URL to point to any image.

    This is all documented :slight_smile: I advise to follow manual Viewport with scenes, camera, navigation | Manual | Castle Game Engine and follow links from API docs there. E.g. this is API docs for TCastleTransform Castle Game Engine: CastleTransform: Class TCastleTransform , this for TCastleImageTransform: Castle Game Engine: CastleScene: Class TCastleImageTransform .

  2. Viewport.Items.MapCanvas.Add is not a valid Pascal. It would mean that MapCanvas is a property or variable or Viewport.Items. But it is not – it is a variable you declared (either in this routine, or in your class – you didn’t attach full source code so I don’t know which).

    What you want is just MapCanvas.Add(MapTiles[TileNum]);

    I would advise to read our “introduction to modern Pascal”, Modern Object Pascal Introduction for Programmers | Castle Game Engine , and follow examples there. The mistake Viewport.Items.MapCanvas.Add suggests you misunderstand how . (dot to access properties/methods/fields inside a class) works – maybe the Modern Object Pascal Introduction for Programmers | Castle Game Engine will help :slight_smile: I wrote that book exactly with this goal, to help developers to understand the language better. The dot and classes in Pascal are also similar to how classes work in other OOP languages, like C# and Java.

Hope this helps :slight_smile: