Ir al contenido

publicidad
publicidad

Foto

Curso MM: 14 Animando la apariencia de los sprites


Este tema ha sido archivado. Esto significa que no puedes responder en este tema.
No hay respuestas en este tema

#1

Escrito 18 agosto 2009 - 21:58

Animando la apariencia de los sprites

El sistema que utiliza el libro es almacenar los frames del sprite en la misma imagen de forma horizontal. La imagen tiene el mismo alto pero el ancho es el ancho del sprite multiplicado por la cantidad de frames. Los sprites ahora tienen que tener en cuenta cuántos fotogramas hay, en cuál están y un retraso que indica cada cuántos ciclos se cambia de un frame a otro.

Añadidos a GameEngine

Los añadidos se harán a las clases Bitmap y Sprite:

Dibujando sólo una parte de un Bitmap

Ahora incluimos un nuevo método llamado DrawPart() que acepta el contexto de dispositivo, las coordenadas y también la posición, ancho y alto del fotograma del Bitmap que queremos dibujar.

[code:1]void Bitmap::DrawPart(HDC hDC, int x, int y, int xPart, int yPart,
int wPart, int hPart, BOOL bTrans, COLORREF crTransColor)
{
if (m_hBitmap != NULL)
{
// Create a memory device context for the bitmap
HDC hMemDC = CreateCompatibleDC(hDC);

// Select the bitmap into the device context
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, m_hBitmap);

// Draw the bitmap to the destination device context
if (bTrans)
TransparentBlt(hDC, x, y, wPart, hPart, hMemDC, xPart, yPart,
wPart, hPart, crTransColor);
else
BitBlt(hDC, x, y, wPart, hPart, hMemDC, xPart, yPart, SRCCOPY);

// Restore and delete the memory device context
SelectObject(hMemDC, hOldBitmap);
DeleteDC(hMemDC);
}
}[/code]

Es parecido al método Draw() excepto que utiliza parámetros para determinar el fotograma a mostrar. De hecho rehacemos el método Draw() para que use DrawPart() para mostrar una imagen en su totalidad.

Cambios en la clase Sprite

Hay que añadir variables a la clase Sprite: m_iNumFrames, m_iCurFrame para llevar la gestión de los fotogramas. m_iFrameDelay, m_iFrameTrigger para gestionar el cambio de fotograma. Se inicializan en el constructor del sprite. Por defecto m_iNumFrames es 1 para los que no usan animación. Las otras tres son 0 porque ese valor es bueno por defecto para un sprite sin animación. Para los que si usan animación habrá que llamar a los métodos SetNumFrames() y SetFrameDelay().

[code:1]void Sprite::SetNumFrames(int iNumFrames)
{
// Set the number of frames
m_iNumFrames = iNumFrames;

// Recalculate the position
RECT rect = GetPosition();
rect.right = rect.left + ((rect.right - rect.left) / iNumFrames);
SetPosition(rect);
}

void SetFrameDelay(int iFrameDelay) { m_iFrameDelay = iFrameDelay; };[/code]

Se recalcula la posición porque ya no se basa en la imagen completa sino en una porción.

Otro cambio es el método GetWidth():

[code:1]int GetWidth() { return (m_pBitmap->GetWidth() / m_iNumFrames); };[/code]

Así se devuelve el ancho de un fotograma o el ancho total si sólo hay uno.

El siguiente médoto actualiza los fotogramas de los sprites:

[code:1]inline void Sprite::UpdateFrame()
{
if ((m_iFrameDelay >= 0) && (--m_iFrameTrigger <= 0))
{
// Reset the frame trigger;
m_iFrameTrigger = m_iFrameDelay;

// Increment the frame
if (++m_iCurFrame >= m_iNumFrames)
m_iCurFrame = 0;
}
}[/code]

A éste método se le llama desde Update(). Primero se asegura de que el fotograma necesita ser actualizado.

[code:1]SPRITEACTION Sprite::Update()
{
// Update the frame
UpdateFrame(); //será lo primero que hagamos.

...
}[/code]

El médoto Draw() actúa diferente si el sprite es animado o no:

[code:1]void Sprite::Draw(HDC hDC)
{
// Draw the sprite if it isn't hidden
if (m_pBitmap != NULL && !m_bHidden)
{
// Draw the appropriate frame, if necessary
if (m_iNumFrames == 1)
m_pBitmap->Draw(hDC, m_rcPosition.left, m_rcPosition.top, TRUE);
else
m_pBitmap->DrawPart(hDC, m_rcPosition.left, m_rcPosition.top,
m_iCurFrame * GetWidth(), 0, GetWidth(), GetHeight(), TRUE);
}
}[/code]

Antes de dibujarlo comprueba si debe usar Draw() o DrawPart().

Programa de ejemplo: Battle Office 2
BattleOffice.h, BattleOffice.cpp

El siguiente código es para el primer sprite animado. Tiene 4 fotogramas y como no se pone retraso cambia de fotograma a máxima velocidad.

[code:1]1: _pGuySprites[3] = new Sprite(_pGuyBitmaps[3], rcBounds, BA_WRAP);
2: _pGuySprites[3]->SetNumFrames(4);
3: _pGuySprites[3]->SetPosition(500, 10);
4: _pGuySprites[3]->SetVelocity(-3, 0);
5: _pGuySprites[3]->SetZOrder(1);
6: _pGuySprites[3]->SetHidden(TRUE);
7: _pGame->AddSprite(_pGuySprites[3]);[/code]

El segundo sprite tiene 4 frames y el retraso se pone a 5, se cambiará el fotograma cada 5 ciclos del juego. Es todo lo que hace falta.

[code:1]1: _pGuySprites[4] = new Sprite(_pGuyBitmaps[4], rcBounds, BA_WRAP);
2: _pGuySprites[4]->SetNumFrames(4);
3: _pGuySprites[4]->SetFrameDelay(5);
4: _pGuySprites[4]->SetPosition(260, 60);
5: _pGuySprites[4]->SetVelocity(5, 0);
6: _pGuySprites[4]->SetZOrder(1);
7: _pGuySprites[4]->SetHidden(TRUE);
8: _pGame->AddSprite(_pGuySprites[4]);[/code]



Código fuente


Este tema ha sido archivado. Esto significa que no puedes responder en este tema.
publicidad
publicidad