1 /* 2 ******************************************************************************************* 3 * Dgame (a D game framework) - Copyright (c) Randy Schütt 4 * 5 * This software is provided 'as-is', without any express or implied warranty. 6 * In no event will the authors be held liable for any damages arising from 7 * the use of this software. 8 * 9 * Permission is granted to anyone to use this software for any purpose, 10 * including commercial applications, and to alter it and redistribute it 11 * freely, subject to the following restrictions: 12 * 13 * 1. The origin of this software must not be misrepresented; you must not claim 14 * that you wrote the original software. If you use this software in a product, 15 * an acknowledgment in the product documentation would be appreciated but is 16 * not required. 17 * 18 * 2. Altered source versions must be plainly marked as such, and must not be 19 * misrepresented as being the original software. 20 * 21 * 3. This notice may not be removed or altered from any source distribution. 22 ******************************************************************************************* 23 */ 24 module Dgame.Graphic.Spritesheet; 25 26 private: 27 28 import Dgame.Graphic.Texture; 29 import Dgame.Graphic.Sprite; 30 31 import Dgame.Math.Vector2; 32 import Dgame.Math.Rect; 33 34 import Dgame.System.StopWatch; 35 36 public: 37 38 /** 39 * SpriteSheet extends Sprite and act like a Texture Atlas. 40 * 41 * Author: Randy Schuett (rswhite4@googlemail.com) 42 */ 43 class Spritesheet : Sprite { 44 protected: 45 uint _lastUpdate = 0; 46 uint _execCount = 0; 47 48 public: 49 /** 50 * The timeout between the slides 51 */ 52 uint timeout = 0; 53 /** 54 * The amount of executions of the <b>whole</b> slide 55 * -1 or less means infinite sliding 56 */ 57 int numOfExecutions = -1; 58 59 final: 60 /** 61 * CTor 62 */ 63 @nogc 64 this(ref Texture tex) pure nothrow { 65 super(tex); 66 } 67 68 /** 69 * CTor 70 */ 71 @nogc 72 this(ref Texture tex, const Rect texRect) pure nothrow { 73 this(tex); 74 75 super.setTextureRect(texRect); 76 } 77 78 /** 79 * Returns the last update which means the last happened slide 80 */ 81 @nogc 82 uint lastUpdate() const pure nothrow { 83 return _lastUpdate; 84 } 85 86 /** 87 * Returns the current execution count 88 */ 89 @nogc 90 uint executionCounter() const pure nothrow { 91 return _execCount; 92 } 93 94 /** 95 * Returns if the execution is completed 96 */ 97 @nogc 98 bool isCompleted() const pure nothrow { 99 return this.numOfExecutions >= 0 && _execCount >= this.numOfExecutions; 100 } 101 102 /** 103 * Slide / move the current view of the Texture, 104 * so that the next view of the Texture will be drawn. 105 * This happens by moving the Texture Rect. 106 * 107 * Note: If you reached the end of the Texture, the procedure starts from scratch. 108 */ 109 @nogc 110 void slideTextureRect() nothrow { 111 if (this.isCompleted()) 112 return; 113 114 if ((_lastUpdate + this.timeout) > StopWatch.getTicks()) 115 return; 116 117 _lastUpdate = StopWatch.getTicks(); 118 119 _texRect.x += _texRect.width; 120 if (_texRect.x >= _texture.width) { 121 _texRect.x = 0; 122 _texRect.y += _texRect.height; 123 if (_texRect.y >= _texture.height) { 124 _texRect.y = 0; 125 _execCount++; 126 } 127 } 128 129 // show the last frame if the execution is completed 130 if (this.isCompleted()) { 131 _texRect.x = _texture.width - _texRect.width; 132 _texRect.y = _texture.height - _texRect.height; 133 } 134 135 _updateVertices(); 136 } 137 138 /** 139 * Selects a specific frame and adapts the position of the texture rect. 140 * The index starts at 0 and line by line. 141 * 142 * Note: The size of your Texture and the size of your Texture-Rect should be divisible without a rest. 143 */ 144 @nogc 145 void selectFrame(ubyte index) pure nothrow { 146 immutable uint nof = this.numOfFrames(); 147 if (index >= nof) 148 index = index % nof; 149 150 int sum = index * _texRect.width; 151 152 int x = 0, y = 0; 153 while (sum >= _texRect.width) { 154 x += _texRect.width; 155 if (x >= _texture.width) { 156 x = 0; 157 y += _texRect.height; 158 } 159 160 sum -= _texRect.width; 161 } 162 163 _texRect.x = x; 164 _texRect.y = y; 165 166 _updateVertices(); 167 } 168 169 /** 170 * Returns how many frames this Spritesheet has. 171 * The width / height of the current Texture is divided through 172 * the corresponding width / height of the current Texture-Rect and both values are being multiplied. 173 */ 174 @nogc 175 uint numOfFrames() const pure nothrow { 176 return (_texture.width / _texRect.width) * (_texture.height / _texRect.height); 177 } 178 }