void SkillManager::initBuff() {
CCObject* pobj;
CCLog("in init Buff");
CCARRAY_FOREACH(mSkills, pobj) {
Skill* skill = (Skill*) pobj;
CCLog("skillDuration:%d,skillIndex: %d",skill->mSkillDuration,skill->mSkillDebuffTag);
if (skill->mSkillDuration <= 0) {
mSkills->removeObject(skill);
}
else
skill->initBuffData();
}
}
I create a CCarray mSkills to save my skills,when the skill's duration is over,i remove it from the array,every time before check one skill's duration i will cclog it's duration and debuff tag.I will also add some skill in array at any time.
In most cases, the code works well . But a occasional error is is an obsession for me.
In normal times the log is :
Cocos2d: in init Buff
Cocos2d: skillDuration:6,skillIndex: 203
Cocos2d: duration:6
Cocos2d: in init Buff
Cocos2d: skillDuration:5,skillIndex: 203
Cocos2d: skillDuration:2,skillIndex: 0
Cocos2d: in init Buff
Cocos2d: skillDuration:4,skillIndex: 203
Cocos2d: duration:4
Cocos2d: skillDuration:1,skillIndex: 0
Cocos2d: skillDuration:0,skillIndex: 0
In error log is :
ocos2d: in init Buff
Cocos2d: skillDuration:1,skillIndex: 0
Cocos2d: skillDuration:6,skillIndex: 203
Cocos2d: duration:6
Cocos2d: in init Buff
Cocos2d: skillDuration:0,skillIndex: 0
Cocos2d: skillDuration:2,skillIndex: 0
Cocos2d: skillDuration:1,skillIndex: 0
Cocos2d: in init Buff
Cocos2d: skillDuration:5,skillIndex: 203
Cocos2d: skillDuration:0,skillIndex: 0
Cocos2d: skillDuration:0,skillIndex: 0
Cocos2d: in init Buff
Cocos2d: skillDuration:4,skillIndex: 203
Cocos2d: duration:4
Cocos2d: skillDuration:2,skillIndex: 0
that means the skill which index is 203 have changed , or CCArray got wrong data at this time?
But i can see in next time init Buff the 203's data is correct.
I found when using CCARRAY_FOREACH will run out some bug if you change the data in array.But this time i change it to for() {} the problem is still here.
Someone knows this problem?
You don't want to remove an element from a CCArray in the middle of iterating through it. Try:
for(int i = mSkills->count() - 1; i >= 0; i--) {
Skill *skill = mSkills->objectAtIndex(i);
...
}
It's not the most efficient, but it also doesn't seem like you're going to be spending a lot of time in this function. Let me know if that helps.
Explanation
When you remove an element from a CCArray, the implementation moves all the later elements up one spot to fill the gap created by the missing element.
If you're iterating in a forward direction, you're moving elements that you haven't visited yet, and you end up skipping the element after the one being removed. Iterating backwards through the array solves this problem because you've already visited the elements being moved.
Related
I have a weird issue only happening on my Intel HD Graphics 530
When rendering an image, some pixels color randomly change.
See the following image:
Bug
For the problematic pixels, the graphics debugger show that the color outputted from the graphics pipeline is the correct one. But the pixel displayed color is wrong.
See: Debugger
From my investigations i have found that these pixels seems using information from the materials of the others. My materials information is handled by a descriptor heap. So the switch between graphics root descriptor table in my rendering loop seems to be my problem (when i only draw one object everything is fine)
Here the code snippet i use:
void ForwardLighningEffect::pushCommands(ForwardLigthningPushArgs data, ID3D12GraphicsCommandList* commandList, int frameIndex) {
// set PSO
commandList->SetPipelineState(m_mainPipelineStateObject);
// set root signature
commandList->SetGraphicsRootSignature(m_rootSignature);
// set constant buffer view
commandList->SetGraphicsRootConstantBufferView(0, m_constantBufferUploadHeaps[frameIndex]->GetGPUVirtualAddress());
const auto& meshes = data.model->getMeshes();
for (auto mesh : meshes)
{
if (auto materialHandle = mesh->material.lock()) // get material handle from weak ptr.
{
ID3D12DescriptorHeap * matDescriptorHeap = materialHandle->material.descriptorHeap;
// set the material descriptor heap
ID3D12DescriptorHeap* descriptorHeaps[] = { matDescriptorHeap };
commandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
// HERE ! set the descriptor table to the descriptor heap (parameter 1, as constant buffer root descriptor is parameter index 0)
commandList->SetGraphicsRootDescriptorTable(1, matDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
}
commandList->IASetVertexBuffers(0, 1, &mesh->vertexBuffer.bufferView);
commandList->IASetIndexBuffer(&mesh->indexBuffer.bufferView);
for (auto camera : data.cameras)
{
updateConstantBuffer(camera, frameIndex);
// Draw mesh.
commandList->DrawIndexedInstanced(mesh->nbIndices, 1, 0, 0, 0);
}
}
}
Whats wrong ?
Found a solution. Updating textures state when not used fixed it.
So when binding a texture:
commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(/*textureResource*/, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
After use then reset state:
commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(/*textureResource*/, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COMMON));
I am populating an NSMutableArray with CCSprites and adding them to the current layer which is added to a scene. When i try to access the elements of the array I get a bad access error
sprites = [[[NSMutableArray alloc] init]autorelease];
int j = 0;
for (int i=0; i<[sprites count]; i++)
{
j=i+1;
sprite = [CCSprite spriteWithFile:[NSString stringWithFormat:#"intro%d.png",j]];
sprite.position = ccp(WIDTH/2, HEIGHT/2+(i*HEIGHT));
[sprites addObject:sprite];
}
for (int i = 0; i<[sprites count]; i++)
{
[self addChild:[sprites objectAtIndex:i]];
}
[self scheduleUpdate];
}
return self;
This is done in the init method and sprites and sprite are declared in the header file. Inside the update method, I have
sprite = [sprites objectAtIndex:1];
sprite.position = ccpAdd(sprite.position, ccp(0,dy));
CCSprite* spr = [sprites objectAtIndex:2];
spr.position = ccpAdd(spr.position, ccp(0,dy));
When control is passed to the update method, I get a bad access. I would be glad if anyone could help me
This is happening because you created an autorelease object, that you then try to access later in your update code. The sprites array has a retain count of zero (since it is autorelease), and gets deallocated, you then try to access it, and get a bad-access error.
To fix, you should not make the sprites array an autorelease object. Since you plan on using the object later on in your code, you should keep it retained (by not adding the autorelease). You should also then make sure to release the array in the (whatever the parent object that is operating on the array)'s dealloc method.
- ( void ) dealloc {
[ sprites release ];
[ super dealloc ];
}
You should retain the sprites array (make certain you release it in your object's dealloc). Since it is autoreleasable, during the cycle from your init to your update method, it gets released.
Also (strange) , if your code is as shown, sprites.count is 0 when you start your first loop. You wont get much in there :).
The others are right (the autorelease call is the culprit - you should just remove it and then release the array in the dealloc method of the scene).
Also note that [[[NSMutableArray alloc] init]autorelease] has the same effect as [NSMutableArray array] (for your scenario, though, this is not what you need).
Is there any way to reduce the game framerate from 30 to 25 fps on the iPhone? I'm porting a Flash game created at 25 fps and exporting the sprites with this frame rate but animations are not shown as correctly as they should.
Any idea?
Try this instead, straight out of the box :
animation = [CCAnimation animationWithSpriteFrames:frames delay:.04];
with 40 ms delay, that should come real close to 25 fps (rendered animation) while the rest of the game is clocking full bore at 60 fps (if you don't have lag issues elsewhere)
I think that you can change your animation interval in your App Delegate with the following snippet in your didFinishLaunching method :
CCDirector *director = [CCDirector sharedDirector];
[director setAnimationInterval:1.0/25];
Hope this helps!
EDIT :
Could this link provide you more information about how to deal with that ?
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:best_practices
Well, at last the solution is by another way.
Kept the framerate to 1.0/60.0
What you need to do for animating the spritesheet slowest is to add the frame more than once to the animation array.
NSMutableArray *walkAnimFrames = [NSMutableArray array];
for(int i = _spriteMetadata.spriteInitFrame; i <= _spriteMetadata.spriteEndFrame; ++i)
{
NSString *spriteFrameName = [NSString stringWithFormat:#"%#%#", _spriteMetadata.spriteBaseName, index];
for (int i=0; i<2; i++)
{
[walkAnimFrames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:spriteFrameName]];
}
}
It's not very orthodox but it works! :)
Thanks for your help Andy!
I use SDL for my programs graphics and I have a problem with it in flipping surfaces.When I compile following code:
int main(int argc , char* argv[])
{
SDL_Surface* scr1 = SDL_SetVideoMode(880 , 600 , 0 , SDL_HWSURFACE |SDL_DOUBLEBUF );
SDL_Surface* scr2 = SDL_SetVideoMode(880 , 600 , 0 , SDL_HWSURFACE |SDL_DOUBLEBUF );
aacircleRGBA(scr1 , 50 , 50 , 30 , 255 , 0 , 0 , 255);
SDL_Flip(scr2);
return 0;
}
It shows the circle on the screen.But I flipped only scr2.Why does it show the circle?
After you call SDL_SetVideoMode() a second time, the original screen buffer pointer is, in the general case, invalid. You shouldn’t be reusing it, because it doesn’t point to an allocated surface anymore.
In this case, calling SDL_SetVideoMode() twice with the same parameters gives scr2 == scr1, because there is no need for SDL to reallocate the video surface. Drawing on the surface referred to by scr1 is thus the same as drawing on that referred to by scr2.
On success. The returned surface is freed by SDL_Quit and must not be freed by the
caller. This rule also includes consecutive calls to SDL_!SetVideoMode (i.e. resize or resolution change) because the existing surface will be released automatically. Whatever flags SDL_!SetVideoMode could satisfy are set in the flags member of the returned surface.
-- SDL_SetVideoMode function (emphasis mine)
There is only one hardware surface to render to, the one that appears on screen immediately after calling SDL_SetVideoMode. where else would you expect that buffer to draw to?
I'm working with NITE/OPENNI and opencv in xcode 4 to work with the kinect. I'm able to get the coordinates of the head for example this is done by :
In the main, outside the wile(true):
IplImage *rgbimg = cvCreateImageHeader(cvSize(640,480), 8, 3);
Then in the wile(true)
XnSkeletonJointPosition Head;
g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition( aUsers[i], XN_SKEL_HEAD, Head);
printf("%d: (%f,%f,%f) [%f]\n", aUsers[i], Head.position.X, Head.position.Y, Head.position.Z, Head.fConfidence); }
I also have a video stream :
// Take current image
const XnRGB24Pixel* pImage = Xn_image.GetRGB24ImageMap();
//process image data
XnRGB24Pixel* ucpImage = const_cast<XnRGB24Pixel*> (pImage);
cvSetData(rgbimg,ucpImage, 640*3);
cvCvtColor(rgbimg,rgbimg,CV_RGB2BGR);
cvShowImage("RGB",rgbimg);
This is all done in the main in a while(true).
Now my question is how can i set some kind of marker (e.g.: *,cross-hair, X ) at the position of the coordinates of the hand in the video stream ?
EDIT
i tried:
XnRGB24Pixel* ucpImage = const_cast<XnRGB24Pixel*> (pImage);
cvSetData(rgbimg,ucpImage, 640*3);
cvCvtColor(rgbimg,rgbimg,CV_RGB2BGR);
cvCircle(rgbimg, cvPoint(Head.position.X,Head.position.Y), 20, cvScalar(0,255,0), 1);
cvShowImage("RGB",rgbimg);
and i get :
as you can see the circle stays in the top left corner for some reason. Any ideas how to change this ?
Try the display functions in OpenCV:
line(), circle(), drawPoly() and apply them to every frame in your video