Files
wagic/JGE/src/JAnimator.cpp
2013-11-29 13:51:13 +01:00

412 lines
8.1 KiB
C++

//-------------------------------------------------------------------------------------
//
// JGE++ is a hardware accelerated 2D game SDK for PSP/Windows.
//
// Licensed under the BSD license, see LICENSE in JGE root for details.
//
// Copyright (c) 2007 James Hui (a.k.a. Dr.Watson) <jhkhui@gmail.com>
//
//-------------------------------------------------------------------------------------
#include "../include/JGE.h"
#include "../include/JResourceManager.h"
#include "../include/JFileSystem.h"
#include "../include/JRenderer.h"
#include "../include/JSprite.h"
#include "../include/JAnimator.h"
#include "tinyxml/tinyxml.h"
//////////////////////////////////////////////////////////////////////////
JAnimator::JAnimator(JResourceManager* resourceMgr)
{
mResource = resourceMgr;
mActive = false;
mAnimating = false;
}
JAnimator::~JAnimator()
{
while (mFrames.size()>0)
{
JAnimatorFrame* frame = mFrames.back();
mFrames.pop_back();
delete frame;
}
mFrames.clear();
}
bool JAnimator::Load(const char* scriptFile)
{
JFileSystem *fileSystem = JFileSystem::GetInstance();
if (fileSystem == NULL) return false;
if (!fileSystem->OpenFile(scriptFile)) return false;
int size = fileSystem->GetFileSize();
char *xmlBuffer = new char[size];
fileSystem->ReadFile(xmlBuffer, size);
TiXmlDocument doc;
doc.Parse(xmlBuffer);
TiXmlNode* script = 0;
TiXmlNode* frame = 0;
TiXmlNode* obj = 0;
TiXmlNode* param = 0;
TiXmlElement* element = 0;
float defaultTime = 0.033f;
script = doc.FirstChild("script");
if (script)
{
element = script->ToElement();
printf("---- Loading %s:%s\n", element->Value(), element->Attribute("name"));
string type[] =
{
"ANIMATION_TYPE_LOOPING",
"ANIMATION_TYPE_ONCE_AND_STAY",
"ANIMATION_TYPE_ONCE_AND_BACK",
"ANIMATION_TYPE_ONCE_AND_GONE",
"ANIMATION_TYPE_PINGPONG"
};
const char* aniType = element->Attribute("type");
for (int i=0;i<5;i++)
if (type[i] == aniType)
{
SetAnimationType(i);
break;
}
float fps;
if (element->QueryFloatAttribute("framerate", &fps) != TIXML_SUCCESS)
fps = 30.0f;
defaultTime = 1/fps;
for (frame = script->FirstChild("frame"); frame; frame = frame->NextSibling())
{
JAnimatorFrame *aniFrame = new JAnimatorFrame(this);
float duration;
element = frame->ToElement();
if (element->QueryFloatAttribute("time", &duration) != TIXML_SUCCESS)
duration = defaultTime;
aniFrame->SetFrameTime(duration);
for (obj = frame->FirstChild(); obj; obj = obj->NextSibling())
{
for (param = obj->FirstChild(); param; param = param->NextSibling())
{
element = param->ToElement();
if (element != NULL)
{
if (element->ValueStr() == "settings")
{
const char* quadName = element->Attribute("quad");
JQuad* quad = mResource->GetQuad(quadName);
float x, y;
float vsize, hsize;
float angle;
int a, r, g, b;
int value;
bool flipped = false;
if (element->QueryFloatAttribute("x", &x) != TIXML_SUCCESS)
x = 0.0f;
if (element->QueryFloatAttribute("y", &y) != TIXML_SUCCESS)
y = 0.0f;
if (element->QueryFloatAttribute("hsize", &hsize) != TIXML_SUCCESS)
hsize = 1.0f;
if (element->QueryFloatAttribute("vsize", &vsize) != TIXML_SUCCESS)
vsize = 1.0f;
if (element->QueryFloatAttribute("rotation", &angle) != TIXML_SUCCESS)
angle = 0.0f;
if (element->QueryIntAttribute("a", &a) != TIXML_SUCCESS)
a = 255;
if (element->QueryIntAttribute("r", &r) != TIXML_SUCCESS)
r = 255;
if (element->QueryIntAttribute("g", &g) != TIXML_SUCCESS)
g = 255;
if (element->QueryIntAttribute("b", &b) != TIXML_SUCCESS)
b = 255;
if (element->QueryIntAttribute("flip", &value) == TIXML_SUCCESS)
flipped = (value==1);
JAnimatorObject *object = new JAnimatorObject();
object->SetQuad(quad);
object->SetPosition(x, y);
object->SetHScale(hsize);
object->SetVScale(vsize);
object->SetRotation(angle);
object->SetColor(ARGB(a,r,g,b));
object->SetFlip(flipped);
aniFrame->AddObject(object);
}
}
}
}
mFrames.push_back(aniFrame);
}
}
fileSystem->CloseFile();
delete[] xmlBuffer;
return true;
}
void JAnimator::Start()
{
mFrameDelta = 1;
mAnimating = true;
mActive = true;
mCurrentFrame = 0;
mFrames[mCurrentFrame]->Start();
}
void JAnimator::Stop()
{
mAnimating = false;
mActive = false;
}
void JAnimator::Pause()
{
mAnimating = false;
}
void JAnimator::Resume()
{
mAnimating = true;
}
void JAnimator::Update(float dt)
{
if (!mAnimating) return;
if (mFrames[mCurrentFrame]->Update(dt))
{
mCurrentFrame+=mFrameDelta;
int frameCount = mFrames.size();
if (mCurrentFrame >= frameCount)
{
if (mAnimationType == JSprite::ANIMATION_TYPE_LOOPING)
mCurrentFrame = 0;
else if (mAnimationType == JSprite::ANIMATION_TYPE_ONCE_AND_GONE)
{
mAnimating = false;
mActive = false;
}
else if (mAnimationType == JSprite::ANIMATION_TYPE_ONCE_AND_STAY)
{
mCurrentFrame = frameCount-1;
mAnimating = false;
}
else if (mAnimationType == JSprite::ANIMATION_TYPE_ONCE_AND_BACK)
{
mCurrentFrame = 0;
mAnimating = false;
}
else // ping pong
{
mFrameDelta *= -1;
mCurrentFrame += mFrameDelta;
}
}
else if (mCurrentFrame < 0)
{
if (mAnimationType == JSprite::ANIMATION_TYPE_PINGPONG)
{
mFrameDelta *= -1;
mCurrentFrame += mFrameDelta;
}
}
if (mAnimating)
mFrames[mCurrentFrame]->Start();
}
}
void JAnimator::Render()
{
if (!mActive)
return;
mFrames[mCurrentFrame]->Render(mX-mHotSpotX, mY-mHotSpotY);
}
bool JAnimator::IsActive()
{
return mActive;
}
bool JAnimator::IsAnimating()
{
return mAnimating;
}
int JAnimator::GetCurrentFrameIndex()
{
return mCurrentFrame;
}
void JAnimator::SetCurrentFrameIndex(int index)
{
if (index < (int)mFrames.size())
mCurrentFrame = index;
}
void JAnimator::SetAnimationType(int type)
{
mAnimationType = type;
}
JResourceManager* JAnimator::GetResourceManager()
{
return mResource;
}
void JAnimator::SetPosition(float x, float y)
{
mX = x;
mY = y;
}
void JAnimator::SetHotSpot(float x, float y)
{
mHotSpotX = x;
mHotSpotY = y;
}
//////////////////////////////////////////////////////////////////////////
JAnimatorFrame::JAnimatorFrame(JAnimator* parent __attribute__((unused)))
{
mTimer = 0.0f;
mFrameTime = 100.0f;
}
JAnimatorFrame::~JAnimatorFrame()
{
while (mObjects.size()>0)
{
JAnimatorObject* obj = mObjects.back();
mObjects.pop_back();
delete obj;
}
mObjects.clear();
}
void JAnimatorFrame::AddObject(JAnimatorObject *obj)
{
mObjects.push_back(obj);
}
bool JAnimatorFrame::Update(float dt)
{
mTimer += dt;
if (mTimer >= mFrameTime)
return true;
else
{
int size = mObjects.size();
for (int i=0;i<size;i++)
mObjects[i]->Update(dt);
return false;
}
}
void JAnimatorFrame::Render(float x, float y)
{
int size = mObjects.size();
for (int i=0;i<size;i++)
mObjects[i]->Render(x, y);
}
void JAnimatorFrame::Start()
{
mTimer = 0.0f;
}
// bool JAnimatorFrame::IsDone()
// {
// return false;
// }
void JAnimatorFrame::SetFrameTime(float duration)
{
mFrameTime = duration;
}
//////////////////////////////////////////////////////////////////////////
JAnimatorObject::JAnimatorObject()
{
mRenderer = JRenderer::GetInstance();
mFlipped = false;
}
JAnimatorObject::~JAnimatorObject()
{
}
void JAnimatorObject::Update(float dt __attribute__((unused)))
{
}
void JAnimatorObject::Render(float x, float y)
{
mQuad->SetHFlip(mFlipped);
mQuad->SetColor(mColor);
mRenderer->RenderQuad(mQuad, x+mX, y+mY, mRotation, mHScale, mVScale);
}
void JAnimatorObject::SetQuad(JQuad *quad) { mQuad = quad; }
void JAnimatorObject::SetPosition(float x, float y) { mX = x; mY = y; }
void JAnimatorObject::SetRotation(float angle) { mRotation = angle; }
void JAnimatorObject::SetHScale(float scale) { mHScale = scale; }
void JAnimatorObject::SetVScale(float scale) { mVScale = scale; }
void JAnimatorObject::SetColor(PIXEL_TYPE color) { mColor = color; }
void JAnimatorObject::SetFlip(bool flag) { mFlipped = flag; }