#include "HelloWorldScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
return
scene;
}
bool
HelloWorld::init()
{
if
(!Layer::init()) {
return
false
;
}
auto visSize = Director::getInstance()->getVisibleSize();
auto background = Sprite::create(
"background.png"
);
background->setPosition(visSize.width / 2,visSize.height / 2);
addChild(background,1);
_staticDraw = DrawNode::create();
addChild(_staticDraw,100);
_touchDraw = DrawNode::create();
_clip = ClippingNode::create();
_clip->setInverted(
false
);
_clip->setAlphaThreshold(255.0f);
auto foreground = Sprite::create(
"foreground.png"
);
foreground->setPosition(visSize.width / 2,visSize.height / 2);
_clip->addChild(foreground,1);
_clip->setStencil(_touchDraw);
addChild(_clip,101);
initSegments();
initPoints();
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = [=](Touch* touch,Event* event) {
onTouchMoved(touch,event);
return
true
;
};
listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved,
this
);
getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,
this
);
return
true
;
}
void
HelloWorld::onTouchMoved(Touch* touch,Event* event)
{
Point tar(0,0);
Point cur(0,0);
float
distance = 0;
_touchDraw->clear();
auto pos = touch->getLocation();
initAngles(pos);
std::sort(_angles.begin(),_angles.end(),[](
float
x,
float
y) {
return
x < y;
});
std::vector<Point> vertex;
for
(auto angle : _angles) {
Vec2 dlt(
cos
(angle),
sin
(angle));
float
closest = -1;
for
(auto s : _segments) {
if
(getIntersection(Line(pos,pos + dlt),s,cur,distance)) {
if
(closest == -1 || closest > distance) {
closest = distance;
tar = cur;
}
}
}
if
(closest != -1) {
vertex.push_back(tar);
}
}
int
limit = vertex.size() - 1;
for
(
int
i = 0; i < limit; i++) {
_touchDraw->drawTriangle(pos,vertex[i],vertex[i+1],Color4F::WHITE);
}
if
(limit > 0) {
_touchDraw->drawTriangle(pos,vertex[limit],vertex[0],Color4F::WHITE);
}
}
void
HelloWorld::initSegments()
{
_segments.clear();
_segments.push_back(Line(Point(0,360),Point(840,360)));
_segments.push_back(Line(Point(840,0)));
_segments.push_back(Line(Point(840,0),Point(0,0)));
_segments.push_back(Line(Point(0,360)));
_segments.push_back(Line(Point(100,210),Point(120,310)));
_segments.push_back(Line(Point(120,310),Point(200,280)));
_segments.push_back(Line(Point(200,280),Point(140,150)));
_segments.push_back(Line(Point(140,150),Point(100,210)));
_segments.push_back(Line(Point(100,160),110)));
_segments.push_back(Line(Point(120,110),Point(60,60)));
_segments.push_back(Line(Point(60,60),160)));
_segments.push_back(Line(Point(200,100),Point(220,210)));
_segments.push_back(Line(Point(220,Point(300,160)));
_segments.push_back(Line(Point(300,Point(350,40)));
_segments.push_back(Line(Point(350,40),100)));
_segments.push_back(Line(Point(540,300),Point(560,320)));
_segments.push_back(Line(Point(560,320),Point(570,290)));
_segments.push_back(Line(Point(570,290),Point(540,300)));
_segments.push_back(Line(Point(650,170),Point(760,190)));
_segments.push_back(Line(Point(760,190),Point(740,90)));
_segments.push_back(Line(Point(740,90),Point(630,70)));
_segments.push_back(Line(Point(630,70),Point(650,170)));
_segments.push_back(Line(Point(600,265),Point(780,310)));
_segments.push_back(Line(Point(780,Point(680,210)));
_segments.push_back(Line(Point(680,Point(600,265)));
for
(auto s : _segments) {
_staticDraw->drawSegment(s.p1,s.p2,Color4F::WHITE);
}
}
void
HelloWorld::initPoints()
{
for
(auto segment : _segments) {
if
(_points.find(segment.p1) == _points.end()) {
_points.insert(segment.p1);
}
if
(_points.find(segment.p2) == _points.end()) {
_points.insert(segment.p2);
}
}
}
void
HelloWorld::initAngles(
const
Point& touchPos)
{
_angles.clear();
const
float
eps =
static_cast
<
float
>(1e-4);
for
(auto p : _points) {
auto angle =
atan2
(p.y - touchPos.y,p.x - touchPos.x);
_angles.push_back(angle);
_angles.push_back(angle - eps);
_angles.push_back(angle + eps);
}
}
float
HelloWorld::getCross(
const
Vec2& v1,
const
Vec2& v2)
{
return
(v1.x * v2.y - v1.y * v2.x);
}
bool
HelloWorld::getIntersection(
const
Line& ray,
const
Line& segment,
Point& point,
float
& distance)
{
Vec2 v1(ray.p2 - ray.p1);
Vec2 v2(segment.p2 - segment.p1);
float
cross = getCross(v1,v2);
if
(cross == 0) {
return
false
;
}
Vec2 u(ray.p1 - segment.p1);
float
t1 = getCross(v2,u) / cross;
float
t2 = getCross(v1,u) / cross;
if
(t1 < 0 || t2 < 0 || t2 > 1) {
return
false
;
}
point = v1 * t1 + ray.p1;
distance = t1;
return
true
;
}