12 thói quen mà các CEO thường làm trước bữa sáng

Người đăng: share-nhungdieuhay on Chủ Nhật, 10 tháng 8, 2014

12 thói quen mà các CEO thường làm trước bữa sáng  

1. Thức dậy sớm
Một cuộc thăm dò được thực hiện bởi nhóm nghiên cứu Vanderkam, thuộc học Florida, Mỹ với 20 giám đốc điều hành đã nhận được câu trả lời rằng 90% trong số họ thức dậy trước 6 giờ sáng các ngày trong tuần.
Giám đốc điều hành PepsiCo Indra Nooyi thường thức dậy lúc 4 giờ sáng và luôn đến văn phòng trước 7 giờ. Trong khi đó, Giám đốc điều hành Disney Bob Iger dậy lúc 4 giờ 30 sáng để đọc và Giám đốc điều hành Square Jack Dorsey dậy lúc 5 giờ 30 để chạy bộ .
2. Tập thể dục buổi sáng
Theo Vanderkam, Giám đốc điều hành Xerox Ursula Burns thường có hai buổi tập thể dục cá nhân một tuần, mỗi buổi kéo dài một giờ bắt đầu từ lúc 6 giờ sáng. Giám đốc điều hành Christies Steve Murphy thường tập yoga vào buổi sáng.
Họ thường tập thể dục vào buổi sáng vì hầu hết thời gian trong ngày họ rất bận, đồng thời, tập luyện trước bữa ăn sáng sẽ giúp giảm bớt căng thẳng trong ngày, phòng chống sự ảnh hưởng của chế độ ăn uống nhiều chất béo và cải thiện giấc ngủ.
3. Tập trung vào một dự án quan trọng
Giờ yên tĩnh của buổi sáng có thể là thời gian lý tưởng để tập trung vào một dự án công việc quan trọng mà không bị gián đoạn vì chắc chắn không có đồng nghiệp nào có thể làm phiền họ vào giờ đó.
4. Dành thời gian cho niềm đam mê cá nhân
Những sở thích cá nhân tốt như đọc sách, viết hay nghe nhạc… rất dễ bị bỏ qua khi bạn đã ở trong cuộc họp cả ngày, mệt mỏi và đói. Đó là lý do tại sao nhiều người thành công thường dành một giờ hoặc lâu hơn cho các sở thích cá nhân của họ trước khi họ chính thức bắt đầu ngày làm việc.
5. Dành thời gian cho gia đình
Một số người thành công sử dụng thời gian buổi sáng cho gia đình, cho dù đó chỉ là đọc truyện cho trẻ em hoặc cùng ăn bữa sáng với nhau.
Judi Rosenthal, một chuyên viên tài chính ở New York, nói rằng buổi sáng là thời gian đặc biệt cô ấy dành cho con gái nhỏ. Cô giúp con gái mặc quần áo, gấp chăn ... Họ cũng cùng ngồi ăn sáng và trò chuyện với nhau. Cô gọi 45 phút đó là "thời gian quý báu nhất mà tôi có trong một ngày".
6. Dành thời gian cho bạn đời
Vào buổi tối, nhiều khả năng bạn sẽ bị mệt mỏi vì công việc trong ngày và thời gian sau đó có thể dễ dàng bị lãng phí với bữa ăn tối và xem TV. Đó là lý do tại sao nhiều người thành công thường dành thời gian cho bạn đời của họ như một thói quen trước bữa sáng.
7. Thưởng thức một cốc cà phê
Christopher Colvin, một doanh nhân và luật sư ở New York cho biết, ngày nào ông cũng thức dậy lúc 5 giờ 30 và thường uống một cốc cà phê để đầu óc tỉnh táo và tăng thêm tinh thần sáng tạo cho ngày làm việc.
8. Ngồi thiền
Manisha Thakor, người sáng lập và hiện đang điều hành MoneyZen Wealth Management, thực hành thiền định siêu việt 20 phút một ngày vào trước bữa ăn sáng và vào buổi tối để giúp tinh thần thoải mái và tăng sự tập trung.
9. Viết ra những điều biết ơn
Viết ra tên những người, địa điểm và cơ hội mà bạn biết ơn chỉ mất một vài phút nhưng có thể tạo nên sự khác biệt thực sự trong quan điểm của bạn.
10. Vạch ra kế hoạch và chiến lược trong thời gian tỉnh táo nhất
Kế hoạch trong ngày, tuần hoặc tháng trước là một công cụ quản lý thời gian quan trọng để giữ cho bạn đi đúng hướng. Vì vậy, hãy sử dụng thời gian trước buổi sáng để suy nghĩ và thiết lập danh sách công việc phải làm trong ngày là một việc hết sức cần thiết.
11. Kiểm tra email
Nhiều người thành công bắt đầu một ngày với email. Họ có thể nhanh chóng lướt qua hộp thư đến để xử lý các thư khẩn cấp mà cần một phản ứng ngay lập tức hoặc phác thảo một vài email quan trọng khi tâm trí đang còn tỉnh táo nhất.
12. Đọc tin tức
Cho dù đang ngồi ở đâu với một tờ báo giấy hay một chiếc điện thoại, laptop, ưu tiên hàng đầu của những người thành đạt cũng là lướt qua những tin tức mới và quan trọng.
Ví dụ, Giám đốc điều hành GE Jeff Immelt bắt đầu ngày của mình với việc tập thể dục và sau đó đọc bài báo và xem tin tức của CNBC. Trong khi đó, Giám đốc điều hành Virgin America David Cush sử dụng buổi sáng của mình để nghe đài phát thanh thể thao và đọc báo trong khi tập thể dục tại phòng tập...
Bạn thấy mình có nhiều nhân tố để trở thành CEO chưa? Hãy để "10 điều khác biệt nhất giữa kẻ làm chủ & người làm thuê" của Keith Cameron Smith trả lời giúp bạn nhé.
More about

Code C/C++: Thuật toán Kruskal tìm cây bao trùm tối thiểu

Người đăng: share-nhungdieuhay on Thứ Sáu, 8 tháng 8, 2014


Mô tả bài toán: Cho đồ thị vô hướng có trọng số G=(V,E) hãy tìm đường đi sao cho tất cả các đỉnh điều có đường đi với nhau và tổng trọng số của đường đi là nhỏ nhất. Tức là tìm đồ thị con liên thông  G'  G sao cho tổng trọng số của G’ là nhỏ nhất.
Ý tưởng thuật toán:
Bước 0: khởi tạo tập cạnh tìm được là rỗng và chuyển sang Bước 1.
Bước 1: chọn một cạnh có trọng số nhỏ nhất sao cho khi đưa cạnh này vào tập cạnh tìm được không tạo thành chu trình. Tăng số cạnh tìm được lên 1  và chuyển sang Bước 2.

Bước 2: nếu số cạnh tìm được bằng n-1 thuật toán kết thúc, ngược lại quay về Bước 1.

Mô tả dữ liệu đầu vào và đầu ra của bài toán:
Dữ liệu vào: lưu trong tập tin Bai8.inp
-  Dòng đầu ghi số n là số đỉnh của một đồ thị (0<n<100)
-  Dòng i+1 (1<=i <=n) lưu ma trận kề của đồ thị với n số A[i,1],A[i,2]…A[i,n] mỗi số cách nhau bởi một khoảng trắng.
Dữ liệu ra: lưu trong file Kruskal.out
-  Dòng đầu ghi trọng số nhỏ nhất của cây bao trùm.

-  Các dòng còn lại lưu đường đi giữa đỉnh i nối với đỉnh j.
Ví dụ:
Cài đặt chương trình:
#include <stdio.h>
#include <values.h>
#define FileInt "Bai8.inp"
#define FileOut "Bai8.out"
typedef structEgde {
      int x,y;
};
//đọc dữ liệu từ tập tin
void Doc_File(int **A,int &n)  {
    FILE*f = fopen(FileInt,"rb");
    fscanf(f,"%d",&n);
    *A = new int [n];
    for(int i =0;i<n;i++) {
       A[i] = new int [n];
       for(int j =0;j<n;j++) {
           fscanf(f,"%d",&A[i][j]);
       }
    }
    fclose(f);
}
//ghi dữ liệu ra tập tin
void Ghi_File(Egde*L,int n,int Sum) {
    FILE*f = fopen(FileOut,"wb");
    fprintf(f,"%d\n",Sum);
    for(int i =0; i<n-1; i++)
    fprintf(f,"%d -%d\n",L[i].x+1,L[i].y+1);
    fclose(f);
}
void Kruskal(int **A, int n) {
    int *D = new int[n];

    Egde *L = new Egde[n-1]; 
    int min = MAXINT, Dem = 0, Sum = 0, T = 0, Temp;
    for(int i=0; i<n; i++)
        D[i] = 0;
        do{
            min = MAXINT;
            for( i=0; i<n; i++)
                 for(int j=0; j<n; j++)
                      if(A[i][j]>0 && min>A[i][j]&& !(D[i]!=0 && D[i]==D[j])) {
                          min = A[i][j];
                          L[Dem].x = i;
                          L[Dem].y = j;
                      }
                      if(D[L[Dem].x] ==0 && D[L[Dem].y] == 0){
                          T++;
                          D[L[Dem].x] = D[L[Dem].y] = T;
                      }
                      if(D[L[Dem].x] == 0 && D[L[Dem].y] != 0){
                          D[L[Dem].x] = D[L[Dem].y];
                      }
                      if(D[L[Dem].x] != 0 && D[L[Dem].y] == 0){
                          D[L[Dem].y] = D[L[Dem].x];
                      }
                      if(D[L[Dem].x] != D[L[Dem].y] && D[L[Dem].y]!=0) {
                          Temp = D[L[Dem].x];
                          for( i=0; i<n; i++)
                             if(Temp==D[i])
                                   D[i]=D[L[Dem].y];
                      }
                   Sum+=min;
                   Dem++;
      } while(Dem<n-1);
      Ghi_File(L,n,Sum);
}
//chương trình chính
int main() {
         int **A,n;
         Doc_File(A,n);
         Kruskal(A,n);
         delete *A;
         return 0;
}
Từ khóa: ky thuat lap trinh, kỹ thuật lập trình, Kruskal, cây bao trùm tối thiểu, programming, algorithm, toán rời rạc, cây, cau truc du lieu, giai thuat.

More about

Bài 30: Học làm game thứ 5 - Space Ship ( Part 2 - End )

Người đăng: share-nhungdieuhay on Thứ Tư, 6 tháng 8, 2014


Hi, Rảnh rỗi tranh thủ viết cho xong game Space Ship này.
Bài trước chúng ta đã thiết kế sơ bộ xong phần màn chơi, song còn thiếu một số phần quan trọng trong game nên có mà chúng ta sẽ bổ sung ngay sau đây:

+ Bắn đạn khi Touch màn hình
+ Bắt sự kiện va chạm giữa đạn và thiên thạch
+ Tính điểm
+ Game Over

Đơn giản có thế thôi, chúng ta sẽ lướt nhanh!

B1: Bắn đạn khi Touch màn hình

Bạn mở file HelloWorldScene.h thêm vào dòng lệnh sau, trong public

// Hàm bắt sự kiện touch, dùng multiTouch, hoặc Touch thôi cũng được
void HelloWorld::onTouchesBegan(const std::vector<Touch*>& touches, Event *event)

Tiếp đó trong HelloWorldScene.cpp ta thiết kế hàm này như sau

void HelloWorld::onTouchesBegan(const std::vector<Touch*>& touches, Event *event)
{
SimpleAudioEngine::getInstance()->playEffect("laser_ship.wav"); // Âm thanh

Size winSize = Director::getInstance()->getWinSize();

// Lấy sprite Laser từ bộ lưu trữ Vector
Sprite *shipLaser = (Sprite *) _shipLasers->at(_nextShipLaser++);

if ( _nextShipLaser >=_shipLasers->size())   // Reset index laser
_nextShipLaser = 0;
// Đặt vị trí ở phía mũi tàu, và cho hiện lên
shipLaser->setPosition(Point(_ship->getPosition().x + shipLaser->getContentSize().width/2, _ship->getPosition().y));
shipLaser->setVisible(true);
// set body
auto laserbody = PhysicsBody::createBox(shipLaser->getContentSize()/2);  

laserbody->setContactTestBitmask(0xf);  
laserbody->setDynamic(true);
shipLaser->setPhysicsBody(laserbody);

// Di chuyển đạn, gọi tới hàm setInvisible để xử lý
shipLaser->stopAllActions();
shipLaser->runAction(Sequence::create( 
MoveBy::create(0.5,Point(winSize.width, 0)),
CallFuncN::create(this, callfuncN_selector(HelloWorld::setInvisible)), 
NULL 
));
}

B2: Bắt sự kiện va chạm

Thêm hàm sau vào file HelloWorldScene.h

bool onContactBegin(const PhysicsContact &contact);

Và xây dựng nó trong file HelloWorldScene.cpp như sau

bool HelloWorld::onContactBegin(const PhysicsContact& contact)    
{
auto laser = (Sprite*)contact.getShapeA()->getBody()->getNode();
int Tag1 = -1;
if(laser) 
Tag1 = laser->getTag();
auto asteroid = (Sprite*)contact.getShapeB()->getBody()->getNode();
int Tag2 = -1;
if(asteroid) Tag2 =  asteroid->getTag();

//Va chạm giữa đạn và Thiên Thạch
if((Tag1==KLASER&Tag2==KASTEROID)||(Tag2==KLASER&Tag1==KASTEROID))
{
SimpleAudioEngine::sharedEngine()->playEffect("explosion_large.wav"); 
_world->removeBody(laser->getPhysicsBody());
laser->setVisible(false);
_world->removeBody(asteroid->getPhysicsBody());
asteroid->setVisible(false); 
}
// Va chạm giữa thiên thạch và Ship
if((Tag1==KSHIP&Tag2==KASTEROID)||(Tag2==KSHIP&Tag1==KASTEROID))

{
_lives--;

}

return true; 
}

Và không được quên đoạn code Listener ở init()

auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegin, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);

OK, giờ là tới phần Tính điểm và GameOver

B3: Tính điểm và GameOver

Trong hàm update() bạn thêm vào 1 đoạn sau đây

if (_lives <= 0) { // Kiểm tra không còn mạng nào thì game Over
_ship->stopAllActions();
_ship->setVisible(false);
_world->removeBody(_ship->getPhysicsBody());
this->endScene(KENDREASONLOSE);   // Game Over

Hàm endScene xây dựng như sau

void HelloWorld::endScene( EndReason endReason ) {

if (_gameOver) // trạng thái game
return;
_gameOver = true;

Size winSize = Director::getInstance()->getWinSize();

char message[10] = "";
if ( endReason == KENDREASONLOSE)
strcpy(message,"You Lose"); 

// Tạo 2 Label để làm thông báo
LabelBMFont * label ;
label = LabelBMFont::create(message, "Arial.fnt");
label->setScale(0.1);
label->setPosition(Point(winSize.width/2 , winSize.height*0.6));
this->addChild(label);


// Tạo 1 nút reset game là 1 label
LabelBMFont * restartLabel;
strcpy(message,"Restart");
restartLabel = LabelBMFont::create(message, "Arial.fnt");

MenuItemLabel *restartItem =  MenuItemLabel::create(restartLabel,CC_CALLBACK_1(HelloWorld::resetGame,this));

restartItem->setScale(0.1);
restartItem->setPosition( Point(winSize.width/2, winSize.height*0.4));

Menu *menu = Menu::create(restartItem, NULL);
menu->setPosition(Point::ZERO);
this->addChild(menu);

restartItem->runAction(ScaleTo::create(0.5, 1.0));
label ->runAction(ScaleTo::create(0.5, 1.0));
this->unscheduleUpdate(); // dừng update Scene
}

Và nhớ phải thêm thuộc tính bool _gameOver vào phần public của HelloWorldScene.h, đồng thời trong hàm init() phải khởi tạo nó với giá trị false

Bổ sung hàm endScene() và resetGame() vào trong lớp HelloWorld, và hàm resetGame như sau

void HelloWorld::resetGame(Ref* pSender) {
auto scene = HelloWorld::createScene();
Director::getInstance()->replaceScene(TransitionZoomFlipY::create(0.5, scene));  

Size winSize = Director::getInstance()->getVisibleSize();

}

Giờ ta thêm 1 chút phần tính điểm. Khi bắn mỗi thiên thạch ta được 10 điểm.

Bạn thêm 1 thuộc tính int score, LabelBMFont * _scoreDisplay;vào lớp HelloWorldScene, và khi khởi tạo thêm đoạn code này

_scoreDisplay = LabelBMFont::create("Score: 0", "Arial.fnt", 
visibaleSize.width * 0.3f);
_scoreDisplay->setAnchorPoint(Point(1, 0.5));
_scoreDisplay->setPosition(
Point(visibaleSize.width * 0.8f, visibaleSize.height * 0.94f));
this->addChild(_scoreDisplay);

Trong hàm kiểm tra va chạm chúng ta sẽ tính điểm bằng đoạn code nhỏ như thế này

score+=10;
char szValue[100] = { 0 }; // Lấy ra điểm qua mảng đệm char
sprintf(szValue, "Score: %i", score); // Chuyển sang chuỗi => chuỗi
_scoreDisplay->setString(szValue); // Hiện điểm lên

Bạn có thể làm thế với Live để theo dõi số mạng của Ship

OK, Build thử xem kết quả thế nào nhé, cũng không tệ với 1 game "tự tui".

Và sau đây mình làm thêm 1 bước Bonus nữa là 

Bonus: Điều khiển Ship bằng Accelerometer - gia tốc kế

Trước hết bạn copy 2 file VisibleRect.h, .cpp trong bài cpp-tests vào Class của chúng ta. sau đó trong phần init() thêm đoạn code này vào

#define FIX_POS(_pos, _min, _max) \
if (_pos < _min)        \
_pos = _min;        \
else if (_pos > _max)   \
_pos = _max; 

auto listener = EventListenerAcceleration::create([=](Acceleration* acc, Event* event){
auto shipSize  = _ship->getContentSize();

auto ptNow  = _ship->getPosition();

log("acc: x = %lf, y = %lf", acc->x, acc->y);

ptNow.x += acc->x * 9.81f;
ptNow.y += acc->y * 9.81f;

FIX_POS(ptNow.x, (VisibleRect::left().x+shipSize.width / 2.0), (VisibleRect::right().x - shipSize.width / 2.0));
FIX_POS(ptNow.y, (VisibleRect::bottom().y+shipSize.height / 2.0), (VisibleRect::top().y - shipSize.height / 2.0));
_ship->setPosition(ptNow);
});

auto dispathcher = Director::getInstance()->getEventDispatcher();

dispathcher->addEventListenerWithSceneGraphPriority(listener, this);

Vậy thôi, hãy build lại và thử trên ĐT thật, khi nghiêng xem Ship có di chuyển không nhé, nếu di chuyển là đã thành công

Kết thúc bài này, chúng ta cùng nghiên cứu 1 số vấn đề sau

+ Bắn đạn = Touche, duyệt vector
+ Va chạm
+ Tính điểm, game Over
+ Di chuyển Ship bằng gia tốc kế

Download Code

Mình dừng bài học ở đây nhé

Bài 31: Làm game gì bây giờ?

More about

Bài 29: Học làm game thứ 5 - Space Ship ( Part 1 )

Người đăng: share-nhungdieuhay on Thứ Sáu, 1 tháng 8, 2014

Hi, Lâu nay bận kiếm cơm nuôi cái dạ dày nên ít có thời gian post bài. Cơ mà, nếu mọi người đã đọc được tới đây rồi thì đã có thể độc lập nghiên cứu rồi đấy. Mình thấy nhiều bạn tiến cũng khá xa rồi ( lạc hậu rồi ). Tuy nhiên lúc rảnh rỗi mình vẫn cứ viết bài thôi, vì đây là Blog học tập của mình mà, nếu bạn nào rảnh rỗi thì vào ôn luyện lại cũng không sao, có gì mình không đúng thì chỉ giúp, OK?

Trong bài học làm game thứ 5 này, mình sẽ cùng mọi người làm 1 cái game nho nhỏ, tên là Space Ship, tất nhiên là dạng đơn giản thôi, chứ phức tạp quá thì lại phải trình bày, chia part khá nhọc. Mọi người thông cảm, hi vọng trong tương lai sẽ post được những bài công phu, chuẩn mực hơn.

Bài code này mình nhặt nhạnh trên mạng thôi, ở trang http://www.raywenderlich.com/ thì phải, code trên phiên bản 2.x. Mình đã convert lại sang 3.x theo đúng cách làm ở bài trước, và có sửa đổi thêm thắt một chút để chuẩn hơn. Nói trước là bài này chỉ là một bài mẫu nên code khá thô, không thiết kế thành nhiều lớp phức tạp, chức năng cũng đơn giản, không cầu kỳ. Do đó bạn nào muốn tham khảo 1 bài học làm game chuẩn mực: Thiết kế lớp tốt, nhiều chức năng, màu mè đồ họa, code tối ưu, có khả năng tái sử dụng trong nhiều dự án thì không nên đọc bài này. Bạn có thể tìm được những bài nâng cao của Game này ở trên mạng nhé.

Trong Part 1 này, chúng ta sẽ có thể làm được những công việc sau:

+ Tái sử dụng lại lớp Parallax ở bài trước, bài 25
+ Thiết kế màn chơi cho game

Bắt đầu

B1: Tái sử dụng lớp Parallax

Trước tiên bạn tạo 1 Project mới, SpaceShip
Copy 2 file ParallaxNodeExtras.h, .cpp từ bài 25 vào Class
Mở file ParallaxNodeExtras.cpp lên ta sửa hàm updatePosition 1 chút như sau
Xóa hết đoạn code trong lệnh if(po->getChild() == node)
thay bằng đoạn sau

if(po->getChild() == node)

if (node->getContentSize().width<visibleSize.width)
{
po->setOffset(po->getOffset() + Point(visibleSize.width + node->getContentSize().width,0));

}else {
// Mục đích chỗ này áp dụng cho với những đối tượng có chiều rộng > màn hình sẽ di chuyển đúng po->setOffset(po->getOffset() + Point(node->getContentSize().width*2,0));
}

B2: Thiết kế màn chơi

Mở file HelloWorldScene.h lên, lớp này được thiết kế như sau

#include "ParallaxNodeExtras.h"

USING_NS_CC;

using namespace cocos2d;

class HelloWorld : public cocos2d::Layer
{
private:

SpriteBatchNode * _batchNode; // Batch node để lưu các đối tượng có Action
Sprite * _ship;

    ParallaxNodeExtras *_backgroundNode; // Backround là 1 đối tượng Parallax
    Sprite *_spacedust1; // đám bụi 1
    Sprite *_spacedust2; // đám bụi 2
    Sprite *_planetsunrise; // hành tinh
    Sprite *_galaxy;      // thiên hà
    Sprite *_spacialanomaly;  // chịu
    Sprite *_spacialanomaly2;   // chịu

    // Vector để lưu các thiên thạch, dạng con trỏ
    Vector<Sprite*>* _asteroids;
    // Chỉ số để truy cập
    int _nextAsteroid;
    float _nextAsteroidSpawn;  // Thời gian xuất hiện thiên thạch tiếp theo
    float _nextAsteroidtimer;       // Bộ định thời ( hay bộ đếm thời gian, cứ 1 khoảng thời gian thì làm 1 việc gì đó
    // 1 Vector để lưu đạn Laser của tàu, dạng con trỏ
    Vector<Sprite*>* _shipLasers;
    // index
    int _nextShipLaser;
    
    int _lives; // mạng  

    void update(float dt);

    PhysicsWorld* _world;
    void setPhyWorld(PhysicsWorld* world){ _world = world; };
    
public:
    virtual bool init();

    bool onContactBegin(const PhysicsContact& contact);

    static cocos2d::Scene* createScene();
    
    void menuCloseCallback(Ref* pSender);

    CREATE_FUNC(HelloWorld);    

    //Lấy giá trị random trong 1 khoảng
    float randomValueBetween(float low, float high);
    // Ẩn đi
    void setInvisible(Node * node);
    void onTouchesBegan(const std::vector<Touch*>& touches, Event *event); // Multi Touch
};

#endif // __HELLOWORLD_SCENE_H__

OK, sang bước tiếp theo, mở file HelloWorldScene.cpp, ta thiết kế các function như sau:

À nhớ phần include thêm đoạn code sau

#include "SimpleAudioEngine.h"
using namespace CocosDenshion;

using namespace cocos2d;
using namespace CocosDenshion;
using namespace std;

// Định nghĩa các Tag, cho 3 loại đối tượng
enum 
{
KSHIP,
KLASER,
KASTEROID

};

// Hàm tạo Scene với Physics, đơn giản quá rồi
Scene* HelloWorld::createScene()
{
    Scene *scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
Vect gravity(0.0f, 0.0f); // Vector gia tốc =0
scene->getPhysicsWorld()->setGravity(gravity);  
    HelloWorld *layer = HelloWorld::create();
layer->setPhyWorld(scene->getPhysicsWorld());
    scene->addChild(layer);

    return scene;
}

Hàm HelloWorld::init()

//Nạp Resource

Size visibaleSize = Director::getInstance()->getVisibleSize();
Size winSize = Director::getInstance()->getWinSize();
_batchNode = SpriteBatchNode::create("Sprites.pvr.ccz"); // File này là file ảnh đã mã hóa, tạo bởi TexturePacker nhé, ko mở được bằng trình xem ảnh thông thường, mở = PVR view của soft TexturePacker, hoặc soft tương tự
this->addChild(_batchNode);
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("Sprites.plist");  

//Dựng các vật thể

_ship = Sprite::createWithSpriteFrameName("SpaceFlier_sm_1.png");
_ship->setPosition(Point(visibaleSize.width * 0.1, winSize.height * 0.5));
_ship->setTag(KSHIP); // đặt tag để phân biệt trong va chạm
_batchNode->addChild(_ship, 1); // Insert vào BatchNode để thực hiện Action

// Tạo body cho Ship, -23 là offset, vì ảnh cắt ko chuẩn nên thừa ra khoảng trống nhiều, mình phải giảm bớt kích thước body cho chuẩn,
auto shipBody = PhysicsBody::createCircle(_ship->getContentSize().width / 2-23); 
// Ko có cái này thì không thể xử lý va chạm được
shipBody->setContactTestBitmask(0xf); 
// Va chạm tĩnh
shipBody->setDynamic(false);
_ship->setPhysicsBody(shipBody); 
//Tạo parallax node
_backgroundNode = ParallaxNodeExtras::create();
this->addChild(_backgroundNode,-1) ;

// 2 mảng bụi, add vào Parallax
unsigned int dustQuantity = 2;
for(unsigned int i = 0; i < dustQuantity; i++)
{
auto dust = Sprite::create("bg_front_spacedust.png");
dust->setAnchorPoint(Point(0,0.5));
_backgroundNode->addChild(dust,
0, //order (thứ tự) lớp. Order lớn hơn thì nằm trên che khuất lớp có order nhỏ hơn
Point(0.5, 1), // tốc độ
Point( i*(dust->getContentSize().width),winSize.height/2)); // vị trí
}

// Tạo các vật thể khác, add vào Parallax

_planetsunrise = Sprite::create("bg_planetsunrise.png");
_galaxy = Sprite::create("bg_galaxy.png"); _galaxy->setAnchorPoint(Point(0,0.5));
_spacialanomaly = Sprite::create("bg_spacialanomaly.png");
_spacialanomaly2 = Sprite::create("bg_spacialanomaly2.png");
// Tốc độ di chuyển của vật thể
Point dustSpeed = Point(0.5, 0);
Point bgSpeed = Point(0.05, 0);

// PARALLAX Scolling
_backgroundNode->addChild(_galaxy,-1, bgSpeed, Point(0,winSize.height * 0.7));
_backgroundNode->addChild(_planetsunrise, -1 , bgSpeed, Point(600, winSize.height * 0));
_backgroundNode->addChild(_spacialanomaly, -1, bgSpeed, Point(900, winSize.height * 0.3));
_backgroundNode->addChild(_spacialanomaly2, -1, bgSpeed, Point(1500, winSize.height * 0.9));

// Update scene
this->scheduleUpdate();

// Làm 3 cái Particle trang trí cho game lung linh 1 tí
HelloWorld::addChild(ParticleSystemQuad::create("Stars1.plist"));
HelloWorld::addChild(ParticleSystemQuad::create("Stars2.plist"));
HelloWorld::addChild(ParticleSystemQuad::create("Stars3.plist"));
    
// Giờ thì tạo bộ lưu trữ 

    // Bộ lưu mảng thiên thạch
    #define KNUMASTEROIDS 15
    _asteroids = new Vector<Sprite*>(KNUMASTEROIDS);
    for(int i = 0; i < KNUMASTEROIDS; ++i) {
        Sprite *asteroid = Sprite::createWithSpriteFrameName("asteroid.png");
        asteroid->setVisible(false); // ẩn Sprite vừa tạo, nếu không ẩn, bạn sẽ thấy nó dồn hết về tọa độ 0,0
        asteroid->setTag(KASTEROID);  // đặt tag
        _batchNode->addChild(asteroid); // insert vào batch node
        _asteroids->pushBack(asteroid); // insert vào Vector
    }
    
// Bộ lưu mảng đạn Laser    #define KNUMLASERS 5
    _shipLasers = new Vector<Sprite*>(KNUMLASERS);
    for(int i = 0; i < KNUMLASERS; ++i) {
        Sprite *shipLaser = Sprite::createWithSpriteFrameName("laserbeam_blue.png");
        shipLaser->setVisible(false); 
        shipLaser->setTag(KLASER);
        _batchNode->addChild(shipLaser);
        _shipLasers->pushBack(shipLaser);
    }

 this->setTouchEnabled(true);

    
_lives = 3;
_nextShipLaser =0; // index
_nextAsteroid = 0; // index
_nextAsteroidtimer =0;
_nextAsteroidSpawn = 1.6f; // Cứ 1.6 giây thì xuất hiện 1 thiên thạch
    
// Nạp Audio
    SimpleAudioEngine::getInstance()->playBackgroundMusic("SpaceGame.wav",true);
    SimpleAudioEngine::getInstance()->preloadEffect("explosion_large.wav");
    SimpleAudioEngine::getInstance()->preloadEffect("laser_ship.wav");
return true;

Xong phần init() rùi, giờ tiếp tục dựng một số function game nào

Hàm update(float delta)

Point scrollDecrement = Point(5, 0); // Tốc độ di chuyển của Parallax
Size winSize = Director::getInstance()->getWinSize();

// Update vị trí của Parallax
_backgroundNode->setPosition(_backgroundNode->getPosition() - scrollDecrement);
_backgroundNode->updatePosition();

_nextAsteroidtimer+=delta; // Đếm thời gian

if (_nextAsteroidtimer > _nextAsteroidSpawn) { 

_nextAsteroidtimer = 0; // reset bộ đếm timer

// Vị trí random
float randY = randomValueBetween(0.0,winSize.height);
float randDuration = randomValueBetween(2.0,10.0); // Thời gian di chuyển trên màn hình

// Lấy ra sprite tại index _nextAsteroid
Sprite *asteroid = (Sprite *)_asteroids->at(_nextAsteroid);
_nextAsteroid++;

//reset index
if (_nextAsteroid >= _asteroids->size())
_nextAsteroid = 0;

asteroid->stopAllActions(); // dừng mọi Action
// Đặt lên màn hình, và hiển thị
asteroid->setPosition( Point(winSize.width+asteroid->getContentSize().width/2, randY));
asteroid->setVisible(true);

// Đặt body, -15 là hiệu chỉnh kích thước fix bug của ảnh
auto asbody = PhysicsBody::createCircle(asteroid->getContentSize().width/2-15);
// Xử lý va chạm
asbody->setContactTestBitmask(0xf); 
asteroid->setPhysicsBody(asbody);

// Di chuyển với tốc độ và vị trí cho trước, khi di chuyển tới cuối màn hình, gọi hàm setInvisible, để thực hiện 1 số thao tác
asteroid->runAction(Sequence::create(
MoveBy::create(randDuration, Point( - winSize.width - asteroid->getContentSize().width, 0)), 
CallFuncN::create(CC_CALLBACK_1(HelloWorld::setInvisible,this)), 
NULL
));        
}

OK, giờ xây dựng thêm 1 số hàm phụ là có thể chạy game được rồi

void HelloWorld::setInvisible(Node * node) {
node->setVisible(false); // ẩn đi
_world->removeBody(node->getPhysicsBody()); // remove Body
}

// Lấy Random trong khoảng cho trước
float HelloWorld::randomValueBetween(float low, float high) {
return (((float) rand() / RAND_MAX) * (high - low)) + low;
}


OK rồi đó, build thử game xem có chạy nổi không, Ngon lành nhé

 Cũng khá đẹp đấy chứ!

Trong bài này chúng ta đã cùng nghiên cứu 1 số vấn đề nhỏ sau đây:

+ Sử dụng lại lớp đã được thiết kế từ bài trước, có mở rộng 1 chút
+ Sử dụng Vector để lưu trữ dữ liệu, cái này mình thấy dùng khá nhiều, và cũng khá là hay
+ Tạo bộ lưu trữ đối tượng bằng vector, nạp đối tượng vào bộ lưu trữ khi bắt đầu vào game, ẩn chúng đi...
+ Định thời cho 1 sự kiện theo thời gian

Vậy thôi nhỉ, tuy chỉ là những vấn đề nhỏ, nhưng nhiều vấn đề nhỏ kết hợp lại với nhau nhuần nhuyễn sẽ cho ra vấn đề LỚN đấy.

Download CODE+RESOURCE

Mình dừng bài này ở đây. Hẹn gặp lại

Bài 30: Học làm game thứ 5 - Space Ship ( Part 2 - End )

More about