๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ“ Development Study/๐Ÿ’ป Win32API

Animator

by eazuooz 2022. 10. 13.

์˜ˆ์ œ :)

https://github.com/eazuooz/WindowAPI/commit/ba073f8950369851aa3b812bf7ed862141d52784

 

Animation Event · eazuooz/WindowAPI@ba073f8

Show file tree Showing 6 changed files with 48 additions and 4 deletions.

github.com

2D ๊ฒŒ์ž„์—์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์žฌ์ƒ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์€ ์˜ํ™”์—์„œ ์“ฐ์ด๋Š” ๋ฐฉ์‹๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š๋‹ค.

์ด๋Ÿฌํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ธฐ๋ฒ•์„ Sprite ์• ๋‹ˆ๋ฉ”์ด์…˜์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

์ด๋Ÿฌํ•œ ๊ทธ๋ฆผ์„ ํ•œ์žฅ์žฅํ•œ์„ ์›€์ง์ด๋Š” ์ˆœ์„œ๋Œ€๋กœ ๋น ๋ฅธ์‹œ๊ฐ„๋™์•ˆ ์žฌ์ƒ์‹œ์ผœ์ฃผ๋ฉด ๋ˆˆ์˜ ์ฐฉ์‹œ๋กœ ์›€์ง์ด๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ๋œ๋‹ค.

 

์šฐ์„ ์€ Animation์ด ์žฌ์ƒ๋˜๊ฒŒ ํ•˜๋Š” Animator ์ปดํฌ๋„ŒํŠธ์™€ 

Animator ์ปดํฌ๋„ŒํŠธ๋Š” Animation ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

	class Animator : public Component
	{
	public:
		struct Event
		{
			void operator=(std::function<void()> func)
			{
				mEvent = std::move(func);
			}
			void operator()()
			{
				if (mEvent)
					mEvent();
			}
			std::function<void()> mEvent;
		};

	public:
		Animator();
		~Animator();

		virtual void Tick() override;
		virtual void Render(HDC hdc) override;

		void CreateAnimaiton(const std::wstring& name, Image* image
			, Vector2 leftTop, Vector2 size, Vector2 offset
			, float columnLegth, UINT spriteLength, float duration, bool bAffectedCamera = false);
		Animation* FindAnimation(const std::wstring& name);
		void Play(const std::wstring& name, bool bLoop = false);

	public:
		Event mStartEvent;
		Event mCompleteEvent;
		Event mEndEvent;

	private:
		std::map<std::wstring, Animation*> mAnimations;
		Animation* mPlayAnimation;
		bool mbLoop;
	};

	typedef std::map<std::wstring, Animation*>::iterator AnimationsIter;

Animator ์ปดํฌ๋„ŒํŠธ๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ Animation ๋“ค (์˜ˆ : ๋‹ฌ๋ฆฌ๊ธฐ, ๊ฑท๊ธฐ, ๋Œ€๊ธฐ, ์ฃฝ๋Š” ๋ชจ์…˜ ๋“ฑ) ์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ฒŒ ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํ˜„์žฌ ์‹คํ–‰๋˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜์€ PlayAnimation์ด๋‹ค.

Loop๊ฐ€ ํ™œ์„ฑํ™” ๋˜์–ด์žˆ๋‹ค๋ฉด ํ•ด๋‹น ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ์ข…๋ฃŒ๋˜์ง€ ์•Š๊ณ  

๋‹ค์‹œ Reset() ์‹œ์ผœ์„œ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์žฌ์ƒ๋˜๊ฒŒ ๋œ๋‹ค.

 

	void Animator::Tick()
	{
		if (mPlayAnimation != nullptr)
		{
			mPlayAnimation->Tick();
			if (mbLoop && mPlayAnimation->isComplete())
			{
				mCompleteEvent();
				mPlayAnimation->Reset();
			}
		}
	}

 

Event๋Š” ๊ฐ๊ฐ์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ฒ˜์Œ ์žฌ์ƒ๋ ๋–„ StartEvent

ํ•˜๋‚˜์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋™์ž‘์ด ์™„๋ฃŒ๋ ๋–„ CompleteEvent

์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ „ํ™˜๋˜๋ฉด์„œ ๋๋‚ ๋•Œ EndEventํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ๋˜๊ฒŒ ๋˜์–ด์žˆ๋‹ค.

 

๊ทธ๋ž˜์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด Event์— ์•Œ๋งž๋Š” ๋ฉค๋ฒ„ํ•จ์ˆ˜๋ฅผ bind์‹œ์ผœ์ฃผ์–ด์•ผ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋œ๋‹ค.

		Image* pImage
			= Resources::Load<Image>(L"PlayerImage", L"..\\Resources\\Images\\link.bmp");
		Animator* animator = GetComponent<Animator>();
		animator->CreateAnimaiton(L"Walk_Up", pImage, Vector2(0.f, 780.f), Vector2(120.f, 130.f), Vector2(0.f, -30.f), 120.f, 10, 0.1f);
		animator->CreateAnimaiton(L"Walk_Down", pImage, Vector2(0.f, 520.f), Vector2(120.f, 130.f), Vector2(0.f, -30.f), 120.f, 10, 0.1f);
		animator->CreateAnimaiton(L"Walk_Left", pImage, Vector2(0.f, 650.f), Vector2(120.f, 130.f), Vector2(0.f, -30.f), 120.f, 10, 0.1f);
		animator->CreateAnimaiton(L"Walk_Right", pImage, Vector2(0.f, 910.f), Vector2(120.f, 130.f), Vector2(0.f, -30.f), 120.f, 10, 0.1f);

		animator->mStartEvent = std::bind(&Player::AnimationStart, this);
		animator->mCompleteEvent = std::bind(&Player::AnimationComplete, this);
		animator->mEndEvent = std::bind(&Player::AnimationEnd, this);

		animator->Play(L"Walk_Down", true);

ํ•ด๋‹น Event๋“ค์€ ์—ฌ๋Ÿฌ๋ถ„๋“ค์˜ ํŽธ๋ฆฌ์„ฑ์„ ์œ„ํ•ด ์ œ๊ณตํ•œ๊ฒƒ์ด๋‹ค.

 

๊ฐ๊ฐ์˜ Event๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ์ˆœ์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ˜ธ์ถœ๋œ๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

 

์• ๋‹ˆ๋ฉ”์ด์…˜ ํด๋ž˜์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.

	class Image;
	class Animator;
	class Animation : public Entity
	{
	public:
		struct Sprite
		{
			Vector2 leftTop;	// ์ขŒ์ธก ์ƒ๋‹จ ํ”ฝ์…€์ขŒํ‘œ
			Vector2 size;		// ์ขŒ์ธก ์ƒ๋‹จ์œผ๋กœ ๋ถ€ํ„ฐ ์ž˜๋ผ๋‚ผ ๊ฐ€๋กœ ์„ธ๋กœ ํ”ฝ์…€ ๊ธธ์ด
			Vector2 offset;
			float duration;			// ํ•ด๋‹น ํ”„๋ ˆ์ž„ ์œ ์ง€์‹œ๊ฐ„

			Sprite()
				: leftTop(0.0f, 0.0f)
				, size(0.0f, 0.0f)
				, offset(0.0f, 0.0f)
				, duration(0.0f)
			{

			}
		};

	public:
		Animation();
		~Animation();
		
		void Tick();
		void Render(HDC hdc);
		void Create(Image* image, Vector2 leftTop, Vector2 size, Vector2 offset
			, float columnLegth, UINT spriteLength, float duration, bool affectedCamera = false);

		void Reset();

		bool isComplete() { return mbComplete; }
		void SetAnimator(Animator* animator) { mAnimator = animator; }

	private:
		Animator* mAnimator;
		Image* mImage;
		std::vector<Sprite> mSpriteSheet;
		int mSpriteIndex;
		float mTime;
		bool mbComplete;
		bool mbAffectedCamera;
	};

 

Animation ํด๋ž˜์Šค๋Š” Sprite Image๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

์—ฌ๋Ÿฌ๊ฐœ์˜ Sprite ๊ฐ€ ๋ชจ์—ฌ์„œ ํ•˜๋‚˜์˜ Sprite sheet๊ฐ€ ๋˜๊ณ  ๊ทธ๊ฒƒ์ด ํ•˜๋‚˜์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ •๋ณด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

 

์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ƒ์„ฑํ• ๋•Œ ํ•ด๋‹น ์ด๋ฏธ์ง€์—์„œ ์‹œ์ž‘์ ์„ ๊ธฐ์ค€์œผ๋กœ ํ•œ์นธ์”ฉ ์ด๋™ํ•˜๋ฉด์„œ ๊ทธ๋ฆผ๋ณ„๋กœ Sprite์ •๋ณด๋ฅผ Spritesheet์—๋‹ค๊ฐ€ ์ €์žฅํ•œ๋‹ค.

	void Animation::Create(Image* image, Vector2 leftTop, Vector2 size, Vector2 offset
		, float columnLegth, UINT spriteLength, float duration, bool affectedCamera)
	{
		mImage = image;
		mbAffectedCamera = affectedCamera;

		for (size_t i = 0; i < spriteLength; i++)
		{
			Sprite sprite;

			sprite.leftTop.x = leftTop.x + (columnLegth * float(i));
			sprite.leftTop.y = leftTop.y;
			sprite.size = size;
			sprite.offset = offset;
			sprite.duration= duration;

			mSpriteSheet.push_back(sprite);
		}
	}
    
    	void Animation::Tick()
	{
		if (mbComplete)
			return;

		mTime += Time::DeltaTime();
		if (mSpriteSheet[mSpriteIndex].duration < mTime)
		{
			mTime = 0.0f;

			if (mSpriteSheet.size() <= mSpriteIndex + 1)
			{
				mbComplete = true;
			}
			else
			{
				mSpriteIndex += 1;
			}
		}
	}
    
    	void Animation::Render(HDC hdc)
	{
		Object* object = mAnimator->GetOwner();
		Vector2 pos = object->GetPos();
		if (mbAffectedCamera)
			pos = Camera::CalulatePos(pos);

		BLENDFUNCTION func = {};
		func.BlendOp = AC_SRC_OVER;
		func.BlendFlags = 0;
		func.AlphaFormat = AC_SRC_ALPHA;
		func.SourceConstantAlpha = 255;

		pos += mSpriteSheet[mSpriteIndex].offset;
		AlphaBlend(hdc
			, int(pos.x - mSpriteSheet[mSpriteIndex].size.x / 2.0f)
			, int(pos.y - mSpriteSheet[mSpriteIndex].size.y / 2.0f)
			, int(mSpriteSheet[mSpriteIndex].size.x)
			, int(mSpriteSheet[mSpriteIndex].size.y)
			, mImage->GetHdc()
			, int(mSpriteSheet[mSpriteIndex].leftTop.x)
			, int(mSpriteSheet[mSpriteIndex].leftTop.y)
			, int(mSpriteSheet[mSpriteIndex].size.x)
			, int(mSpriteSheet[mSpriteIndex].size.y)
			, func);
	}

์žฌ์ƒํ• ๋•Œ๋Š” ๊ฐ๊ฐ์˜ ํ”„๋ ˆ์ž„๋งˆ๋‹ค ์žฌ์ƒ์‹œ๊ฐ„์„ ๊ณ„์‚ฐํ•œํ›„  sprite๋ฅผ ํ•˜๋‚˜์”ฉ ์žฌ์ƒํ•˜๋ฉด๋œ๋‹ค.

'๐Ÿ“ Development Study > ๐Ÿ’ป Win32API' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Rigidbody  (0) 2022.10.20
API Math  (0) 2022.10.20
Object Delete  (0) 2022.10.12
Alphablend, Camera Effect  (0) 2022.10.05
Camera  (1) 2022.10.04

๋Œ“๊ธ€