2010年7月26日 星期一

[C++] Poker with OOP

Introduction
I found a OOP question from CSND.
That is how to design a OO with Poker.

Source Code


#include <iostream>
#include <vector>
using namespace std;

enum Suit
{
Spade = 0,
Heart,
Diamond,
Club
};

class Poker
{
private:
Suit m_suit;
int m_number;
public:
Poker(Suit suit,int number)
{
m_suit = suit;
m_number = number;
}

string GetSuit()
{
string suit = "Spade";
if(m_suit == Heart)
suit = "Heart";
if(m_suit == Diamond)
suit = "Diamond";
if(m_suit == Club)
suit = "Club";
return suit;
}

friend ostream& operator <<(ostream& os, Poker* pk)
{
string suit = pk->GetSuit();
os << "[" << suit.c_str() << ":" << pk->m_number << "]";
return os;
}
};

class Cards
{
private:
vector<Poker*> m_cards;
public:
Cards()
{
for(int i = 0 ; i < 52 ; i++)
{
m_cards.push_back(new Poker((Suit)(i / 13), (i % 13)+1));
}
}
void Output()
{
vector<Poker*>::iterator iter = m_cards.begin();
for(; iter != m_cards.end() ; iter++)
{
cout<<(Poker*)(*iter)<<endl;
}
}
};

int _tmain(int argc, _TCHAR* argv[])
{
Cards *cards = new Cards();
cards->Output();
int a = 0;
a = cin.get();
return 0;
}

2010年7月20日 星期二

[Game] Develop Game Loop

Introduction
Game is a real-time application.
In the section, I use some image and sample code to explain how to develop game loop.


Background
First, game status need to update in game world.
Secound, game allow interaction with player.
And last, the result need to dislpay for players, whether screen, sound or other outputs.
Game status and player input can consider as a behavior.
So game is as a combination of update and render.



Game Loop


while(!GameEnd)
{
Update();
Render();
}


void Loader()
{
thread t1 = new thread(&Update,1000/frequency);
t1.Start();
thread t2 = new thread(&Render,1000/60);
t2.Start();
}

void Update()
{
// do update
}

void Render()
{
// do render
}



long lastTime = getTimeTick();
while(!GameEnd)
{
if( (getTimeTick() - lastTime) > (1000/frequency) )
{
Update();
lastTime = getTimeTick();
}
Render();
}


First loop, update and render everytime.
When game logic is too complex, it may reduce render's performance.
Secound loop, using multi-thread to update and render.
Last loop, using a timer to record last update time.

2010年7月18日 星期日

[IPhone] Memory management with UIView

Introduction
Memory management in the Iphone is a hot topic.
I might as well share some tips here from my own experience.

Background
I got a game project of iphone at the end of March, 2010.
Then I started to study development in Iphone with Object-C and C++.
I developed a library that named CloudBox and used to develop my project of game.
In the past, I had met many times of crash, the reason was issue of memory management.

Sample 1

    UIImage *tmp = [UIImage imageNamed:@"logo.png"]; // imageNamed will return an autorelease object
bigpicture = [[UIImageView alloc] initWithImage:tmp];
//[tmp release];
// if you release a autorelease object, you application may be crash.
// so it dose not need release
Avoid using autorelease object.
If you use an autorelease object, you can not control when it was released.
And if you release an autorelease object by yourself, sometimes might cause crash.
[NSxxx xxxGenerate] naming function will return an autorelease object, like [UIImage imageNamed] or [NSString stringWithFormat].

Sample 2

class SuccessView
{
private:
UIImageView* m_View;
public:
SuccessView(UIView* parentView);
~SuccessView();
};

SuccessView::SuccessView(UIView* parentView)
{
m_View = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
// after alloc, m_View's retainCount = 1
[parentView addSubView:m_View];
// after addSubView, m_View's retainCount = 2
}

SuccessView::~SuccessView()
{
[m_View removeFromSuperview];
// after removeFromSuperview, m_View's retainCount = 1
[m_View release];
// after release, m_View's retainCount = 0, release success.
}

class CrashView
{
private:
UIImageView* m_View;
public:
CrashView(UIView* parentView);
~CrashView();
};

CrashView::CrashView(UIView* parentView)
{
m_View = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
// after alloc, m_View's retainCount = 1
[parentView addSubView:m_View];
// after addSubView, m_View's retainCount = 2
[m_View release];
// after release, m_View's retainCount = 1
}

CrashView::~CrashView()
{
[m_View release];
// this release may cause application crash.
}

class DemoSample
{
private:
UIView* m_MainView;
SuccessView* success;
CrashView* crash;
public:
DemoSample();
~DemoSample();

void TestRemoveSuccessView();
void TestRemoveCrashView();
};

DemoSample::DemoSample()
{
m_MainView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 100.0)];
success = new SuccessView(m_MainView); // draw success view on m_MainView
crash = new CrashView(m_MainView); // draw crash view on m_MainView
}

DemoSample::~DemoSample()
{
[m_MainView release];
}

void DemoSample::TestRemoveSuccessView()
{
delete success; // it will success to remove this view from m_MainView
}
void DemoSample::TestRemoveCrashView()
{
delete crash; // it will cause crash
}
In develop of game, I used random generate NPC.
If NPC dead, I will remove NPC on screen and release it.
In the past, I got a experience.
When I release UIImageView without removeFromSuperview, the application will crash.
I got some conclusions:
1. view = [UIImageView alloc] => view's retainCount = 1
2. [parentView addSubview:view] => view's retainCount = 2
3. [view removeFromSuperview] => view's retainCount = 1
4. [view release] => view's retainCount = 0

Reference
IPhone Memory Management
IPhone Memory Management Tips
Apple Document

2010年7月17日 星期六

2010年7月15日 星期四

[C++] How to implement property in C++

Introduction

In the past, I used property to develop .NET program frequently.
But in Java or C++, I must use get/set method to access private member in Object-Oriented Programming.
I like to use property not get/set method!

Background

Startand C++ dose not support property statement, so programmers need to declare get/set method to access private member.
First programmers should understand template and function point.
I found a sample code from google, that use template and function point to solve type and access get/set method.
This solution is not good, because use a class and function point to access will reduce performance.
Directly use get/set method is better.

Source Code
template<class _Prop_t,class _ObjClass_t>
class Property
{
private:
typedef _Prop_t (_ObjClass_t::* _pmGet_t)() const;
typedef void (_ObjClass_t::* _pmSet_t)(_Prop_t);

_ObjClass_t& m_objInstance;
_pmGet_t m_pmGet;
_pmSet_t m_pmSet;

public:
Property(_ObjClass_t& objInstance, _pmGet_t pmGet, _pmSet_t pmSet)
: m_objInstance(objInstance), m_pmGet(pmGet), m_pmSet(pmSet)
{}
operator _Prop_t() { return (_Prop_t)(m_objInstance.*m_pmGet)(); }
void operator =(_Prop_t value) { (m_objInstance.*m_pmSet)(value); }
};



Download
Sample Code

2010年7月12日 星期一

[.NET] ArrayList,Hashtable,Dictionary compare

Introduction
Sometime we need to save some const infotmation in Collection(ArrayList/HashTable in .NET Framework), and get some information from an indepentdent id.
Suppose you do not understand the data structure, maybe you will using array or arraylist to save const, then coding search algorithm by yourself.
If your const is excessive, maybe the program performance will be reduce.

Background
In my job, I have a event log manager, a event resource file and a event id definition.
I will load resource file used by event log manager, and the event will be save into an ArrayList object in memory.
Then I will add an event log by event id, the event log manager will return a event log where search from ArrayList everytime.
But in my program, add an event log is a repetitive behavior, so I think that maybe I can use a more efficient solution to improve it.


Comparation



I will use ArrayLit/HashTable/Dictionary to compare the search algorithm's performance.

I will test it on Windows XP and Windows CE 5.0 Emulator.
I have 2048 event log and these are non-continuous data.
private void btnArrayList_Click(object sender, EventArgs e)
{
int t_ulStartTime = AccurateTimer.GetTimeTick();
for (int i = 1000; i < 42880; i++)
{
m_event.AddEventLogWithArrayList(i);
}
int t_ulEndTime = AccurateTimer.GetTimeTick();
double t_r8PassedTime = (double)(t_ulEndTime - t_ulStartTime) / (double)1000.0;
MessageBox.Show("ArrayList spend time:" + t_r8PassedTime);
}

private void btnHashTable_Click(object sender, EventArgs e)
{
int t_ulStartTime = AccurateTimer.GetTimeTick();
for (int i = 1000; i < 42880; i++)
{
m_event.AddEventLogWithHashtable(i);
}
int t_ulEndTime = AccurateTimer.GetTimeTick();
double t_r8PassedTime = (double)(t_ulEndTime - t_ulStartTime) / (double)1000.0;
MessageBox.Show("Hashtable spend time:" + t_r8PassedTime);
}

private void btnDictionary_Click(object sender, EventArgs e)
{
int t_ulStartTime = AccurateTimer.GetTimeTick();
for (int i = 1000; i < 42880; i++)
{
m_event.AddEventLogWithDictionary(i);
}
int t_ulEndTime = AccurateTimer.GetTimeTick();
double t_r8PassedTime = (double)(t_ulEndTime - t_ulStartTime) / (double)1000.0;
MessageBox.Show("Dictionary spend time:" + t_r8PassedTime);
}




In my test, I found Hashtable's performance is best.
And I found the Hashtable is better then Dictionary.
If key is not exist in Dictionary, it will throw a System.Collections.Generic.KeyNotFoundException.
It will reduce the program's performance, and the generic in C# without a good performance, so I don't use it.

Reference

An Extensive Examination of Data Structures Using C# 2.0
Sample Code:Test Hashtable and ArrayList

2010年7月4日 星期日

[.NET] How to implement rotate image in user control.

Introduction
Sometimes we need to rotate image in user control.
I override OnPaint method, and use Graphics.RotateTransform to rotate image.

Source Code
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.Default;
Rectangle rect=new Rectangle(0,0,this.Width,this.Height);
PointF center=new PointF(rect.Width/2,rect.Height/2);

float offsetX=0;
float offsetY=0;
offsetX = center.X - DoorWidth / 2;
offsetY = center.Y - DoorHeight / 2;
picRect = new RectangleF(offsetX, offsetY, DoorWidth, DoorHeight);
PointF Pcenter=new PointF(picRect.X+picRect.Width/2,
picRect.Y+picRect.Height/2);

e.Graphics.TranslateTransform(Pcenter.X, Pcenter.Y);
e.Graphics.RotateTransform(-m_i4Angle);

e.Graphics.TranslateTransform(-Pcenter.X, -Pcenter.Y);
if (m_bIsOpened)
{
int t_i4doorWidth = (DoorWidth - DoorOpenWidth) / 2;
RectangleF picRect1 = new RectangleF(offsetX, offsetY, t_i4doorWidth, DoorHeight);
e.Graphics.FillRectangle(new SolidBrush(m_OpenColor), picRect1);
RectangleF picRect2 = new RectangleF(offsetX + DoorOpenWidth + t_i4doorWidth, offsetY, t_i4doorWidth, DoorHeight);
e.Graphics.FillRectangle(new SolidBrush(m_OpenColor), picRect2);
}
else
{
e.Graphics.FillRectangle(new SolidBrush(m_CloseColor), picRect);
}
e.Graphics.ResetTransform();
}



Image