CCSprite setTexture creates black square cocos2d (iOS) - cocos2d-iphone

I am trying to make a screen where I am listing questions with anwers. Good answer should have a green marker, bad answers should have red markers.
When I create the screen, I set all markers to green or red. When I load the question and answers from a website I am changing the markers to represent the right/wrong answers.
My problem is that instead of having the new marker appear, I am receiving a black square where the new maker should be. The weird thing is that if I have set the markers originally green than the green marker still appear, but the red ones are not and viva-versa.
Here is my code for the marker change:
-(void) SetMarker:(int)ToColor {
switch (ToColor) {
case Marker_Red: {
[Marker_Sprite setTexture:[[CCSprite spriteWithFile:#"RedDot.png"] texture]];
break;
}
case Marker_Green: {
[Marker_Sprite setTexture:[[CCSprite spriteWithFile:#"GreenDot.png"] texture]];
break;
}
default:
break;
}
}
I am using Cocos2d version 2.

I think you should call [Marker_Sprite visit]; after you set the texture so that the sprite will call it's draw method again and the texture will change.
Either that or transition between the 2 texture using an animation.
Also...instead of [[CCSprite spriteWithFile:#"GreenDot.png"] texture] use [[CCTextureCache sharedTextureCache]addImage:#"GreenDot.png"]; .This is purely for optimization :)

I have actually found the answer for this question. It seems that the texture change is made originally out of the main thread and this caused the problem.
The solution was to put the call of the function which was calling the setMarker function into the main thread like this:
[self performSelectorOnMainThread:#selector(SetGoodAnswer) withObject:nil waitUntilDone:YES];
-(void) SetGoodAnswer {
for (int i=1; i<5; i++) {
[ButtonSprites[i] SetMarker:AnswerGood[i-1]];
}
}
After this call is making the changes, all markers are appearing correctly.

Related

how can i draw a sprite by left clicking?

i've tried to make a project, but i can't draw a sprite as i want. I mean that everything works when i just draw a sprite, but it stop working when i am trying to draw the sprite by clicking left mouse button. There's code i tried:
if(zdarzenie.type == Event::MouseButtonPressed && zdarzenie.mouseButton.button == Mouse::Left)
{
pocisk.setPosition(10, 10);
oknoAplikacji.draw(pocisk);
}
Btw, I am writing in Polish as if it would change something.
And yes, i have everything good besides that.
(and i am using 2.4.1 version of SFML)
I don't know what you are doing now because you didn't provide enough of your code and I actually don't understand your if statement but, it can just be :
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
sprite.setPosition(sf::Mouse::getPosition());
renderTarget.draw(sprite);
}
By the way I strongly suggest that you do not use the draw function here but organize your code to have a draw method called in a render loop, because depending on where your code is in your program, the sprite could be drawn for only one frame and then erased since it's not updated.
From what I understand in your code in Polish, you have the right code to do what you want, but the problem comes from the fact that you draw the sprite only once.
The draw method is called every frame and it will erase everything on screen and then redraw them. Doing it only once, like in your code, will only draw it a single time then delete it the very next frame.
At that point multiple solution can be used. If its a GameObject clicking can activate the object to then draw it or a simple bool could be used has a switch in your draw to make it appear.

It seems, that method is called twice, when collision happens . cocos2d-iphone

I use this code to show game over menu after _hero sprite and _enemy sprite collide :
if (CGRectIntersectsRect(_hero.boundingBox,_enemy.boundingBox)) {
CCActionCallFunc *_callShowMenu=[CCActionCallFunc actionWithTarget:self selector:#selector(showMenu)];
[self runAction:_callShowMenu];
// EDIT : I also remove both sprites when collision happens.
[_hero removeFromParent];
[_enemy removeFromParent];
}
In _callShowMenu I just stop all actions and show a sprite with half transparent black background image and buttons.
Sometimes when collision happens, it seems to me, that _callShowMenu is called twice, because
background is completely black, like there is the same image behind. Has anyone had a similar problem? (Mostly background image is half-transparent, as it should be).
EDIT:
-(void)showMenu{
[[CCDirector sharedDirector] pause];
CCSprite *_halfTransparentBackground=[CCSprite spriteWithImageNamed:#"halfTransparentBackground.png"];
_halfTransparentBackground.position=ccp(160, 280);
[self addChild:_blackBack z:5];
}
I found a solution using BOOL. Actually everyone uses BOOL in this case, so I don't need to reinvent the wheel.
BOOL doNotCallMeTwice;
Somewhere in the didLoad method:
doNotCallMeTwice=NO;
In the collision detection method:
if (doNotCallMeTwice==NO) {
[self showMenu];
}
And finally:
-(void)showMenu{
doNotCallMeTwice=YES;
}
Possibly, showMenu was called twice(or much more times),because collision detection is in the update method.

How can I get a child CCSprite to draw on top of its parent?

I'm trying to control the order in which CCSprites are being layered one on top of the other. I'd use zOrder, but I'm animating characters made up of articulated sprites (some sprites parented on others with addChild) and zOrder is only honored among sibling sprites.
Basically, I want to parent my sprites so they can inherit each others' transforms, but I want to determine the draw order.
Looking around, it sounds like using a CCSprite's vertexZ property is the way to go. I've tried that. I set the draw method of my custom CCSprite like so:
- (void)draw
{
glEnable(GL_BLEND);
CHECK_GL_ERROR_DEBUG();
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
CHECK_GL_ERROR_DEBUG();
[super draw];
glDisable(GL_BLEND);
}
Each of my sprites now has a zOrder of 0 and a unique vertexZ to layer them as I'd like, but it's not working: any sprite that has a parent is not displayed!
Trying some things, I find if I don't set vertexZ, all sprites are displayed. And if I keep the vertexZs and don't parent, they're all displayed. But with vertexZs set, any child sprite won't display.
What's going on here and how can I get it to work?
Update: More clues. I can comment out the GL functions around my call to [super draw] entirely and the results are the same. Also, it turns out child sprites with a vertexZ do display, but wherever they overlap any other sprite they go invisible. The purple paper sprite is a child of the creature's left forearm sprite (on screen right) yet should go on top of it.
For the picture above, I'm basically doing this in my CCLayer. I want the parenting, but I want hand and paper to be on the top.
[self addChild:lUpperarm];
[self addChild:lForearm];
[self addChild:face];
[self addChild:rUpperarm];
[self addChild:rForearm];
[lForearm addChild:handAndPaper];
lUpperarm.vertexZ = -100;
lForearm.vertexZ = -99;
face.vertexZ = -98;
rUpperarm.vertexZ = -97;
rForearm.vertexZ = -96;
handAndPaper.vertexZ = -95;
This is how I want it to look. (I changed the last line to [self addChild:handAndPaper] which loses lForearm's transformations, not what I want.)
Update 2: Some have suggested I add all children with zOrder set to -1: e.g. [lForearm addChild:handAndPaper z:-1]. This changed things a little, but still didn't fix it, alas. Seems either vertexZ is not determining draw order and/or the blending is wrong.
I dealt with this issue when writing an RPG with Cocos2d. The problem is the alpha blending. As you are seeing, the paper is being covered up by the left arm sprite, even though it is transparent. For some reason, when Cocos2d's vertexZ technique is used, this problem can sometimes occur. To fix it, you can try changing your alpha blending level. Try 0.0, 0.5 and 1.0:
-(void) draw
{
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
[super draw];
glDisable(GL_ALPHA_TEST);
}
If that doesn't work, then I recommend a complete workaround solution. Keep all your sprites as part of the same parent node and use regular z ordering. It's not an ideal solution, but if you use a "meta" parent node then you can still transform all the children easily.
While adding only u can control z-order?
[self addChild:lUpperarm z:1];
[self addChild:lForearm z:2];
[self addChild:face z:3];
[self addChild:rUpperarm z:4];
[self addChild:rForearm z:5];
[lForearm addChild:handAndPaper z:6];
I can't be sure that this is your problem but I've had issues in the past when playing with draw() and it turned out to be that I wasn't resetting the blendfunc at the end of the call.
Here's a draw function I use that does some basic drawing with some transparency. Again, no guarantees.
- (void) draw {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
ccDrawSolidPoly(vertices, 4, fillColor);
// This is the important bit. Must do this last.
//
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
}
set higher z value to set object on top. and lower z value to set in back..

Stars for scrolling shooter with CCParticleSystemQuad?

My code for init function:
NSArray *starsArray = [NSArray arrayWithObjects:#"Stars1.plist", #"Stars2.plist", #"Stars3.plist", nil];
for(NSString *stars in starsArray) {
CCParticleSystemQuad *starsEffect = [CCParticleSystemQuad particleWithFile:stars];
[self addChild:starsEffect z:-1];
}
The problem is that these particles appear and fully fill the screen rectangle during few seconds. But I need the sky full of stars from the beginning.
According to the answer at cocos2d starting particles from a specific time in the future , you can manually update the particle system. Example in cocos2d-x:
CCParticleSystemQuad *particle = CCParticleSystemQuad::create("res/Particles/Stars1.plist");
for (int i = 0; i < 10; ++i) {
particle->update(.1);
}
You may need to change the interval to suit the particles.
Add them to a layer, hide the layer, then unhide the layer after everything is done loading. That way you can set stuff up and not have it display right away.
That's just one approach. Another idea is to load all your images into Cocos before game play and game logic processes begin. That way there is no pause and delay while images are loading.

Cocos2d iPhone. Scrollayer contentSize. Layers

I want to set the contentsize of scrollayer.
I have a scrollayer, it's CCLayer type and moving is set by ccTouchMove. I have one schedule for smoothing. BUT.
Problem is that scrolling layer is big like the whole display. I want to set the contentsize of scrollayer. Content in this layer will be scroll and showing ONLY in this layer. Not taking up the whole display. Something like this
Scrolling just in gray CCLayer (scrollayer) ....NOT WHOLE SCREEN.
Can you help me?
P.S.: Setting CCLayerColor and initWithColor:Width:Height: is not working. It just makes some stupid color box and it's moving too.
ok, honestly i would put the window frame at a higher z than the scrolling object ... if you dont you may have to crop and change sprite on the fly for the window content, nasty (at least that is the one way i could do this, without further research).
so :
// initialize this logic somewhere useful
CCNode scrollableContent;
CCSprite windowFrame;
BOOL isScrollPossible;
[self addChild:scrollableContent z:0];
[self addChild:windowFrame z:1];
// and in the touch delegate methods
-(void) ccTouchBegan:{
check if the touch happened in the window, if yes, scrolling is possible
}
-(void) ccTouchMoved:{
if (isScrollPossible) {
compute displacement
compute nextPosition for scrollableContent node;
if ( nextPosition in window ) {
// make scrollableContent follow touch
scrollableContent.position=nextPosition;
} else {
// stop any further scrolling until the next 'touch began'
isScrollPossible=NO;
}
} else {
// scroll not possible, do nothing
}
}
This is the basic idea. You may need clamping logic to prevent the creeping of scrollableContent beyond the edges of the window.
Edited for typos.
After trying desperately with masking and GL_SCISSOR, I settled on cutting a hole in the foreground and only moving the background object when onTouchMoved updated.
To see it in action, have a look at the Stats page of Angry Gran.