I'm assinging a swipe event to a cocos2dx sprite but basically the problem is the event is assigned to the whole screen. I want it to be assigned only to the single sprite. Here is my code:
rect = Sprite::create();
rect->setTextureRect(Rect(0, 0, 180, 80));
// ekranın y ekseninde ortası | visibleSize.height / 2 + origin.y
rect->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height + 80));
auto grad = LayerGradient::create(Color4B(255, 255, 38, 255), Color4B(199, 173, 68, 255));
grad->changeHeight(rect->getContentSize().height);
grad->changeWidth(rect->getContentSize().width);
//grad->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
//grad->addChild(rect);
rect->addChild(grad);
this->addChild(rect);
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = CC_CALLBACK_2(GameScene::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(GameScene::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(GameScene::onTouchEnded, this);
listener->onTouchCancelled = CC_CALLBACK_2(GameScene::onTouchCancelled, this);
listener->setSwallowTouches(true);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, rect);
A touch event is usually triggered when the player touches the screen. The best way to implement a listener on a sprite would be by sub-classing it:
http://www.cocos2d-x.org/wiki/How_To_Subclass_Sprite_And_Add_Event_Listeners
You can later check the collision of the touch within the sprite listener event (on Touch Began) and then perform your function
Related
I have added a widget to a graphic scene QGraphicScene through a QGraphicsProxyWidget. To move it I have set QGraphicsRectitem as its parent. The widget is resized with the use of a sizegrip.
The first time I create an object I can enlarge it upto some dimension. The second time I can enlarge it less than the first one. The third time less than the second one and so on.
It seems to me that it behaves randomly. Why is this happening?
Here is the code:
void GraphicsView::dropEvent(QDropEvent *event)// subclass of QGraphicsView
{
if(event->mimeData()->text() == "Dial")
{
auto *dial= new Dial; // The widget
auto *handle = new QGraphicsRectItem(QRect(event->pos().x(),event->pos().y(), 120, 120)); // Created to move and select on scene
auto *proxy = new QGraphicsProxyWidget(handle); // Adding the widget through the proxy
dial->setGeometry(event->pos().x()+10,event->pos().y()+10, 100, 100);
proxy->setWidget(dial);
QSizeGrip * sizeGrip = new QSizeGrip(dial);
QHBoxLayout *layout = new QHBoxLayout(dial);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(sizeGrip, 0, Qt::AlignRight | Qt::AlignBottom);
handle->setPen(QPen(Qt::transparent));
handle->setBrush(Qt::gray);
handle->setFlags(QGraphicsItem::ItemIsMovable |
QGraphicsItem::ItemIsSelectable);
scene->addItem(handle); // adding to scene
connect(dial, &Dial::sizeChanged, [dial, handle](){ handle->setRect(dial->geometry().adjusted(-10, -10, 10, 10));});
} }
I cannot enlarge the widget more than that, what is shown in the image.
Your Dial can't be resized past the GraphicView's right (horizonally) and bottom (vertically) edges. If you make the scene big enough, say 2000x2000 (setSceneRect(2000, 2000);), scrollbars will appear. If you move the scrollbars manually, you will be able to enlarge your widgets more.
You could also experiment with automatic scrollbar movement by changing the lambda function like this:
connect(dial, &Dial::sizeChanged, [this, dial, handle](){
handle->setRect(dial->geometry().adjusted(-10, -10, 10, 10));
int dx = handle->rect().bottomRight().x() > viewport()->rect().bottomRight().x();
int dy = handle->rect().bottomRight().y() > viewport()->rect().bottomRight().y();
if (dx > 0) {
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx);
}
if (dy > 0) {
verticalScrollBar()->setValue(verticalScrollBar()->value() + dy);
}
});
Please note, that although this code works, is is very cumbersome. However, it could give you an idea how to start.
I am having trouble drawing a basic white rectangle using the Cocos2dx library in the iOS environment. I have looked at a couple of other implementations for guidance.
http://discuss.cocos2d-x.org/t/draw-rectangle-with-drawrect-in-cocos2dx-not-working/14836/3
Cocos2d-x: How can I draw a resizing rectangle?
It basically looks like I need to use the class method of DrawNode::create() to make the node, then establish the vertices like in openGL, then draw it with the DrawNode->drawPolygon method and add the child node to the scene with the addChild method of the cocos2d::Layer subclass.
Here is my code.
bool JFScene::init()
{
if ( !Layer::init() )
{
return false;
}
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(JFScene::menuCloseCallback, this));
closeItem->setScale(2.0);
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
origin.y + closeItem->getContentSize().height/2));
auto menu = Menu::create(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);
auto CButton = Sprite::create("CButton.png");
CButton->setPosition(
Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)
);
this->addChild(CButton, 1);
auto rectNode = DrawNode::create();
Vec2 vertices[4] = {
Vec2(-50, -50),
Vec2(50, -50),
Vec2(50, 50),
Vec2(-50, 50)
};
rectNode->drawPolygon(vertices, 4, Color4F::WHITE, 1, Color4F::WHITE);
this->addChild(rectNode);
return true;
}
The odd thing is that the CButton Node appears to render when I run it on my iPhone 5s as well as the close item that was included in the default file, but the white rectangle I am trying to draw does not render. Any ideas why?
You want to draw a rectangle... Look at this code snippet:
auto rectNode = DrawNode::create();
Vec2 rectangle[4];
rectangle[0] = Vec2(-50, -50);
rectangle[1] = Vec2(50, -50);
rectangle[2] = Vec2(50, 50);
rectangle[3] = Vec2(-50, 50);
Color4F white(1, 1, 1, 1);
rectNode->drawPolygon(rectangle, 4, white, 1, white);
this->addChild(rectNode);
I hope it works for you.
Reference: cocso2d-x forum
Besides, I recommend you take a look at this similar question if you didn't.
I'm having trouble with my MFC application
It's supposed to display the coordinates of the window, and then when you move the window, display a new line with the new coordinates. My problem is that the OnMove() function seems to be called immediately and everything is always displayed all at once.
Here is my code for OnPaint():
void CMainFrame::OnPaint()
{
CRect rect;
HWND hWnd;
CPaintDC dc(this); // device context for painting
GetClientRect(&rect);
CString topLeftx, topLefty, topRightx, topRighty;
CString bottomLeftx, bottomLefty, bottomRightx, bottomRighty;
CString topLeft, topRight, bottomLeft, bottomRight;
CString topLeftxL, topLeftyL, topRightxL, topRightyL;
CString bottomLeftxL, bottomLeftyL, bottomRightxL, bottomRightyL;
CString topLeftL, topRightL, bottomLeftL, bottomRightL;
topLeftx.Format(_T("%d"), (rect.TopLeft().x));
topLefty.Format(_T("%d"), rect.TopLeft().y);
topLeft = topLeftx + "," + topLefty;
topRightx.Format(_T("%d"), rect.TopLeft().x + rect.Width());
topRighty.Format(_T("%d"), rect.TopLeft().y);
topRight = topRightx + "," + topRighty;
bottomLeftx.Format(_T("%d"), rect.BottomRight().x - rect.Width());
bottomLefty.Format(_T("%d"), rect.BottomRight().y);
bottomLeft = bottomLeftx + "," + bottomLefty;
bottomRightx.Format(_T("%d"), rect.BottomRight().x);
bottomRighty.Format(_T("%d"), rect.BottomRight().y);
bottomRight = bottomRightx + "," + bottomRighty;
GetWindowRect(&rect);
topLeftxL.Format(_T("%d"), rect.left);
topLeftyL.Format(_T("%d"), rect.top);
topLeftL = topLeftxL + "," + topLeftyL;
topRightxL.Format(_T("%d"), rect.TopLeft().x + rect.Width());
topRightyL.Format(_T("%d"), rect.TopLeft().y);
topRightL = topRightxL + "," + topRightyL;
bottomLeftxL.Format(_T("%d"), rect.BottomRight().x - rect.Width());
bottomLeftyL.Format(_T("%d"), rect.BottomRight().y);
bottomLeftL = bottomLeftxL + "," + bottomLeftyL;
bottomRightxL.Format(_T("%d"), rect.BottomRight().x);
bottomRightyL.Format(_T("%d"), rect.BottomRight().y);
bottomRightL = bottomRightxL + "," + bottomRightyL;
dc.TextOutW(0, 20, _T("Hello from ROSSSSSSS!!!!"));
dc.TextOutW(0, 40, _T("TopLeft:"));
dc.TextOutW(60, 40, topLeft);
dc.TextOutW(130, 40, _T("TopRight:"));
dc.TextOutW(200, 40, topRight);
dc.TextOutW(280, 40, _T("BottomLeft:"));
dc.TextOutW(365, 40, bottomLeft);
dc.TextOutW(445, 40, _T("BottomRight:"));
dc.TextOutW(550, 40, bottomRight);
dc.TextOutW(0, 60, _T("TopLeft:"));
dc.TextOutW(60, 60, topLeftL);
dc.TextOutW(130, 60, _T("TopRight:"));
dc.TextOutW(200, 60, topRightL);
dc.TextOutW(280, 60, _T("BottomLeft:"));
dc.TextOutW(365, 60, bottomLeftL);
dc.TextOutW(445, 60, _T("BottomRight:"));
dc.TextOutW(550, 60, bottomRightL);
Invalidate();
UpdateWindow();
}
And here is OnMove
void CMainFrame::OnMove(int x, int y)
{
CFrameWnd::OnMove(x, y);
CDC *dc;
dc = GetDC();
Invalidate();
dc->TextOutW(0, 80, _T("TEST"));
UpdateWindow();
}
Any idea why the word TEST appears as soon as I run the application instead of waiting for a move?
Because the initial creation and display of a window causes a call to OnMove(). Another hint - you will save many headaches by only drawing text in the OnPaint() function. Other message handlers should capture data for later use by OnPaint(), and not do the drawing immediately.
I'm newbie in cocos2d-x and I need your help.
I need to make transparent a touched portion of the layer.
How to make a portion of the layer transparent? I had thought to use ССClippingNode, but I'm not find examples or docs.
I use C++. Thanks.
In TestCpp, project that was added to all cocos2d-x version, you can find examples of CCClipingNode.
If you want to hide part of CCNode(for example "layer") using CCClipingNode, you should add your layer to CCClipingNode.
This is the example that you can paste in the HelloWorld init:
bool HelloWorld::init()
{
if ( !CCLayer::init() )
{
return false;
}
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
addChild(CCLayerColor::create(ccc4(122, 144, 0, 255), visibleSize.width, visibleSize.height));
//this is the layer that we want to "cut"
CCLayer *layer = CCLayer::create();
CCSprite* pSprite = CCSprite::create("HelloWorld.png");
pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
layer->addChild(pSprite, 0);
//we need to create a ccnode, which will be a stencil for ccclipingnode, draw node is a good choice for that
CCDrawNode * stecil = CCDrawNode::create();
stecil->drawDot(ccp(visibleSize.width/2 + origin.x - 100, visibleSize.height/2 + origin.y), 30, ccc4f(0, 0, 0, 255));
stecil->drawSegment(ccp(0, 0), ccp(visibleSize.width, visibleSize.height), 20, ccc4f(0, 0, 0, 255));
//CCClipingNode show the intersection of stencil and theirs children
CCClippingNode *cliper = CCClippingNode::create(stecil);
//you want to hide intersection so we setInverted to true
cliper->setInverted(true);
cliper->addChild(layer);
addChild(cliper);
return true;
}
I tried to use Direct2D in our map application. But it is much more slower than GDI because D2D draw the whole screen.
When user scroll the window, GDI scroll the video buffer and ONLY draw a small portion of screen. That is why GDI is faster than D2D.
My questions are:
How D2D scroll screen? (Similar to ScrollWindow())
How I only draw a small portion of screen in D2D? (Similar to InvalidateRect() and GetClipBox())
I found a solution in
How to scroll window contents using Direct2D api?
Does anyone have a better solution?
My example is:
D2D1::Matrix3x2F matrix;
CPoint org(GetDeviceScrollPosition());
FLOAT scaleW=(FLOAT)m_totalLog.cx/m_totalDev.cx;
FLOAT scaleH=(FLOAT)m_totalLog.cy/m_totalDev.cy;
if(scaleW > scaleH) scaleW = scaleH;
matrix.SetProduct(D2D1::Matrix3x2F::Scale(scaleW, scaleH, D2D1::Point2F(0.0f, 0.0f)), D2D1::Matrix3x2F::Translation((FLOAT)-org.x, (FLOAT)-org.y));
//"Scale Device Screen" * "Scroll Device Screen"
pRenderTarget->SetTransform(matrix);
in CScrollView. But the performance is very poor.
I found one solution: Using "CDCRenderTarget". Then we can use the scroll/GetClipBox() functions in CScrollView.
void CMFCGdi_D2D2View::OnDraw(CDC* pDC)
{
CMFCGdi_D2D2Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc) return;
// TODO: add draw code for native data here
#define LINE_WIDTH 3
CRect rcInvalid;
pDC->GetClipBox(rcInvalid);
if(rcInvalid.left==0 && rcInvalid.top==0) pDC->FillSolidRect(rcInvalid, RGB(255,0,0));
else pDC->FillSolidRect(rcInvalid, RGB(0, 255, 0)); //visible redraw area
CRect rcLogical;
GetClientRect(rcLogical);
rcLogical.bottom+=GetScrollPosition().y;
rcLogical.right+=GetScrollPosition().x;
m_RenderTarget.BindDC(*pDC, rcLogical);
m_RenderTarget.BeginDraw();
m_RenderTarget.SetTransform(D2D1::Matrix3x2F::Identity());
m_RenderTarget.DrawEllipse(CD2DEllipse(CD2DPointF(150.0f, 150.0f), CD2DSizeF(100., 100.)), m_pBlackBrush, LINE_WIDTH);
m_RenderTarget.DrawLine(CD2DPointF(150.0f, 150.0f), CD2DPointF(150.0f + 100.0f * 0.15425f, 150.0f - 100.0f * 0.988f),
m_pBlackBrush, LINE_WIDTH);
m_RenderTarget.DrawLine(CD2DPointF(150.0f, 150.0f), CD2DPointF(150.0f + 100.0f * 0.525f, 150.0f + 100.0f * 0.8509f),
m_pBlackBrush, LINE_WIDTH);
m_RenderTarget.DrawLine(CD2DPointF(150.0f, 150.0f), CD2DPointF(150.0f - 100.0f * 0.988f, 150.0f - 100.0f * 0.15425f),
m_pBlackBrush, LINE_WIDTH);
HRESULT hr = m_RenderTarget.EndDraw();
if (SUCCEEDED(hr))
{
// Draw the pie chart with GDI.
CPen penBlack(PS_SOLID, LINE_WIDTH, RGB(255, 0, 0));
CPen* pOldPen = pDC->SelectObject(&penBlack);
pDC->Ellipse(300, 50, 500, 250);
POINT pntArray1[2];
pntArray1[0].x = 400;
pntArray1[0].y = 150;
pntArray1[1].x = static_cast<LONG>(400 + 100 * 0.15425);
pntArray1[1].y = static_cast<LONG>(150 - 100 * 0.9885);
POINT pntArray2[2];
pntArray2[0].x = 400;
pntArray2[0].y = 150;
pntArray2[1].x = static_cast<LONG>(400 + 100 * 0.525);
pntArray2[1].y = static_cast<LONG>(150 + 100 * 0.8509);
POINT pntArray3[2];
pntArray3[0].x = 400;
pntArray3[0].y = 150;
pntArray3[1].x = static_cast<LONG>(400 - 100 * 0.988);
pntArray3[1].y = static_cast<LONG>(150 - 100 * 0.15425);
pDC->Polyline(pntArray1, 2);
pDC->Polyline(pntArray2, 2);
pDC->Polyline(pntArray3, 2);
pDC->SelectObject(&pOldPen);
}
}