Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon


26. January 2015

 

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.

 

Creating a Sprite

 

Start by creating a new node in your scene panel.

image

 

Locate and create a “Sprite” node in the resulting dialog:

image

 

Now you need an image file to use as a Sprite.  You could simply copy one into the folder structure of your project at the file system level but in this case I am going to use the Import menu.  Select Import->2D Texture:

image

 

Locate the file ( it doesn’t have to be in your project directory ), and pick where you want it to be located locally, like so:

image

 

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.

image

Select your newly imported 2D Texture.

 

Now in your 2D view you will see your sprite positioned centered about the screen origin:

image

 

Navigating the 2D View

 

Now might be a good time to do a quick overview of how the 2D view works.  Let’s start off by looking at the 2D view itself

(Click image to expand)

image

 

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.

 

Mouse Controls:

Button Action
Left Mouse Button Click Select clicked node
Left Mouse Button Click + Drag Translate or Rotate selected
Middle Mouse Button Pan the scene
Scroll Wheel Zoom in/out

 

Keyboard Controls

Key Action
Q Select Mode
W Translate/Move Mode
E Rotate Mode
Arrow Keys Move selected, very fine
Shift + Arrow Keys Move selected
ESC Unselect
F1 Help Panel
F Center Camera on Selected
Ctrl + F Frame Camera (Zoom to fit) on Selected
Ctrl + P Expand to selected node’s parent
V (hold) Move pivot point

 

Snapping

 

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.

image

 

Using Configure Snap you can set the size of each grid in the snapping overlay.   Now your scene will look like this:

image

 

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.

 

Rotating, Translating and Scaling a Sprite using Code

 

So that covers how to add a Sprite to your world and how to navigate the 2D view, let’s take a quick look at the three most commonly performed actions… translating(moving), scaling and rotating.  The following code does all three:

 
extends Sprite


func _ready():

      #translate to center of the parent, in this case, the viewport
   var newPos = Vector2(self.get_parent().get_rect().size.width/2,self.get_parent().get_rect().size.height/2)
   self.set_pos(newPos)
   
   #rotate by 90 degrees.  set_rot takes radians so we need to convert using in-built function
   self.set_rot(deg2rad(90))
   
   #scale by 2x
   self.set_scale(Vector2(2,2))
   
func _draw():  
   # each frame draw a bounding rect to show boundaries clearer
   self.draw_rect(self.get_item_rect(),Color(0,0,1,0.2))
 

And when you run that, you should see:

image

 

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!

 

One important thing to understand is, all of these transformations happened relative to the Sprite’s pivot point, which by default is at it’s center.  If you zoom in on your Sprite object you should be able to see the pivot point:

image

 

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.

 

Here for example I hit W then left click dragged to move the sprite slightly.  Then I held down V and moved the sprite only and not the pivot point, like so:

image

 

Now if I run the same code, you will see that transforms are performed relative to this point instead of the middle:

image

 

This value can also be controlled in the Inspector.  It is called the offset and it is a value relative to the Node’s center point:

image

 

Or you can change the offset in code.  For example, to make the pivot the bottom left corner of the Sprite, you could do the following:

func _ready():

   var newOffset = Vector2(self.get_item_rect().size.width/2, -self.get_item_rect().size.height/2)
   self.set_offset(newOffset)

 

With the following result:

image

 

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.

 

A Bit about Viewports

 

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!

 

image

 

In the Scene menu select Project Settings.  The following dialog appears ( this is where we set default scene earlier ):

image

 

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.

 

The Video Version

 

Programming , ,

blog comments powered by Disqus

Month List

Popular Comments

Unreal Engine 4.13 Preview Release
Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon


25. August 2016

 

Epic have just released another preview release of Unreal Engine, this time 4.13.  Being a preview this release is not meant for production use, so expect the occasional bug and glitch.  This preview release consists entirely of bug fixes, there are no no features.  There is no forum post about the release this time due to the recent security breach of their forums.  The release was instead announced on the Unreal Engine blog, release notes copied below.

 

4.13 PREVIEW 3 RELEASED

4.13 Preview 3 is now available for download on the launcher! As a reminder, the Preview releases are an early look at what is to come and are not yet production-ready. Here's what you can expect in this release:

FIXED IN PREVIEW 3 - CL 3095848
  • UE-34697 - Samples Trigger Fails for Strategy Game on Android
  • UE-34785 - Successive launches via the Project Launcher yield "LogStats:Warning: MetaData mismatch..." in the console
  • UE-34788 - Launching from Project Launcher consecutively without closing previous launch's command window will crash the game
  • UE-34627 - Crash using Camera Rig Rail when deleting a point moving another
  • UE-34804 - Editor crashes when attempting to change units in project settings
  • UE-34758 - SplineComponent debug render is sometimes not in sync with the current spline points
  • UE-34733 - Crash when closing the timeline tab inside UMG editor and reopening UMG editor
  • UE-34702 - [CrashReport] UE4Editor_CoreUObject!UClass::GetDefaultObject() [class.h:2194]
  • UE-33301 - The cap of a sliced procedural mesh is not affected by lighting
  • UE-30405 - Accessing vertex data from CPU side code can cause crashes on merged skeletal meshes.
  • UE-34701 - Prevent preview scene assets being loaded in-game
  • UE-34776 - Ensure when automapping a rig to a skeletal mesh with matching bone names
  • UE-34015 - Rename OrientationDriver to PoseDriver before release
  • UE-34832 - Debris particles constantly firing in ending sequence of Infiltrator Demo
  • UE-34715 - XB1 fails to compile due to FXAudioDeviceProperties symbols undefined
  • UE-34680 - CLONE - Client stops working and crashes if headphones are unplugged on Windows 10
  • UE-34101 - Stat Soundcues not working
  • UE-34951 - Zero-volume vorbis decoded sounds are too expensive
  • UE-34689 - LOD's pop in after LOD actors is visible in viewport
  • UE-34807 - Force View is enabled after Generating Proxy Meshes
  • UE-34739 - [CrashReport] UE4Editor_Engine!FInitBodiesHelper<0>::CreateShapes_PhysX_AssumesLocked() [bodyinstance.cpp:1282]
  • UE-34348 - Crash opening levels with landscape in them via the command console in standalone game
  • UE-34794 - PS4 packaging failing with GLEO errors in 4.13 for project that worked previously
  • UE-34843 - KiteDemo Standalone crashes on launch
  • UE-34513 - Editor crashes while switching to paint mode if material has a grass output and landscape visibility mask
  • UE-34877 - [CrashReport] UE4Editor_Engine!UMaterialInstance::SetParentInternal() [materialinstance.cpp:2141]
  • UE-33593 - Vulkan projects crash on device
  • UE-34257 - Cannot package project with landscape to mobile
  • UE-32323 - App does not resume after locking and unlocking on iOS
  • UE-34639 - Steam libraries are not being packaged with ShooterGame on Mac
  • UE-34450 - Linux: crashes during crash handling
  • UE-34857 - Mac/iOS: Movies with spaces in name won't play
  • UE-34721 - Blank Blueprints project with Starter Content crashes when PIE Standalone Game or Mobile Preview
  • UE-34852 - Give a better error message if OBB would need Zip64 format
  • UE-34719 - CIS Failure Package UnrealMatch3 IOS
  • UE-19996 - [Linux] Setting fullscreen game resolution below set window resolution does not stretch the game across the window
  • UE-28322 - Converting BSP to static mesh on Linux causes the editor to crash
  • UE-34849 - Force OBB to never use Zip64 format
  • UE-34841 - Possible to read past end of central directory in OBB (NumEntries may be 65535)
  • UE-34699 - Need way to insert newlines in UPL
  • UE-34773 - iOS - Packaged .ipa will not deploy to device via iTunes
  • UE-34735 - Regression: Xbox One ESRAM usage has been disabled, causing severe perf degradation
  • UE-34590 - AtmosphericFog for translucent material is not working correctly with 4.12
  • UE-34514 - Game crashes when opening TM-ShaderModels while running -featureleveles2 -OpenGL
  • UE-34241 - Crash with mesh particles
  • UE-33077 - Editor crashed when exiting PIE session in test map involving FDebugCanvasDrawer::DrawRenderThread
  • UE-34688 - Mac compilation error with ClearBufferData
  • UE-34917 - Screen Percentage post process volume causes black screen flickers during transition in Standalone Game
  • UE-34712 - Media Shaders won't compile in ES2 with integer modulo operations
  • UE-34658 - Text overflows on Material_Properties sample 1.6
  • UE-34667 - Buggy gets stuck on medium speed bumps in Vehicle Advance template
  • UE-34653 - ContentExamples: Landscape examples are solid black in editor viewport
  • UE-34139 - Tutorial Asset outdated in all BP templates causing highlighting to fail
  • UE-34910 - ContentExamples: Parameter is misspelled in Example 1.3 on MorphTargets map
  • UE-34419 - Duplicate mappings on the flying template for the game pad
  • UE-34660 - Navmesh map's floor display banners obscured by navmesh while PIE
  • UE-34846 - SideScrollerCharacter.uasset has been saved with empty engine version
  • UE-34848 - Ledge_17 location is different in Blueprint and code Side Scroller 2D templates
  • UE-34950 - ContentExamples PostProcessing map demo 1.13 post process volume screen percentage is not low enough
  • UE-34907 - Misspelling in Blueprint_Splines level of Content Examples
  • UE-34911 - Misspelling in Cloth level of Content Examples
  • UE-34611 - Crash when trying to edit a key value via the context menu for FVector2D
  • UE-34823 - FBX imported from maya have incorrect tangents
  • UE-34459 - Exported Sequence camera has incorrect tangents
  • UE-34970 - VR Template has FinishCurrentFrame set, which will degrade performance unnecessarily

GameDev News

blog comments powered by Disqus

Month List

Popular Comments