Low FPS issues in cocos2dx - cocos2d-x

I have finished the following function, It is containing 26 if else block in update. So it reflects little drop in FPS.
I have checked the 26 object using dynamic casting. Depend on shape, i checked the logic.
Here is the coding.
void WagonNode::update(float dt)
{
int found = 0;
for (int32 i = 0; i < kMaxContactPoints100 && found < contactPointCount100_; i++)
{
ContactPoint100* point = contactPoints100_ + i;
b2Fixture *otherFix = point->otherFixture;
if( otherFix )
{
found++;
b2Body *otherBody = otherFix->GetBody();
BodyNode *otherNode = (BodyNode*) otherBody->GetUserData();
if (dynamic_cast<ShapeA*>(otherNode) != NULL)
{
tagWord(CCString::create("A"));
}
else if (dynamic_cast<ShapeB*>(otherNode) != NULL)
{
tagWord(CCString::create("B"));
}
else if (dynamic_cast<ShapeC*>(otherNode) != NULL)
{
tagWord(CCString::create("C"));
}
else if (dynamic_cast<ShapeD*>(otherNode) != NULL)
{
tagWord(CCString::create("D"));
}
else if (dynamic_cast<ShapeE*>(otherNode) != NULL)
{
tagWord(CCString::create("E"));
}
else if (dynamic_cast<ShapeF*>(otherNode) != NULL)
{
tagWord(CCString::create("F"));
}
else if (dynamic_cast<ShapeG*>(otherNode) != NULL)
{
tagWord(CCString::create("G"));
}
else if (dynamic_cast<ShapeH*>(otherNode) != NULL)
{
tagWord(CCString::create("H"));
}
else if (dynamic_cast<ShapeI*>(otherNode) != NULL)
{
tagWord(CCString::create("I"));
}
else if (dynamic_cast<ShapeJ*>(otherNode) != NULL)
{
tagWord(CCString::create("J"));
}
else if (dynamic_cast<ShapeK*>(otherNode) != NULL)
{
tagWord(CCString::create("K"));
}
else if (dynamic_cast<ShapeL*>(otherNode) != NULL)
{
tagWord(CCString::create("L"));
}
else if (dynamic_cast<ShapeM*>(otherNode) != NULL)
{
tagWord(CCString::create("M"));
}
etc...
}
}
}
If there is any changes in the above coding, it would help me a lot.
Can any one assist me to handle or stabilise the FPS?

Dynamic casting is slow and might be the problem here. In this case you could try using typeid to resolve the dynamic type:
example:
if (typeid (*othernode) == typeid (ShapeA))
{
tagWord(CCString::create("A"));
} elseif
...
Another thing is, you are creating potentially a lot of strings there, you might want to check if that causes the performance issues. Use a profiler to find out the actual bottleneck.

Related

How can I fix this System.IndexOutOfRangeException: Index was outside the bounds of the array DMG

I am currently trying to fix this issue I am encountering is where the console is giving off errors for the array if anyone knows how to fix this.
If you can add me on skype mine is Bradley.dale4
The error is on line 247 which is.
if (Tamer.DigimonList[3] == null) qry.Add("mercenary3", null);
Accepting a client: 151.226.122.217:60417 27
System.IndexOutOfRangeException: Index was outside the bounds of the
array. at Digital_World.SqlDB.SaveTamer(Client client) in
C:\Users\Digimon Master\Dropbox\Digimon Master
Project\DMOFrosty'sPost\Server\ServerBuildingSection\DigitalWorld\Database
- Game.cs:line 247 A connection has closed.
The Code
public static void SaveTamer(Client client)
{
int lastChar = -1, charId = -1;
try
{
using (MySqlConnection con = Connect())
using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM `acct` WHERE `accountId` = #acct", con))
{
cmd.Parameters.AddWithValue("#acct", client.AccountID);
using (MySqlDataReader dr = cmd.ExecuteReader(System.Data.CommandBehavior.SingleRow))
if (dr.HasRows && dr.Read())
{
lastChar = (int)dr["lastChar"];
if (lastChar != -1)
{
charId = (int)dr[string.Format("char{0}", lastChar + 1)];
}
}
}
if (lastChar != -1)
{
Character Tamer = client.Tamer;
using (MySqlConnection con = Connect())
{
Query qry = new Query(Query.QueryMode.UPDATE, "chars", new Tuple<string, object>("characterId", Tamer.CharacterId));
qry.Add("charModel", (int)Tamer.Model);
qry.Add("charName", Tamer.Name);
qry.Add("charLv", Tamer.Level);
qry.Add("experience", Tamer.EXP);
qry.Add("money", Tamer.Money);
qry.Add("partner", Tamer.DigimonList[0].DigiId);
if (Tamer.DigimonList[1] == null) qry.Add("mercenary1", null);
else qry.Add("mercenary1", Tamer.DigimonList[1].DigiId);
if (Tamer.DigimonList[2] == null) qry.Add("mercenary2", null);
else qry.Add("mercenary2", Tamer.DigimonList[2].DigiId);
if (Tamer.DigimonList.Length >= 3)
{
if (Tamer.DigimonList[3] == null) qry.Add("mercenary3", null);
else qry.Add("mercenary3", Tamer.DigimonList[3].DigiId);
}
qry.Add("map", Tamer.Location.Map);
qry.Add("x", Tamer.Location.PosX);
qry.Add("y", Tamer.Location.PosY);
qry.Add("inventoryLimit", Tamer.InventorySize);
qry.Add("storageLimit", Tamer.StorageSize);
qry.Add("archiveLimit", Tamer.ArchiveSize);
qry.Add("maxHP", Tamer.MaxHP);
qry.Add("maxDS", Tamer.MaxDS);
qry.Add("HP", Tamer.HP);
qry.Add("DS", Tamer.DS);
qry.Add("AT", Tamer.AT);
qry.Add("DE", Tamer.DE);
qry.Add("MS", Tamer.MS);
qry.Add("Fatigue", Tamer.Fatigue);
qry.Add("incubator", Tamer.Incubator);
qry.Add("incubatorLevel", Tamer.IncubatorLevel);
BinaryFormatter f = new BinaryFormatter();
using (MemoryStream m = new MemoryStream())
{
f.Serialize(m, Tamer.ArchivedDigimon);
qry.Add("archive", m.ToArray());
}
//Trying to add cashvault and tempvault
qry.Add("inventory", Tamer.Inventory.Serialize());
qry.Add("equipment", Tamer.Equipment.Serialize());
qry.Add("storage", Tamer.Storage.Serialize());
qry.Add("quests", Tamer.Quests.Serialize());
using (MySqlCommand cmd = qry.GetCommand(con))
{
cmd.ExecuteNonQuery();
}
}
for (int i = 0; i < Tamer.DigimonList.Length; i++)
{
if (Tamer.DigimonList[i] != null)
SaveDigimon(Tamer.DigimonList[i]);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
It means there is no 4th (index starts with zero) item on your array. You should first check for the array count before performing your if condition.
UPDATE
Your condition should be "if your array count is equal to 4"
if (Tamer.DigimonList.Length == 4)
{
if (Tamer.DigimonList[3] == null) qry.Add("mercenary3", null);
else qry.Add("mercenary3", Tamer.DigimonList[3].DigiId);
}

How to get exact data after applying filter on data provider?

I am having N-Level hierarchical data.
It is the data about Products inside N-Level of Product categories.
After applying filter on the data, I want only that much data which satisfies the filter condition because I need to display counts after applying filter.
But the problem is I am not able to get such data from anywhere.
I have found such data in visibleData property of AdvanceDataGrid, but there is no way to access that property as it is defined as protected.
Please reply me if you have any other solution for my problem.
Please find my code as below:
<common:MyAdvancedDataGrid id="productsDataGrid"
width="100%"
height="100%"
focusRect="null"
borderVisible="false"
horizontalScrollPolicy="auto"
doubleClickEnabled="true"
selectionMode="multipleRows"
sortExpertMode="true"
draggableColumns="false"
defaultLeafIcon="{ null }"
displayItemsExpanded="true"
folderOpenIcon="{ null }"
folderClosedIcon="{ null }"
focusSkin="{ null }"
rowHeight="33"
sortableColumns="false"
variableRowHeight="true"
headerHeight="35"
resize="productsDataGrid_resizeHandler(event)"
keyDown="onProductDataGridKeyDown(event)"
creationComplete="onDataGridCreationComplete(event)"
selectedIndex="0">
<common:dataProvider>
<mx:HierarchicalData id="hierarchicalData"
source="{_hirarchyProductArr}"
childrenField="childCategory"/>
</common:dataProvider>
Filter Code:
<fx:Script>
<![CDATA[
private var _searchProductArr:Array;
private function onSearchChange1():void
{
_searchProductArr = new Array();
productsCount = 0;
IHierarchicalCollectionView(productsDataGrid.dataProvider).filterFunction = browseFilter;
// refresh the ADG's dataProvider
IHierarchicalCollectionView(productsDataGrid.dataProvider).refresh();
}
//Filter Function
private function browseFilter(item:Object):Boolean
{
if (item is Product)
{
var searchString:String = txtSearch.text;
if (searchString.length == 0 || item.productName.toLowerCase().indexOf(searchString.toLowerCase()) >= 0)
{
if (drdSelectProductType.selectedItem.label == ProductConstants.ALL_STR)
{
if(!isProductExist(item as Product))
{
_searchProductArr.push(item);
productsCount = _searchProductArr.length;
}
return true;
}
else if (drdSelectProductType.selectedItem.label == ProductConstants.ACTIVE_STR && (item as Product).isActive)
{
if(!isProductExist(item as Product))
{
_searchProductArr.push(item);
productsCount = _searchProductArr.length;
}
return true;
}
else if (drdSelectProductType.selectedItem.label == ProductConstants.INACTIVE_STR && !(item as Product).isActive)
{
if(!isProductExist(item as Product))
{
_searchProductArr.push(item);
productsCount = _searchProductArr.length;
}
return true;
}
else
return false;
return true;
}
else
return false;
}
else
{
var hasValidChildren:Boolean = false;
for each(var node:Object in item.childCategory)
{
if (browseFilter(node))
{
// productsCount = productsCount - 1;
hasValidChildren = true;
break;
}
}
return hasValidChildren;
}
}
private function isProductExist(value:Product):Boolean
{
for each(var product:Product in _searchProductArr)
{
if(product.productId == value.productId)
{
return true;
break;
}
}
return false;
}
]]>

For each loop not looping through everything

I have a loop that runs in an onEnter function (bad i know). I only want it to run once but it doesnt loop through every object. I think it doesnt have time before the next frame runs. Any ideas on how to make it loop all the way?
private function onEnter(e: Event) {
if (deleteThis == true) {
if (timer == 0 || 1) {
if (checkExplosion == false) {
gotoAndStop(2)
if (Main.bloonList.length > 0) {
for each(Main.bloon in Main.bloonList) {
if (Main.areaOfCollision(Main.bloon, this, 0)) {
if (Main.bloon.currentFrame != 5) {
Main.money++;
Main.bloon.nextFrame();
Main.bloon.gotShot();
} else {
Main.money++;
Main.bloon.deleteBloon();
}
}
}
}
checkExplosion=true
}
}
}
}
Edit - deleteBloon();
public function deleteBloon()
{
this.parent.removeChild(this);
}
Firstly, this:
if (timer == 0 || 1)
Should be this:
if (timer == 0 || timer == 1)
Then you may need to change the code a little bit. Something like this could work. I do suspect your issue may actually lie in the deleteBloon function, though. Without seeing it I can't be sure, but there is nothing (technically) wrong with your for loop.
private function onEnter(e: Event) {
if (deleteThis == true) {
if (timer == 0 || timer == 1) {
if (checkExplosion == false) {
gotoAndStop(2);
if (Main.bloonList.length > 0) {
// This isn't optimised as I wasn't sure what Main.bloon could be
for each(var bloon:Main.bloon in Main.bloonList) {
if (Main.areaOfCollision(bloon, this, 0)) {
if (bloon.parent && bloon.currentFrame != 5) {
bloon.nextFrame();
bloon.gotShot();
} /*else {
// Make sure that deleteBloon is deleteing the correct array index. This is likely where the issue is.
bloon.deleteBloon();
}*/
Main.money++;
}
}
}
checkExplosion = true;
}
}
}
}
This would be in bloon:
import flash.utils.setTimeout;
function gotShot():void{
// second parameter is time in milliseconds before executing
setTimeout(deleteBloon, 250);
}

Windows phone 8 LongListMultiSelector dynamically select items

How to dynamically (in code behind) select few items in Windows Phone Toolkit's LongListMultiSelector. The property SelectedItems has no setter.
My code:
private async void GetGenres()
{
var genres = await App.MusClient.GetGenresAsync();
var preferencedGenresIdsList = App.GetFromIsoStorage<List<string>>(App.GENRES_IDS_KEY_STRING);
GenresListBox.ItemsSource = genres;
foreach (var item in GenresListBox.ItemsSource)
{
if (preferencedGenresIdsList.Contains(((Genre)item).Id))
{
LongListMultiSelectorItem container = GenresListBox.ContainerFromItem(item) as LongListMultiSelectorItem;
if (container != null)
{
container.IsSelected = true;
}
}
}
if (genres.Result == null || genres.Count == 0)
{
MessageBox.Show("No results available");
}
}
I found solution
private async void GetGenres()
{
var genres = await App.MusClient.GetGenresAsync();
var preferencedGenresIdsList = App.GetFromIsoStorage<List<string>>(App.GENRES_IDS_KEY_STRING);
GenresListBox.ItemsSource = genres;
foreach (var item in GenresListBox.ItemsSource)
{
if (preferencedGenresIdsList.Contains(((Genre)item).Id))
{
GenresListBox.ScrollTo(item);
LongListMultiSelectorItem container = GenresListBox.ContainerFromItem(item) as LongListMultiSelectorItem;
if (container != null)
{
container.IsSelected = true;
}
}
}
GenresListBox.ScrollTo(GenresListBox.ItemsSource[0]);
if (genres.Result == null || genres.Count == 0)
{
MessageBox.Show("No results available");
}
}
Reason it didn't work is because item is not created on UI yet.
GenresListBox.ScrollTo(item); - forces UI to create element!

StackOverflow exception

I am using DDE client to attach and listen stock market prices. That client has a callback method I implemented what to do when it receives price changes. The problem is that I get StackOverflowException (periodically and not at the same time interval). I found something about Thread.BeginCriticalRegion(), but I'm not sure if it would help. I have a few more hours until market opening when I can test it.
I would be more than greatful if someone could give me an idea how to override this exception.
Thanks in advance,
Aleksandar
IList<SymbolObject> _symbols; //initialized when the app runs for the first time
void _ddeClient_Advise(object sender, DdeAdviseEventArgs args)
{
if (!IsReady)
return;
if (string.IsNullOrEmpty(args.Text))
{
_logMessages.LogMessagesAdd("advise dde symbol", string.Format("args.Text is empty or NULL for {0}", args.Item), true);
return;
}
try
{
string[] argsArray = args.Text.Replace("\0", "").Replace('\0'.ToString(), "").Split(' '); // sometimes happens here
var list = _symbols.Where(s => s.DDESymbol == args.Item).ToList();
if (list.Count == 0)
return;
decimal? val = null;
try
{
var stringParts = StringUtils.CleanProphitXUrl(argsArray[0]).Split('.');
argsArray = null;
if (stringParts.Length >= 2)
val = decimal.Parse(stringParts[0] + "." + (stringParts[1].Length > 2 ? stringParts[1].Substring(0, 2) : stringParts[1]));
else
val = decimal.Parse(stringParts[0]);
stringParts = null;
}
catch (Exception ex)
{
_logMessages.LogMessagesAdd("call Price Alerts application service", ex.Message, true);
return;
}
foreach (var l in list)
{
if (_lastPrices[l.DDESymbol] == null)
continue;
if (_lastPrices[l.DDESymbol].ToString() != val.ToString())
{
try
{
_quotePublishingService.PublishQuote(l.DDESymbolId, l.Symbol, args.Item, val, WebSyncPublisherUrl,
PublishingChannel); // a call to wcf service
}
catch (Exception ex)
{
_logMessages.LogMessagesAdd("call the service", ex.Message, true); // save to sql db
return;
}
_lastPrices[l.DDESymbol] = val.ToString();
}
}
list = null;
val = null;
}
catch
{
}
}
public static string CleanProphitXUrl(string value) // StringUtils.CleanProphitXUrl snippet
{
StringBuilder sb = new StringBuilder();
sb.Append(value.Substring(0, value.LastIndexOf(".") + 1));
try
{
value = value.Replace('\r'.ToString(), "").Replace('\t'.ToString(), "").Replace('\n'.ToString(), "");
for (int i = sb.Length; i < value.Length; i++)
{
if (char.IsNumber(value[i]))
sb.Append(value[i]);
}
}
catch
{
}
return sb.ToString();
}
A StackOverflowException is caused by making to many method calls usually resulting from unintended recursion. Based on a cursory check of the code you posted I do not believe it is the culprit. The problem likely lies somewhere else.