void Player::Init(UnitObject* pUnit,ITriangleSelector* pTerrain)
{
    Irrdevice* pDevice 	= Irrdevice::GetInstance();
    m_pUnitObject		= pUnit;

    ISceneManager* pSmgr = pDevice->GetSceneManager();

    SKeyMap aKeyMap[5];
    aKeyMap[0].Action = EKA_MOVE_FORWARD;
    aKeyMap[0].KeyCode = KEY_KEY_W;
    aKeyMap[1].Action = EKA_MOVE_BACKWARD;
    aKeyMap[1].KeyCode = KEY_KEY_S;
    aKeyMap[2].Action = EKA_STRAFE_LEFT;
    aKeyMap[2].KeyCode = KEY_KEY_A;
    aKeyMap[3].Action = EKA_STRAFE_RIGHT;
    aKeyMap[3].KeyCode = KEY_KEY_D;
    aKeyMap[4].Action = EKA_JUMP_UP;
    aKeyMap[4].KeyCode = KEY_SPACE;

    //각 유닛마다 카메라 생성
    m_pCamera = pSmgr->addCameraSceneNodeFPS(0,100.0f,0.5f,-1,aKeyMap,9,false,0,false,false);
    m_pCollisionAnimator = static_cast<ISceneNodeAnimatorCameraFPS*>(*(m_pCamera->getAnimators().begin()));	//카메라가 가지고 있는 FPS 카메라 애니메이션 을 가지온다. 이것은 줌 확대 기능 등!!


    //카메라 따라댕기는 유닉 오브젝트... 방향에 대한것도 설정해줘야함... 이것은 일단 나중에 테스트를 위하여
    m_pUnitObject->GetAnimatedNode()->setParent(m_pCamera);


    IMeshSceneNode* pNode = pSmgr->addCubeSceneNode(10,m_pCamera);
    m_pCamera->addChild(pUnit->GetAnimatedNode());

    pNode->setVisible(true);

    m_pMyTriangle = pSmgr->createTriangleSelector(pNode->getMesh(),pNode);

    m_pMetaTriangle = pSmgr->createMetaTriangleSelector();
    m_pMetaTriangle->addTriangleSelector(pTerrain);

    //역시 스크립트 적용 안할 수가 없다... 파일을 읽어와서 적용하던지.... 아우
    ISceneNodeAnimatorCollisionResponse * pani = pSmgr->createCollisionResponseAnimator(m_pMetaTriangle,m_pCamera);
    m_pCamera->addAnimator(pani);
    pani->drop();

}
Exemple #2
0
int main()
{
	Input input;
	IrrlichtDevice *device = createDevice(video::EDT_DIRECT3D9, dimension2d<u32>(800, 600), 16, false, true, false, &input);
	device->setWindowCaption(L"Seas of Gold");
	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();
	IGUIEnvironment* guienv = device->getGUIEnvironment();
	E_DRIVER_TYPE driverType = driverChoiceConsole();
	EffectHandler *effect = new EffectHandler(device, driver->getScreenSize(), false, true);
	E_FILTER_TYPE filterType = (E_FILTER_TYPE)core::clamp<u32>((u32)3 - '1', 0, 4);
	MapID currentMap;
	int skyR = 30, skyG = 30, skyB = 70;
	int timer = 0;
	SColor sky = SColor(255, skyR, skyG, skyB);
	float plPos_x = 0.0f, plPos_y = 0.0f, plPos_z = 0.0f;
	bool updateCam = true;
	bool menu1 = false;
	int state = Main;
	int frameCount = 0;
	LoadMap loadMap;
	Player player;
	Interface playerInterface(driver);
	ITriangleSelector* selector = 0;
	ISceneNodeAnimator* anim = 0;
	Vendor southVendor;
	Vendor eastVendor;
	Vendor northVendor;
	//InitializeVendors(northVendor, southVendor, eastVendor, itemD);

	//ItemDatabase* itemD = new ItemDatabase;
	ItemDatabase itemD;
	itemD.Initialize();

	//initialize player's inventory
	player.AddGold(1000);
	player.getInventory()->addItem(itemD.getItem(bronzeOre), 50);
	player.getInventory()->addItem(itemD.getItem(ironOre), 50);
	player.getInventory()->addItem(itemD.getItem(goldOre), 50);

	//initialize south vendor's inventory
	southVendor.getInventory()->addItem(itemD.getItem(bronzeOre), 100);
	southVendor.getInventory()->addItem(itemD.getItem(coalOre), 100);
	southVendor.getInventory()->addItem(itemD.getItem(supplies), 1000);

	//initialize north vendor's inventory
	northVendor.getInventory()->addItem(itemD.getItem(obsidianOre), 50);
	northVendor.getInventory()->addItem(itemD.getItem(supplies), 1000);

	//initialize south vendor's inventory
	eastVendor.getInventory()->addItem(itemD.getItem(goldOre), 100);
	eastVendor.getInventory()->addItem(itemD.getItem(ironOre), 100);
	eastVendor.getInventory()->addItem(itemD.getItem(supplies), 1000);

	//Item item(0, "bronzeOre", "Sprites/ore_Bronze.png");
	//Item item2 = item;
	//Item* item2 = itemD.getItem(3);
	//inventory.addItem(&item, 2);
	//inventory.addItem(&item, 2);
	//inventory.addItem(item2, 2);

	//int test = 0;

	// Load the map scene
	//loadMap.Load(smgr, device, Map_Africa);
	//loadMap.Load(smgr, device, Map_India);
	//loadMap.Load(smgr, device, selector, plyrNode, anim, Map_England);

	IAnimatedMeshSceneNode* plyrNode = player.loadPlayerNode(device, smgr);
	//plyrNode->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(plyrNode->isDebugDataVisible() ^ scene::EDS_BBOX));

	ICameraSceneNode* camera = smgr->addCameraSceneNode(0, plyrNode->getPosition() + vector3df(0, 2, 2), vector3df(0, 0, 100));

	loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_Africa);
	currentMap = Map_Africa;
	//loadMap.setCollisions(smgr, selector, plyrNode, anim);

	if (loadMap.CollNode)
	{
		selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32);
		for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++)
		{
			loadMap.CollNode->getMaterial(i).NormalizeNormals = true;
		}
		loadMap.CollNode->setTriangleSelector(selector);
	}

	if (selector)
	{
		anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f),
			core::vector3df(0.0f, -0.725f, 0.0f));

		plyrNode->addAnimator(anim);
	}

	ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();

	////////////// The Sun ////////////
	ILightSceneNode *sun_node;
	SLight sun_data;
	ISceneNode *sun_billboard;
	float sun_angle = 0;
	video::SColorf Diffuse_Night = video::SColorf(0.0f, 0.0f, 0.0f, 1.0f);
	video::SColorf Diffuse_Day = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f);

	sun_node = smgr->addLightSceneNode();
	sun_data.Direction = vector3df(0, 0, 0);
	sun_data.Type = video::ELT_DIRECTIONAL;
	sun_data.AmbientColor = video::SColorf(0.1f, 0.1f, 0.1f, 1);
	sun_data.SpecularColor = video::SColorf(0, 0, 0, 0);
	sun_data.DiffuseColor = Diffuse_Day;
	sun_data.CastShadows = true;
	sun_node->setLightData(sun_data);
	sun_node->setPosition(vector3df(0, 0, 0));
	sun_node->setRotation(vector3df(0, 0, 0));

	sun_billboard = smgr->addBillboardSceneNode(sun_node, core::dimension2d<f32>(60, 60));
	if (sun_billboard)
	{
		sun_billboard->setPosition(vector3df(0, 0, -100));
		sun_billboard->setMaterialFlag(video::EMF_LIGHTING, false);
		sun_billboard->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
		sun_billboard->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
		sun_billboard->setMaterialTexture(0, driver->getTexture("Assets/particlewhite.bmp"));
	}
	/////////// End ////////////

	//------- candleLight -----//
	ILightSceneNode *candleLight = smgr->addLightSceneNode();
	SLight candleLight_data;

	candleLight_data.Type = video::ELT_POINT;
	candleLight_data.DiffuseColor = SColorf(1.0f, 0.546f, 0.016f, 1.0f);
	candleLight_data.SpecularColor = video::SColorf(0, 0, 0, 0);
	candleLight->setPosition(vector3df(2.43467f, 1.55795f, -3.94657));
	candleLight_data.Radius = 1.5f;
	candleLight->setLightData(candleLight_data);
	//------- end -----//

	//// Make the player
	//player.AddGold(1000);
	//player.SetCurrentPort(eMapDest::South);
	//Item* itemCi = new Item("Iron Ore", 1);
	//player.getItems()->addItem(itemCi);
	//Item* itemCb = new Item("Bronze Ore", 1);
	//player.getItems()->addItem(itemCb);

	//Vendor vN;
	//Item* itemG = new Item("Gold Ore", 1000);
	//vN.getItems()->addItem(itemG);
	//Vendor vS;
	//Item* itemI = new Item("Iron Ore", 1000);
	//vS.getItems()->addItem(itemI);
	//Vendor vE;
	//Item* itemB = new Item("Bronze Ore", 1000);
	//vE.getItems()->addItem(itemB);
	//Vendor northVendor

	//delete &itemD;

	int test99 = 0;


	// Make the menus
	MainMenu mainMenu(device, driver);

	MapMenu mapMenu(device, driver);
	mapMenu.SetPlayer(&player);

	TradeMenu tradeMenu;
	tradeMenu.Initialize(device, driver, &player, &southVendor);
	//TradeMenu tradeMenu(device, driver);
	//tradeMenu.SetPlayer(&player);
	//tradeMenu.SetVendor(&vS);
	//
	CraftingMenu craftMenu(device, driver, &player, itemD);
	//craftMenu.SetPlayer(&player);

	//////////////////////////////////////////////////////////////////////////
	// Initialize timer to compute elapsed time between frames
	//////////////////////////////////////////////////////////////////////////
	__int64 cntsPerSec = 0;
	QueryPerformanceFrequency((LARGE_INTEGER*)&cntsPerSec);
	float secsPerCnt = 1.0f / (float)cntsPerSec;

	__int64 prevTimeStamp = 0;
	QueryPerformanceCounter((LARGE_INTEGER*)&prevTimeStamp);

	while (device->run())
	{
		//for scaling animation by time, not by frame
		__int64 currTimeStamp = 0;
		QueryPerformanceCounter((LARGE_INTEGER*)&currTimeStamp);
		float dt = (currTimeStamp - prevTimeStamp) * secsPerCnt;

		sun_node->setRotation(vector3df(sun_angle, 0.0f, 0.0f));
		sun_angle += dt;
		frameCount += 1;
		if ((sun_angle > 0 && sun_angle < 109) || (sun_angle>350))
		{
			timer++;
			if (timer > 10)
			{
				if (skyR < 100) skyR += 1;
				if (skyG < 100) skyG += 1;
				if (skyB < 140) skyB += 1;
				timer = 0;
			}
		}
		if (sun_angle > 170 && sun_angle < 330)
		{
			timer++;
			if (timer > 10)
			{
				if (skyR > 0) skyR -= 1;
				if (skyG > 0) skyG -= 1;
				if (skyB > 40) skyB -= 1;
				timer = 0;
			}
		}

		player.updatePlayer(plyrNode, dt, collMan, selector);
		playerInterface.update(plyrNode, loadMap, driver, device, input, updateCam, state);

		switch (state)
		{
		case Map:
		{
			int out = mapMenu.Update(&input, frameCount);

			switch (out)
			{
			case eMapDest::Exit:
			{
				state = None;
				break;
			}
			case eMapDest::East:
			{
				state = None;
				//Item* itemB = new Item("Bronze Ore", 1000);
				//vE.getItems()->addItem(itemB);
				tradeMenu.SetVendor(&eastVendor);
				loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_India);
				currentMap = Map_India;
				if (loadMap.CollNode)
				{
					selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32);

					for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++)
					{
						loadMap.CollNode->getMaterial(i).NormalizeNormals = true;
					}
					loadMap.CollNode->setTriangleSelector(selector);
				}

				if (selector)
				{
					anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f),
						core::vector3df(0.0f, -0.725f, 0.0f));
					plyrNode->addAnimator(anim);
				}
				collMan = smgr->getSceneCollisionManager();
				break;
			}
			case eMapDest::North:
			{
				state = None;
				//Item *itemG = new Item("Gold Ore", 1000);
				//vN.getItems()->addItem(itemG);
				//tradeMenu.SetVendor(&vN);
				tradeMenu.SetVendor(&northVendor);
				loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_England);
				currentMap = Map_England;
				if (loadMap.CollNode)
				{
					selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32);

					for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++)
					{
						loadMap.CollNode->getMaterial(i).NormalizeNormals = true;
					}
					loadMap.CollNode->setTriangleSelector(selector);
				}

				if (selector)
				{
					anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f),
						core::vector3df(0.0f, -0.725f, 0.0f));
					plyrNode->addAnimator(anim);
				}
				collMan = smgr->getSceneCollisionManager();
				break;
			}
			case eMapDest::South:
			{
				state = None;
				//Item *itemI = new Item("Iron Ore", 1000);
				//vS.getItems()->addItem(itemI);
				//tradeMenu.SetVendor(&vS);
				tradeMenu.SetVendor(&southVendor);
				loadMap.Load(smgr, device, selector, plyrNode, anim, driver, Map_Africa);
				currentMap = Map_Africa;
				if (loadMap.CollNode)
				{
					selector = smgr->createOctreeTriangleSelector(loadMap.CollNode->getMesh(), loadMap.CollNode, 32);

					for (int i = 0; i < loadMap.CollNode->getMaterialCount(); i++)
					{
						loadMap.CollNode->getMaterial(i).NormalizeNormals = true;
					}
					loadMap.CollNode->setTriangleSelector(selector);
				}

				if (selector)
				{
					anim = smgr->createCollisionResponseAnimator(selector, plyrNode, vector3df(0.6f, 0.75f, 0.4f), core::vector3df(0.0f, -0.05f, 0.0f),
						core::vector3df(0.0f, -0.725f, 0.0f));
					plyrNode->addAnimator(anim);
				}
				collMan = smgr->getSceneCollisionManager();
				break;
			}
			default:
				break;
			}

			break;
		}
		case Trade:
		{

			bool out = false;
			out = tradeMenu.Update(&input, frameCount, device, currentMap);
			if (out)
				state = None;
			break;
		}
		case Main:
		{
			int out = mainMenu.Update(&input, frameCount);

			switch (out)
			{
			case MSstart:
			{
				state = None;
				break;
			}
			case MSexit:
			{
				device->closeDevice();
				//return 0;
				break;
			}
			default:
				break;
			}

			break;
		}
		case Craft:
		{
			bool out = craftMenu.Update(&input, frameCount, device);
			if (out)
				state = None;
			break;
		}
		default:
			// Do nothing
			break;
		}

		if (updateCam) moveCameraControl(plyrNode, device, camera);

		////////////////////////////////////////////////////////

		if (sun_angle > 360) sun_angle = 0;
		if (sun_angle < 180) sun_data.DiffuseColor = Diffuse_Day; else sun_data.DiffuseColor = Diffuse_Night;
		sun_node->setLightData(sun_data);

		sky.setRed(skyR);
		sky.setGreen(skyG);
		sky.setBlue(skyB);
		driver->beginScene(true, true, sky);

		smgr->drawAll();

		playerInterface.render(driver, state);

		// Draw the menu
		switch (state)
		{
		case Map:
		{
			mapMenu.Draw(driver, device);
			break;
		}
		case Trade:
		{
			tradeMenu.Render(driver, device);
			break;
		}
		case Main:
		{
			mainMenu.Draw(driver);
			break;
		}
		case Craft:
		{
			craftMenu.Draw(driver);
			break;
		}
		default:
			// Do nothing
			break;
		}

		driver->endScene();
		
		// Update the prev time stamp to current
		prevTimeStamp = currTimeStamp;

	}

	device->drop();

	return 0;
}
/** Test that collision response animator will reset itself when removed from a
	scene node, so that the scene node can then be moved without the animator
	jumping it back again. */
bool collisionResponseAnimator(void)
{
	IrrlichtDevice * device = irr::createDevice(video::EDT_NULL);
	assert(device);
	if(!device)
		return false;

	ISceneManager * smgr = device->getSceneManager();

	// Create 2 nodes to the left of a "wall"
	ISceneNode * testNode1 = smgr->addEmptySceneNode();
	ISceneNode * testNode2 = smgr->addEmptySceneNode();
	testNode1->setPosition(vector3df(-50, 0,0));
	testNode2->setPosition(vector3df(-50, 0,0));

	// Create a "wall" node, and collision response animators for each test node.
	IMeshSceneNode * wallNode = smgr->addCubeSceneNode(10.f);

	ITriangleSelector * wallSelector = smgr->createTriangleSelectorFromBoundingBox(wallNode);
	ISceneNodeAnimatorCollisionResponse * collisionAnimator1 =
		smgr->createCollisionResponseAnimator(wallSelector,
												testNode1,
												vector3df(10,10,10),
												vector3df(0, 0, 0));
	testNode1->addAnimator(collisionAnimator1);

	CMyCollisionCallback collisionCallback;
	collisionAnimator1->setCollisionCallback(&collisionCallback);

	collisionAnimator1->drop();
	collisionAnimator1 = 0;

	ISceneNodeAnimatorCollisionResponse * collisionAnimator2 =
		smgr->createCollisionResponseAnimator(wallSelector,
												testNode2,
												vector3df(10,10,10),
												vector3df(0, 0, 0));
	testNode2->addAnimator(collisionAnimator2);
	collisionAnimator2->setCollisionCallback(&collisionCallback);

	wallSelector->drop();
	// Don't drop() collisionAnimator2 since we're going to use it.

	// Get the system in a good state
	device->run();
	smgr->drawAll();

	// Try to move both nodes to the right of the wall.
	// This one should be stopped by its animator.
	testNode1->setPosition(vector3df(50, 0,0));
	collisionCallback.setNextExpectedCollision(testNode1,
												vector3df(-5.005f, 0, 0),
												vector3df(-15.005f, 0, 0),
												false);

	// Whereas this one, by forcing the animator to update its target node, should be
	// able to pass through the wall. (In <=1.6 it was stopped by the wall even if
	// the animator was removed and later re-added);
	testNode2->setPosition(vector3df(50, 0,0));
	collisionAnimator2->setTargetNode(testNode2);
	collisionAnimator2->drop(); // We're done using this now.

	device->run();
	smgr->drawAll();

	bool result = true;

	if(testNode1->getAbsolutePosition().X > -15.f)
	{
		logTestString("collisionResponseAnimator test node 1 wasn't stopped from moving.\n");
		assert(false);
		result = false;
	}

	if(testNode2->getAbsolutePosition().X < 50.f)
	{
		logTestString("collisionResponseAnimator test node 2 was stopped from moving.\n");
		assert(false);
		result = false;
	}

	// Now try to move the second node back through the wall again. Now it should be
	// stopped by the wall.
	testNode2->setPosition(vector3df(-50, 0, 0));

	// We'll consume this collision, so the node will actually move all the way through.
	collisionCallback.setNextExpectedCollision(testNode2,
												vector3df(5.005f, 0, 0),
												vector3df(15.005f, 0, 0),
												true);

	device->run();
	smgr->drawAll();

	if(testNode2->getAbsolutePosition().X != -50.f)
	{
		logTestString("collisionResponseAnimator test node 2 was stopped from moving.\n");
		assert(false);
		result = false;
	}

	// Now we'll try to move it back to the right and allow it to be stopped.
	collisionCallback.setNextExpectedCollision(testNode2,
												vector3df(-5.005f, 0, 0),
												vector3df(-15.005f, 0, 0),
												false);
	testNode2->setPosition(vector3df(50, 0, 0));

	device->run();
	smgr->drawAll();

	if(testNode2->getAbsolutePosition().X > -15.f)
	{
		logTestString("collisionResponseAnimator test node 2 moved too far.\n");
		assert(false);
		result = false;
	}


	device->drop();

	result &= expectedCollisionCallbackPositions;
	return result;
}
/** Test functionality of the ISceneNodeAnimator implementations. */
bool sceneNodeAnimator(void)
{
	IrrlichtDevice * device = irr::createDevice(video::EDT_NULL, dimension2d<u32>(160, 120));
	assert_log(device);
	if(!device)
		return false;

	ISceneManager * smgr = device->getSceneManager();

	// Test the hasFinished() method.
	ISceneNodeAnimatorCollisionResponse* collisionResponseAnimator
		= smgr->createCollisionResponseAnimator(0, 0);

	ISceneNodeAnimator* deleteAnimator = smgr->createDeleteAnimator(1);

	ISceneNodeAnimator* flyCircleAnimator = smgr->createFlyCircleAnimator();

	ISceneNodeAnimator* flyStraightAnimator
		= smgr->createFlyStraightAnimator(vector3df(0, 0, 0), vector3df(0, 0, 0), 1, false);

	ISceneNodeAnimator* flyStraightAnimatorLooping
		= smgr->createFlyStraightAnimator(vector3df(0, 0, 0), vector3df(0, 0, 0), 1, true);

	ISceneNodeAnimator* rotationAnimator = smgr->createRotationAnimator(vector3df(0, 0, 0));

	array<vector3df> points;
	points.push_back(vector3df(0, 0, 0));
	points.push_back(vector3df(0, 0, 0));
	ISceneNodeAnimator* followSplineAnimator = smgr->createFollowSplineAnimator(0, points, 1000.f);

	array<video::ITexture*> textures;
	textures.push_back(0);
	textures.push_back(0);

	ISceneNodeAnimator* textureAnimator = smgr->createTextureAnimator(textures, 1, false);
	ISceneNodeAnimator* textureAnimatorLooping = smgr->createTextureAnimator(textures, 1, true);

	bool result = true;

	ISceneNode * deletedNode = smgr->addEmptySceneNode();
	deletedNode->addAnimator(deleteAnimator);

	ISceneNode * testNode = smgr->addEmptySceneNode();
	testNode->addAnimator(collisionResponseAnimator);
	testNode->addAnimator(deleteAnimator);
	testNode->addAnimator(flyCircleAnimator);
	testNode->addAnimator(flyStraightAnimator);
	testNode->addAnimator(flyStraightAnimatorLooping);
	testNode->addAnimator(rotationAnimator);
	testNode->addAnimator(followSplineAnimator);
	testNode->addAnimator(textureAnimator);
	testNode->addAnimator(textureAnimatorLooping);

	result &= !collisionResponseAnimator->hasFinished();
	result &= !deleteAnimator->hasFinished();
	result &= !flyCircleAnimator->hasFinished();
	result &= !flyStraightAnimator->hasFinished();
	result &= !flyStraightAnimatorLooping->hasFinished();
	result &= !rotationAnimator->hasFinished();
	result &= !followSplineAnimator->hasFinished();
	result &= !textureAnimator->hasFinished();
	result &= !textureAnimatorLooping->hasFinished();

	device->run();
	device->sleep(10);
	device->run();
	smgr->drawAll();

	// These animators don't have an endpoint.
	result &= !collisionResponseAnimator->hasFinished();
	result &= !flyCircleAnimator->hasFinished();
	result &= !rotationAnimator->hasFinished();
	result &= !followSplineAnimator->hasFinished();

	// These animators are looping and so can't finish.
	result &= !flyStraightAnimatorLooping->hasFinished();
	result &= !textureAnimatorLooping->hasFinished();

	// These have an endpoint and have reached it.
	result &= deleteAnimator->hasFinished();
	result &= flyStraightAnimator->hasFinished();
	result &= textureAnimator->hasFinished();

	collisionResponseAnimator->drop();
	deleteAnimator->drop();
	flyCircleAnimator->drop();
	flyStraightAnimator->drop();
	flyStraightAnimatorLooping->drop();
	rotationAnimator->drop();
	followSplineAnimator->drop();
	textureAnimator->drop();
	textureAnimatorLooping->drop();

	device->closeDevice();
	device->run();
	device->drop();

	if(!result)
	{
		logTestString("One or more animators has a bad hasFinished() state\n.");
		assert_log(false);
	}

	return result;
}