This question already has answers here:
CCSprite Fadeout with children
(2 answers)
Closed 9 years ago.
Suppose I have a CCSprite object named sprite,and add a label to be its' child.While I find out if I call
sprite.opacity = 0;
[sprite runAction:[CCFadeTo actionWithDuration:5.0 opacity:255]];
the label won't be faded with sprite,instead it will appear immediately.It seems like opacity property can't be inherited from its' parent.So How should I do this if I want both sprite and its' children to fade simultaneously without having to runAction for both parent and children.
You can also use CCRenderTexture to render you whole hierarchy of nodes and manipulate it like a single node.
With this solution you will avoid the issue of overlapping nodes causing a darker opacity if you propagate opacity to the children individually.
This technique is explained here: http://2sa-studio.blogspot.com/2013/01/fading-node-hierarchy-with.html
Related
I'm making an endless running game in which users dodge obstacles, and I'm working on producing the obstacles right now. The plan I had where I'm spawning these obstacles is as follows:
obstacle->setPosition(CCPointMake(this->getContentSize().width, this->getContentSize().height*.75));
obstacle->setScale(.5);
this->addChild(obstacle);
_obstacles->addObject(obstacle);
obstacle->runAction(CCMoveBy::create(2.0, CCPointMake(-(this->getContentSize().width + obstacle->getContentSize().width/2), 0)));
obstacle->removeFromParent();
I set the position, set it's scale, add it to the scene, run an action on it so that it moves across the screen from right to left, add it to an array called _obstacles to be used elsewhere, and then I remove it from the scene so as to save memory. However, the problem is that once I try implement this, the obstacle doesn't show up at all as if it's nowhere to be seen. When I don't call obstacle->removeFromParent() it shows up and performs the action. What am I doing wrong here? If I don't call removeFromParent(), what do I call? Is there a problem in my code not related to removeFromParent()?
The reason that obstacle doesn't apeear at all is that it is removed as it start moving. You just have to create a sequence of move action and function call with obstacle as parameter and than remove this obstacle in that function , so that obstacle will be removed after moving out of screen.
CCCallFuncN *myCallFunc = CCCallFuncN::create(this, callfuncN_selector(CLASS_NAME::removeObstacles));
obstacle->runAction(CCSequence::create(CCMoveBy::create(2.0, CCPointMake(-(this->getContentSize().width + obstacle->getContentSize().width/2), 0)),myCallFunc,NULL));
Method to remove obstacle from array and from parent view
void CLASS_NAME::removeObstacles(CCObject* pSender){
// Type cast pSender to obstacle type e.g if obstacle is of CCSprite type.
CCSprite *tempObstacle = (CCSprite *)pSender;
_obstacle.pop_back(tempObstacle);
tempObstacle->removeFromParent();
}
Don't forget to replace CLASS_NAME by your class name
I would need more info on what removeFromParent is doing and how you use _obstacles
I'm taking a guess on how the parent is structured. I would guess that it has a list of children and when the parent is updated/render, it calls those functions for its children. If removeFromParent removes the object from its parent list, then that would explain why it is not being render or used in the scene. If you have a setup like this, then you should only call removeFromParent before destroying the parent object
I need to create an object that contains several sprites (2 for simplicity: the game object and its' shadow).
I need to compose them into the same class, so having the following questions:
what is the best ancestor class to the described one?
I used CCNode for this purpose. I overridden its draw method in the following way:
- (void)draw {
[super draw];
[_item draw];
[_itemShadow draw];
}
and suddenly found that need to change all other CCNode methods in the same way. For ex. change position, visible, etc. in order to change these properties in both Sprites my custom container aggregates:
#interface NBChecker : CCNode {
CCSprite *_item;
CCSprite *_itemShadow;
}
#end
There is the other way I see - to make both sprites parent property pointing to self. This should synchronise positions, visibility, etc. for these sprites.
Who has better ideas?
Would like to use aggregation and not sure I'm right in my thoughts.
Thanks!
Scrap the draw code. All you need to do is to add the two sprites as children of the CCNode subclass. Write your logic code in the CCNode subclass and have two ivars for each sprite for easier access (like you already have).
You don't need to draw the sprites yourself as long as they are part of the scene graph.
The sprites will move and rotate relative to their parent automatically. Move the node to move the sprites in unison, etc.
I'm using cocos2d 1.0.1.
I've created a CCSpriteBatchNode, it includes a CCSprite (let's name it parentLayer) which includes some X number of childs(CCSprites).
The problem is - when I rotate parentLayer all sprites (childs) correctly displayed, however bounding boxes are at the same place (where they've been before rotation), so world coordinates of those sprites won't be changed.
Off course, all of the above works great without CCSpriteBatchNode. But, I would like to use batch node due to amount of sprites involved.
The question is, is there any way to update bounding boxes & child positions correspondingly?
How many sprites are we talking about? I would just go with a fast enumeration call to rotate each one individually. I nave never noticed a performance hit when doing this, have you?
CCArray *listOfChildren = [parentLayer children];
for (CCSprite *sprite in listOfChildren) {
[sprite setRotation:someValue];
}
I am making a top-down shooter that makes extensive use of TMX maps created with the "Tiled" application. Within my TMX map, I have a "Background" layer with floor tiles, which appears beneath my characters (CCSprites.)
I have another layer in the TMX file called "Foreground" which I would like to appear "above" my CCSprites, giving the illusion of them walking underneath various objects.
I tried using the vertexZ property of the CCNode class to do this:
CCTMXLayer *backgroundLayer = ...
CCSprite *spriteNode = ...
CCTMXLayer *foregroundLayer = ...
[backgroundLayer setVertexZ:1];
[spriteNode setVertexZ:2];
[foregroundLayer setVertexZ:3];
...but it turns out vertexZ actually alters the node's visual appearance within the openGL view. It effectively causes a CCNode to appear larger, or closer to the user when it has a higher vertexZ value. I don't want that- all I want is a sort of layers-of-an-impossibly-thin-cake effect, without any visual differences between the layers.
So I thought I would try altering the zOrder property of the nodes, like this:
[[backgroundLayer parent] reOrderChild:backgroundLayer z:1];
[[spriteNode parent] reOrderChild:backgroundLayer z:2];
[[foregroundLayer parent] reOrderChild:backgroundLayer z:3];
But I realized there's a fundamental problem with what I'm doing here, since my spriteNode is a direct child of the CCScene, but the background and foreground nodes are both children of my CCTMXTiledMap, which itself is a child of the CCScene.
So I'm basically trying to slip a CCSprite between two layers of the map, which, from the CCScene's perspective, are really just two parts of the same layer.
It seems I could create an additional instance of CCTMXTiledMap just to hold the foreground layer, but that also seems like overkill. My other thought was to create CCSprites to serve the same purpose, but it seems like there's got to be a better way.
Yes, I have used Tiled once very lightly and I do believe there is an option to add an Object Layer into your TMXTiledMap (Tiled -> Layer -> Add Object Layer...), then once imported into your build you can link up a CCSprite with the corresponding Object Layer you have created. I would post your question on the cocos2d forum, as people there are more experienced and equipped to answer this with examples.
This question already has an answer here:
Draw an item in a static location relative to the QGraphicsView
(1 answer)
Closed 9 years ago.
I have a QGraphicsScene that is filled with QGraphicsItems, and the user is able to pan and zoom around to inspect all of the various QGraphicsItems. However, I would like to have a QGraphicsTextItem label that always stays put at the top left of the screen. Ignoring the zooms is easy, as I can just setFlags(QGraphicsItem::ItemIgnoresTransformations), but I've yet to figure out how to force the position to stay at the top-left. What's the best way to make my label "float" in the same place?
I think the only (realiable) way to do that is to recalculate position for your text item every frame. To do this, simply subclass QGraphicsView, override paintEvent and use QGraphicsView::mapToScene() to calculate new position. Something like:
void MyGraphicsView::paintEvent(QPaintEvent*)
{
QPointF scenePos = mapToScene(0,0); // map viewport's top-left corner to scene
m_textItem->setPos(scenePos);
}
I have done this many many times and it has worked very well.
Of course you could just create normal QLabel like Arnold Spence mentions in his answer. However, this won't work in many situations (e.g. if you really want to place label on top of graphics view and you are using OpenGL-accelerated viewport).
Perhaps you just want to put a regular QLabel right on the view instead of trying to make a part of the scene stay in one place as discussed in this question.
Note: As mentioned in another answer, this trick will often not work with hardware accelerated views. In these cases, you will need to make the text items a part of the scene.