增加节点轮廓

This commit is contained in:
Nomango 2018-07-07 18:04:18 +08:00
parent de951eaa40
commit 7e3b224b69
7 changed files with 123 additions and 133 deletions

View File

@ -4,9 +4,8 @@
e2d::Collider::Collider(Node * parent) e2d::Collider::Collider(Node * parent)
: _visible(true) : _visible(true)
, _color(Color::Red, 0.7) , _color(Color::Blue, 0.7)
, _parentNode(parent) , _parentNode(parent)
, _transformed(nullptr)
, _geometry(nullptr) , _geometry(nullptr)
, _enabled(true) , _enabled(true)
, _type(Collider::Type::None) , _type(Collider::Type::None)
@ -16,7 +15,6 @@ e2d::Collider::Collider(Node * parent)
e2d::Collider::~Collider() e2d::Collider::~Collider()
{ {
SafeRelease(_transformed);
SafeRelease(_geometry); SafeRelease(_geometry);
} }
@ -30,11 +28,6 @@ ID2D1Geometry * e2d::Collider::getGeometry() const
return _geometry; return _geometry;
} }
ID2D1TransformedGeometry * e2d::Collider::getTransformedGeometry() const
{
return _transformed;
}
void e2d::Collider::setEnabled(bool enabled) void e2d::Collider::setEnabled(bool enabled)
{ {
_enabled = enabled; _enabled = enabled;
@ -52,7 +45,7 @@ void e2d::Collider::setColor(Color color)
void e2d::Collider::_render() void e2d::Collider::_render()
{ {
if (_transformed && _enabled) if (_geometry && _enabled)
{ {
auto renderer = Renderer::getInstance(); auto renderer = Renderer::getInstance();
// 삿혤늉<ED98A4>뺌岬 // 삿혤늉<ED98A4>뺌岬
@ -61,20 +54,19 @@ void e2d::Collider::_render()
brush->SetColor(_color.toD2DColorF()); brush->SetColor(_color.toD2DColorF());
brush->SetOpacity(1.f); brush->SetOpacity(1.f);
// 삥齡섯부툭旒竟 // 삥齡섯부툭旒竟
renderer->getRenderTarget()->DrawGeometry(_transformed, brush); renderer->getRenderTarget()->DrawGeometry(_geometry, brush);
} }
} }
e2d::Collider::Relation e2d::Collider::getRelationWith(Collider * pCollider) const e2d::Collider::Relation e2d::Collider::getRelationWith(Collider * collider) const
{ {
if (_transformed && pCollider->_transformed) if (_geometry && collider->_geometry)
{ {
if (_enabled && pCollider->_enabled) if (_enabled && collider->_enabled)
{ {
D2D1_GEOMETRY_RELATION relation; D2D1_GEOMETRY_RELATION relation;
_geometry->CompareWithGeometry(
_transformed->CompareWithGeometry( collider->_geometry,
pCollider->_transformed,
D2D1::Matrix3x2F::Identity(), D2D1::Matrix3x2F::Identity(),
&relation &relation
); );
@ -85,14 +77,14 @@ e2d::Collider::Relation e2d::Collider::getRelationWith(Collider * pCollider) con
return Relation::Unknown; return Relation::Unknown;
} }
void e2d::Collider::_recreate(Collider::Type type) void e2d::Collider::_recreate()
{ {
_type = type;
SafeRelease(_geometry); SafeRelease(_geometry);
SafeRelease(_transformed);
switch (type) if (_type == Type::None)
return;
switch (_type)
{ {
case Type::Rect: case Type::Rect:
{ {
@ -147,23 +139,14 @@ void e2d::Collider::_recreate(Collider::Type type)
_geometry = ellipse; _geometry = ellipse;
} }
break; break;
default:
break;
} }
}
void e2d::Collider::_transform() ID2D1TransformedGeometry * _transformed;
{
if (_enabled && _type != Type::None)
{
// 重新生成碰撞体
_recreate(_type);
// 二维变换
Renderer::getFactory()->CreateTransformedGeometry( Renderer::getFactory()->CreateTransformedGeometry(
_geometry, _geometry,
_parentNode->_finalMatri, _parentNode->_finalMatri,
&_transformed &_transformed
); );
} SafeRelease(_geometry);
_geometry = _transformed;
} }

View File

@ -5,6 +5,7 @@ e2d::Config::Config()
: _gameName() : _gameName()
, _nodeDefPivot() , _nodeDefPivot()
, _soundEnabled(true) , _soundEnabled(true)
, _outlineVisible(false)
, _collisionEnabled(false) , _collisionEnabled(false)
, _colliderVisible(false) , _colliderVisible(false)
, _nodeDefColliderType(Collider::Type::None) , _nodeDefColliderType(Collider::Type::None)
@ -21,6 +22,11 @@ void e2d::Config::setGameName(const String & name)
_gameName = name; _gameName = name;
} }
void e2d::Config::setOutlineVisible(bool visible)
{
_outlineVisible = visible;
}
void e2d::Config::setSoundEnabled(bool enabled) void e2d::Config::setSoundEnabled(bool enabled)
{ {
if (_soundEnabled != enabled) if (_soundEnabled != enabled)
@ -63,6 +69,11 @@ bool e2d::Config::isSoundEnabled() const
return _soundEnabled; return _soundEnabled;
} }
bool e2d::Config::isOutlineVisible() const
{
return _outlineVisible;
}
bool e2d::Config::isCollisionEnabled() const bool e2d::Config::isCollisionEnabled() const
{ {
return _collisionEnabled; return _collisionEnabled;

View File

@ -20,11 +20,15 @@ void e2d::Scene::_render()
{ {
_root->_render(); _root->_render();
if (Game::getInstance()->getConfig()->isOutlineVisible())
{
Renderer::getInstance()->getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
_root->_renderOutline();
}
if (Game::getInstance()->getConfig()->isColliderVisible()) if (Game::getInstance()->getConfig()->isColliderVisible())
{ {
// 恢复矩阵转换
Renderer::getInstance()->getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity()); Renderer::getInstance()->getRenderTarget()->SetTransform(D2D1::Matrix3x2F::Identity());
// 绘制所有几何图形
_root->_renderCollider(); _root->_renderCollider();
} }
} }

View File

@ -47,7 +47,7 @@ void e2d::ColliderManager::updateCollider(Node * node)
{ {
if (node->getCollider()->_type != Collider::Type::None) if (node->getCollider()->_type != Collider::Type::None)
{ {
node->getCollider()->_transform(); node->getCollider()->_recreate();
_nodes.insert(node); _nodes.insert(node);
} }
} }
@ -79,7 +79,8 @@ void e2d::ColliderManager::update()
// 判断两碰撞体交集情况 // 判断两碰撞体交集情况
Collider::Relation relation = node1->getCollider()->getRelationWith(node2->getCollider()); Collider::Relation relation = node1->getCollider()->getRelationWith(node2->getCollider());
// 忽略 UNKNOWN 和 DISJOIN 情况 // 忽略 UNKNOWN 和 DISJOIN 情况
if (relation != Collider::Relation::Unknown && relation != Collider::Relation::Disjoin) if (relation != Collider::Relation::Unknown &&
relation != Collider::Relation::Disjoin)
{ {
// 更新碰撞监听器 // 更新碰撞监听器
Collision::__update(node1, node2); Collision::__update(node1, node2);

View File

@ -22,7 +22,6 @@ e2d::Node::Node()
, _initialMatri(D2D1::Matrix3x2F::Identity()) , _initialMatri(D2D1::Matrix3x2F::Identity())
, _finalMatri(D2D1::Matrix3x2F::Identity()) , _finalMatri(D2D1::Matrix3x2F::Identity())
, _visible(true) , _visible(true)
, _collider(this)
, _parent(nullptr) , _parent(nullptr)
, _parentScene(nullptr) , _parentScene(nullptr)
, _hashName(0) , _hashName(0)
@ -30,6 +29,8 @@ e2d::Node::Node()
, _needTransform(false) , _needTransform(false)
, _autoUpdate(true) , _autoUpdate(true)
, _positionFixed(false) , _positionFixed(false)
, _outline(nullptr)
, _collider(this)
{ {
// 设置默认中心点位置 // 设置默认中心点位置
Point defPivot = Game::getInstance()->getConfig()->getNodeDefaultPivot(); Point defPivot = Game::getInstance()->getConfig()->getNodeDefaultPivot();
@ -39,6 +40,8 @@ e2d::Node::Node()
e2d::Node::~Node() e2d::Node::~Node()
{ {
SafeRelease(_outline);
ActionManager::getInstance()->clearAllBindedWith(this); ActionManager::getInstance()->clearAllBindedWith(this);
ColliderManager::getInstance()->__remove(this); ColliderManager::getInstance()->__remove(this);
for (auto child : _children) for (auto child : _children)
@ -143,6 +146,27 @@ void e2d::Node::_render()
} }
} }
void e2d::Node::_renderOutline()
{
if (_outline)
{
auto renderer = Renderer::getInstance();
// 获取纯色画刷
ID2D1SolidColorBrush * brush = renderer->getSolidColorBrush();
// 设置画刷颜色和透明度
brush->SetColor(D2D1::ColorF(D2D1::ColorF::Red, 0.7f));
brush->SetOpacity(1.f);
// 渲染轮廓
renderer->getRenderTarget()->DrawGeometry(_outline, brush);
}
// 渲染所有子节点的轮廓
for (auto child : _children)
{
child->_renderOutline();
}
}
void e2d::Node::_renderCollider() void e2d::Node::_renderCollider()
{ {
// 绘制自身的几何碰撞体 // 绘制自身的几何碰撞体
@ -190,6 +214,25 @@ void e2d::Node::_updateTransform()
_finalMatri = _finalMatri * _parent->_initialMatri; _finalMatri = _finalMatri * _parent->_initialMatri;
} }
// 为节点创建一个轮廓
ID2D1RectangleGeometry * rectGeo;
ID2D1TransformedGeometry * transformedGeo;
auto factory = Renderer::getFactory();
factory->CreateRectangleGeometry(
D2D1::RectF(0, 0, _width, _height),
&rectGeo
);
factory->CreateTransformedGeometry(
rectGeo,
_finalMatri,
&transformedGeo
);
SafeRelease(rectGeo);
SafeRelease(_outline);
_outline = transformedGeo;
// 更新碰撞体 // 更新碰撞体
ColliderManager::getInstance()->updateCollider(this); ColliderManager::getInstance()->updateCollider(this);
// 标志已执行过变换 // 标志已执行过变换
@ -541,7 +584,7 @@ void e2d::Node::setColliderType(Collider::Type type)
{ {
if (_collider._type != type) if (_collider._type != type)
{ {
_collider._recreate(type); _collider._type = type;
_needTransform = true; _needTransform = true;
} }
} }
@ -760,101 +803,44 @@ void e2d::Node::stopAction(const String& name)
} }
} }
bool e2d::Node::containsPoint(const Point& point) const bool e2d::Node::containsPoint(const Point& point)
{ {
_updateTransform();
if (_outline)
{
BOOL ret = 0; BOOL ret = 0;
// 如果存在碰撞体,用碰撞体判断 _outline->FillContainsPoint(
if (_collider.getGeometry()) D2D1::Point2F(float(point.x), float(point.y)),
{ D2D1::Matrix3x2F::Identity(),
_collider.getGeometry()->FillContainsPoint(
D2D1::Point2F(
float(point.x),
float(point.y)),
_finalMatri,
&ret &ret
); );
}
else
{
// 为节点创建一个临时碰撞体
ID2D1RectangleGeometry * rect;
Renderer::getFactory()->CreateRectangleGeometry(
D2D1::RectF(0, 0, _width, _height),
&rect
);
// 判断点是否在碰撞体内
rect->FillContainsPoint(
D2D1::Point2F(
float(point.x),
float(point.y)),
_finalMatri,
&ret
);
// 删除临时创建的碰撞体
SafeRelease(rect);
}
if (ret) if (ret)
{ {
return true; return true;
} }
}
return false; return false;
} }
bool e2d::Node::intersects(Node * node) const bool e2d::Node::intersects(Node * node)
{ {
// 如果存在碰撞体,用碰撞体判断 _updateTransform();
if (this->_collider.getGeometry() && node->_collider.getGeometry()) node->_updateTransform();
if (_outline)
{ {
Collider::Relation relation = this->_collider.getRelationWith(&node->_collider);
if ((relation != Collider::Relation::Unknown) &&
(relation != Collider::Relation::Disjoin))
{
return true;
}
}
else
{
// 为节点创建一个临时碰撞体
ID2D1RectangleGeometry * pRect1;
ID2D1RectangleGeometry * pRect2;
ID2D1TransformedGeometry * pCollider;
D2D1_GEOMETRY_RELATION relation; D2D1_GEOMETRY_RELATION relation;
// 根据自身大小位置创建矩形
Renderer::getFactory()->CreateRectangleGeometry(
D2D1::RectF(0, 0, _width, _height),
&pRect1
);
// 根据二维矩阵进行转换
Renderer::getFactory()->CreateTransformedGeometry(
pRect1,
_finalMatri,
&pCollider
);
// 根据相比较节点的大小位置创建矩形
Renderer::getFactory()->CreateRectangleGeometry(
D2D1::RectF(0, 0, node->_width, node->_height),
&pRect2
);
// 获取相交状态 // 获取相交状态
pCollider->CompareWithGeometry( _outline->CompareWithGeometry(
pRect2, node->_outline,
node->_finalMatri, D2D1::Matrix3x2F::Identity(),
&relation &relation
); );
// 删除临时创建的碰撞体
SafeRelease(pRect1);
SafeRelease(pRect2);
SafeRelease(pCollider);
if ((relation != D2D1_GEOMETRY_RELATION_UNKNOWN) && if ((relation != D2D1_GEOMETRY_RELATION_UNKNOWN) &&
(relation != D2D1_GEOMETRY_RELATION_DISJOINT)) (relation != D2D1_GEOMETRY_RELATION_DISJOINT))
{ {
return true; return true;
} }
} }
return false; return false;
} }

View File

@ -496,9 +496,6 @@ public:
// 获取 ID2D1Geometry* 对象 // 获取 ID2D1Geometry* 对象
ID2D1Geometry* getGeometry() const; ID2D1Geometry* getGeometry() const;
// 获取 ID2D1TransformedGeometry* 对象
ID2D1TransformedGeometry* getTransformedGeometry() const;
protected: protected:
Collider( Collider(
Node * parent Node * parent
@ -509,12 +506,7 @@ protected:
E2D_DISABLE_COPY(Collider); E2D_DISABLE_COPY(Collider);
// 重新生成 // 重新生成
void _recreate( void _recreate();
Collider::Type type
);
// 二维变换
void _transform();
// 渲染碰撞体 // 渲染碰撞体
void _render(); void _render();
@ -526,7 +518,6 @@ protected:
Node * _parentNode; Node * _parentNode;
Type _type; Type _type;
ID2D1Geometry* _geometry; ID2D1Geometry* _geometry;
ID2D1TransformedGeometry* _transformed;
}; };
@ -757,6 +748,12 @@ public:
const String& name const String& name
); );
// 显示或隐藏节点轮廓
// 默认:隐藏
void setOutlineVisible(
bool visible
);
// 打开或关闭声音 // 打开或关闭声音
// 默认:打开 // 默认:打开
void setSoundEnabled( void setSoundEnabled(
@ -793,6 +790,9 @@ public:
// 获取声音打开状态 // 获取声音打开状态
bool isSoundEnabled() const; bool isSoundEnabled() const;
// 获取节点轮廓显示状态
bool isOutlineVisible() const;
// 获取碰撞监听状态 // 获取碰撞监听状态
bool isCollisionEnabled() const; bool isCollisionEnabled() const;
@ -811,6 +811,7 @@ protected:
protected: protected:
bool _unconfigured; bool _unconfigured;
bool _soundEnabled; bool _soundEnabled;
bool _outlineVisible;
bool _collisionEnabled; bool _collisionEnabled;
bool _colliderVisible; bool _colliderVisible;
String _gameName; String _gameName;

View File

@ -51,12 +51,12 @@ public:
// 判断点是否在节点内 // 判断点是否在节点内
virtual bool containsPoint( virtual bool containsPoint(
const Point& point const Point& point
) const; );
// 判断两物体是否相交 // 判断两物体是否相交
virtual bool intersects( virtual bool intersects(
Node * node Node * node
) const; );
// 获取节点名称 // 获取节点名称
virtual String getName() const; virtual String getName() const;
@ -386,6 +386,9 @@ protected:
// 渲染节点 // 渲染节点
void _render(); void _render();
// 渲染节点轮廓
void _renderOutline();
// 渲染碰撞体轮廓 // 渲染碰撞体轮廓
void _renderCollider(); void _renderCollider();
@ -431,6 +434,7 @@ protected:
Collider _collider; Collider _collider;
Scene * _parentScene; Scene * _parentScene;
Node * _parent; Node * _parent;
ID2D1Geometry* _outline;
D2D1::Matrix3x2F _initialMatri; D2D1::Matrix3x2F _initialMatri;
D2D1::Matrix3x2F _finalMatri; D2D1::Matrix3x2F _finalMatri;
std::vector<Node*> _children; std::vector<Node*> _children;