I have this piece of code:
TShape* T[256];
/* Other code ... */
for (int i = 255; i > 0; i--) {
T[i]->Brush->Color = T[i - 1]->Brush->Color;
T[i]->Pen->Color = T[i - 1]->Pen->Color;
};
The cycle is executed by a TTimer each 100 milliseconds and the Color of the first TShape change each 100 milliseconds.
During this cycle, I see a blinking white horizontal lines, because before receiving the color of the other TShape, each TShape is invalidated and becomes white.
Is there a way to avoid this behaviour?
Maybe, I must override some method?
I think double buffering is the key to your problem. If you are using C++Builder 2009 or newer probably setting property Controls::TWinControl::DoubleBuffered for your current frame will be enough.
TShape invalidates itself every time you change its Brush and Pen properties, so your loop is double-invalidating each TShape. As a workaround, try temporarily removing the OnChange event handlers that TShape assigns internally, and then Invalidate() the TShape only once after you have finished updating it. For example:
for (int i = 255; i > 0; i--)
{
TNotifyEvent OldBrushChange = T[i]->Brush->OnChange;
T[i]->Brush->OnChange = NULL;
TNotifyEvent OldPenChange = T[i]->Pen->OnChange;
T[i]->Pen->OnChange = NULL;
T[i]->Brush->Color = T[i - 1]->Brush->Color;
T[i]->Pen->Color = T[i - 1]->Pen->Color;
T[i]->Brush->OnChange = OldBrushChange;
T[i]->Pen->OnChange = OldPenChange;
T[i]->Invalidate();
};
Related
I want to add new entries generated by logs at run time from my software at the bottom of StringGrid widget (20 rows and 2 columns) in C++ Builder 5.
Whether there is any Property of StringGrid widget which can automatically delete entry in top most row before adding new entry in bottom most row in case all rows of fixed size StringGrid is occupied with data.
Please inform me if you need any other information from me.
Many thanks
Saurabh Jain
As I told you in the Embarcadero forums...
There is no public property/method for what you are asking for. You will just have to set/increment the RowCount property as needed, then manually shift up the contents of the Cells property, and then finally fill in the bottom row.
if (StringGrid1->RowCount < SomeMaxValue)
StringGrid1->RowCount = StringGrid1->RowCount + 1;
for(int row = 1; row < StringGrid1->RowCount; ++row)
{
for(int col; col < StringGrid1->ColCount; ++col)
{
StringGrid1->Cells[col][row-1] = StringGrid1->Cells[col][row];
}
}
// fill in StringGrid1->Cells[...][StringGrid1->RowCount-1] for the last row as needed...
However, TStringGrid does have a protected DeleteRow() method, but being protected, you need to use an accessor class to reach it, eg:
class TStringGridAccess : public TStringGrid
{
public:
void RemoveRow(int row) { TStringGrid::DeleteRow(row); }
};
if (StringGrid1->RowCount > 0)
((TStringGridAccess*)StringGrid1)->RemoveRow(0);
StringGrid1->RowCount = StringGrid1->RowCount + 1;
for(int row = 1; row < StringGrid1->RowCount; ++row)
{
for(int col; col < StringGrid1->ColCount; ++col)
{
StringGrid1->Cells[col][row-1] = StringGrid1->Cells[col][row];
}
}
// fill in StringGrid1->Cells[...][StringGrid1->RowCount-1] for the last row as needed...
That said, TStringGrid is really not the best choice for what you are trying to do. I would strongly suggest using TListView in vsReport mode instead. That is what I use in my log viewer, and it works very well, especially in virtual mode (OwnerData=true), and it just looks more natural than TStringGrid, since TListview is a wrapper for a native Windows control whereas TStringGrid is not.
if (ListView1->Items->Count > 0)
ListView1->Items->Items[0]->Delete();
TListItem *Item = ListView1->Items->Add();
// fill in Item->Caption (column 0) and Item->SubItems (columns 1+) as needed...
I'm making a simple SpriteKit game. It has one randomly generated world made up of lines. These lines are represented by the NHRLineNode class. I generate these lines all at once in the beginning of the level with two for loops, one for each side of the screen. This works fine. In addition to the main gameplay scene of the game, there is a "game over" screen that displays between plays and shows your score etc and a main menu scene. The problem comes when I play the game, die, see the game over screen, and play again. Looking at the memory usage in Xcode, it seems like the memory usage goes up when I first start the game from the menu scene, stays steady throughout the gameplay, and then jumps 6-10 MB when I die. This memory is never regained and the app uses more and more memory every time I play. I think this is because my for loops that generate the platforms are just creating a new instance of the NHRLineNode class, positioning it correctly, and then doing it again. Is this what is causing my memory issues? Or is it more likely something on the game over scene?
Relevant snippets:
The for loops that generate the platforms:
int previousXVal1 = -10;
int previousYVal1 = 425;
int newXPosition = 0;
//How many do you want?
int numToGen = 100;
for(int i = 1; i<=numToGen; i++) {
NHRLineNode *lineGen = [NHRLineNode initAtPosition:CGPointMake(previousXVal1 + arc4random_uniform(85), previousYVal1 - 75)];
[worldNode addChild:lineGen];
if(lineGen.position.x > 390) {
newXPosition = lineGen.position.x - 100; //That should bring it onscreen!
lineGen.position = CGPointMake(newXPosition, lineGen.position.y); //Make the new position
} else if (lineGen.position.x < 100) {
newXPosition = lineGen.position.x + 100; //That will bring it onscreen!!
lineGen.position = CGPointMake(newXPosition, lineGen.position.y);
}
previousXVal1 = lineGen.position.x;
previousYVal1 = lineGen.position.y;
}
//This creates the lines on the right side (performing the inverse calculation on the x pos
//int numToGen = 10;
int previousXVal2 = 350;
int previousYVal2 = 525;
for(int i = 1; i<=numToGen; i++) {
NHRLineNode *lineGen = [NHRLineNode initAtPosition:CGPointMake(previousXVal2 - arc4random_uniform(85), previousYVal2 - 75)];
[worldNode addChild:lineGen];
if(lineGen.position.x > 390) { //It is partially off-screeb=n
newXPosition = lineGen.position.x - 100; //That should bring it onscreen!
lineGen.position = CGPointMake(newXPosition, lineGen.position.y); //Make the new position
} else if (lineGen.position.x < 100) { //It is partially off-screen
newXPosition = lineGen.position.x + 100; //That will bring it onscreen!!
lineGen.position = CGPointMake(newXPosition, lineGen.position.y);
}
previousXVal2 = lineGen.position.x;
previousYVal2 = lineGen.position.y;
}
The initAtPosition method of NHRLineNode:
+(id)initAtPosition:(CGPoint)point {
//This is all the properties of one of the lines in the level
SKSpriteNode *theLine = [SKSpriteNode spriteNodeWithImageNamed:#"newLine"];
//The physics body is slightly smaller than the image itself -- why idk
theLine.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(75,5)];
//It is not affected by gravity
theLine.physicsBody.dynamic = NO;
//Its position is the point given us when the function was called
theLine.position = point;
//Return it for further positioning by the generator
return theLine;
}
Entire implementation of GameOverScene: http://pastebin.com/wUpguueb
Thanks for your help.
Even though you have ARC on your side, sometimes you need to give it "incentive" to free objects, especially when creating many in a loop. Really, this simply has to do with providing scope, so ARC understands that it may release allocated instances.
Try wrapping the bodies of your for loops (i.e. not around the entire for loops), with #autoreleasepool { …} - i.e., as if that #autoreleasepool block is the only statement for the for loop.
Let is know if it helps! I commonly have to do this when iteratively importing data to Core Data.
In my OpenGL loop, Instruments is showing a total of 14% of my processor time in my particle processing loop going to objc_object::sidetable_release(bool) and objc_object:sidetable_retain(). This is significant, because the loop is using 100% of a CPU on an iPhone 5.
I'm wondering if there's a way I can reduce this. I don't know what causes it, and I don't see these in very many of my methods. I think they are related to doing a fast enumeration of an array of objects.
Here is what the offending method looks like:
-(void) updateWithTime:(ccTime)dt sceneHeightAboveHorizon:(CGFloat)yMax{
_elapsed = (_elapsed+dt) ;
float farTotalWidth = EQ_SCENE_WIDTH + 2*EQ_SIZE_FAR;
float farHalfWidth = farTotalWidth/2.0;
for (MyParticleData *data in self.farParticleData){
//Calculate position
float newX = data.pos.x + data.xVelocity * dt;
if (newX > 1)
newX -= 1;
float newY = data.y0 + EQ_A_FAR*sin(EQ_F_FAR*_elapsed+data.phasePosition);
data.pos = cc3v(newX,newY,0);
//Apply new position to sprites
data.sprite.position = cc3v(newX*farTotalWidth-farHalfWidth, newY*yMax, 0);
data.reflectedSprite.position = cc3v(data.sprite.position.x,-data.sprite.position.y,0);
//Calculate color
float f = MIN(14, MAX(data.pos.x*14.0, 0));
ccColor4F newColor = cycBlendColors(self.settings.eqColumnColors[(int)f], self.settings.eqColumnColors[(int)f+1], f-(int)f);
float colorAmp = MAX(0, (sin(data.frequencyColor*_elapsed+data.phaseColor)+1)/2.0);
newColor = cycScaleColor(newColor,colorAmp);
colorAmp *= colorAmp;//the alpha (white component) should be squared twice
newColor.a *= colorAmp*colorAmp;
//Apply new color to sprites
data.sprite.color4F = newColor;
data.reflectedSprite.color4F = cycScaleColor(newColor, self.settings.eqReflectionBrightness);
}
}
I'll try and psychically debug here -
1) You have ARC enabled
2) Some of the intermediate variables in your expressions (ex. data.sprite, self.settings) are Objective-C objects
3) One or more of these intermediate objects are weak or atomic (or are themselves accessing weak or atomic properties), both of which will require extra retain/release handling when accessed.
- IIRC atomic properties won't involve the side table rigamarole, just normal autoreleasing, but no guarantees on that.
I would try assigning some/all of these references to a local (on the stack) variable before enumeration, and inside your loop use the local references exclusively. This will have the added benefit of shaving off some accessor time from your loop as well.
If you know these references will remain strongly referenced through the entire enumeration 100% of the time, then you can use the __unsafe_unretained specifier on your local variables, which will (mostly) prevent any ARC shenanigans whatsoever from occurring in this method.
This is my current code:
_root.createEmptyMovieClip("noteGrid", _root.getNextHighestDepth());
for(i = 1; i <= 14; i++){
currentBlock = _root.noteGrid.attachMovie("block", "block" + i, _root.noteGrid.getNextHighestDepth);
currentBlock._x = Math.floor(i / 7) * 25;
currentBlock._y = (i % 7) * 25;
}
I have a movieclip with linkage set to block. When I compile this, the block appears however they are all on top of each other. When I used trace commands to find currentBlock._x, they are the correct values.
The problem lies with your setting of depths.
_root.noteGrid.getNextHighestDepth
You are trying to access a property of noteGrid, if you trace it you will see it tells you it is a function, rather than calling a function. To call the function do
_root.noteGrid.getNextHighestDepth()
By the looks of things your code isn't quite what you want but that can't really be fixed without you giving more details about what you're trying to do. Assuming you're trying to make a 2x7 grid, then you'll want to change your for loop to
for(i = 0; i < 14; i++)
How can I adjust the size of the window in XNA.
Default it starts in a 800x600 resolution.
As of XNA 4.0 this property is now found on the GraphicsDeviceManager.
Ie. this code would go in your Game's constructor.
graphics = new GraphicsDeviceManager(this);
graphics.IsFullScreen = false;
graphics.PreferredBackBufferHeight = 340;
graphics.PreferredBackBufferWidth = 480;
// if changing GraphicsDeviceManager properties outside
// your game constructor also call:
// graphics.ApplyChanges();
I found out that you need to set the
GraphicDevice.PreferredBackBufferHeight = height;
GraphicDevice.PreferredBackBufferWidth = width;
When you do this in the constructor of the game class it works, but when you try do to this outside the constructor you also need to call
GraphicsDevice.ApplyChanges();
Furthermore to have fullscreen (which is not really working correctly while debugging) you can use
if (!GraphicsDevice.IsFullScreen)
GraphicsDevice.ToggleFullScreen();
You should look at this, http://forums.xna.com/forums/p/1031/107718.aspx.
This solution works in XNA 3.0. Just put it in your game object's constructor:
// Resize the screen to 1024 x 768.
IntPtr ptr = this.Window.Handle;
System.Windows.Forms.Form form = (System.Windows.Forms.Form)System.Windows.Forms.Control.FromHandle(ptr);
form.Size = new System.Drawing.Size(1024, 768);
graphics.PreferredBackBufferWidth = 1024;
graphics.PreferredBackBufferHeight = 768;
graphics.ApplyChanges();