OpenGL: How to darken a sprite in Cocos2d - opengl-es

I've tried shooting the dark with all the GL functions, to no avail on what I'm sure has to be pretty simple. I'm new to it.
I want to take a sprite and simply darken it. My thoughts on this were to load the sprite, add a grey layer overtop of it (using CCLayerColor with a grey color), apply some kind of GL function, and then grab the output and display it onscreen. However, in every variant I tried where my source image was correctly darkened, the transparency around it was also affected, showing the grey. I need the darkening effect to be masked to the shape of the source sprite.
Here's the code I have so far. How can I correctly mask the darkening effect?
CCSprite* sprite = [CCSprite spriteWithSpriteFrameName: mod.backgroundImagePath];
CCLayerColor* tint = [CCLayerColor node];
[tint setColor:ccc3(205, 205, 205)];
//[tint setBlendFunc: (ccBlendFunc){GL_SRC_COLOR, GL_ONE_MINUS_DST_ALPHA}]; Need help here?
[sprite addChild:tint];
CCRenderTexture* rt = [CCRenderTexture renderTextureWithWidth:sprite.boundingBox.size.width height:sprite.boundingBox.size.height];
[rt begin];
[sprite visit];
[rt end];

You can just set the color property of CCSprite (which is inherited from CCNode):
CCSprite* sprite = [CCSprite spriteWithSpriteFrameName:#"foobar"];
sprite.color = [CCColor colorWithRed:r green:g blue:b alpha:a];
Where the r,g,b,a variables are the color you want to use, normalized between 0 and 1.
I.e.:
Setting to 0,0,0,1 will make the object completely black.

Related

Opposite of glscissor in Cocos2D?

I found a class called ClippingNode that I can use on sprites to only display a specified rectangular area: https://github.com/njt1982/ClippingNode
One problem is that I need to do exactly the opposite, meaning I want the inverse of that. I want everything outside of the specified rectangle to be displayed, and everything inside to be taken out.
In my test I'm using a position of a sprite, which will update frame, so that will need to happen to meaning that new clipping rect will be defined.
CGRect menuBoundaryRect = CGRectMake(lightPuffClass.sprite.position.x, lightPuffClass.sprite.position.y, 100, 100);
ClippingNode *clipNode = [ClippingNode clippingNodeWithRect:menuBoundaryRect];
[clipNode addChild:darkMapSprite];
[self addChild:clipNode z:100];
I noticed the ClippingNode class allocs inside but I'm not using ARC (project too big and complex to update to ARC) so I'm wondering what and where I'll need to release too.
I've tried a couple of masking classes but whatever I mask fits over the entire sprite (my sprite covers the entire screen. Additionally the mask will need to move, so I thought glscissor would be a good alternative if I can get it to do the inverse.
You don't need anything out of the box.
You have to define a CCClippingNode with a stencil, and then set it to be inverted, and you're done. I added a carrot sprite to show how to add sprites in the clipping node in order for it to be taken into account.
#implementation ClippingTestScene
{
CCClippingNode *_clip;
}
And the implementation part
_clip = [[CCClippingNode alloc] initWithStencil:[CCSprite spriteWithImageNamed:#"white_board.png"]];
_clip.alphaThreshold = 1.0f;
_clip.inverted = YES;
_clip.position = ccp(self.boundingBox.size.width/2 , self.boundingBox.size.height/2);
[self addChild:_clip];
_img = [CCSprite spriteWithImageNamed:#"carrot.png"];
_img.position = ccp(-10.0f, 0.0f);
[_clip addChild:_img];
You have to set an extra flag for this to work though, but Cocos will spit out what you need to do in the console.
I once used CCScissorNode.m from https://codeload.github.com/NoodlFroot/ClippingNode/zip/master
The implementation (not what you are looking for the inverse) was something :
CGRect innerClippedLayer = CGRectMake(SCREENWIDTH/14, SCREENHEIGHT/6, 275, 325);
CCScissorNode *tmpLayer = [CCScissorNode scissorNodeWithRect:innerClippedLayer];
[self addChild:tmpLayer];
So for you it may be like if you know the area (rectangle area that you dont want to show i.e. inverse off) and you know the screen area then you can deduct the rectangle are from screen area. This would give you the inverse area. I have not did this. May be tomorrow i can post some code.

SCNView Re-sizing Issue

I am trying to render 3D bar chart in SCNView using ScreenKit framework.
My rendering code is,
int height=10,y=0,x=0;
for (int i=0; i<10; i++) {
SCNBox *box1 = [SCNBox boxWithWidth:4 height:height length:2 chamferRadius:0];
boxNode1 = [SCNNode nodeWithGeometry:box1];
boxNode1.position = SCNVector3Make(x, y, 0);
SCNMaterial *material = [SCNMaterial material];
material.diffuse.contents = (NSColor *)[self.colorArray objectAtIndex:i%6];
material.specular.contents = [NSColor whiteColor];
material.shininess = 1.0;
box1.materials = #[material];
//boxNode1.transform = rot;
[scene.rootNode addChildNode:boxNode1];
x+=6;
height+=10;
y += 5 ;
}
I can render but while re-sizing the view the chart bars goes to the center of the view.
I need to render the chart, which cover the margins of the view and when Re-size it have to change accordingly. The image(s) below shows my problem.
Original Image:
Image where less stretching of both windows:
Can anyone please help me to fix the issue.
The the windows in the image that you had linked to in your original question was very stretched and that made it very hard to see what was going on. When I took that image and made the windows less stretched it was easier to have some idea of what is going on.
I think that you are seeing a general resizing issue. Either you are using springs and struts and have configured flexible margins on the left and right or you are using auto layout with a centered view with fixed width.
I assume that the red boxes that I have drawn in the image below is the bounds of your scene view in both these cases. You can easily see if this is the case by giving the scene view a different background color and resize it again.
My solution to your problem would be to change how your view resizes as the window resizes, to better meet your expectations.

Drawing UI elements directly to the WebGL area with Three.js

In Three.js, is it possible to draw directly to the WebGL area (for a heads-up display or UI elements, for example) the way you could with a regular HTML5 canvas element?
If so, how can you get the context and what drawing commands are available?
If not, is there another way to accomplish this, through other Three.js or WebGL-specific drawing commands that would cooperate with Three.js?
My backup plan is to use HTML divs as overlays, but I think there should be a better solution.
Thanks!
You can't draw directly to the WebGL canvas in the same way you do with with regular canvas. However, there are other methods, e.g.
Draw to a hidden 2D canvas as usual and transfer that to WebGL by using it as a texture to a quad
Draw images using texture mapped quads (e.g. frames of your health box)
Draw paths (and shapes) by putting their vertices to a VBO and draw that with the appropriate polygon type
Draw text by using a bitmap font (basically textured quads) or real geometry (three.js has examples and helpers for this)
Using these usually means setting up a an orthographic camera.
However, all this is quite a bit of work and e.g. drawing text with real geometry can be expensive. If you can make do with HTML divs with CSS styling, you should use them as it's very quick to set up. Also, drawing over the WebGL canvas, perhaps using transparency, should be a strong hint to the browser to GPU accelerate its div drawing if it doesn't already accelerate everything.
Also remember that you can achieve quite much with CSS3, e.g. rounded corners, alpha transparency, even 3d perspective transformations as demonstrated by Anton's link in the question's comment.
I had exactly the same issue. I was trying to create a HUD (Head-up display) without DOM and I ended up creating this solution:
I created a separate scene with orthographic camera.
I created a canvas element and used 2D drawing primitives to render my graphics.
Then I created an plane fitting the whole screen and used 2D canvas element as a texture.
I rendered that secondary scene on top of the original scene
That's how the HUD code looks like:
// We will use 2D canvas element to render our HUD.
var hudCanvas = document.createElement('canvas');
// Again, set dimensions to fit the screen.
hudCanvas.width = width;
hudCanvas.height = height;
// Get 2D context and draw something supercool.
var hudBitmap = hudCanvas.getContext('2d');
hudBitmap.font = "Normal 40px Arial";
hudBitmap.textAlign = 'center';
hudBitmap.fillStyle = "rgba(245,245,245,0.75)";
hudBitmap.fillText('Initializing...', width / 2, height / 2);
// Create the camera and set the viewport to match the screen dimensions.
var cameraHUD = new THREE.OrthographicCamera(-width/2, width/2, height/2, -height/2, 0, 30 );
// Create also a custom scene for HUD.
sceneHUD = new THREE.Scene();
// Create texture from rendered graphics.
var hudTexture = new THREE.Texture(hudCanvas)
hudTexture.needsUpdate = true;
// Create HUD material.
var material = new THREE.MeshBasicMaterial( {map: hudTexture} );
material.transparent = true;
// Create plane to render the HUD. This plane fill the whole screen.
var planeGeometry = new THREE.PlaneGeometry( width, height );
var plane = new THREE.Mesh( planeGeometry, material );
sceneHUD.add( plane );
And that's what I added to my render loop:
// Render HUD on top of the scene.
renderer.render(sceneHUD, cameraHUD);
You can play with the full source code here:
http://codepen.io/jaamo/pen/MaOGZV
And read more about the implementation on my blog:
http://www.evermade.fi/pure-three-js-hud/

How to fill color in nsbox on nsslider movement?

I want to fill color in an NSBox on slider movement.
I am using the following code.
-(IBAction)slider1move:(id)sender {
[self.box setFillColor:[NSColor colorWithCalibratedRed: ([self.slider1 floatValue])/255.0 green:0.0 blue:0.0 alpha:0.0]];
}
Please correct me. I have three sliders in my application with each correspond to red , green and blue color.
How do I fill the color in the box on slider movement based on the current value of slider.
Like if my slider showing value of 50 the box should be half filled with red color if it is for red color.
First, make sure you've met the requirements listed in NSBox's setFillColor: documentation:
Functional only when the receiver’s box type (boxType) is NSBoxCustom
and its border type (borderType) is NSLineBorder.
Assuming that's not the problem, a quick guess would be that you may need to call setNeedsDisplay: on the box to get it redrawn with the new color.
Look at Your color, You set fully transparent color - alpha to 0.0 that's why Your color it's not changing.
Change Your color to alpha 1.0 like this:
[NSColor colorWithCalibratedRed: ([self.slider1 floatValue])/255.0 green:0.0 blue:0.0 alpha:1.0]

Scrolling Background

I'm trying out new things for a simple game in Portrait mode, I want to add a seamless scrolling background to a game, the image is 512x512px.
The Main scrolling I want to have is Vertically, but I want to be able to scroll sideways too within the bounds of the image size. How should I go about with this, I'm using cocos2d.
David
Try repeating the texture (in this case within 2000px)
CGRect repeatRect = CGRectMake(0, 0, 2000, 2000);
CCSprite *background = [CCSprite spriteWithFile:#"Background.png" rect:repeatRect];
ccTexParams params =
{
GL_NEAREST,
GL_NEAREST_MIPMAP_LINEAR,
GL_REPEAT,
GL_REPEAT
};
[background.texture setTexParameters:&params];

Resources