In this tutorial we are going to be taking a look at what seems to be everyone’s favorite subject, graphics. We are going to start by creating a Sprite. A Sprite is basically a 2D image with spatial information such as scale, rotation and position. We are then going to take a closer look at coordinates and viewports, critical concepts to understand.
The video version of this tutorial is available here.
Start by creating a new node in your scene panel.
Once again, you do not have to import this way, you could have simply copied in the files to your project directory!
Ok, now that we have an image, let’s use it with our Sprite. With the Sprite selected, in the Inspector panel locate Texture, drop it down and select Load.
Select your newly imported 2D Texture.
This is where you position and manipulate the nodes that make up your world. As you can see, the X-axis is marked in red and the Y axis is marked in green. Where the two join, that is the world origin. In this particular example, the viewport ( blue rectangle ) is in the negative Y and positive X quadrant. However, child nodes positioning is relative to it’s parent, so to our sprite 0,0 appears to be the top left corner of the screen.
The selected object is surrounded by a manipulator cage. This can be used to easily scale the image, while left clicking and dragging within the cage will move the selected node around. Remember you can also set positioning information in the Inspector numerically. You can switch to Rotate mode to rotate an object, objects rotate relative to their center point. Pan on the other hand allows you to move the camera itself around, enabling you to “pan” through your world.
Some times snapping can be incredibly useful when laying out a scene. Snapping essentially super imposes a grid over your scene and “snaps” the selected to that grid. To enable Snapping, simply select Use Snap from the Edit Menu.
Note, this grid is just there to help you with accurate placement only! It will not appear when you render your game. Turn if off again by clicking Use Snap again. If you are working on a tile based game, snapping can be invaluable.
Please note, I quite often use self because I find it adds a bit of clarity and frankly makes code completion easier. In the above code, “self” is the inherited class “Sprite”. If you prefer shorter code, you can omit the use of self and it is functionally identical!
It’s the T like cross hair. This point determines where local transforms occur relative to. For example, when you say “rotate 90 degrees’ you are rotating 90 degrees around this point. In the 2D editor, you can move this point ( or more accurately, move the Sprite relative to this point ), by holding the V key down while moving.
So, quick summary… child Nodes are positioned relative to their parents and the top level node is the viewport. All transformations happen relative to an objects offset, that offset is relative to the objects center which by default is the Node’s midpoint.
We should pause a bit to discuss the viewport, it’s a critical concept in graphics. As you may notice in the earlier screenshots, the Viewport is drawn as a blue rectangle, with it’s top left corner at 0,0 in 3D space. By default in Godot 2D, the root node is a viewport, which is why we could access it using get_parent() from our sprite node. So, where exactly are this viewport’s dimensions set? Good question!
These are your key viewport related settings. Obviously width and height are what determine the dimensions of your viewport. There are a few other key settings here too, such as resizable and fullscreen, that determine how the window works on a desktop computer ( these settings are meaningless on mobile devices ). Orientation on the other hand is important to mobile devices ( landscape vs portrait or lengthwise vs widthwise ) but meaningless on PCs. stretch_mode and stretch_aspect are useful for dealing with devices of differing resolutions, we will probably cover this in more detail in a separate posting.
Viewports are critical as they allow you to work across a number of different devices in different resolutions using the same basic code.