2015년 6월 8일 월요일

[인도베다수학] 곱셈


[인도베다수학] 곱셈 수학
2014.05.01. 11:37 수정 삭제
전용뷰어 보기
일의 자리가 5인 수의 제곱
곱셈을 암산할 때는 머리속으로 사각형을 그려보면 쉽게 할수 있습니다. 곱셈은 주로 사각형의 면적을 구할때 쓰이니까요.
25 x 25를 계산해봅시다. 먼저 머리속으로 25 x 25의 사각형을 생각하세요. 이제 사각형을 계산하기 쉽게 나눕니다. (20 + 5) x (20 + 5) 로 하면 쉽겠죠? 이렇게 하면 20 x 20, 5 x 20, 5 x 20, 5 x 5 4개의 사각형이 만들어 집니다. 정리하면 20 x (20 + 5 + 5) + 5 x 5 = 20 x 30 + 5 x 5  = 625가 됩니다.
사각형 생각하기 복잡하시면 그냥 이렇게 생각하시면 됩니다.
(십의 자리의 수 x (십의 자리의 수 + 10)) + 25 = (20 x 30) + 25 = 625
85 x 85를 계산해보면 (80 x 90) + 25 = 7225 쉽죠?

25를 곱하는 곱셈
어떤 수에 25를 곱하려고 하면 머릿속이 복잡해집니다. 하지만 100을 곱한다면 쉽죠. 25는 100을 4로 나누면 되죠? 따라서 100을 곱한후 4로 나누면 원래 구하려는 값을 구할수 있습니다.
32 x 25 = 32 x 100 / 4 = 3200 / 4 = 800

십의 자리가 수가 같은 수의 곱셈
이것도 사각형을 그려놓고 생각하면 쉽게 할수 있습니다. (라고 하더라구요 -_-) 근데 저는 사각형 생각하는데 왠지 복잡해서 이렇게 암산합니다.
십의 자리의 수 x (십의 자리의 수 + 일의 자리의 수의 합) + 일의 자리의 수의 곱
33 x 34를 계산해 보면 30 x (30 + (3 + 4)) + (3 x 4) = 1110 + 12 = 1122

십의 자리의 합이 10이고 일의 자리의 수가 같은 곱셉
(첫번째 십의 자리의 수 x 두번째 십의 자리의 수) + (일의 자리의 수 x (첫번째 십의 자리의 수 + 두번째 십의 자리의 수)) + (일의 자리의 수의 제곱)
83 x 23를 계산해 보면 (80 x 20) + (3 x (80 + 20)) + (3 x 3) = 1600 + 300 + 9 = 1909

100에 가까운 두 자릿수의 곱셈
100 x (100 - (100에서 첫번째 수를 뺀 값 + 100에서 두번째 수를 뺀 값)) + (100에서 첫번째 수를 뺀 값 x 100에서 두번째 수를 뺀 값)
96 x 97을 계산해보면 100 x (100 - (4 + 3)) + (4 x 3) = 100 x 93 + 12 = 9312

[Cocos2d-x] 메뉴

메뉴를 사용하려면 메뉴 아이템을 먼저 생성하고 메뉴에 추가해야 합니다. 메뉴 아이템을 생성할 수 있는 클래스는 여러가지가 있습니다. 필요에 맞게 골라서 사용하시면 됩니다.

  • MenuItemLabel
  • MenuItemAtlasFont
  • MenuItemFont
  • MenuItemSprite
  • MenuItemImage
  • MenuItemToggle
이중에서 MenuItemImage를 생성하려면 다음과 같이 하면 됩니다.

auto menuItem = MenuItemImage::create("normal.png", "pressed.png", 
CC_CALLBACK_1(HelloWorld::doClick, this)); // 평소 이미지, 눌렸을때 이미지, 눌렸을때 호출될 함수와 넘겨줄 인자 입니다.



doClick 함수는 없는 함수이므로 HelloWorldScene.h에 선언하고 HelloWorldScene.cpp에 구현해줘야 합니다.

// HelloWorldScene.h
class ...
{
...
void doClick(cocos2d::Object *sender);
}



// HelloWorldScene.cpp
...
void HelloWorld::doClick(Object *sender)
{
log("Menu is clicked"); // 메뉴를 누르면 디버그 창에 로그가 출력됩니다.
}


위와 같이 메뉴 아이템을 생성했으면 메뉴를 생성할수 있습니다.
auto menu = Menu::create(menuItem, NULL); // 여러개를 넣을수 있고 마지막은 NULL이어야 합니다.


아이템을 만들었으면 정렬을 하고 장면에 추가합니다.
menu->alignItemsVertically();
this->addChild(menu);

실행하면 가운데 메뉴 이미지가 보이고 클릭하면 디버그창에 로그가 출력될 것입니다.

위와 같은 방법으로 할때 메뉴가 여러개 있으면 콜백 함수를 메뉴마다 연결해야 하므로 함수를 메뉴 개수만큼 만들어야 합니다. 하지만 태그를 이용하면 모든 메뉴를 클릭했을때 한 하나의 콜백 함수로 처리할 수 있습니다.
bool HelloWorld::init()
{
...
auto menuItem1 = ...;
auto menuItem2 = ...;

menuItem1->setTag(1); // 메뉴 아이템에 태그를 지정합니다.
menuItem2->setTag(2);
...
}

void HelloWorld::doClick(Object *sender)
{
auto item = (MenuItem*)sender;
int i = item->getTag(); // 태그를 읽어와서 어떤 메뉴가 클릭되었는지 확인합니다.
log("%d th menu pressed", i);
}

[Cocos2d-x] 스프라이트

스프라이트를 이용해 화면에 이미지을 보여주려면 먼저 프로젝트에 이미지를 추가해야 합나다. 먼저 Resources 폴더 및에 images 폴더를 만들고 보여주려는 이미지를 넣습니다. 그리고 레이블에서 했던것처럼 images 폴더를 Xcode의 Resources밑으로 드래고 해서 놓으면 프로젝트에 추가가 됩니다.

스프라이트를 사용하려면 Sprite::create() 함수를 이용해서 인스턴스를 생성하면 됩니다.
auto man = Sprite::create("images/man.png");


스프라이트도 마찬가지로 위치, 색상, 투명도 등을 조절할수 있습니다.
man->setPosition(Point(100, 100)); // man.png를 (100, 100)에 보여줍니다.
man->setTextureRect(Rect(0, 0, 100, 100)); // 이미지중 가로로 0~100, 세로로 0~100 픽셀만 보여줍니다.
man->setColor(Color3B(0, 0, 255)); // 색상을 파란색으로 설정합니다.


생 성된 스프라이트를 장면에 넣으려면 레이블 처럼 addChild() 함수를 사용하면 됩니다. 모든 구성 요소는 Node 클래스를 상속받기 때문에 속성이 같고 사용할수 있는 함수도 거의 같습니다. 따라서 앞으로 자세히 언급하지 않겠습니다.
this->addChild(man);

간 혹 하나의 이미지가 아니라 두개 이상의 이미지가 같이 움직여야 할때가 있습니다. 예를 들면 주인공 머리 위에 떠다니는 에너지바 같은 거죠. 이럴때는 부모 스프라이트를 만들어 장면에 추가한 후 자식 스프라이트를 만들어 부모 스프라이트에 추가하면 됩니다.
auto parent = Sprite::create("images/parent.png");
this->addChild(parent); // 부모 스프라이트를 장면에 추가
auto child = Sprite::create("images/child.png");
parent->addChild(child); // 자식 스프라이트를 부모에 추가

[Cocos2d-x] 레이블


[Cocos2d-x] 레이블 Cocos2d-x / Programming
2014.05.01. 00:39 수정 삭제
전용뷰어 보기


내장된 트루 타입 폰트(이하 TTF) 사용하기
레이블은 LabelTTF 클래스를 이용해 사용할수 있습니다. HelloWorldScene.cpp의 init() 함수에 넣으면 됩니다.
// 출력할 문자열, 폰트 이름, 폰트 크기를 넣고 LabelTTF 클래스의 인스턴스를 생성합니다.
auto lable = LabelTTF::create("Hello World", "Arial", 32);

위치는 setPosition(), 색상은 setColor(),  투명도는 setOpacity() 함수로 설정할수 있습니다. 이 함수들은 레이블 뿐만 아니라 화면에 보여주는 모든 구성 요소에 적용할수 있습니다.
label->setPosition(Point(100, 100)); // (100, 100)의 위치에 문자열을 출력합니다.
label->setColor(Color3B(255, 0, 0); // 문자열의 색상을 빨간색으로 합니다.
label->setOpacity(100.0f); // 불투명하게 설정합니다.

위의 함수들은 여러가지 인자 형식을 가질수 있습니다.  Xcode의 경우 label->을 입력하면 사용할수 있는 함수 목록이 뜨기 때문에 어떤 인자 형식을 가지는 함수를 사용할지 쉽게 선택할수 있습니다.

이제 레이블에 대한 설정이 다 끝났으면 화면에 보여줘야 합니다.
this->addChild(label); // 장면에 레이블을 추가합니다.


추가한 TTF 사용하기
TTF 파일을 추가하려면 프로젝트의 Resources 폴더에 fonts 폴더를 만들고 TTF 파일을 넣어주세요. 그리고 fonts 폴더를 드래그 해서 Xcode의 Resouces 폴더 밑으로 내려놓으면 창이 하나 뜨는데 Folders 에서 두번째를 선택하고 Add to targets는 iOS를 선택하세요. 이렇게 하면 Xcode에서 Resources 밑에 fonts 폴더가 추가되었다고 인식합니다.

TTF를 추가했다고 해서 방법이 다른건 아니고 내장된 TTF를 사용할때랑 방법은 같습니다. 다른점은 폰트 이름입니다.
auto label = LabelTTF::create("Hello World", "fonts/Verdana.ttf", 32);

생성된 레이블은 위치, 색상, 투명도 등을 설정하여 장면에 넣을수 있습니다.

[C++11] tuple


[C++11] tuple C++11 / Programming
2014.04.30. 17:33 수정 삭제
전용뷰어 보기
함수를 만들때 간혹 2개 이상의 값을 한번에 리턴해야 할 경우가 있습니다. 이럴때 기존에는 구조체를 정의하고 구조체 변수를 하나 선언한 후 값을 넣고 리턴해야 했습니다. 단지 리턴값을 여러개 받고 싶을 뿐인데 구조체를 정의해야 한다는 것이 좀 부담이었죠.

C++11에서는 이런 불편함을 없애기 위해 tuple을 도입했습니다. tuple을 사용하면 2개 이상의 변수를 한번에 묶어서 리턴할 수 있습니다. tuple을 사용하기 위해서는 #include <tuple>을 추가해야 합니다. tuple은 다음과 같이 생성하고 사용할 수 있습니다.

// int, int, string 타입으로 tuple 생성
std::tuple<int, int, std::string> items = std::make_tuple(1, 2, "test");
// std::tuple<int, int, std::string> items(1, 2, "test"); // 이렇게 해도 가능합니다

std::cout << std::get<0>(items) << std::endl; // 첫번째 값을 출력합니다. 값은 1입니다.
std::cout << std::get<1>(items) << std::endl; // 두번째 값을 출력합니다. 값은 2입니다.
std::cout << std::get<2>(items) << std::endl; // 세번째 값을 출력합니다. 값은 test입니다.

std::get<0>(items) = 5; // 첫번째 값을 5로 변경합니다.
빈 값으로 tuple을 생성하고 나중에 값을 저장할 수도 있습니다.

tuple의 데이터 개수는 tuple_size 함수를 이용해 알아낼수 있습니다. 위와 같이 tuple을 만들었다면 count가 3이 될것입니다.
auto count = std::tuple_size<decltype(items)>::value;


tie 함수를 이용하면 tuple에 데이터를 하나씩 넣지 않고 여러개를 한번에 넣거나 읽어올수도 있습니다.
std::tuple<int, int, std::string> items(1, 2, "test");

int a, b;
std::string str;
std::tie(a, b, str) = items; // a는1, b는 2, str은 test가 들어갑니다.


모두 넣지 않고 일부만 넣을수도 있습니다.
std::tie(a, std::ignore, str) = items; // a는1, str은 test가 들어갑니다.


tuple을 합치려면 tuple_cat 함수를 사용하면 됩니다.
std::tuple<int, int, std::string> items1(1, 2, "test1");
std::tuple<int, int, std::string> items2(3, 4, "test2");

auto tupleSet = std::tuple_cat(items1, items2); // tupleSet은 1, 2, test1, 3, 4, test2 가 됩니다.

[C++11] 퍼펙트 포워딩

함수의 인자로 받은 값을 변경했을때 함수의 외부로 적용되게 하려면 참조 또는 포인터로 받아야 합니다. 여기서는 참조로만 받는다고 가정합니다.
void increment(int &i)
{
i++;
}

int main()
{
int a = 1;
increment(a);
// increment(1); // 에러가 발생합니다.

return 0;
}
increment(1)을 성공하게 하려면 함수 오버로딩을 사용하면 됩니다. 하지만 귀찮죠?

C++11의 R-Value 레퍼런스를 사용하면 함수 오버로딩을 사용하지 않아도 해결할수 있습니다.
void increment(int &&i)
{
i++;
}

하지만 컴파일해보면 이번엔 increment(a)에서 에러가 발생합니다. R-Value 레퍼런스를 사용하여 인자를 넘기려면 메모리를 이동해야 하는데 이를 위해 std::move() 함수를 사용하면 됩니다.
 increment(std::move(a)); // 에러가 발생하지 않습니다

[Cocos2d-x] 화면에 구성 요소 추가

프로젝트를 생성하면 여러 파일들이 있는 것을 볼수 있습니다. 저는 한 장면에 여러 구성 요소들을 넣으면서 공부할 생각이라 화면을 관장하는 HelloWorldScene.h와 HelloWorldScene.cpp를 주로 수정할 것입니다.
멤버 변수는 HelloWorldScene.h에 넣고 구성 요소의 생성 및 등록은 HelloWorldScene.cpp의 init() 함수에서 하면 됩니다.

Cocos2d-x의 구성 요소는 모두 ClassName::create() 함수로 생성할수 있습니다. 반환값은 아시다시피 생성한 클래스의 인스턴스입니다. 나중에 소멸은 자동으로 되니 신경쓰지 않아도 됩니다.
이 제 생성을 했으니 등록을 해야겠죠? 등록은 addChild 함수를 이용하면 됩니다. 어디에다 하냐면 장면에다 해야겠죠. HelloWorldScene 클래스가 장면이니 this->addChild(instance)를 호출하면 됩니다. 이렇게 하면 장면에 추가한 구성 요소가 보입니다.

[Cocos2d-x] 좌표계와 앵커포인트

좌표계
iOS, 안드로이드와 cocos2d-x는 좌표계가 다릅니다. iOS, 안드로이드의 경우는 좌측 상단이 0,0 이고 cocos2d-x는 좌측 하단이 0,0 입니다. 따라서 iOS, 안드로이드는 오른쪽으로 가면 x값이 증가하고 아래로 내려가면 y값이 증가하는 반면 cocos2d-x는 오른쪽으로 가면 x값이 증가하고 위로 올라가면 y값이 증가합니다.

앵커포인트
메 뉴나 스프라이트 등의 구성 요소가 좌표에 지정될때 구성 요소의 어느 부분을 기준으로 좌표에 지정할지 결정하는 값입니다. 예를 들어 (100, 100)의 좌표에 스프라이트를 넣을때 스프라이트의 좌측 하단을 지정된 좌표로 할지 스프라이트의 가운데를 지정된 좌표로 할지 정할수 있습니다.
앵커포인트의 범위는 (0.0, 0.0) 에서 (1.0, 1.0) 이며 (0.0, 0.0)이면 좌측 하단이고 (0.5, 0.5)이면 가운데 입니다.

[C++11] 이동 시맨틱

기존 C++의 성능(주로 STL)을 개선하기 위해 도입된 개념입니다. vector를 예로 들자면 기존 C++의 경우 계속 항목을 추가하다 보면 공간이 부족해지고 공간을 늘리기 위해 다음 절차를 수행합니다.
1. 이전보다 큰 메모리 공간을 할당한다.
2. 기존 영역의 항목을 모두 복사한다.
3. 복사가 끝나면 기존 영역의 메모리를 해제한다.
깊은 복사가 일어나기 때문에 매우 비효율적입니다.

이 런 비효율을 극복하기 위해 C++11에서는 전에 언급한 R-Value 레퍼런스를 이용해 이동 시맨틱을 구현했습니다. vector 내부의 구현을 보면 기존에 메모리를 복사하는 부분이 메모리를 이동하는 것으로 바뀐것을 알수 있습니다. 따라서 vector 공간이 늘어나도 수행 시간이 거의 소요되지 않습니다. vector 뿐만 아니라 기타 다른 STL도 이런 식으로 구현이 변경되었습니다. 전체적으로 성능이 많이 향상되었겠죠?
std::vector<int> vec1;
std::vector<int> vec2;

vec1.push_back(1);
vec1.push_back(2);

vec2 = std::move(vec1); // 이동 시맨틱을 지원하기 위해 추가된 함수입니다. 객체를 
    // 복사하지 않고 이동합니다.

PS. 임베디드 리눅스에서 C프로그래밍을 주업무로 하는 저로써는 이런거 구현안하고 메모리 포인터만 넘겨주는게 훨씬 편할것 같습니다. 어차피 객체 소유권 이전도 내부적으로 보면 메모리 포인터 변경이니까요. 소유권 이전하면 기존 객체는 사용 못하고... 참조와 템플릿을 주로 사용하는 C++ 입장에서 보면 저런 개념이 필요할것 같긴 합니다.
조작을 위해 기존 객체를 새로 복사해서 쓰는 경우가 많은데 기존 객체도 유지되고 동일한 새로운 객체도 생성되는데 수행 시간이 0이라면? +_+ (불가능하겠죠?)

[C++11] R-Value 레퍼런스


[C++11] R-Value 레퍼런스 C++11 / Programming
2014.04.29. 17:16 수정 삭제
전용뷰어 보기
C++11에서는 R-Value 라는 용어가 새로 등장했습니다. 이와 함께 L-Value 라는 용어도 등장했는데 L-Value는 사실 기존 C++ 부터 사용하던 레퍼런스의 다른 말입니다. R-Value 레퍼런스와 기존 레퍼런스를 구분하기 위해 L-Value 라는 용어를 사용한 것이죠.
그렇다면 L-Value와 R-Value가 뭘까요? 그냥 보면 왼쪽에 있는 값과 오른쪽에 있는 값 같습니다. 저도 처음에는 그렇게 생각했습니다.

정확하게 정의하자면 L-Value는 왼쪽 오른쪽 어디에도 올수 있는 값이고 R-Value는 오른쪽에만 올수 있는 값입니다. 그리고 L-Value는 참조가 가능하고 R-Value는 참조가 불가능합니다.
int a = 1; // a는 L-Value이고 1은 R-Value 입니다.
int b = a; // b는 L-Value입니다.
// 1 = a; // 에러가 발생합니다. 1은 R-Value이므로 왼쪽에 올수 없습니다.

대충 이해가 가시나요? 값을 참조하는 경우를 살펴봅시다.
int a = 1;
int *b = &a; // a는 L-Value이므로 참조가 가능합니다.
// int c = &1; // 1은 R-Value이므로 참조가 불가능합니다.


그런데 C++11에서 R-Value를 참조 가능하게 만들었습니다. 이동 시맨틱과 퍼펙트 포워딩을 위해 적용한 개념이라고 합니다. 이동 시맨틱과 퍼펙트 포워딩은 추후 정리하겠습니다.
그럼 R-Value를 어떻게 참조할까요? R-Value를 참조하기 위해 약간 다른 참조 연산을 사용합니다.

int &&a = 1; // &&가 R-Value 참조 연산자이고 에러가 발생하지 않습니다.
L-Value 처럼 아래와 같은 코드도 가능합니다.
int a = 1;
int &&b = 2;
b = a; // b의 값이 1로 바뀝니다.


[인도베다수학] 뺄셈

두 자릿수의 뺄셈
뺄셈도 덧셈과 마찬가지로 일의 자리의 수를 0으로 만들면 암산이 쉬워집니다.
35 - 19 = 35 - 20 + 1 = 15 + 1 = 16

세 자릿수의 뺄셈
빼는 수의 십의 자리와 일의 자리의 수를 0으로 만들면 됩니다.
247 - 189 = 247 - 200 + 11 = 47 + 11 = 58

[C++11] 람다 표현식

람다의 장점
코딩을 하다보면 종종 함수 포인터나 함수 객체(Class 변수를 함수처럼 사용)를 인자로 넘겨줘야 하는 경우가 있습니다. 이러한 경우 기존에는 함수를 별도로 선언하거나 Class를 정의해서 사용해야 했습니다.
다른 곳에서 사용하지 않고 그곳에서만 한번 사용하는 경우 별도의 선언은 코딩 양을 늘리고 코드를 읽을때 그 함수를 쫓아가서 확인해야 하는 수고가 있습니다.
람다는 함수 인자가 필요한 곳에서 바로 함수를 선언함과 동시에 인자로 넣을 수 있는 장점이 있습니다. 이로 인해 코드의 양을 줄이고 가독성을 높일수가 있습니다.
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);

std::for_each(vec.begin(), vec.end(), [](int val){
std::cout << val << std::endl;
});
빨간색 부분이 람다 함수입니다. 

람다 함수
람다 함수 원형은 []{} 입니다. []는 람다 소재자이고 {}는 람다 몸체입니다. [](){} 처럼 ()를 추가하여 일반 함수처럼 인자를 전달할수도 있습니다. 람다 함수 몸체를 한번 채워보겠습니다.
[]{ std::cout << "Hello World" << std::endl; }; 

많 이 보았던 Hello World를 출력하는 함수입니다. 하지만 이렇게만 코딩하면 실제로 출력이 되지 않습니다. 람다 함수를 선언만 하고 호출은 하지 않았기 때문입니다. 람다 함수를 호출하려면 다음과 같이 뒤에 ()를 붙여주면 됩니다.
[]{ std::cout << "Hello World" << std::endl; }(); 


인자를 넘기려면 앞의 ()에 일반 함수와 같이 인자를 정의하고 뒤의 ()에 넘겨줄 인자를 넣으면 됩니다.
[](int i){ std::cout << "Argument "<< i <<std::endl;}(5);

이렇게 하면 Argument 5 가 출력됩니다.

반환 타입은 일반 함수와 달리 -> 기호를 이용해서 지정합니다.
 bool isTrue = []()->bool{ return true; }();

반환 타입을 지정하지 않았을 경우에는 함수 내부의 결과값을 가지고 컴파일러가 자동으로 추정합니다. 만약 컴파일러가 추정하지 못할 경우 void 타입으로 추정합니다.

람다 함수의 장점 중 하나가 람다 함수 외부의 변수를 바로 참조할수 있다는 것입니다. 람다 소재자인 []가 그 역할을 하는데 캡처절이라고도 부릅니다.
int a = 1;
int b = 2;

int c = [&]{ return a + b; }();
std::cout << "Result " << c << std::endl;

실행해보면 Result 3 이 출력됩니다. [&]가 람다 함수 외부 변수를 참조 타입으로 캡처했기 때문입니다.
참 조 타입이 아니라 값으로 캡처할 수도 있는데 차이점은 참조 타입으로 캡처했을 경우 람다 함수 내부에서 값을 변경하면 함수 외부에도 적용된다는 점이고 값으로 캡처했을 경우 외부에 적용이 되지 않는다는 점입니다. 이 부분은 일반 함수와도 같습니다.
이 외에도 여러가지 캡쳐 규칙이 있습니다.
[]: 아무것도 캡처하지 않음
[&]: 모든 외부 변수를 참조로 캡처
[&x]: x만 참조로 캡처하고 다른 변수는 캡처하지 않음
[&x, &y]: x, y만 참조로 캡처하고 다른 변수는 캡처하지 않음
[=]: 모든 외부 변수를 값으로 캡처
[x]: x를 값으로 캡쳐
[x, y]: x, y만 값으로 캡처하고 다른 변수는 캡처하지 않음
[&x, y]: x를 참조로 캡처하고 y는 값으로 캡처

한 함수 내에서 람다 함수를 선언하고 이를 여러변 사용해야 할 경우에는 auto 키워드를 사용하여 람다 함수를 변수로 할당하고 호출하면 됩니다.
auto printValue = [](int i){ std::cout << i << std::endl; };
printValue(1);
printValue(2);

[Cocos2d-x] 기본 구조

Node
Cocos2d-x의 최상위 클래스 이고 모든 클래스는 Node를 상속받습니다. 주요 클래스인 Sprite, Lable, Menu, Layer, Scene 등도 모두 Node를 상속받고 Node가 제공하는 다양한 프로퍼티를 사용할수 있습니다. 
또한 스케줄러를 가지고 있어서 게임 루프를 만들때 사용되며 중지나 재시작 기능도 제공합니다.

Director
한 어플리케이션에서 단 하나의 인스턴스만 존재합니다. 게임을 진행하다 보면 여러가지 장면 전환이 필요한데 이 장면 전환을 관리하는 클래스가 Director입니다.

Scene
하 나의 게임에는 여러 장면이 있는데 그 장면이 Scene입니다. Scene 안에는 게임의 여러가지 요소인 Sprite나 Menu등을 넣어서 세부적인 게임 화면을 구성할수 있습니다. 하지만 Scene은 터치 이벤트를 받을수 없습니다.

Layer
게 임 화면을 보면 배경, 주인공, 상태 정보 등 각각 독립적으로 움직이는 여러 요소들이 있습니다. 이러한 요소들을 모두 한 화면으로 만들면 관리가 어렵기 때문에 Layer를 사용해서 독립적으로 관리할수 있습니다. 하나의 Scene안에는 여러 Layer를 넣을수 있고 터치 이벤트도 받을수 있습니다.

Sprite
배경, 움직이는 물체와 같이 이미지를 관리하는 역할을 합니다. 이미지를 출력하거나 숨기고 움직이게 할수 있습니다.

Action
Sprite의 애니매이션 처리를 위해 주로 사용됩니다. 이동, 회전, 점프, 크기 변환등 다양한 액션을 제공하고 결합할 수도 있습니다. 또한 reverse 액션도 가능합니다. 
액션에는 To와 By 두 종류가 있는데 By는 현재 위치에서 액션을 수행하고 To는 지정한 위치로 액션을 수행합니다.

[영어듣기] 영어 방송 사이트

제가 자주 듣는 영어 방송 사이트 입니다. 들리지는 않지만 들으려고 노력하고 있습니다. ㅠㅠ

TBS eFM
http://www.tbsefm.seoul.kr
프로그램을 다운받아 설치하면 웹사이트에 들어가지 않아도 방송 청취가 가능합니다. 발음도 또박또박하고 중간 중간에 노래도 나와서 편하게 들을수 있습니다. 
주로 한국에 관한 내용을 다루기 때문에 이해하는데 도움이 됩니다.

Arirang
http://www.arirang.co.kr/
TV 와 Radio가 있는데 전 TV를 더 선호합니다. Radio는 K-Pop이 너무 많이 나오더군요. 노래 좋아하시는 분들은 Radio를 들어도 괜찮을것 같습니다. TV는 주로 뉴스가 나옵니다. 발음은 TBS eFM 보다는 알아듣기 어렵더군요 (저만? -_-)
여기도 주로 한국에 관한 내용을 다루고 있습니다.

BBC World Service
www.bbc.co.uk/worldservice
세 계 곳곳의 방대한 내용을 다루고 있고 말도 빨라서 매우 어렵습니다. (역시 저만? -_-) 영국과 미국 현지인의 영어를 체험해보고 싶으신 분은 좋을 것 같습니다. 전 위의 두 사이트에서 모두 음악만 나올때 이 사이트를 이용합니다. ㅋㅋ

2015년 6월 7일 일요일

[인도베다수학] 덧셈

두 자릿수의 덧셈
두 자릿수의 덧셈을 할때 둘중 하나의 일의 자리의 수를 0으로 만들면 반올림을 하지 않아도 되기 때문에 암산이 쉬워집니다.
58 + 79 = 58 + 80 - 1 = 138 - 1 = 137

세 자릿수 이상의 덧셈
세 자릿수 이상의 덧셈을 할때 둘중 하나의 일의 자리와 십의 자리의 수를 0으로 만들면 암산이 쉬워집니다.
195 + 238 = 200 + 238 - 5 = 438 - 5 = 433

[C++11] 유니폼 초기화

vector를 하나 만들었다고 가정합시다. 기존 C++에서는 vector에 객채를 넣으려면 객체를 모두 생성하여 vector 변수에 넣어줘야 했습니다. 하지만 C++11에서는 vector 변수를 생성함과 동시에 객체들을 생성해 넣을 수가 있습니다.
// 이름과 나이를 넣는 class Person이 있다고 가정하고
vector<Person> persons {
{20, "Park"}, {21, "Lee"}, {22, "Song"}, {23, "Kim"}
};


위와 같이 한방에 생성할수 있습니다. vector 뿐만 아니라 다른 STL에도 적용 가능하니 코드를 줄이는데 효과적입니다.

[C++11] 범위 기반 for 문

기존 C++ 에서는 for 문을 사용할때 변수를 초기화 하고 범위를 정확하게 지정해 주어야 했습니다. 간혹 범위를 지정할때 실수를 해서 경계 에러가 발생하는 경우가 종종 있습니다.

하지만 C++11 에서는 변수를 초기화 하거나 범위를 지정할 필요가 없습니다. 예를 들어보겠습니다.
int values[4] = {0, 1, 2, 3};
for (int i: values)
{
cout:: << i << endl;
}


위 코드를 실행하면 에러 없이 values의 숫자들을 출력해줍니다. 또한 배열뿐 아니라 vector도 사용할수 있습니다.

[C++11] 컴파일

C++11으로 작성된 코드를 컴파일하려면 GCC 4.7 이상이 필요하며 컴파일 시에 -std=c++11 항목을 추가하면 됩니다.

[Cocos2d-x] 개발 환경 꾸미기

제가 공부하면서 간단하게 정리하는 글입니다. 잘못되거나 부족한 내용이 있으면 조언 부탁드립니다.
Windows에서 Visual C++로도 개발이 가능하지만 전 맥의 Xcode가 좋아서 Xcode로 개발하는 내용만 정리하였습니다.

다운로드
cocos2d-x는 아래 사이트에서 내려받을 수 있습니다.
http://www.cocos2d-x.org
전 3.0를 받아서 진행하였습니다.

설 치
맥에서는 별도의 설치 절차가 필요 없습니다. 그냥 받아서 압축을 풀면 됩니다.

샘플 테스트
샘플을 테스트할수 있는 프로젝트 파일은 build 디렉토리 안에 있습니다. 저처럼 Xcode를 사용하시는 분은 cocos2d_tests.xcodeproj를 더블클릭하면 Xcode에서 프로젝트가 열립니다. 
전 C++을 사용하고 iPhone Retina (4-inch)를 기반으로 개발할 것이라서 왼쪽 위 Scheme에서 cpp-test iOS >  iPhone Retina (4-inch) 를 선택했습니다.
command + r을 누르면 빌드와 실행이 되며 cocos2d-x가 제공하는 여러가지 기능을 테스트 해볼수 있습니다.

환경 변수 추가
cocos2d-x를 다른 디렉트로에서 사용하려면 환경 변수를 추가해야 합니다. 맥에서는 .bash_profile에 다음과 같으 추가하면 됩니다.
export COCOS_CONSOLE_ROOT=/Users/thomas/Documents/cocos2d-x-3.0/tools/cocos2d-console/bin

export PATH=$COCOS_CONSOLE_ROOT:$PATH

추가한 다음에 source .bash_profile을 실행하면 추가한 환경 변수가 바로 적용이 됩니다.

프로젝트 만들기
새로운 프로젝트를 만들려면 터미널에서 다음과 같이 입력하면 됩니다.
cocos new 프로젝트 이름 -p 패키지 이름 -l 사용할 언어 -d 프로젝트가 생성되는 디렉트리

C++로 개발하고 맥의 도큐멘트 디렉토리에 프로젝트를 만들려면 다음과 같이 입력하세요.
cocos new first_project -p com.company.cocos2d -l cpp -d /Users/thomas/Documents

proj.ios_mac/first_project.xcodeproj 를 더블클릭하면 Xcode가 실행되며 프로젝트가 열립니다. 왼쪽 위 Scheme에서 first_project iOS > iPhone Retina (4-inch)가 없다면 New Scheme에서 추가하면 됩니다.

Shell에서 main 함수의 return 값 얻어오기

 ./a.out
echo $?

$? 안에 main 함수의 return 값이 들어가 있습니다.

process간 mutex 지원 가능하는지 확인하는 방법

$ getconf _POSIX_THREAD_PROCESS_SHARED
200112

$ getconf GNU_LIBPTHREAD_VERSION
NPTL 2.8

Linux prompt에서 위와 같이 나오면 process간 mutex를 지원합니다.
결과값의 숫자는 kernel과 library의 버전에 따라 다를 수 있습니다.

Thread 우선 순위 높이기

struct sched_param param;
pthread_t thread;

// create thread
...

param.sched_priority = 1;
pthread_setschedparam(thread, SCHED_RR, &param);

thread 우선 순위를 높이면 CPU 자원이 부족할 경우 다른 thread가 많이 느려질 수 있습니다.

socket 수신 버퍼에 남은 데이터의 크기 구하는 방법


unsigned int read_bytes;
int res;
int sock;

// craete socket
...

res = ioctl(sock, FIONREAD, &read_bytes); 

위와 같이 하면 socket에 수신 버퍼에 남아있는 데이터의 크기를 알수 있습니다.

gprof를 이용한 profiling 방법

1. 소스코드를 -pg 옵션을 사용하여 컴파일합니다. GCC 최적화 옵션은 빼야 합니다.
2. 컴파일을 하고 실행하면 gmon.out 파일이 생성됩니다.
3. gprof 실행파일 gmon.out > 결과 파일 (ex. gprof test gmon.out > test.txt)
4. test.txt 파일을 열어보면 함수별 수행 횟수및 시간이 나옵니다.