4.1. g raphics ii animated image sequences, fonts and image transforms

Download 4.1. G RAPHICS II Animated image sequences, fonts and image transforms

Post on 01-Apr-2015




0 download

Embed Size (px)


  • Slide 1

4.1. G RAPHICS II Animated image sequences, fonts and image transforms Slide 2 Animated image sequences; playback speed and image source Slide 3 An image sequence is simply a series of images, displayed one after the other. If the playback is fast a series of progressive images will appear as continuous, unbroken animation. Typically, how many frame/s are needed to give the appearance of unbroken animation? A 50 frame/s B 30 frame/s C 20 frame/s D 10 frame/s E 5 frame/s Slide 4 TV provides either 25 or 30 frame/s (PAL = 30) Consider the set of 6 images: At 2 frame/s it is not smooth At 10 frame/s it is reasonably smooth A typical animated cartoon run at 12 frame/s Slide 5 Images to be played back as a sequence may reside within a number of different file structures, including: A series of files (1 image per file) A continuous image strip (1 file) An image sheet (1 file) Aside: For best performance, all images should be stored in an image sheet, with all animations using that sheet rendered together. Slide 6 Animating a sequence of images Slide 7 Playback of an image sequence can be integrated into the update/draw loop as follows: During the update phase determine when the next image in the sequence should be selected to provide the target number of frames/second During the draw phase, render the current selected image Aside: The following example is based on the ImageAssetSequence within the Java code repository Slide 8 Assuming the images are stored as an array (or an array of rectangles into a single image sheet) the following parameters can be used to offer different playback options: playCount- number of times to play the animation (-1 = loop forever, 0 = pause) homeFrame frame to display when not animating currentFrame current frame to display animationPeriodms number of ms which a single playback should take animationStartTime start time of the animation (if playback has commenced) private int playCount ; private int homeFrame ; private int currentFrame ; private long animationPeriodms ; private long animationStartTime ; private BufferedImage[] images ; Slide 9 The update() method determines the current frame that should be displayed in the animation. In turn the draw() method simply draws the current frame. public void update () { determineCurrentFrame(); } public void draw(Graphics2D graphics2D, int drawX, int drawY) { graphics2D.drawImage( images[currentFrame], drawX, drawY, null); } Slide 10 A check is made to see if the animation has completed, in which case the playCount is reset to zero. Based on the current time, target animation period and playCount value the current frame is calculated and returned. private int determineCurrentFrame () { long currentTime = GetCurrentTime(); if (animinationStartTime == -1) animinationStartTime = currentTime; if (playCount > 0) { if (currentTime - animinationStartTime > (long) playCount * animationPeriodms) { playCount = 0; } } if (playCount == 0) { currentFrame = homeFrame; } else { long timeIntoAniminationPeriod = (currentTime animinationStartTime) % animationPeriodms; currentFrame = (int) ( (timeIntoAniminationPeriod * (long)images.length ) / animationPeriodms ); } return currentFrame; } Aside: This is a slightly different version of the ImageAssetSequence implementation the later ensures that the end frame of the animation is always drawn at least once. The start time will be reset to -1 anytime the play count is changed. Slide 11 Displaying textual information within games Slide 12 Early fonts were bitmap based. Most modern fonts (e.g. TrueType) are outline based, providing a set of line and curve equations describing the shape of each glyph (character). When drawing a font, the outline is rendered and then filled by an ink colour. Generating text by doing this 50-60 times per second is needlessly expensive. How can we improve performance? Render text once into a bitmap and use bitmap until text changes Revert to using a bitmap font Slide 13 /\\? ", ""); TextElement someText = guiText. getMatchingElement (Hello!"); someText.draw(graphics2D, x, y);"> Load an image asset sequence holding the bitmap font characters. Create a base TextElement, holding the image sequence and a corresponding text-to- image mapping. Use the base TextElement to create text strings that can be drawn. TextElement guiText = new TextElement(this, (ImageAssetSequence) assetManager.retrieveAsset( "GUIFont" ), 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ + "abcdefghijklmnopqrstuvwxyz" + "1234567890`!\"$%^&*()-+={}[];:'@#~,./\\? ", ""); TextElement someText = guiText. getMatchingElement (Hello!"); someText.draw(graphics2D, x, y); Slide 14 Specify and add a SpriteFont content asset (the SpriteFont converts any installed TrueType font into an XNB sprite sheet) Load in the SpriteFont within the game. Use the SpriteBatch. DrawString() method to render text. Courier New 10 0 true Regular SpriteFont spriteFont ; SpriteBatch spriteBatch; spriteFont = content.Load ("SpriteFont"); spriteBatch.Begin(); spriteBatch. DrawString ( spriteFont, Hello! ", position, Color.White); spriteBatch.End(); Aside: For more information on importing fonts, see: http://blogs.msdn.com/shawnhar/ar chive/2007/04/26/bitmap-fonts-in- xna.aspx Slide 15 Assume you have a series of images representing the digits 0 to 9 stored in an array Develop an approach that will take a positive integer score and graphically illustrate it using the image sequence. Start 10 mins9 mins8 mins7 mins6 mins5 mins4 mins3 mins2 mins 1 min 30 secFinished ImageAsset[] digitImage = new ImageAsset[10]; Slide 16 By using the modulus (%) operator the last digit in the score can be extracted and printed. Using integer division, the last digit can then be removed and the process iterated until no more digits remain. void drawScore ( int targetScore ) { int scoreFragment = targetScore; do { int digit = scoreFragment % 10; digitImages[digit].Draw(... ) scoreFragment = scoreFragment / 10; } while(scoreFragment > 9 ); } Aside: When drawing the images, it will be necessary to ensure the draw location of each image is determined. Additionally, the score will need to be drawn right-to-left. Slide 17 Basic forms of image transform Slide 18 A number of affine image transforms can be usefully employed within games, including: Resizing Rotating FlippingFadding Depth of view effects Object rotation Appear / disappear effects Left / right / up / down sprite reuse To do: Consider game applicability Slide 19 drawResizedImage ( Graphics2D graphics2D, BufferedImage image, int drawX, int drawY, double scaleX, double scaleY ) { int newWidth = (int) (image.getWidth() * scaleX ); int newHeight = (int) (image.getHeight() * scaleY ); // Optional if desired int newDrawX = drawX + image.getWidth()/2 - newWidth/2; int newDrawY = drawY + image.getHeight()/2 - newHeight/2; graphics2D.drawImage( image, newDrawX, newDrawY, newWidth, newHeight, null ); } newWidth newHeight drawX, drawY newDrawX, newDrawY SpriteBatch.Draw( Texture2D texture, Rectangle destinationRectangle, Color color ) For Java use: For XNA use: The source texture will be scaled to fit the destination rectangle. Slide 20 drawRotatedImage ( Graphics2D graphics2D, BufferedImage image, int drawX, int drawY, double rotationDeg ) { AffineTransform origAT = graphics2D.getTransform(); AffineTransform rotation = new AffineTransform(); rotation.rotate( Math.toRadians(rotationDeg), drawX + image.getWidth()/2, drawY + image.getHeight()/2 ); graphics2D.setTransform( rotation ); graphics2D.drawImage( image, drawX, drawY, null ); graphics2D.setTransform(origAT); } drawX, drawY For Java use: SpriteBatch.Draw( Texture2D texture, Rectangle destinationRectangle, Nullable sourceRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth ) The source texture will be rotated around the specified origin For XNA use: Slide 21 drawX, drawY For Java use: drawFadedImage ( Graphics2D graphics2D, BufferedImage image, int drawX, int drawY, float alpha ) { Composite origComposite = graphics2D.getComposite(); graphics2D.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, alpha) ); graphics2d.drawImage( image, drawX, drawY, null); graphics2D.setComposite( origComposite ); } Specify a colour with an alpha component < 256, e.g. for 50% fading new Color( ???, ???, ???, 128 ); SpriteBatch.Draw( Texture2D texture, Rectangle destinationRectangle, Color color ) For XNA use: Slide 22 drawX, drawY For Java use: drawHorizFlip (Graphics2D graphics2D, BufferedImage image, int drawX, int drawY ) { int width = image.getWidth(); int height = image.getHeight(); graphics2d.drawImage( image, drawX, drawY+height, drawX+width, drawY, 0, 0, width, height, null); } drawImage ( Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver obs) SpriteBatch.Draw( Texture2D texture, Rectangle destinationRectangle, Nullable sourceRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth ) SpriteEffects includes FlipVertically and FlipHorizontally For XNA use: Slide 23 To do: Continue to explore image repository and select graphics Think about the types of image animation/transform and font usage in your game. Write code snippets to load / display and animate / transform images Today we explored: The basics behind image sequence playback How in-game fonts can be efficiently rendered Some useful image transforms