2010年8月20日 星期五

[C] OOP in C sample

Because I got a job, it was a C project.
So I am learning how to implement OOP in C now.
This is a example searched form google.
I use Xcode 3.2.3 with gcc4.2 to implement and test it.


#include <stdio.h>
#include <stdlib.h>

typedef void (*Walk_Fun)(struct Animal *a_This);
typedef struct Animal * (*Dtor_Fun)(struct Animal *a_This);

typedef struct _Animal_Vtable{
Walk_Fun Walk;
Dtor_Fun Dtor;
}Animal_Vtable;

typedef struct _Animal{
Animal_Vtable vtable;

char *Name;
}Animal;

typedef struct _Dog{
Animal_Vtable vtable;

char *Name; // mirror member variables for easy access
char *Type;
}Dog;

void Animal_Walk(Animal *a_This){
printf("Animal (%s) walking\n", a_This->Name);
}

struct Animal* Animal_Dtor(struct Animal *a_This){
printf("animal::dtor\n");
return a_This;
}

Animal *Animal_Alloc(){
return (Animal*)malloc(sizeof(Animal));
}

Animal *Animal_New(Animal *a_Animal){
a_Animal->vtable.Walk = Animal_Walk;
a_Animal->vtable.Dtor = Animal_Dtor;
a_Animal->Name = "Anonymous";
return a_Animal;
}

void Animal_Free(Animal *a_This){
a_This->vtable.Dtor(a_This);

free(a_This);
}

void Dog_Walk(Dog *a_This){
printf("Dog walking %s (%s)\n", a_This->Type, a_This->Name);
}

Dog* Dog_Dtor(Dog *a_This){
// explicit call to parent destructor
Animal_Dtor((Animal*)a_This);

printf("dog::dtor\n");

return a_This;
}

Dog *Dog_Alloc(){
return (Dog*)malloc(sizeof(Dog));
}

Dog *Dog_New(Dog *a_Dog){
// explict call to parent constructor
Animal_New((Animal*)a_Dog);

a_Dog->Type = "Dog type";
a_Dog->vtable.Walk = (Walk_Fun) Dog_Walk;
a_Dog->vtable.Dtor = (Dtor_Fun) Dog_Dtor;

return a_Dog;
}


int main (int argc, const char * argv[]) {
/*
base class:
Animal *a_Animal = Animal_New(Animal_Alloc());
*/
Animal *a_Animal = (Animal*)Dog_New(Dog_Alloc());

a_Animal->vtable.Walk(a_Animal);

Animal_Free(a_Animal);

return 0;
}

2010年8月5日 星期四

[IPhone] How to make iphone automatically distinguish 640 * 960 and 320 * 640 resolution






Using two images named a.png for 480*320 and named a@2x.png for 960*480.
Then use this code.
UIImage* anImage = [UIImage imageNamed:@"a"];

[.NET] How to draw on desktop

This is a demo for draw on desktop.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace DrawDesktop
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
IntPtr hdc = GetDCEx(GetDesktopWindow(), IntPtr.Zero, 1027);
using (Graphics g = Graphics.FromHdc(hdc))
{
g.FillEllipse(Brushes.Red, 0, 0, 400, 400);
}
}

[DllImport("user32.dll")]
static extern IntPtr GetDesktopWindow();

[DllImport("user32.dll")]
static extern IntPtr GetDCEx(IntPtr hwnd, IntPtr hrgn, uint flags);
}
}

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