Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
There are 2 basic methods to draw 2D stuff in Castle Game Engine:
Simple: Render using TGLImage
TGLImage as your main way to draw. In this approach, you create
TGLImage instance for each image, and then draw it in overridden
TUIControl.Render method. This is the same approach as we use for our user-interface rendering (various
TUIControl instances). The main advantage of this approach is simplicity: you just draw 2D images.
A similar approach is to draw your game using multiple
TCastleImageControl is a simple user-interface control that draws images, using
TGLImage under the hood, exposing mostly the same features.
- http://castle-engine.io/manual_quick_2d_game.php contains some very basic demo of TGLImage usage.
- http://castle-engine.io/manual_2d_user_interface.php talks about our user-interface.
http://castle-engine.io/manual_2d_ui_custom_drawn.php shows the "core" of this approach: new
TUIControldescendant with your own
Renderimplementation, in which we call
The important API reference links: TGLImage and TGLImageCore.
TGLImageCoreis an ancestor of
TGLImage(these 2 classes may be merged into one during CGE 6.6 development; just use
TGLImagein your applications and freely use methods documented at both
TGLImageCorereference). I sometimes use the name
TGLImageCoreinterchangeably here, as I already merged these two classes into one in my head :)
You can render sprites using the appropriate
TGLImage.Drawoverload (where you specify which part of the source image to render). Or use ready class
To render pixel-art, set
Numerous engine demos use
isometric_gamedraws simple map using it.
TSprite, there are also simple drawing helpers like
To have fixed resolution (regardless of the actual window size in pixels), use UI scaling ( http://castle-engine.io/manual_2d_user_interface.php#section_scaling ). However, while it scales correctly all the existing
TUIControlinstances, you will need to put some additional work to make UI scaling affect your custom
TUIControldescendant. This is documented at the bottom of http://castle-engine.io/manual_2d_ui_custom_drawn.php -- basically, look at your
ScreenRectand scale all coordinates by
UIScalebefore passing them to
TGLImage. So the scaling is not hidden from you in this case -- you get the information you need, but you need to put some code to make it happen correctly.
To have the scaling automatically applied, you can use
TCastleImageControlinstead of directly drawing with
TCastleImageControlis an UI control that wraps
TGLImageunderneath, and allows to control the image like a normal UI control: with anchors, automatically applied scaling and so on.
To use custom shader, set
TCastleImageControl.CustomShader. Demo in
Advice when to use: This approach is very easy to start. You have relatively small API to learn. You just learn how to use
TGLImage, and you draw inside your own
TMyControl.Render however you like. If all you really want is a flexible API to draw images -- this is it.
Full-featured: Render using TCastle2DScene
T2DSceneManager in CGE <= 6.4). Add
TCastle2DSceneManager control to the window, and inside it draw things by creating
https://castle-engine.io/manual_load_3d.php introduces the
TCastleScene, an ancestor of
TCastleSceneis incredibly versatile. You can load game models from files. E.g. Spine animations, Blender models etc. You can play animations. Everything described on http://castle-engine.io/manual_scene.php works.
T2DSceneManageris briefly shown in http://castle-engine.io/manual_2d_user_interface.php .
- https://castle-engine.io/manual_physics.php shows how to use physics with it.
- https://castle-engine.io/manual_load_3d.php introduces the
The engine examples
physics/physics_2d_game_sopwith/show this approach.
To construct your own scene (not loaded from external file), you need to create a graph of X3D nodes. Various examples showing it are around the engine, the simpler is http://castle-engine.io/x3d_implementation_geometry2d.php . It instantiates a
TRectangle2DNode. One could instead instantiate also
TIndexedFaceSetNodewhich represents a free mesh, with custom texture coordinates and anything else you may need.
You can render sprites by constructing your own
TIndexedFaceSetNodeinstances and changing texture coordinates. Or you can use existing utility
tools/sprite-sheet-to-x3d/that converts sprite sheets in various formats to an X3D model. Such model can then be easily loaded to
TCastle2DScene, you can play it's animation (using
Scene.PlayAnimationmethod, test with view3dscene menu "Animations -> Names Animations -> ..."). You can look at the X3D file using a text editor to see how the "sprite" is really just an
IndexedFaceSetnode with animated texture coordinates.
To render pixel-art, set texture filtering to "nearest". It's easiest to do this by setting
Scene.Attributes.MagnificationFilter := magNearest. Alternatively, you could control this on a particular shape using
TTexturePropertiesNode, links on http://castle-engine.io/x3d_implementation_texturing.php .
To have fixed resolution (regardless of the actual window size in pixels), set
falseand set either
ProjectionWidth. See the
2d_dragon_spine_gameexample. Or you can use UI scaling ( http://castle-engine.io/manual_2d_user_interface.php#section_scaling ) to just make
TCastle2DSceneManagerhave the same width or height, regardless of the actual window size -- in this case, the projection width or height will be the same, even if you leave
true. All the scaling is completely hidden from you, inside
TCastle2DSceneManageryou just work in your preferred coordinates.
You can use physics in this approach (see example
You can mix 2D and 3D freely.
TCastle2DSceneManageris a descendant of a general
TCastle2DSceneManagerdefines projection settings and controls camera in a way that is usually most comfortable for 2D games, but it does not limit the rendering to 2D in any way. You can insert a
TCastleScenewith 3D content to
(Or you could insert a
TCastle2DSceneinto a 3D world in
TCastleSceneManager. Really, every combination works. The "2D" classes can be mixed, and can even contain, 3D content. The "2D" classes add some comfortable stuff to make 2D rendering more natural (see API docs), but it's nothing limiting.)
To use custom shader, use X3D shader nodes. Demo in
examples/3d_rendering_processing/display_box_custom_shaders.lpr. You can use
ComposedShadernode and friends (that override standard engine shaders, see https://castle-engine.io/x3d_implementation_shaders.php ) or
Effectnode and friends (that extend standard engine shaders, see https://castle-engine.io/compositing_shaders.php ). Various demos as X3D scenes are inside our demo models, see in particular shaders and compositing_shaders subdirectories.
Advice when to use:
This approach is extremely versatile, so this is the approach I advice if you plan to draw something more than images.
This approach is also easy, if you mostly load 2D models from existing files (Spine JSON, X3D exported from Blender or sprite-sheet-to-x3d). But it is a little more work to construct your own X3D graph -- as there are simply a lot of X3D nodes that you can use. But it pays off in my experience, you really can do everything. Our Cat-astrophe Games games ("Dragon Squash", "Escape from the Universe", "The Unholy Society") are all implemented using this approach.
This approach allows engine to take care of animations, physics, and other cool stuff for you.