I'm using CCScrollLayer files at here CCScrollLayer for my cocos2d-x project (version 2.2.2).
I adapted them to make it can scroll vertically. And I got a problem: when I add two CCScrollLayer in a layer, I just can only scroll the last CCScrollLayer that are added.
Here is my code:
I add a layer that contains the two CCScrollLayer to a Scene
void ChooseMapScene::addSlidingLayers()
{
mChooseCharacterLayer = createChooseCharaterLayer();
mChooseCharacterLayer->setPosition(CCPointZero);
mChooseCharacterLayer->setTouchEnabled(true);
this->addChild(mChooseCharacterLayer, GR_FOREGROUND);
}
I add SlideCharacter1 and SlideCharacter2 in a layer (chooseCharacterLayer) but just the SlideCharacter2 can scroll
CCLayer* ChooseMapScene::createChooseCharaterLayer()
{
CCLayer* chooseCharacterLayer = CCLayer::create();
CCArray* characterArr1 = createCharactersArray(CHARACTER_LEFT_LAYER_POS);
CCArray* characterArr2 = createCharactersArray(CHARACTER_RIGHT_LAYER_POS);
mSlideCharacter1 = CCScrollLayerVertical::nodeWithLayers(characterArr1, 0);
chooseCharacterLayer->addChild(mSlideCharacter1, GR_FOREGROUND);
mSlideCharacter2 = CCScrollLayerVertical::nodeWithLayers(characterArr2, 0);
chooseCharacterLayer->addChild(mSlideCharacter2, GR_FOREGROUND);
// I add SlideCharacter1 and SlideCharacter2 in a layer (chooseCharacterLayer) but just the SlideCharacter2 can scroll
return chooseCharacterLayer;
}
.
CCArray* ChooseMapScene::createCharactersArray(CCPoint pPos)
{
CCArray* characterArr = CCArray::createWithCapacity(NUMBER_CHARACTERS);
for (int i = 1; i <= NUMBER_CHARACTERS; ++i)
{
CCLayer* characterLayer = CCLayer::create();
CCSprite* character = CCSprite::create(CCString::createWithFormat("Images/Game/Object/c%i.png", i)->getCString());
character->setPosition(pPos);
characterLayer->addChild(character, GR_FOREGROUND, i);
characterArr->addObject(characterLayer);
}
return characterArr;
}
You can manually call SlideCharacter1's touch methods (began, cancelled, moved, ended) from SlideCharacter2's touch methods to simulate the touches
Related
I build up a ruse of CustomWidgets in a QListWidget. So far, it works well.
A problem occurs when I move the vertical scroll bar downwards and want to display items that were not previously visible.
Then they are inserted as transparent rectangles, I can click them and respond to the clicks, but they are not drawn. They stay transparent!
I insert a picture to get a rough idea of the problem:
In my QListWidget I try to repaint it, but it doesn't work:
QListWidget::verticalScrollbarValueChanged(value);
auto item = this->itemAt(QPoint(24, value));
if (!item)
{
return;
}
auto widget = this->itemWidget(item);
if (!widget)
{
return;
}
// widget->resize(widget->size());
// widget->repaint();
widget->update();
What can I do? Thanks for help!
EDIT:
According to the request of Martin, I insert here a routine, which shows the addition of items:
void ListControl::AddCustomWidget(QWidget* customWidget, const QSize& size, bool forceSize)
{
if (forceSize)
{
customWidget->adjustSize();
}
auto displaySize = customWidget->size();
auto width = size.width();
auto height = size.height();
auto item = new QListWidgetItem(this);
this->addItem(item);
if (width >= 0)
{
displaySize.setWidth(width);
}
else
{
displaySize.setWidth(displaySize.width() - (this->verticalScrollBar()->width() + this->rightSpace));
}
if (height >= 0)
{
displaySize.setHeight(height);
}
item->setSizeHint(displaySize);
this->setItemWidget(item, customWidget);
}
Hey I am developing a Cocos2dx application with XCode and iPhone 5c and I am looking to change the coordinate system to portrait.
I looked at these directions http://www.cocos2d-x.org/wiki/Device_Orientation. According to the direction, you need to change a couple of methods in the RootViewController so that before Cocos does its magic, iOS has already handled rotating the container.
Now the applicable methods of my RootViewController.mm look as follows. It builds and runs.
#ifdef __IPHONE_6_0
- (NSUInteger) supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
#endif
- (BOOL) shouldAutorotate {
return YES;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsPortrait ( interfaceOrientation );
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
auto glview = cocos2d::Director::getInstance()->getOpenGLView();
if (glview)
{
CCEAGLView *eaglview = (__bridge CCEAGLView *)glview->getEAGLView();
if (eaglview)
{
CGSize s = CGSizeMake([eaglview getWidth], [eaglview getHeight]);
cocos2d::Application::getInstance()->applicationScreenSizeChanged((int) s.width, (int) s.height);
}
}
}
#end
The code for the init() method of my level looks like this
bool Level1::init()
{
//////////////////////////////
// 1. super init first
if ( !Scene::init() )
{
return false;
}
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
for(int i= 0; i < MAX_TOUCHES; ++i) {
labelTouchLocations[i] = Label::createWithSystemFont("", "Arial", 42);
labelTouchLocations[i]->setVisible(false);
this->addChild(labelTouchLocations[i]);
}
auto eventListener = EventListenerTouchAllAtOnce::create();
// Create an eventListener to handle multiple touches, using a lambda, cause baby, it's C++11
eventListener->onTouchesBegan = [=](const std::vector<Touch*>&touches, Event* event){
// Clear all visible touches just in case there are less fingers touching than last time
std::for_each(labelTouchLocations,labelTouchLocations+MAX_TOUCHES,[](Label* touchLabel){
touchLabel->setVisible(false);
});
// For each touch in the touches vector, set a Label to display at it's location and make it visible
for(int i = 0; i < touches.size(); ++i){
labelTouchLocations[i]->setPosition(touches[i]->getLocation());
labelTouchLocations[i]->setVisible(true);
labelTouchLocations[i]->setString("Touched");
std::cout << "(" << touches[i]->getLocation().x << "," << touches[i]->getLocation().y << ")" << std::endl;
}
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(eventListener, this);
return true;
}
When I touch the point at the lowest left part of the iPhone, the x coordinate of the touch point I print out is about 150. The y coordinate is 0, as expected. Why is the x coordinate not zero? Is there something I am missing in the creation of the scene? I believe I made all the changes that the Cocos documentation requires. Are their docs out of date?
The coordinate system does not start at (0,0) at the bottom left as would be suggested by the documentation. However, there are simple methods that can be used to get the origin and size of the container that are included in the default scene.
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
I am developing an Application in Xcode using cocos2dx.In my Application I want my admob banner to display in Bottom of the screen, for that I am using the following code. It moves the game content to top and displays the banner in bottom. But I want the banner in bottom without moving the content. The banner is displaying in top without moving the content. please advise me to correct my mistake.
- (void)viewDidLayoutSubviews
{
CGRect contentFrame = self.view.bounds;
CGRect bannerFrame = CGRectZero;
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
bannerFrame = _bannerView.frame;
#else
bannerFrame.size = [_bannerView sizeThatFits:contentFrame.size];
#endif
bannerFrame.origin.x = (contentFrame.size.width - bannerFrame.size.width) / 2;
////To display the banner in Bottom
if (_bannerLoaded) {
contentFrame.size.height -= bannerFrame.size.height;
bannerFrame.origin.y = contentFrame.size.height;
} else {
bannerFrame.origin.y = contentFrame.size.height;
}
////To display the banner in top
// if (_bannerLoaded) {
// bannerFrame.origin.y = 0;
// } else {
// bannerFrame.origin.y = -bannerFrame.size.height;
// }
_contentController.view.frame = contentFrame;
_bannerView.frame = bannerFrame;
}
In the above coding make Some changes in the if condition like this.
if (_bannerLoaded)
{
contentFrame.size.height = 0;
bannerFrame.origin.y = contentFrame.size.height-bannerFrame.size.height;
}
else
{
bannerFrame.origin.y = contentFrame.size.height-bannerFrame.size.height;
}
In my view I have in the right part 3 UISlider and in the left part the user can slide the menu with a UIPanGestureRecognizer. Sometimes, when the user uses the slider, it also drag the view. I don't want this to happen. I have this code in my panLayer method:
- (IBAction)panLayer:(UIPanGestureRecognizer *)pan {
if (pan.state == UIGestureRecognizerStateChanged) {
CGPoint point= [pan translationInView:self.topLayer];
CGRect frame = self.topLayer.frame;
frame.origin.x = MIN(258.0f, self.layerPosition + point.x);
if (frame.origin.x < 0) frame.origin.x = 0;
self.topLayer.frame = frame;
}
if (pan.state == UIGestureRecognizerStateEnded) {
if (self.topLayer.frame.origin.x <=160) {
[self animateLayerToPoint:0];
}
else {
[self animateLayerToPoint:VIEW_HIDDEN];
}
}
}
I want to create an if statement with the x position. Something like this:
if (firstTouch.x < 150 && firstTouch.x > 0) {
//Add my previous code
}
How can I access to the firstTouch in the view, and if it is in this area, run the UIPanGestureRecognizer?
Thanks
This can be easily achieved by adopting UIGestureRecognizerDelegate and implementing the following method:
-(BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldReceiveTouch:(UITouch*)touch
{
return touch.view != myUISlider;
}
I have one question when infinite background scrolling is done, is the object remain fixed(like doodle in doodle jump, papy in papi jump) or these object really moves.Is only background move or both (background and object )move.plz someone help me.I am searching for this solution for 4/5 days,but can't get the solution.So plz someone help me. And if object does not move how to create such a illusion of object moving.
If you add the object to the same layer as the scrolling background, then it will scroll as the background scrolls.
If your looking for an effect like the hero in doodle jump, you may want to look at having two or more layers in a scene.
Layer 1: Scrolling Background Layer
Layer 2: Sprite layer
SomeScene.m
CCLayer *backgroundLayer = [[CCLayer alloc] init];
CCLayer *spriteLayer= [[CCLayer alloc] init];
[self addChild:backgroundLayer z:0];
[self addChild:spriteLayer z:1];
//Hero stays in one spot regardless of background scrolling.
CCSprite *squidHero = [[CCSprite alloc] initWithFile:#"squid.png"];
[spriteLayer addChild:squidHero];
If you want objects to scroll with the background add it to the background layer:
//Platform moves with background.
CCSprite *bouncePlatform= [[CCSprite alloc] initWithFile:#"bouncePlatform.png"];
[backgroundLayer addChild:bouncePlatform];
Another alternative is to use a CCFollow action. You would code as if the background is static (which it will be) and the player is moving (which it will be), but add a CCFollow action to the player. This essentially moves the camera so that it tracks your player.
You can also modify the classes so that you can get the CCFollow action to follow with an offset (i.e., so the player is not in the middle of the screen) as well as to have a smoothing effect to it, so that when the player moves, the follow action is not jerky. See the below code:
*NOTE I am using cocos2d-x, the c++ port. The methods are similar in cocos2d, and you should be able to modify these to fit the cocos2d syntax. Or search around -- I found these for cocos2d and then ported to c++.
//defines the action to constantly follow the player (in my case, "runner.p_sprite is the sprite pointing to the player)
FollowWithOffset* followAction = FollowWithOffset::create(runner.p_sprite, CCRectZero);
runAction(followAction);
And separately, I have copied the class definition for CCFollow to create my own class, CCFollowWithAction. This also has a smoothing effect (you can look this up more online) so that when the player moves, the actions are not jerky. I modified "initWithTarget," to take into account an offset, and "step," to add a smoothing action. You can see the modifications in the comments below.
bool FollowWithOffset::initWithTarget(CCNode *pFollowedNode, const CCRect& rect/* = CCRectZero*/)
{
CCAssert(pFollowedNode != NULL, "");
pFollowedNode->retain();
m_pobFollowedNode = pFollowedNode;
if (rect.equals(CCRectZero))
{
m_bBoundarySet = false;
}
else
{
m_bBoundarySet = true;
}
m_bBoundaryFullyCovered = false;
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
m_obFullScreenSize = CCPointMake(winSize.width, winSize.height);
//m_obHalfScreenSize = ccpMult(m_obFullScreenSize, 0.5f);
m_obHalfScreenSize = CCPointMake(m_obFullScreenSize.x/2 + RUNNER_FOLLOW_OFFSET_X,
m_obFullScreenSize.y/2 + RUNNER_FOLLOW_OFFSET_Y);
if (m_bBoundarySet)
{
m_fLeftBoundary = -((rect.origin.x+rect.size.width) - m_obFullScreenSize.x);
m_fRightBoundary = -rect.origin.x ;
m_fTopBoundary = -rect.origin.y;
m_fBottomBoundary = -((rect.origin.y+rect.size.height) - m_obFullScreenSize.y);
if(m_fRightBoundary < m_fLeftBoundary)
{
// screen width is larger than world's boundary width
//set both in the middle of the world
m_fRightBoundary = m_fLeftBoundary = (m_fLeftBoundary + m_fRightBoundary) / 2;
}
if(m_fTopBoundary < m_fBottomBoundary)
{
// screen width is larger than world's boundary width
//set both in the middle of the world
m_fTopBoundary = m_fBottomBoundary = (m_fTopBoundary + m_fBottomBoundary) / 2;
}
if( (m_fTopBoundary == m_fBottomBoundary) && (m_fLeftBoundary == m_fRightBoundary) )
{
m_bBoundaryFullyCovered = true;
}
}
return true;
}
void FollowWithOffset::step(float dt)
{
CC_UNUSED_PARAM(dt);
if(m_bBoundarySet){
// whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
if(m_bBoundaryFullyCovered)
return;
CCPoint tempPos = ccpSub( m_obHalfScreenSize, m_pobFollowedNode->getPosition());
m_pTarget->setPosition(ccp(clampf(tempPos.x, m_fLeftBoundary, m_fRightBoundary),
clampf(tempPos.y, m_fBottomBoundary, m_fTopBoundary)));
}
else{
//custom written code to add in support for a smooth ccfollow action
CCPoint tempPos = ccpSub( m_obHalfScreenSize, m_pobFollowedNode->getPosition());
CCPoint moveVect = ccpMult(ccpSub(tempPos,m_pTarget->getPosition()),0.25); //0.25 is the smooth constant.
CCPoint newPos = ccpAdd(m_pTarget->getPosition(), moveVect);
m_pTarget->setPosition(newPos);
}
}