Khaotic Engine Reborn
Loading...
Searching...
No Matches
sprite_class.cpp
1#include "sprite_class.h"
2
3
4sprite_class::sprite_class()
5{
6 m_vertexBuffer = 0;
7 m_indexBuffer = 0;
8 m_Textures = 0;
9}
10
11
12sprite_class::sprite_class(const sprite_class& other)
13{
14}
15
16
17sprite_class::~sprite_class()
18{
19}
20
21bool sprite_class::Initialize(ID3D11Device* device, ID3D11DeviceContext* deviceContext, int screenWidth, int screenHeight, char* spriteFilename, int renderX, int renderY)
22{
23 bool result;
24
25
26 // Store the screen size.
27 m_screenWidth = screenWidth;
28 m_screenHeight = screenHeight;
29
30 // Store where the sprite should be rendered to.
31 m_renderX = renderX;
32 m_renderY = renderY;
33
34 // Initialize the frame time for this sprite object.
35 m_frameTime = 0;
36
37 // Initialize the vertex and index buffer that hold the geometry for the sprite bitmap.
38 result = InitializeBuffers(device);
39 if (!result)
40 {
41 return false;
42 }
43
44 // Load the textures for this sprite.
45 result = LoadTextures(device, deviceContext, spriteFilename);
46 if (!result)
47 {
48 return false;
49 }
50
51 return true;
52}
53
54
55void sprite_class::Shutdown()
56{
57 // Release the textures used for this sprite.
58 ReleaseTextures();
59
60 // Release the vertex and index buffers.
61 ShutdownBuffers();
62
63 return;
64}
65
66
67bool sprite_class::Render(ID3D11DeviceContext* deviceContext)
68{
69 bool result;
70
71
72 // Update the buffers if the position of the sprite has changed from its original position.
73 result = UpdateBuffers(deviceContext);
74 if (!result)
75 {
76 return false;
77 }
78
79 // Put the vertex and index buffers on the graphics pipeline to prepare them for drawing.
80 RenderBuffers(deviceContext);
81
82 return true;
83}
84
85void sprite_class::Update(float frameTime)
86{
87 // Increment the frame time each frame.
88 m_frameTime += frameTime;
89
90 // Check if the frame time has reached the cycle time.
91 if (m_frameTime >= m_cycleTime)
92 {
93 // If it has then reset the frame time and cycle to the next sprite in the texture array.
94 m_frameTime -= m_cycleTime;
95
96 m_currentTexture++;
97
98 // If we are at the last sprite texture then go back to the beginning of the texture array to the first texture again.
99 if (m_currentTexture == m_textureCount)
100 {
101 m_currentTexture = 0;
102 }
103 }
104
105 return;
106}
107
108
109int sprite_class::GetIndexCount()
110{
111 return m_indexCount;
112}
113
114ID3D11ShaderResourceView* sprite_class::GetTexture()
115{
116 return m_Textures[m_currentTexture].GetTexture();
117}
118
119
120bool sprite_class::InitializeBuffers(ID3D11Device* device)
121{
122 VertexType* vertices;
123 unsigned long* indices;
124 D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
125 D3D11_SUBRESOURCE_DATA vertexData, indexData;
126 HRESULT result;
127 int i;
128
129
130 // Initialize the previous rendering position to negative one.
131 m_prevPosX = -1;
132 m_prevPosY = -1;
133
134 // Set the number of vertices in the vertex array.
135 m_vertexCount = 6;
136
137 // Set the number of indices in the index array.
138 m_indexCount = m_vertexCount;
139
140 // Create the vertex array.
141 vertices = new VertexType[m_vertexCount];
142
143 // Create the index array.
144 indices = new unsigned long[m_indexCount];
145
146 // Initialize vertex array to zeros at first.
147 memset(vertices, 0, (sizeof(VertexType) * m_vertexCount));
148
149 // Load the index array with data.
150 for (i = 0; i < m_indexCount; i++)
151 {
152 indices[i] = i;
153 }
154
155 // Set up the description of the dynamic vertex buffer.
156 vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
157 vertexBufferDesc.ByteWidth = sizeof(VertexType) * m_vertexCount;
158 vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
159 vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
160 vertexBufferDesc.MiscFlags = 0;
161 vertexBufferDesc.StructureByteStride = 0;
162
163 // Give the subresource structure a pointer to the vertex data.
164 vertexData.pSysMem = vertices;
165 vertexData.SysMemPitch = 0;
166 vertexData.SysMemSlicePitch = 0;
167
168 // Now finally create the vertex buffer.
169 result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer);
170 if (FAILED(result))
171 {
172 return false;
173 }
174
175 // Set up the description of the index buffer.
176 indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
177 indexBufferDesc.ByteWidth = sizeof(unsigned long) * m_indexCount;
178 indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
179 indexBufferDesc.CPUAccessFlags = 0;
180 indexBufferDesc.MiscFlags = 0;
181 indexBufferDesc.StructureByteStride = 0;
182
183 // Give the subresource structure a pointer to the index data.
184 indexData.pSysMem = indices;
185 indexData.SysMemPitch = 0;
186 indexData.SysMemSlicePitch = 0;
187
188 // Create the index buffer.
189 result = device->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer);
190 if (FAILED(result))
191 {
192 return false;
193 }
194
195 // Release the arrays now that the vertex and index buffers have been created and loaded.
196 delete[] vertices;
197 vertices = 0;
198
199 delete[] indices;
200 indices = 0;
201
202 return true;
203}
204
205
206void sprite_class::ShutdownBuffers()
207{
208 // Release the index buffer.
209 if (m_indexBuffer)
210 {
211 m_indexBuffer->Release();
212 m_indexBuffer = 0;
213 }
214
215 // Release the vertex buffer.
216 if (m_vertexBuffer)
217 {
218 m_vertexBuffer->Release();
219 m_vertexBuffer = 0;
220 }
221
222 return;
223}
224
225
226bool sprite_class::UpdateBuffers(ID3D11DeviceContext* deviceContent)
227{
228 float left, right, top, bottom;
229 VertexType* vertices;
230 D3D11_MAPPED_SUBRESOURCE mappedResource;
231 VertexType* dataPtr;
232 HRESULT result;
233
234
235 // If the position we are rendering this bitmap to hasn't changed then don't update the vertex buffer.
236 if ((m_prevPosX == m_renderX) && (m_prevPosY == m_renderY))
237 {
238 return true;
239 }
240
241 // If the rendering location has changed then store the new position and update the vertex buffer.
242 m_prevPosX = m_renderX;
243 m_prevPosY = m_renderY;
244
245 // Create the vertex array.
246 vertices = new VertexType[m_vertexCount];
247
248 // Calculate the screen coordinates of the left side of the bitmap.
249 left = (float)((m_screenWidth / 2) * -1) + (float)m_renderX;
250
251 // Calculate the screen coordinates of the right side of the bitmap.
252 right = left + (float)m_bitmapWidth;
253
254 // Calculate the screen coordinates of the top of the bitmap.
255 top = (float)(m_screenHeight / 2) - (float)m_renderY;
256
257 // Calculate the screen coordinates of the bottom of the bitmap.
258 bottom = top - (float)m_bitmapHeight;
259
260 // Load the vertex array with data.
261 // First triangle.
262 vertices[0].position = XMFLOAT3(left, top, 0.0f); // Top left.
263 vertices[0].texture = XMFLOAT2(0.0f, 0.0f);
264
265 vertices[1].position = XMFLOAT3(right, bottom, 0.0f); // Bottom right.
266 vertices[1].texture = XMFLOAT2(1.0f, 1.0f);
267
268 vertices[2].position = XMFLOAT3(left, bottom, 0.0f); // Bottom left.
269 vertices[2].texture = XMFLOAT2(0.0f, 1.0f);
270
271 // Second triangle.
272 vertices[3].position = XMFLOAT3(left, top, 0.0f); // Top left.
273 vertices[3].texture = XMFLOAT2(0.0f, 0.0f);
274
275 vertices[4].position = XMFLOAT3(right, top, 0.0f); // Top right.
276 vertices[4].texture = XMFLOAT2(1.0f, 0.0f);
277
278 vertices[5].position = XMFLOAT3(right, bottom, 0.0f); // Bottom right.
279 vertices[5].texture = XMFLOAT2(1.0f, 1.0f);
280
281 // Lock the vertex buffer.
282 result = deviceContent->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
283 if (FAILED(result))
284 {
285 return false;
286 }
287
288 // Get a pointer to the data in the constant buffer.
289 dataPtr = (VertexType*)mappedResource.pData;
290
291 // Copy the data into the vertex buffer.
292 memcpy(dataPtr, (void*)vertices, (sizeof(VertexType) * m_vertexCount));
293
294 // Unlock the vertex buffer.
295 deviceContent->Unmap(m_vertexBuffer, 0);
296
297 // Release the pointer reference.
298 dataPtr = 0;
299
300 // Release the vertex array as it is no longer needed.
301 delete[] vertices;
302 vertices = 0;
303
304 return true;
305}
306
307
308void sprite_class::RenderBuffers(ID3D11DeviceContext* deviceContext)
309{
310 unsigned int stride;
311 unsigned int offset;
312
313
314 // Set vertex buffer stride and offset.
315 stride = sizeof(VertexType);
316 offset = 0;
317
318 // Set the vertex buffer to active in the input assembler so it can be rendered.
319 deviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset);
320
321 // Set the index buffer to active in the input assembler so it can be rendered.
322 deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
323
324 // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.
325 deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
326
327 return;
328}
329
330bool sprite_class::LoadTextures(ID3D11Device* device, ID3D11DeviceContext* deviceContext, char* filename)
331{
332 std::string textureFilename(256, '0');
333 std::ifstream fin;
334 int i, j;
335 char input;
336 bool result;
337
338
339 // Open the sprite info data file.
340 fin.open(filename);
341 if (fin.fail())
342 {
343 return false;
344 }
345
346 // Read in the number of textures.
347 fin >> m_textureCount;
348
349 // Create and initialize the texture array with the texture count from the file.
350 m_Textures = new texture_class[m_textureCount];
351
352 // Read to start of next line.
353 fin.get(input);
354
355 // Read in each texture file name.
356 for (i = 0; i < m_textureCount; i++)
357 {
358 j = 0;
359 fin.get(input);
360 while (input != '\n')
361 {
362 textureFilename[j] = input;
363 j++;
364 fin.get(input);
365 }
366 textureFilename[j] = '\0';
367
368 // Once you have the filename then load the texture in the texture array.
369 result = m_Textures[i].Initialize(device, deviceContext, textureFilename);
370 if (!result)
371 {
372 return false;
373 }
374 }
375
376 // Read in the cycle time.
377 fin >> m_cycleTime;
378
379 // Convert the integer milliseconds to float representation.
380 m_cycleTime = m_cycleTime * 0.001f;
381
382 // Close the file.
383 fin.close();
384
385 // Get the dimensions of the first texture and use that as the dimensions of the 2D sprite images.
386 m_bitmapWidth = m_Textures[0].GetWidth();
387 m_bitmapHeight = m_Textures[0].GetHeight();
388
389 // Set the starting texture in the cycle to be the first one in the list.
390 m_currentTexture = 0;
391
392 return true;
393}
394
395void sprite_class::ReleaseTextures()
396{
397 int i;
398
399
400 // Release the texture objects.
401 if (m_Textures)
402 {
403 for (i = 0; i < m_textureCount; i++)
404 {
405 m_Textures[i].Shutdown();
406 }
407
408 delete[] m_Textures;
409 m_Textures = 0;
410 }
411
412 return;
413}
414
415
416void sprite_class::SetRenderLocation(int x, int y)
417{
418 m_renderX = x;
419 m_renderY = y;
420 return;
421}