193 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
| // Copyright (C) 2019 Nomango
 | |
| 
 | |
| #pragma once
 | |
| #include "common.h"
 | |
| 
 | |
| // 老虎
 | |
| E2D_DECLARE_SMART_PTR(Tiger);
 | |
| class Tiger
 | |
| 	: public Sprite
 | |
| {
 | |
| 	FramesPtr run_frames;			// 跑步序列帧
 | |
| 	FramesPtr stand_frames;			// 站立序列帧
 | |
| 	bool facing_left;				// 面朝左或面朝右
 | |
| 	bool running;					// 是否正在跑步
 | |
| 	Direction running_direction;	// 跑步方向
 | |
| 
 | |
| public:
 | |
| 	Tiger()
 | |
| 	{
 | |
| 		// 获取图片原始大小
 | |
| 		ImagePtr image = new Image(L"res/tiger.png");
 | |
| 		Size source_size = image->GetSize();
 | |
| 		// 计算每帧图片大小
 | |
| 		Size frame_size = { source_size.x / 5, source_size.y / 3 };
 | |
| 
 | |
| 		// 加载帧动画
 | |
| 		run_frames = new Frames;
 | |
| 		for (int i = 0; i < 6; ++i)
 | |
| 		{
 | |
| 			Point pos = { (i % 5) * frame_size.x, (i / 5) * frame_size.y };
 | |
| 			ImagePtr frame = new Image(L"res/tiger.png", Rect{ pos, frame_size });
 | |
| 			run_frames->Add(frame);
 | |
| 		}
 | |
| 
 | |
| 		stand_frames = new Frames;
 | |
| 		for (int i = 0; i < 6; ++i)
 | |
| 		{
 | |
| 			Point pos = { ((i + 1) % 5) * frame_size.x, ((i + 1) / 5 + 1) * frame_size.y };
 | |
| 			ImagePtr frame = new Image(L"res/tiger.png", Rect{ pos, frame_size });
 | |
| 			stand_frames->Add(frame);
 | |
| 		}
 | |
| 
 | |
| 		// 执行动画
 | |
| 		AddAction(
 | |
| 			Tween::Animation(stand_frames)
 | |
| 			.SetDuration(1000)
 | |
| 			.SetLoops(-1)
 | |
| 		);
 | |
| 
 | |
| 		// 添加按键监听
 | |
| 		AddListener(Event::KeyDown, Closure(this, &Tiger::OnKeyDown));
 | |
| 		AddListener(Event::KeyUp, Closure(this, &Tiger::OnKeyUp));
 | |
| 
 | |
| 		// 默认方向为 Left
 | |
| 		facing_left = true;
 | |
| 		running = false;
 | |
| 
 | |
| 		// 设置锚点
 | |
| 		SetAnchor(0.5f, 0.5f);
 | |
| 	}
 | |
| 
 | |
| 	void OnKeyDown(Event const& e)
 | |
| 	{
 | |
| 		if (e.key.code == KeyCode::Left)
 | |
| 			Run(Direction::Left);
 | |
| 		else if (e.key.code == KeyCode::Right)
 | |
| 			Run(Direction::Right);
 | |
| 		else if (e.key.code == KeyCode::Up)
 | |
| 			Run(Direction::Up);
 | |
| 		else if (e.key.code == KeyCode::Down)
 | |
| 			Run(Direction::Down);
 | |
| 	}
 | |
| 
 | |
| 	void OnKeyUp(Event const& e)
 | |
| 	{
 | |
| 		switch (e.key.code)
 | |
| 		{
 | |
| 		case KeyCode::Left:
 | |
| 		case KeyCode::Right:
 | |
| 		case KeyCode::Up:
 | |
| 		case KeyCode::Down:
 | |
| 			StopRun();
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	void Run(Direction d)
 | |
| 	{
 | |
| 		if (!running)
 | |
| 		{
 | |
| 			running = true;
 | |
| 			StopAllActions();
 | |
| 
 | |
| 			// 执行跑步动画
 | |
| 			AddAction(
 | |
| 				Tween::Animation(run_frames)
 | |
| 				.SetDuration(500)
 | |
| 				.SetLoops(-1)
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		running_direction = d;
 | |
| 		if (running_direction == Direction::Left)
 | |
| 		{
 | |
| 			facing_left = true;
 | |
| 		}
 | |
| 		else if (running_direction == Direction::Right)
 | |
| 		{
 | |
| 			facing_left = false;
 | |
| 		}
 | |
| 
 | |
| 		// 缩放可以调整图片显示方向
 | |
| 		// 缩放至 -1 图片会反转
 | |
| 		SetScaleX(facing_left ? 1.0f : -1.0f);
 | |
| 	}
 | |
| 
 | |
| 	void StopRun()
 | |
| 	{
 | |
| 		if (running)
 | |
| 		{
 | |
| 			running = false;
 | |
| 			StopAllActions();
 | |
| 
 | |
| 			// 执行站立动画
 | |
| 			AddAction(
 | |
| 				Tween::Animation(stand_frames)
 | |
| 				.SetDuration(1000)
 | |
| 				.SetLoops(-1)
 | |
| 			);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	void OnUpdate(Duration dt)
 | |
| 	{
 | |
| 		if (running)
 | |
| 		{
 | |
| 			// 计算移动距离
 | |
| 			// OnUpdate 并不是一个稳定间隔执行的函数, 如果想实现稳定
 | |
| 			// 每秒移动 150 像素, 应根据 dt 参数计算移动距离
 | |
| 			const float moving_per_sec = 150;
 | |
| 			const float distance = moving_per_sec * dt.Seconds();
 | |
| 
 | |
| 			switch (running_direction)
 | |
| 			{
 | |
| 			case Direction::Up:
 | |
| 				Move(0, -distance);
 | |
| 				break;
 | |
| 			case Direction::Down:
 | |
| 				Move(0, distance);
 | |
| 				break;
 | |
| 			case Direction::Left:
 | |
| 				Move(-distance, 0);
 | |
| 				break;
 | |
| 			case Direction::Right:
 | |
| 				Move(distance, 0);
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| };
 | |
| 
 | |
| class Demo4
 | |
| 	: public Scene
 | |
| {
 | |
| public:
 | |
| 	static ScenePtr Create()
 | |
| 	{
 | |
| 		return new Demo4;
 | |
| 	}
 | |
| 
 | |
| 	Demo4()
 | |
| 	{
 | |
| 		// 创建老虎
 | |
| 		TigerPtr tiger = new Tiger;
 | |
| 		// 在屏幕上居中显示
 | |
| 		tiger->SetAnchor(0.5f, 0.5f);
 | |
| 		tiger->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
 | |
| 
 | |
| 		// 创建说明文字
 | |
| 		TextPtr text = new Text(L"按上下左右键移动");
 | |
| 		// 设置节点大小为文字布局大小
 | |
| 		text->SetSize(text->GetLayoutSize());
 | |
| 		// 设置文字位置
 | |
| 		text->SetAnchor(0.5f, 0.5f);
 | |
| 		text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT - 80);
 | |
| 		text->SetAlignment(TextAlign::Center);
 | |
| 
 | |
| 		// 添加到场景
 | |
| 		this->AddChild(tiger);
 | |
| 		this->AddChild(text);
 | |
| 	}
 | |
| };
 |