I am working on a small 2d game engine for android-ndk using opengl.
I am facing difficulty on how to change levels, eg. from menu to game screen.
Because the texture ids are not working when loading new textures for game screen using glGenTextures, glGenTextures keeps returning duplicate ids.
// class to bind ndk with java
Renderer.java
void onSurfaceChanged(gl, width, height){
nativeSurfaceChanged();
}
void onDrawFrame(){
nativeDrawFrame();
}
// c++ code
Game.cpp
Screen *screen;
void SetScreen(Screen *scrn){
screen = scrn;
// load textures and create openGL objects (mesh and textures)
screen->Initialize();
}
void Update(){
screen->Update();
screen->Render();
}
NDKActivity.cpp
Game *game;
void nativeSurfaceChanged(){
// initlizes stuff like audio engine, rendering engine
game->Initialize();
// set current screen to main menu
game->SetScreen(new MainMenu());
}
void nativeDrawFrame(){
game->Update();
}
MainMenu.cpp
void Update(){
// if some button is clicked
game->SetScreen(new GameScreen());
}
Now when menu is initialized, everything works fine. But on loading GameScreen textue ids get all mixed up
I basically ported it from windows app where I was using GLUT for creating OpenGL context and there it was working fine.
And please let me know if more info is needed
glGenTextures keeps returning duplicate ids
That should not happen, unless you're deleting the texture with that ID somewhere (else) or end up in a different GL context.
I am facing difficulty on how to change levels, eg. from menu to game screen.
It's as easy as drawing something different. Have two functions draw_menu and draw_level; maybe a draw_loadingscreen and while you're in the loading screen or menu you can replace all the stuff the level uses.
Or you could use a modern streaming approach, where you don't discriminate between menu, loading screen and level and instead upon drawing each frame collect the resources required to draw it, load what's not yet loaded into the GL context and then draw.
Deleting GL resources can be mostly offloaded into a background garbage collection routine. I.e. every frame for every resource of your game you increment a counter; in the frame setup, when you actually are about to draw it you reset the counter to zero. Once the counter hits a certain threshold you delete it. If when loading resources into GL you hit an out-of-memory condition you can work yourself through the resources with the highest counter value downward, deleting them from the GL context.
so as it turns out I was listening for change screen method in OnTouch() method which apparently runs on different thread than opengl and thus every thing was falling apart. So I had to add a callback which would change screen in onDrawFrame and it fixed the issue.
thanks for helping :)
Related
I'm building a system which has a set of quads in front of each other, forming a layer system. This layers are being rendered by a orthographic camera with a render texture, which is used to generate a texture and save it to disk after the layers are populated. It happens that I need to disable some of those layers before the final texture is generated. So I built a module that disable those specific layers' mesh renderers and raise an event to start the render to texture conversion.
To my surprise, the final image still presents the disabled layers in the final image. I'm really confused about this, cause I already debugged the code in every way I could and those specific layers shouldn't be visible at all considering the code. It must have something to do with how often render textures update or some other obscure execution order. The entire module is composed of 3 or 4 classes with dozens of lines, so to exemplify the issue in a more succinct way, I'll post only the method where the RT is being converted into a texture with some checks I made just before the RT pixels are read into the new texture:
public void SaveTexture(string textureName, TextureFormat textureFormat)
{
renderTexture = GetComponent<Camera>().targetTexture;
RenderTexture.active = renderTexture;
var finalTexture = new Texture2D(renderTexture.width,
renderTexture.height, textureFormat, false);
/*First test, confirming that the marked quad' mesh renderer
is, in fact, disabled, meaning it shouldn't be visible in the camera,
consequently invisible in the RT. The console shows "false", meaning it's
disabled. Even so, the quad still being rendered in the final image.*/
//Debug.Log(transform.GetChild(6).GetChild(0).GetComponent<MeshRenderer>().enabled);
/*Second test, changing the object' layer, because the projection camera
has a culling mask enabled to only capture objects in one specific layer.
Again, it doesn't work and the quad content still being saved in the final image.*/
//transform.GetChild(6).GetChild(0).gameObject.layer = 0;
/*Final test, destroying the object to ensure it doesn't appear in the RT.
This also doesn't work, confirming that no matter what I do, the RT is
"fixed" at this point of execution and it doesn't update any changes made
on it's composition.*/
//Destroy(transform.GetChild(6).GetChild(0).gameObject);
finalTexture.ReadPixels(new Rect(0, 0, renderTexture.width,
renderTexture.height), 0, 0);
finalTexture.Apply();
finalTexture.name = textureName;
var teamTitle = generationController.activeTeam.title;
var kitIndex = generationController.activeKitIndex;
var customDirectory = saveDirectory + teamTitle + "/"+kitIndex+"/";
StorageManager<Texture2D>.Save(finalTexture, customDirectory, finalTexture.name);
RenderTexture.active = null;
onSaved();
}
Funny thing is, if I manually disable that quad in inspector (at runtime, just before trigger the method above), it works, and the final texture is generated without the disabled layer.
I tried my best to show my problem, this is one of those issues that are kinda hard to show here but hopefully somebody will have some insight of what is happening and what should I do to solve that.
There are two possible solutions to my issue (got the answer at Unity Forum). The first one, is to use the methods OnPreRender and OnPostRender to properly organize what should happens before or after the camera render update. What I end up doing though was calling the manual render method in the Camera, using the "GetComponenent().Render();" line, which updates the camera render manually. Considering that my structure was ready already, this single line solved my problem!
I'm currently working on a new app, and I want to add customized animations to it (not talking about activity transitions).
To show you exactly what I mean, take a look at this video at 2:30-2:33:
https://www.youtube.com/watch?v=XBMdjX5bbvk&nohtml5=False
You see the chest jumping to the screen and opens smoothly with beautiful animation?
I'd really like to know how can it be added to an Android app, is it a frame animation?
I mean, I can make this animation, in 2D, I just want to know how to add it (I'm using Android Studio) without causing memory overflow.
Thanks!
For you question:
You see the chest jumping to the screen and opens smoothly with
beautiful animation? I'd really like to know how can it be added to an
Android app, is it a frame animation?
I don't think it is a frame animation. I guess this has been implemented using OpenGL. You can find the official tutorial here.
If you want to make simple 2d animations, you can use the AnimationDrawable api provided by android. You basically need frames for the sequence of animations and then you can create the animation using the following code:
// you would need an `ImageView` object as a placeholder for the animation
ImageView mMascotView = findViewById(...);
// prepare the animation object ..
AnimationDrawable mMascotAnimation = new AnimationDrawable();
final int frameTime = 250; // time in milliseconds
// adding the frames to the animation object. You can specify different
// times for each of these in milliseconds
mMascotAnimation.addFrame(getResources().getDrawable(R.drawable.frame1),frameTime);
mMascotAnimation.addFrame(getResources().getDrawable(R.drawable.frame2),frameTime);
mMascotAnimation.addFrame(getResources().getDrawable(R.drawable.frame3),frameTime);
// make it loop infinitely ..
mMascotAnimation.setOneShot(false);
// set the background of the `ImageView` as the `AnimationDrawable`object ..
mMascotView.setBackground(mMascotAnimation);
// start the animation ..
mMascotAnimation.start();
Note: You should not call the AnimationDrawable.start()inside the onCreate() method of the activity. The views are not ready yet. You should use the callback on onWindowFocusChanged() method and start the animation there:
#Override
public void onWindowFocusChanged (boolean hasFocus)
{
//Start animation here
if(hasFocus) {
mMascotAnimation.start();
}
}
I'm an engineer and we are currently porting our Red5 + Flash game into a Node.js + Easeljs html5 application.
Basicly: it's a board game, not an rpg. The layer system means we have multiple canvasses, based on functionally. For example there is a static background stage, with images. There is a layer for just the timers.
At default, all canvas size is 1920x1080, if needed we downscale to fit to the resolution.
The first approach used kinetic.js, but the performance fallen when the game got complex. Then we switched to easel, because it's abstraction level is lower, so we can decide how to implement some more function, not just use the provided robust one.
I was optimistic, but now it's starting to show slowness again, that's why I want to look deeper inside and do fine performance tuning. (Of course everything is fine in Chrome, Firefox is the problem, but the game must run smoothly on all modern browser).
The main layer (stage) is the map, contains ~30 containers, in each there is a complex custom shape, ~10 images. The containers are listening to mouse events, like mouseover, out, click. Currently, for example on mouseover I refill the shape with gradient.
Somehow, when I use cache, like the way in the tuts the performance get even worse, so I assume I'm messing up something.
I collected some advanced questions:
In the described situation when can I use cache and how? I've already tried cache on init, cacheUpdate after fill with other color or gradient, then stage.update(). No impact.
If I have a static, never changing stage cache doesn't make sense on that layer, right?
What stage.update() exactly do? Triggering the full layer redraw? The doc mentions some kind of intelligent if changed then redraw effect.
If I want to refill a custom shape with new color or gradient I have to completely redraw its graphics, not just use a setFill method, right?
In easel there is no possibility to redraw just a container for example, so how can I manage to not update the whole stage, but just the one container that changed? I thought I can achieve this with caching, cache all containers the just update the one that changed, but this way didn't work at all for me.
Does it make sense to cache bitmap images? If there are custom shapes and images in a container what is better? Cache the container or just the shape in container.
I found a strange bug, or at least an interesting clue. My canvas layers totally overlapping. On the inferior layers the mouseover listening is working well, but the click isn't on the very same container/object.
How can I produce a click event propagation to overlapped layers those have click listeners? I've tried it with simple DOM, jquery, but the event objects were far away from what canvas listeners wanted to get.
In brief, methods and props I've already played with bare success when tried tuning: cache(), updateCache(), update(), mouseEnabled, snapToPixel, clear(), autoClear, enableMouseOver, useRAF, setFPS().
Any answer, suggestion, starting point appreciated.
UPDATE:
This free board game is a strategy game, so you are facing a world map, with ~30 territories. The custom shapes are the territories and a container holds a territory shape and the icons that should be over the territory. This container overlapping is minimal.
An example mouse event is a hover effect. The player navigate over the territory shape then the shape is getting recolored, resized, etc and a bubble showing up with details about the place.
Basically, maximum amount of 1-3 container could change at once (except the init phase -> all at this time). Not just the animations and recoloring slow in FF, but the listener delay is high too.
I wrote a change handler, so I only stage.update() up on tick the modified stages and the stages where an animation is running (tweenjs).
In my first approach I put every image to the container that could be needed at least once during the game, so I only set visible flags on images (not vectors).
Regarding caching:
There are some strange caching-issues, somehow the performance can drop with certain sizes of the caching rectangle: CreateJS / EaselJS Strange Performance with certain size shapes
(2) Depending on how often you call stage.update();
(3)
Each time the update method is called, the stage will tick any
descendants exposing a tick method (ex. BitmapAnimation) and render
its entire display list to the canvas. Any parameters passed to update
will be passed on to any onTick handlers.
=> Afaik it rerenders everything if not cached
(4) Yes.
(5) No. (I don't know of any)
(6) If the content's of the container don't change often, I'd cache the whole container, otherwise the container will be reconstructed every frame.
I have a question though: Why do you use multiple canvases? How many do you use? I could imagine that using multiple canvases might slow down the game.
How many sprites do you use in total?
2: if your layer or stage doesn't change, don't call stage.update() for that layer (so it doesn't gets rerendered, gives me a much lower cpu!)
For example, keep a global "stagechanged" variable and set this to true when something has changed:
createjs.Ticker.addEventListener("tick",
function() {
if (stagechanged)
{
stagechanged = false;
stage.update();
}
});
(or do you already use this, as stated in your "update"?)
4: I found a way to update for example the fill color :)
contaier1.shape1.graphics._fillInstructions[0].params[1] = '#FFFFFF';
(use chrome debugger to look at the _fillInstructions array to see which array position contains your color)
5: I found a way to just paint one container :)
//manual draw 1 component (!)
var a = stage.canvas.getContext("2d");
a.save();
container1.updateContext(a); //set position(x,y) on context
container1.draw(a);
a.restore();
Write now, I'm creating an interactive ebook using cocos2d. When the program runs the cover page animation is choppy only on initial load. This animation is on the cover page and it is huge. We're talking 13 texture atlases, 26 images.
I know the problem stems from preloading/loading images, but I already loaded all the images before the animation occurs.
-(id) init {
if( (self=[super init]) ) {
isTouchEnabled_=YES;
//Pg0 Animations
[[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:#"CB0A0.plist"];
[[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:#"CB0A1.plist"];
...etc.}}
The overall set up of the book is as follows. I build a scene, a menu layer, and then the menu layer pushes and pops different layers/ different pages.
When the cover page is loaded (Pg0), if the user touches a picture it runs through the animation. Then when the user, touches the picture again, a second animation runs.
All the images of the book are loaded in the menu layer (so before any page pushes or pops). I've tried loading these images on the scene, or the individual pages to speed up the process, but that doesn't affect time.
I am running my animation through an animation helper, which loops through the images for me.
Any help would be wonderful, and I am would love to share more code or info about the project if it needed.
Have the same problem. When use cocos2d v0.9 animation was ok, no lag. Lag appears when migrating to cocos2d v2.0.
When you add sprites to cache (addSpriteFramesWithFile:(NSString*)plist) in cocos2d v0.9 texture2d is also created (CCSpriteFrameCache.m:238), in cocos2d v2.0 there is no textture2d creation, texture is created at first use of CCSpriteFrame. I fix it by adding
[[CCTextureCache sharedTextureCache] addImage:textureFileName];
in CCSpriteFrameCache.m:207 (v2.0)
I was just experiencing this problem in cocos2D v3.1 iphone. I had spritesheets that were cached but still were stuttering on loading. I found somewhere on another post that you need to load the texture itself as well to get rid of the initial lag. This is what I did in my caching sprites method:
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"spritesheet.plist"];
CCTexture *temporaryLoadTexture = [CCTexture textureWithFile:#"spritesheet.png"];
Just by loading a dummy CCTexture file, that got rid of all first-time animation and sprite lag. Hope this helps!
Check if your AppDelegate implements the memory warning method. Check what that method does.
By default, cocos2d implements that method and purges all caches. Now when that gets triggered while preloading textures, what happens is that cocos2d removes the preloaded textures because a memory warning was received yet those preloaded textures aren't in use yet. Cocos2d considers them to be "unused" and removes them from memory. Which means next time you use that texture, it needs to be loaded from disk again.
I wrote a blog post where I describe this issue, and ways to solve it. Most importantly: get TexturePacker and use only .pvr.ccz for texture atlases. Try to reduce texture color depth to 16 bit where possible. And be sure to dump texture memory usage to learn how much memory you're actually using, and whether that amount of memory is within reasonable limits. Including older devices with fewer memory that you may be supporting.
I am amazed at how well the native Symbian components are implemented. One of them is CAknSlider. CAknSlider is a control that has a slider that users can use to slide it along a bar whose orientation can be vertical or horizontal.
Now when you slide the slider the sliding is very smooth and does not flicker. But if for some reason I were to implement a custom slider control I would not get it as neat as CAknSlider.
So my question is how can I figure out how CAknSlider is implemented under the hood. I want to implement a custom slider for my radio application to control the volume of audio stream.
Any idea how should I go about it.
[EDIT: In response to the comment from laalto]
The CAknSlider control is often implemented as a setting item in the settings screen.
I have never seen it implemented as a component control within a compound control container ( like CCoeControl or CAknView ). This is what I have tried so far:
First I created a resource file describing the slider control like below:
RESOURCE SLIDER r_volume_slider
{
layout=EAknCtSlider;
minvalue=0;
maxvalue=10;
step=1;
valuetype=EAknSliderValuePercentage;
minlabel="mute";
maxlabel="full";
}
Then I am using the resource file in my source to create the slider like below:
void CVolumePopupAppView::ConstructL(const TRect& aRect)
{
// Create a window for this application view
CreateWindowL();
InitComponentArrayL( );
iSlider = new ( ELeave ) CAknSlider( );
TResourceReader reader;
iEikonEnv->CreateResourceReaderLC( reader, R_VOLUME_SLIDER );
iSlider->ConstructFromResourceL( reader );
CleanupStack::PopAndDestroy ( );
iSlider->SetContainerWindowL( *this );
iSlider->SetParent( this );
Components().AppendLC( iSlider );
CleanupStack::Pop ( iSlider );
// Set the windows size
SetRect(aRect);
// Activate the window, which makes it ready to be drawn
ActivateL();
}
Now here is the comparison between the CAknSlider as a setting item ( Screenshot1 ) and the CAknSlider that gets created by the above described technique ( Screenshot2 ). Notice that the one I create does not have a percentage value indicator and the minimum and maximum text labels even though I specified them in the resource. The look and feel is also pathetic.
There are lots of techniques to avoid flicker, from double-buffering the whole screen down to more simple optimizations, like only re-drawing the parts of the control that have actually changed. Having appropriate rectangles pre-drawn to blit over where the slider was and its next step is probably the easiest way to do it efficiently.
To find out exactly how CAknSlider does it, you can either:
1) Wait for the relevant package in the Symbian Foundation platform to go open source (EPL) - should sometime in the next 12 months, or
2) Join the Symbian Foundation and get access to the source now
EDIT: (In response to request for more details on graphics optimisation)
Most commonly flicker is caused by redrawing the whole control. I have implemented (via a porting project) some custom controls that don't flicker here:http://developer.symbian.com/main/documentation/porting/#linux2
There's even something a bit like a slider. This example is far from ideal, it doesn't have pre-drawn rectangles for blitting but the graphics are very simple lines and filled rectangles. The concept of overwriting just the changed part is identical though. To blit pre-drawn sections. Draw the backgroud of the slider to an off-screen bitmap and do the same with the movable part of the slider. When the slider is moved, erase the movable part by doing a BitBlt() from the off-screen background (of only the part that needs to be erased) and then BitBlt() the movable part into the new position.
Does that make sense?
You need CAknSlider? steal it! :) CAknSliderSettingPage do everything for us. We, just use that.
iSettingPage = new(ELeave) CAknSliderSettingPage(R_SLIDER_PAGE, iValue);
iSettingPage->ConstructL();
iSettingPage->SetSize(iSettingPage->MinimumSize());
TInt CCustomColorPalette::CountComponentControls() const
{
return 1;
}
CCoeControl* CCustomColorPalette::ComponentControl( TInt aIndex ) const
{
return iSettingPage->SliderControl();
}