I have a problem.
i'm trying to make a screenshot of a scene then make a sprite and pass this sprite to other scene.
i'm doing this:
RenderTexture* texture = RenderTexture::create((int)Director::getInstance()->getWinSize().width, (int)Director::getInstance()->getWinSize().height, Texture2D::PixelFormat::RGBA8888);
texture->begin();
Director::getInstance()->getRunningScene()->visit();
texture->end();
Sprite* bgSprite = Sprite::createWithTexture(texture->getSprite()->getTexture());
bgSprite->setRotationX(180);
/-------------------------------------
LoadScreen* loadLayer = LoadScreen::create(GameScene, this->_carModel, bgSprite/*, this*/);
/-------------------------------------
then in next scene i do:
bgSprite->setPosition(Point(Director::getInstance()->getVisibleSize().width / 2, Director::getInstance()->getVisibleSize().height / 2));
bgSprite->setOpacity(200);
this->addChild(bgSprite, 1, 1);
I debug this. Sprite is not null. The texture in this sprite has size and etc.
I try to save texure in file. The result is empty .png file.
It's an engine problem, the file is alway saved with RGB in the previous version.
Since the rendering of cocos2d-x 3.0 is based on the command queue, we should always wrap the read/write frame buffer operations with commands. Invoking newImage() directly is not guaranteed to work fine. But "RenderTexture::saveToFile" should work fine because it's wrapped with a custom command in code.
I think this issue has already been solved in cocos2d-x v3.3, please refer http://www.cocos2d-x.org/issues/5562 for more information.
And also you could take a look at "cpp-tests" bundled with cocos2d-x to see how to save screenshot of your scene or sprite.
Related
This may be a simple question but I'm having a hard time finding a straight answer to it: is there a way to resize a loaded Texture in SFML 2.0? For instance, if I have a 3264x2448 png and I want to scale it down to fit a 900x1200 rendered window without cropping, how would I do so?
Is there a way to scale all rendered windows to fit whatever monitor
of whatever system the application is running on?
First, here's a way to scale the image to the current RenderWindow size.
// assuming the given dimension
// change this dynamically with the myRenderWindow->getView().getSize()
sf::Vector2f targetSize(900.0f, 1200.0f);
yourSprite.setScale(
targetSize.x / yourSprite.getLocalBounds().width,
targetSize.y / yourSprite.getLocalBounds().height);
Be aware that this may stretch your image if the aspect ratio is not maintained. You might want to add code to adjust the decision for your case.
Then, if you want to stretch the RenderWindow to fill all the screen, may I suggest you use fullscreen mode?
Here's a snippet of how it's done:
// add the flag to the other ones
mStyleFlag = sf::Style::Default | sf::Style::Fullscreen;
// get the video mode (which tells you the size and BPP information of the current display
std::vector<sf::VideoMode> VModes = sf::VideoMode::getFullscreenModes();
// then create (or automatically recreate) the RenderWindow
mMainWindow.create(VModes.at(0), "My window title", mStyleFlag);
is there a way to resize a loaded Texture in SFML 2.0?
Not an sf::Texture directly. But you can use an sf::Sprite: you load load your texture, you pass it to an sf::Sprite and you play with sf::Sprite::setScale or sf::Sprite::scale.
In my application I take snapshots of a QGLWidget's contents for two purposes:
Not redraw the scene all the time when only an overlay changes, using a cached pixmap instead
Lat the user take screenshots of the particular plots (3D scene)
The first thing I tried is grabFrameBuffer(). It is natural to use this function as for the first application, what is currently visible in the widget is exactly what I want to cache.
PROBLEM: On some hardware (e.g. Intel integrade graphics, Mac OS X with GeForce graphics), the image obtained does not contain the current screen content, but the content before that. So if the scene would be drawn two times, on the screen you see the second drawing, in the image you see the first drawing (which should be the content of the backbuffer?).
The second thing I tried is renderToPixmap(). This renders using paintGL(), but not using paint(). I have all my stuff in paint(), as I use Qt's painting functionality and only a small piece of the code uses native GL (beginNativePainting(), endNativePainting()).
I also tried the regular QWidget's snapshot capability (QPixmap::fromWidget(), or what it is called), but there the GL framebuffer is black.
Any ideas on how to resolve the issue and get a reliable depiction of the currently drawn scene?
How to take reliable QGLWidget snapshot
Render current scene to framebuffer, save data from framebuffer to file. Or grab current backbuffer after glFlush. Anything else might include artifacts or incomplete scene.
It seems that QGLWidget::grabFrameBuffer() internally calls glReadPixels() from OpenGL. On double-bufferd configurations the initial mode reads the back buffer (GL_BACK), switch with the OpenGL call glReadBuffer(GL_FRONT) to the front buffer before using QGLWidget::grabFrameBuffer() displaying an image on the screen.
The result of QGLWidget::grabFrameBuffer(), like every other OpenGL calls, depends on the video driver. Qt merely forwards your call to the driver and grabs the image it returns, but the content of the image is not under Qt's control. Other than making sure you have installed the latest driver for your video card, there is not much you can do except report a bug to your video card manufacturer and pray.
I use paintGL(); and glFlush(); before using grabFrameBuffer(). The paintGL helps to draw current frame again before grab the frame buffer, which makes an exact copy of what is currently showing.
Recently I migrate my project to Kobold2D 1.1 with Cocos2D 1.1beta2 inside for iPad Retina Display. But when I run my project and try to put a TMX tile map, the program hung up. The problem is CCTexture2D is call in InitWithImage and there's no Case for texture format AI88. Because of that, program goes to default and hang up.
I add to the code:
case kCCTexture2DPixelFormat_AI88:
data = malloc(POTHigh * POTWide);
info = kCGImageAlphaOnly;
context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, POTWide, NULL, info);
break;
Is the same config as kCCTexture2DPixelFormat_A8 and now code works. I used a TMX made with Tile Editor 0.8 and uses a simple PNG not in any texture packer. The name inside TMX is fondomaze.png but in the project I must rename to fondomaze-ipad.png.
Hope you find useful. Now I can breathe relax with my project still working!
Discover a workaround for Retina Display iPad... Must to increase malloc by 4.
data = malloc(POTHigh * POTWide * 4);
Hope helps people who want to work with RD iPad.
Is there any possibility to show only a part of an CCSprite?
It seams that contentSize property doesn't have a good result.
I think you might have to create a new sprite for this. The general pseudo code is this.
CCTexture2D *origTexture = originalSprite->getTexture();
CGRect rect = {0, 0, 20, 20};
CCSprite *destSprite = CCSprite::spriteWithTexture(origTexture, CGRect);
Both doc_180's and James' answers work by creating new CCSprite using a portion of the texture, but if you are using clipping method, you will get CCSprite that uses the full texture but have the ability to only draw a portion of it on screen. One advantage of this method is you are able to modify how big or small the portion that you want shown or hidden on the fly rather than having to re-create the CCSprite again and again (or replacing the texture again and again).
So, to use the clipping method, simply download the ClippingNode class from here, and add the CCSprite you want clipped to that ClippingNode. Then you call one of its methods to specify which region to limit the drawing to. I'm currently using it to create a progress bar so I know for sure it works great.
Get the [sprite displayedFrame], change the frame of that, and create a new sprite with that spriteframe: CCSprite *sprite2 = [CCSprite spriteWithSpriteFrame:frame]
In the isometric tiled map z-ordering example for cocos2d-iphone, they use an object that is already in the tilemap as the player sprite, which is rendered as moving through the trees.
Is there a way to use a random CCNode, created though code (not in the tmx file, and not part of the sprite sheet), and have it z-ordered correctly with the tilemap? addChild is not supported on a CCTMXLayer, and the gives an error when using that reads:'addChild: is not supported on CCTMXLayer. Instead use setTileGID:at:/tileAt:'.
There's got to be a way to have a CCNode (let's say a simple CCSprite) z-order correctly with a tilemap, either using cocos2d's API, or some z-buffer technique. Any pointers?
The CCTMXLayer doesn't support adding tiles at runtime because it's implemented with all sprites on a single spritesheet. Because of this implementation detail you also can't call setTexture on an individual tile.
The easiest solution would be to have the sprite you want to use on the spritesheet at the beginning. If you can't do this because it's generated at runtime or something, the next best thing (without touching cocos2d code) would be to modify the spritesheet.
Put a dummy tile in the spritesheet you're using for the TMXLayer and then, once you have the image you want to use, write it to the spritesheet using CCRenderTexture or something and use the newly generated Texture as your TMXLayer's texture.
You could also modify the CCTMXLayer to allow for your functionality but it sounds like you want to avoid that.
If you want to add a tile to say tile (x,y) ( (x,y) in Tiled Map editor coordinates ) then use the following code -
myTileMap is the reference to the CCTMXTiledMap object.
CCTMXLayer *layer=[myTileMap layerNamed:#"yourlayer"];
NSAssert(floorLayer !=nil, #"Ground layer not found!");
CGPoint tileAddPosition = [layer positionAt: CGPointMake(x,y)];
//Create your CCNode or CCSprite or whatever...say object name is **tileToBeAdded**
tileToBeAdded.anchorPoint = CGPointZero;
tileToBeAdded.position = tileAddPosition;
[myTileMap addChild:addedTile z:1];