Introduction to Computer Game Production: 2D Graphics based on S. Madhav (2014) Game Programming Algorithms and Techniques, Addison-Wesley

Dr. Mathias Lux Klagenfurt University 2D Graphics

2D rendering mostly limited by display device capabilities • Nowadays LCD • influenced from cathode ray tube (CRT)

By Blue tooth7 (Own work) [CC BY-SA 3.0 (http://creativecommons.org/licenses/by- sa/3.0)], via Wikimedia Commons CRT

• Scan lines and pixels per scan line • way back: vertical blank interval (VBLANK)

Early game systems couldn’t store all pixels in RAM, ie. 320 pixels on 200 scan lines Color Buffers & Vertical Sync

• Newer hardware has color buffer – Game writes into buffer – CRT gun reads from buffer • Problem with synchronization – Buffer updated while reading? – Buffer just updated in VBLANK?

Screen tearing Double Buffering

• Two instead of one buffers – Write into one buffer – Wait for VBLANK, then switch buffers function RenderWorld() // Draw all objects in the game world ... wait for VBLANK swap color buffers } Double & Triple Buffering

• LCD Monitors can still experience tearing – so double buffering is still a good idea • Switching in VBLANK – caps framerate to refresh rate of the monitor – option: switch when ready • Some games use triple buffering – further smooth out frame rates – at cost of input lag, cp. VR Sprites

2D visual object, that can be drawn with a single image at any given frame. • backgrounds, objects, avatars, ... • games often have hundreds of sprites • so sprites need to managed efficiently Sprite Formats and Loading

• Format depends on system capabilities – iOS can natively handle PVR – TGA can be handled natively, but is uncompressed – JPG and PNG have to decoded • Typically ones uses libraries/frameworks – SDL, libGDX, cocos2d, ... Drawing Sprites

• Like painting on a canvas – from back to front • Painter’s Algorithm – All sprites are sorted from back to front – Drawn beginning with the background Painters Algorithm

(CC) BY Gabriel Napetschnig Sprite Class class Sprite ImageFile image int drawOrder int x , y function Draw() // Draw the image at (x,y) ... } } Drawing Sprites

SortedList spriteList // When creating a new sprite... Sprite newSprite = specify image and desired x/y newSprite.drawOrder = set desired draw order value // Add to sorted list based on draw order value spriteList .Add( newSprite.drawOrder , newSprite ) // When it's time to draw... foreach Sprite s in spriteList s .Draw() } Where is (x,y)?

• Choice is arbitrary • Decided upon by framework

(x,y) top left

(x,y) bottom left

(CC) BY Gabriel Napetschnig Animating Sprites

Typically based on flipbook animations • A series of images is played in rapid succession • This creates illusion of motion (>~ 12 fps) • Smooth animation may require 24 fps and more Animation

(CC) BY Gabriel Napetschnig Implementing Animation

• Array of images per Sprite – Example: 0-9 walking, 10-19 running – start, end & current frame have to be managed

class AnimFrameData // The index of the first frame of an animation int startFrame // The total number of frames for said animation int numFrames }

class AnimData // Array of images for all the animations ImageFile images [] // The frame data for all the different animations AnimFrameData frameInfo [] } Animated Sprite

class AnimatedSprite inherits Sprite // All of the animation data AnimData animData // The particular animation that is active int animNum // The frame number of the active animation being displayed int frameNum // Amount of time the current frame has been displayed float frameTime // The FPS the animation is running at (24FPS by default). float animFPS = 24.0f function Initialize( AnimData myData , int startingAnimNum ) function UpdateAnim( float deltaTime ) function ChangeAnim( int num ) } Animated Sprite

• Control speed through animFPS – Go faster, run slower, etc. • Switch animations through animNum – Eg. from walking to running • Synchronize with game time – For switching frames Sprite Sheets

• In the past images’ side length had to be powers of 2 (2, 4, 8, 16, 32, 64, ...) – so padding was applied images to satisfy this • It’s not required any more, but still valid – so padding for an animation ends up with a lot of unused space. • Idea: put everything in a single image file Sprite Sheets Sprite Sheets – TexturePacker

{"frames": [

{ "filename": "barricade.psd", "frame": {"x":371,"y":1587,"w":999,"h":376}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":25,"y":142,"w":999,"h":376}, "sourceSize": {"w":1024,"h":1024} }, { "filename": "car-top1-red.psd", "frame": {"x":1,"y":1,"w":575,"h":1021}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":284,"y":0,"w":575,"h":1021}, "sourceSize": {"w":1024,"h":1024} }, ... TexturePacker 2d Graphics

• Basics • Sprites • Scrolling • Tile Maps Scrolling

• Sometimes games don’t fit on one screen • Avatar moves through world • Camera moves along

 Scrolling

Fair use, https://en.wikipedia.org/w/index.php?curid=533608 Scrolling - Examples

• Xenon 2 Megablast – https://www.youtube.com/watch?v=gBMBXkoTbwE • Rick Dangerous – https://www.youtube.com/watch?v=zfxES5zAuZ8 Single Axis Scrolling

• Scrolling the game world on one axis only – ie. right to left, top to bottom • Infinite Scrollers, eg.Jetpack Joyride – https://www.youtube.com/watch?v=OBWtXm1_a6U • We assume: all textures are in-memory Single Axis Scrolling

• Splitting background in screen sized segments – say 20-30 segments for the sake of an example • Given their world (x,y) coordinates – we can position them on the screen Single Axis Scrolling

Setting up the background const int screenWidth = 960 // An iPhone 4/4S sideways is 960x640 // All the screen-sized image backgrounds string backgrounds [] = { "bg1.png" , "bg2.png" , /*...*/ } // The total number of screen-sized images horizontally int hCount = 0 foreach string s in backgrounds Sprite bgSprite bgSprite.image .Load(s) // 1st screen would be x=0, 2nd x=960, 3rd x=1920, ... bgSprite.x = hCount * screenWidth bgSprite.y = 0 bgSpriteList .Add( bgSprite ) screenCount ++ } Single Axis Scrolling

Painting the background

// camera.x is player.x as long as its clamped within the valid range camera.x = clamp( player.x , screenWidth / 2, hCount * screenWidth – screenWidth / 2) Iterator i = bgSpriteList .begin() while i != bgSpriteList .end() Sprite s = i .value() // find the first bg image to draw if ( camera.x – s.x ) < screenWidth // Image 1: s.x = 0, camera.x = 480, screenWidth/2 = 480 // 0 – 480 + 480 = 0 draw s at ( s.x – camera.x + screenWidth /2, 0) // draw the bg image after this, since it might also be visible i ++ s = i .value() draw s at ( s.x – camera.x + screenWidth /2, 0) break end i ++ loop Infinite Scrolling

• Games that scroll until player dies • There’s no end to the world – endless runners like Canabalt • Textures have to used multiple times – background is repeating Parallax Scrolling

• Background is broken into multiple layers – far away (eg. mountains) moving very slowly – ground layer is moving fastest • Three layers are sufficient – More add to the depth • Used by many popular games – Angry Birds, Jetpack Joyride, … Parallax Scrolling

Source: http://en.wikipedia.org/wiki/Parallax_scrolling Parallax Scrolling: Examples

• Adapt speed per layer:

float speedFactor = 0.2f draw s at ( s.x – ( camera.x – screenWidth /2) * speedFactor , 0)

• Example: Canabalt – https://youtu.be/IMBg75_TiLw?t=1m13s • Example: California Games – https://youtu.be/Qw56bU9Hfww Four Way Scrolling

• World scroll both ways – horizontally and vertically – for most 2D games since Super Mario Bros. 2 • Point of origin? – Often in top left corner Four Way Scrolling

• Implementation adds the y-axis …

// updating camera on y-axis camera.y = clamp(player.y, screenHeight / 2, vCount * screenHeight – screenHeight / 2) [...] // drawing sprites on the right (x,y) draw s at ( s.x – camera.x + screenWidth /2, s.y – camera.y – screenHeight / 2) Tile Maps

• Scrolling of screen sized segments is limited • Considering Legend of Zelda … – huge outdoor landscapes – massive dungeons – https://youtu.be/c4bvZZa5Mtg?t=5m10s Tile Maps

• Tile maps partition worlds – into polygons of equal size – each having a sprite assigned • Tile sets – organize the sprites referenced by the tile map – eg. trees, empty ground, doors, walls, … Jazz Jackrabbit 2 Tile Maps

• Support by many frameworks – Cocos2D, libGDX, , … • Size of the tiles – typically 2^n, ie. square with 32 pixels per side – fitting nicely into common screen sizes • iPhone 960x640 -> 30x20 tiles Tile Set & World Generation

1 2 3 4 5 6

8x3 00001300 12234600 45564613 Benefits of Tile Maps

• Skinning easily possible • Level editor separate from engine • Rapid prototyping with existing tile sets • Support in many frameworks Tiled Open Tile Map Editor Isometric tiles Isometric tiles

• Square tiles rotated by 45° – Sometimes also hexagons • Can exceed boundaries (on top) – Implies depth through painters algorithm – Painting from back ie. trees obstruct other tiles Procedurally generated content

• Tile maps are especially used with procedurally generated game levels – Level design is based on rules – Rules leave a lot of space for randomness – Therefore, a dungeon looks different every time you enter it. • Examples – Spelunky – tile maps – Diablo – isometric tiles maps