code-prettify

2014年11月3日 星期一

如何使用 ssh 連接到 VirtualBox 下的 Linux Mint Cinnamon

使用 VirtualBox 安裝 Linux Mint Cinnamon 17












2014年10月30日 星期四

Cocos2d-x 3.2 - Chapter 6 - How to Play Music and Sound Effect

Cocos2d-x 3.2 - Chapter 6 - How to Play Music and Sound Effect

Cocos2d-x 3.2 - Step by Step Cocos2dxSimpleGame Series

接著上一篇 Cocos2d-x 3.2 - Chapter 5 - How to Detect the Collisions

在這個章節,我們加入背景音樂及發射子彈時的聲音。

在 HelloWorldScene.cpp 加入 include SimpleAudioEngine.h


#include "SimpleAudioEngine.h"
然後在 init 函式裡面加上這段程式碼,撥放背景音樂。


CocosDenshion::SimpleAudioEngine::getInstance()->playBackgroundMusic(
  "audio/background-music-aac.wav", true);
然後在 addProjectile函式裡面加上這段,撥放子彈音效。

CocosDenshion::SimpleAudioEngine::getInstance()->playEffect("audio/pew-pew-lei.wav");

參考資料:
Cocos2d-x
http://www.cocos2d-x.org/

Step by Step Cocos2dxSimpleGame Series (Old Version for cocos2d-x v2.x)
http://www.cocos2d-x.org/wiki/Step_by_Step_Cocos2dxSimpleGame_Series

使用 VirtualBox 安裝 Linux Mint Cinnamon 17

Host: Windows 7

VM:
VirtualBox 4.3.18

Guest:
Linux Mint Cinnamon 17 Qiana

Mint Cinnamon 版本的系統需求為:
Processor (x86) 700 MHz
Memory 512 MB
Hard Drive (free space) 8.6 GB
Monitor Resolution 800 x 600

安裝流程:

.先到 Mint 網站下載 Mint Cinnamon ISO 檔案
選擇第一個 Cinnamon 版本 64-bit (linuxmint-17-cinnamon-64bit-v2.sio)

.開啟 Virtual Box 點選新增

.建立虛擬機器,名稱:Mint-Cinnamon-17;類型:Linux;版本:UBuntu (64 bit)

.調整記憶體大小為 2048MB (如果主機的記憶體不多的話,依建議設為 512 MB 即可)

.建立虛擬機硬碟空間

.選擇 VMDK (只是個人偏好,因為歷史因素,多數虛擬器皆直接支援該格式)


.這裡要特別注意,硬碟大小改為 16 GB。
(預設值是 8GB,因為 Mint Cinnamon 要求硬碟空間至少要 8.6 GB,所以一定要調整。)

.到第一步已經完成虛擬機的建立了,接著進行設定微調。
這些設定都是個人偏好,可以依自己的需求及硬體規格改變。



.所有設定完成,啟動虛擬機。

.第一次啟動虛擬機時,會出現選擇啟動磁碟。
這時候選擇之前下載好的 image。(linuxmint-17-cinnamon-64bit-v2.iso)

.這個錯誤訊息我不了解發生原因為何,目前是直接跳過。

.進入(虛擬)光碟開機中。時間倒數完會自動進入 Mint 光碟啟動環境。

.如果在倒數過程中按下任意鍵,則會出現此畫面,
保持第一個選項按 Enter 進入 Mint 光碟啟動環境。

.過了一段時間後,進入Mint 光碟啟動環境,選擇桌面上的 Install Linux Mint。
這個環境可以讓你無需安裝先試用一下 Mint,當然不是所有的動作都可以執行的。

.選擇語系為 中文(繁體)。

.如果之前的步驟沒有跳過,這裡的硬碟空間應該會大於 8.6 GB。
如果第一項檢查沒有過,表示你用到預設值,硬碟空間只有 8 GB。
Vitrual Box 預設網路設定為 NAT,會直接使用 Host 的網路,
如果沒有網路,先確認一下主機是否有網路。

.預設值不變更,立刻安裝。

.這一步是選擇時區的意思。

.雖然預設是「漢語」,但是個人偏好改為英語(美式)。

.接著設定電腦及使用者資訊。這裡設定的密碼同時也會作為 root 的密碼。

.設定完成,看到這畫面表示開啟安裝了,可以出去走走再回來。

.安裝完成,重新啟動電腦。

.重開機之後,進入了登入畫面,登入使用者名稱及密碼後登入。

.登入後的桌面環境。

.接著進行關機,左下角選單 / 關機。

.選擇「關閉電腦」

.接著回到 Virtual Box 的管理介面,選 機器 / 再製。
目的是保留一個剛安裝好的環境,省去之後重新安裝的動作。
(雖然有快照可以用,但是還是想完整 Copy 一份)

.輸入新虛擬機名稱。


.點選新的虛擬機,啟動。


以上 Mint Cinnamon 教學到此告一段落,
接著有興趣的人可以參考:
如何使用 ssh 連接到 VirtualBox 下的 Linux Mint Cinnamon


參考來源:

MagicLen - Linux Mint 17 MATE 安裝教學
http://magiclen.org/linux-mint-17-mate-install/

How to Enable SSH on Linux Mint 15 /14 / 13 / 12
http://linuxg.net/how-to-enable-ssh-on-linux-mint-15-14-13-12/

2014年10月16日 星期四

Cocos2d-x 3.2 - Chapter 5 - How to Detect the Collisions

Cocos2d-x 3.2 - Chapter 5 - How to Detect the Collisions

Cocos2d-x 3.2 - Step by Step Cocos2dxSimpleGame Series

接著上一篇 Cocos2d-x 3.2 - Chapter 4 - How to Fire some Bullets
我們的英雄現在會發射子彈了,但是子彈只有視覺效果,要怎麼殺死敵人呢?

在這個章節,我們會介紹並實現碰撞。

我們將 Sprites 分成兩類,tag = 1 的是敵人,tag = 2 的是子彈。因為 Sprite 類別是繼承 Node 類別,已經有一個成員變數 _tag 及兩個用來操作的函式 getTag()、setTag()。我們可以直接使用他們來區分兩種 Sprites。

在 HelloWorldScene.h 加兩個成員變數


protected:
 cocos2d::Vector<cocos2d::Sprite *> _targets;
 cocos2d::Vector<cocos2d::Sprite *> _projectiles;


然後針對兩個變數在建構式及解構式作處理


HelloWorld::HelloWorld()
{

}

HelloWorld::~HelloWorld()
{
 for (auto target : this->_targets)
 {
  this->removeChild(target, true);
 }

 this->_targets.clear();

 for (auto projectile : this->_projectiles)
 {
  this->removeChild(projectile, true);
 }

 this->_projectiles.clear();
}


在 addTarget() 將新產生的 target 加到 vector


 target->setTag(1);
 _targets.pushBack(target);


同樣在 addProjectile() 將新產生的 projectile 加到 vector


 projectile->setTag(2);
 _projectiles.pushBack(projectile);


然後,將 spriteMoveFinished() 修改為下列的樣子,將 sprites 從 vecotr 移除


 Sprite *sprite = (Sprite *)sender;
 this->removeChild(sprite, true);

 if (sprite->getTag() == 1)  // target
 {
  _targets.eraseObject(sprite);
 }
 else if (sprite->getTag() == 2) // projectile
 {
  _projectiles.eraseObject(sprite);
 }


新增一個 update() 函式,用來偵測是否發生碰撞,移除碰撞的敵人及子彈。
函式的內容如下


void HelloWorld::update(float dt)
{
 cocos2d::Vector<cocos2d::Sprite *> targetsToDelete;
 cocos2d::Vector<cocos2d::Sprite *> projectilesToDelete;

 for (auto projectile : this->_projectiles)
 {
  Rect projectileRect = Rect(
   projectile->getPosition().x - (projectile->getContentSize().width / 2),
   projectile->getPosition().y - (projectile->getContentSize().height / 2),
   projectile->getContentSize().width,
   projectile->getContentSize().height);

  for (auto target : this->_targets)
  {
   Rect targetRect = Rect(
    target->getPosition().x - (target->getContentSize().width / 2),
    target->getPosition().y - (target->getContentSize().height / 2),
    target->getContentSize().width,
    target->getContentSize().height);

   if (projectileRect.intersectsRect(targetRect))
   {
    targetsToDelete.pushBack(target);
    projectilesToDelete.pushBack(projectile);
   }
  }
 }

 for (auto target : targetsToDelete)
 {
  _targets.eraseObject(target);
  this->removeChild(target, true);
 }

 for (auto projectile : projectilesToDelete)
 {
  _projectiles.eraseObject(projectile);
  this->removeChild(projectile, true);
 }
}


最後,在 init() 將 update() 加入排程 (schedule),每個 frame 都會呼叫一次。


this->schedule(schedule_selector(HelloWorld::update));


這章的成果圖跟上一章一樣,但是現在的子彈充滿了力量,哈哈,敵人來一個殺一個啦!

下一章,Cocos2d-x 3.2 - Chapter 6 - How to Play Music and Sound Effect

參考資料:
Cocos2d-x
http://www.cocos2d-x.org/

Step by Step Cocos2dxSimpleGame Series (Old Version for cocos2d-x v2.x)
http://www.cocos2d-x.org/wiki/Step_by_Step_Cocos2dxSimpleGame_Series

2014年10月13日 星期一

Cocos2d-x 3.2 - Step by Step Cocos2dxSimpleGame Series

Cocos2d-x 3.2 - Step by Step Cocos2dxSimpleGame Series

將原先官方 wiki 上的 範例,從 Cocos2d-x 2.x 版本,改為 3.x 版本。
Souse : Step by Step Cocos2dxSimpleGame Series ( for cocos2d-x 2.x)

其中關於 Cocos2d-x 2.x to 3.x 的注意事項,請參考 Cocos2d-x 2.x to 3.x 。

Chapter 1 - How to Create a New cocos2d-x project
Chapter 2 - How to Add a sprite
Chapter 3 - How to Move a sprite
Chapter 4 - How to Fire some Bullets
Chapter 5 - How to Detect the Collisions
Chapter 6 - How to Play Music and Sound Effect
Chapter 7 - Some Icing on the Cake

Cocos2d-x 3.2 - Chapter 4 - How to Fire some Bullets

Cocos2d-x 3.2 - Chapter 4 - How to Fire some Bullets

Cocos2d-x 3.2 - Step by Step Cocos2dxSimpleGame Series

接著上一篇 Cocos2d-x 3.2 - Chapter 3 - How to Move a sprite,我們增加了敵人之後。
接著,我們試著發射子彈來殺死敵人。

首先,先開啟觸控事件,在 init 函式最後加入下列程式碼:


 //Create a "one by one" touch event listener (processes one touch at a time)
 auto listener1 = EventListenerTouchOneByOne::create();

 // When "swallow touches" is true, then returning 'true' from the onTouchBegan method will "swallow" the touch event, preventing other listeners from using it.
 listener1->setSwallowTouches(true);

 // Example of using a lambda expression to implement onTouchBegan event callback function
 listener1->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
 listener1->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);

 _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);


然後實作 onTouchBegan 及 onTouchEnded 兩個函式:



bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
{
 return true;
}

void HelloWorld::onTouchEnded(Touch* touch, Event* event)
{
 // Choose one of the touches to work with
 Point location = touch->getLocationInView();
 location = Director::getInstance()->convertToGL(location);
 addProjectile(location.x, location.y);
}

最後是 addProjectile 函式



void HelloWorld::addProjectile(float x, float y)

{

 // Set up initial location of projectile

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

 Sprite *projectile = Sprite::create("Projectile.png", Rect(0, 0, 20, 20));

 projectile->setPosition(Point(20, winSize.height / 2));



 // Determinie offset of location to projectile

 int offX = x - projectile->getPosition().x;

 int offY = y - projectile->getPosition().y;



 // Bail out if we are shooting down or backwards

 if (offX <= 0) return;



 // Ok to add now - we've double checked position

 this->addChild(projectile);



 // Determine where we wish to shoot the projectile to

 int realX = winSize.width

  + (projectile->getContentSize().width / 2);

 float ratio = (float)offY / (float)offX;

 int realY = (realX * ratio) + projectile->getPosition().y;

 Point realDest = Point(realX, realY);



 // Determine the length of how far we're shooting

 int offRealX = realX - projectile->getPosition().x;

 int offRealY = realY - projectile->getPosition().y;

 float length = sqrtf((offRealX * offRealX)

  + (offRealY*offRealY));

 float velocity = 480 / 1; // 480pixels/1sec

 float realMoveDuration = length / velocity;



 // Move projectile to actual endpoint

 projectile->runAction(CCSequence::create(

  CCMoveTo::create(realMoveDuration, realDest),

  CCCallFuncN::create(std::bind(&HelloWorld::spriteMoveFinished, this, std::placeholders::_1)), NULL));



 projectile->runAction(CCSequence::create(

  CCMoveTo::create(realMoveDuration, realDest),

  CCCallFuncN::create(std::bind(&HelloWorld::spriteMoveFinished, this, std::placeholders::_1)), NULL));

}

完成圖:



參考資料:
Cocos2d-x
http://www.cocos2d-x.org/

Step by Step Cocos2dxSimpleGame Series (Old Version for cocos2d-x v2.x)
http://www.cocos2d-x.org/wiki/Step_by_Step_Cocos2dxSimpleGame_Series

EventDispatcher Mechanism
http://www.cocos2d-x.org/wiki/EventDispatcher_Mechanism

2014年10月8日 星期三

SQL - First day of week

SQL - First day of week

Find Monday of week
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0)
is Wrong. (Not first day of week)
Find Monday of week by first day of week is Sunday.
( 2014/10/05 is Sunday, then this find Monday is 2014/10/06)

Find Sunday of week
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), -1)
is Right.
Find Sunday of week by first day of week is Sunday.
( 2014/10/05 is Sunday, then this find Sunday is 2014/10/05)

Find fist of week by DATEFIRST
SET DATEFIRST 1
DATEADD(day,DATEDIFF(day,0,DATEADD(day, 1 - DATEPART(weekday, GETDATE()), GETDATE())),0)
is Great



=== Unit Test ===

-- 2014/10/04 Saturday
-- 2014/10/05 Sunday
-- 2014/10/06 Monday
-- 2014/10/07 Tuesday

-- First day of week is Monday
-- Use 2014/10/07 Tuesday
-- expected '2014/10/06', actual '2014/10/06', Right
SELECT DATEADD(wk, DATEDIFF(wk, 0, '2014/10/07'), 0)

-- Use 2014/10/06 Monday
-- expected '2014/10/06', actual '2014/10/06', Right
SELECT DATEADD(wk, DATEDIFF(wk, 0, '2014/10/06'), 0)

-- Use 2014/10/05 Sunday
-- expected '2014/09/29', actual '2014/10/06', Wrong
SELECT DATEADD(wk, DATEDIFF(wk, 0, '2014/10/05'), 0)

-- Use 2014/10/04 Saturday
-- expected '2014/09/29', actual '2014/09/29', Right
SELECT DATEADD(wk, DATEDIFF(wk, 0, '2014/10/04'), 0)

-- Why, because DATEDIFF fist day of week is Sunday,
-- and DATEADD(wk, 0, 0) = 1990/01/01 is Monday

-- So, we can't find Monday of week,
-- but we can find Sunday of week

-- First day of week is Sunday
-- Use 2014/10/07 Tuesday
-- expected '2014/10/05', actual '2014/10/05', Right
SELECT DATEADD(wk, DATEDIFF(wk, 0, '2014/10/07'), -1)

-- Use 2014/10/06 Monday
-- expected '2014/10/05', actual '2014/10/05', Right
SELECT DATEADD(wk, DATEDIFF(wk, 0, '2014/10/06'), -1)

-- Use 2014/10/05 Sunday
-- expected '2014/10/05', actual '2014/10/05', Right
SELECT DATEADD(wk, DATEDIFF(wk, 0, '2014/10/05'), -1)

-- Use 2014/10/04 Saturday
-- expected '2014/09/28', actual '2014/09/28', Right
SELECT DATEADD(wk, DATEDIFF(wk, 0, '2014/10/04'), -1)



-- Test Data
DECLARE @TableTest TABLE
([Date] VARCHAR(20),
[Expected] VARCHAR(20),
[Actual] VARCHAR(20))

-- Test Case 1
INSERT @TableTest
VALUES
('2014/10/04', '2014/09/29', '')
,('2014/10/05', '2014/09/29', '')
,('2014/10/06', '2014/10/06', '')
,('2014/10/07', '2014/10/06', '')

SET DATEFIRST 1

UPDATE @TableTest
SET [Actual] = CONVERT(VARCHAR(20), DATEADD(wk, DATEDIFF(wk, 0, [Date]), 0), 111)

SELECT
*
, CASE WHEN [Expected] = [Actual] THEN 'TRUE' ELSE 'FALSE' END AS Result
FROM @TableTest

-- Test Case 2

DELETE @TableTest

INSERT @TableTest
VALUES
('2014/10/04', '2014/09/28', '')
,('2014/10/05', '2014/10/05', '')
,('2014/10/06', '2014/10/05', '')
,('2014/10/07', '2014/10/05', '')

SET DATEFIRST 7

UPDATE @TableTest
SET [Actual] = CONVERT(VARCHAR(20), DATEADD(wk, DATEDIFF(wk, 0, [Date]), -1), 111)

SELECT
*
, CASE WHEN [Expected] = [Actual] THEN 'TRUE' ELSE 'FALSE' END AS Result
FROM @TableTest

-- Test Case 3

DELETE @TableTest

INSERT @TableTest
VALUES
('2014/10/04', '2014/09/29', '')
,('2014/10/05', '2014/09/29', '')
,('2014/10/06', '2014/10/06', '')
,('2014/10/07', '2014/10/06', '')

SET DATEFIRST 1

UPDATE @TableTest
SET [Actual] = CONVERT(VARCHAR(20), DATEADD(day,DATEDIFF(day,0,DATEADD(day, 1 - DATEPART(weekday, [Date]), [Date])),0), 111)

SELECT
*
, CASE WHEN [Expected] = [Actual] THEN 'TRUE' ELSE 'FALSE' END AS Result
FROM @TableTest


-- Test Case 4

DELETE @TableTest

INSERT @TableTest
VALUES
('2014/10/04', '2014/09/28', '')
,('2014/10/05', '2014/10/05', '')
,('2014/10/06', '2014/10/05', '')
,('2014/10/07', '2014/10/05', '')

SET DATEFIRST 7

UPDATE @TableTest
SET [Actual] = CONVERT(VARCHAR(20), DATEADD(day,DATEDIFF(day,0,DATEADD(day, 1 - DATEPART(weekday, [Date]), [Date])),0), 111)

SELECT
*
, CASE WHEN [Expected] = [Actual] THEN 'TRUE' ELSE 'FALSE' END AS Result
FROM @TableTest


-- Test Case 5

DELETE @TableTest

INSERT @TableTest
VALUES
('2014/10/04', '2014/09/30', '')
,('2014/10/05', '2014/09/30', '')
,('2014/10/06', '2014/09/30', '')
,('2014/10/07', '2014/10/07', '')
,('2014/10/08', '2014/10/07', '')

SET DATEFIRST 2

UPDATE @TableTest
SET [Actual] = CONVERT(VARCHAR(20), DATEADD(day,DATEDIFF(day,0,DATEADD(day, 1 - DATEPART(weekday, [Date]), [Date])),0), 111)

SELECT
*
, CASE WHEN [Expected] = [Actual] THEN 'TRUE' ELSE 'FALSE' END AS Result
FROM @TableTest

2014年10月5日 星期日

Cocos2d-x 3.2 - Chapter 3 - How to Move a sprite

Cocos2d-x 3.2 - Chapter 3 - How to Move a sprite

Cocos2d-x 3.2 - Step by Step Cocos2dxSimpleGame Series

在上一篇 Cocos2d-x 3.2 - Chapter 2 - How to Add a sprite 中,我們已經增加了一位英雄。但是英雄只有一個人太孤單了,所以我們來增加一些敵人。

addTarget() 這個函式會讓敵人隨機的出現,並從右向左移動。


void HelloWorld::addTarget()
{
 Sprite *target = Sprite::create("Target.png", Rect(0, 0, 27, 40));

 // Determine where to spawn the target along the Y axis
 Size winSize = Director::getInstance()->getWinSize();
 int minY = target->getContentSize().height / 2;
 int maxY = winSize.height - target->getContentSize().height / 2;
 int rangeY = maxY - minY;
 // srand( TimGetTicks() );
 int actualY = (rand() % rangeY) + minY;

 // Create the target slightly off-screen along the right edge,
 // and along a random position along the Y axis as calculated
 target->setPosition(Point(winSize.width + (target->getContentSize().width / 2), actualY));
 this->addChild(target);

 // Determine speed of the target
 int minDuration = (int)2.0;
 int maxDuration = (int)4.0;
 int rangeDuration = maxDuration - minDuration;
 // srand( TimGetTicks() );
 int actualDuration = (rand() % rangeDuration) + minDuration;

 // Create the actions
 FiniteTimeAction* actionMove =
  MoveTo::create((float)actualDuration,
  Point(0 - target->getContentSize().width / 2, actualY));

 FiniteTimeAction* actionMoveDone =
  CallFuncN::create(std::bind(&HelloWorld::spriteMoveFinished, this, std::placeholders::_1));

 target->runAction(Sequence::create(actionMove, actionMoveDone, NULL));
}

其中 CallFuncN::create(std::bind(&HelloWorld::spriteMoveFinished, this, std::placeholders::_1)) 使用了回呼函式,所以我們需要宣告 spriteMoveFinished 函式在 HelloWorld。


void HelloWorld::spriteMoveFinished(Node* sender)
{
 Sprite *sprite = (Sprite *)sender;
 this->removeChild(sprite, true);
}

接著,我們需要定時讓敵人出現在場景上,加入下列這段程式到 init 函中的 return 之前


this->schedule(schedule_selector(HelloWorld::gameLogic), 1.0);

然後實作 gameLogic() 函式


void HelloWorld::gameLogic(float dt)
{
 this->addTarget();
}

好了,所有的工作都完成了,建置然後看看結果吧:



參考資料:
Cocos2d-x
http://www.cocos2d-x.org/

Step by Step Cocos2dxSimpleGame Series (Old Version for cocos2d-x v2.x)
http://www.cocos2d-x.org/wiki/Step_by_Step_Cocos2dxSimpleGame_Series

2014年10月4日 星期六

Cocos2d-x 3.2 - Chapter 2 - How to Add a sprite

Cocos2d-x 3.2 - Chapter 2 - How to Add a sprite

Cocos2d-x 3.2 - Step by Step Cocos2dxSimpleGame Series

一、前言
接續前一篇 Cocos2d-x 3.2 - Chapter 1 - How to Create a New cocos2d-x project 產生的專案,如果還沒有專案的話可以先參考上面的連結。如果之前用過 Cocos2d-x 2.x 版本的話,那你可能會想要參考一下 Cocos2d-x 2.x 到 3.x 筆記

在第一篇我們已經建置過整個方案了,習慣上我會將 libcocos2d, libchipmunk, libAudio 三個專案「卸載專案」,避免之後重新建置這三個專案。只留下 MyGame 這個主要專案。




二、準備工作
在開始前,因為 3.2 的 Layer 預設是黑底,所以我們先把他改為白底。先將 HelloWorldScene.h 裡面,HelloWorld 繼承的 Layer 改為 LayerColor,然後將 HelloWorldScene.cpp 裡面的 init 函式的 if ( !Layer::init() ) 改為 if (LayerColor::initWithColor(Color4B(255, 255, 255, 255)) == false)。

if (LayerColor::initWithColor(Color4B(255, 255, 255, 255)) == false)
{
    return false;
}

將背景改為白色的同時,也可以把原本的  Hello World 文字改為黑字,新增這一行。

label->setColor(Color3B::BLACK);

順便把預設的 COCOS2DX 圖片拿掉,免得擋住之後的畫面。
刪除下列程式碼。

auto sprite = Sprite::create("HelloWorld.png");
sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
this->addChild(sprite, 0);

三、新增 Sprite
在 MyGame 專案中,找到 HelloWorldScene.cpp 中的 init 函式,在 return true 之前加上這一段

Size winSize = Director::getInstance()->getWinSize();
Sprite *player = Sprite::create("Player.png",Rect(0, 0, 27, 40));
player->setPosition(Point(player->getContentSize().width / 2, winSize.height / 2));
this->addChild(player);

最後,我們可以看到一位英雄孤獨的站在白色背景中



下一篇: Cocos2d-x 3.2 - Chapter 3 - How to Move a sprite

參考資料:
Cocos2d-x
http://www.cocos2d-x.org/

Step by Step Cocos2dxSimpleGame Series (Old Version for cocos2d-x v2.x)
http://www.cocos2d-x.org/wiki/Step_by_Step_Cocos2dxSimpleGame_Series

Cocos2d-x 3.2 - Chapter 1 - How to Create a New cocos2d-x project

Cocos2d-x 3.2 - Chapter 1 - How to Create a New cocos2d-x project

Cocos2d-x 3.2 - Step by Step Cocos2dxSimpleGame Series

Cocs2d-x v3.2 建置環境需求 (Build Requirements)
------------------
* Mac OS X 10.7+, Xcode 4.6+
* or Ubuntu 12.10+, CMake 2.6+
* or Windows 7+, VS 2012+
* Python 2.7.5

實際測試環境
* Cocos2d-x v3.2 版本。
* Windows 7。
* Vistual Studio 2013 Express for Desktop。
* Ptyhon 2.7.6

步驟
一、下載 並解壓縮 cocos2d-x (這裡使用的是 v3.2),假設解壓縮後的資料夾為 D:/cocos2d-x-3.2。

二、進入 D:/cocos2d-x-3.2/build 資料夾,執行 win32-msvc-2013-x86.bat。等一陣子之後就會開始建置了,然建置過程會比較久一點。

三、進入 D:/cocos2d-x-3.0rc1/tools/cocos2d-console/bin,使用 command line 輸入
「cocos new MyGame -p com.MyCompany.MyGame -l cpp -d D:/MyCompany」
之後會在 D:/MyCompany 產生一個 MyGame 資料夾,一個 Cocos2d-x 專案就產生了!



四、開啟 D:/MyCompany/MyGame/proj.win32/MyGame.sln 後,開始建置。
等待建置完成後執行程式,噹噹!


小結:Cocos2d-x 專案越來越方便了…

番外篇:
由於個人對於 warning 反感,所以先對這個「空專案」進行一下整理。

一、有一些 warning 是因為程式碼字元問題,考慮到不想變動 cocos2d-x 原始碼的情況下,
只好在專案屬性把警告關閉了。
在專案點擊右鍵 > 屬性 > 組態屬性 > C/C++ > 進階 > 停用特定警告
把 4819 加進去就好。

二、另外的警告則是 cocos2d-x 3.0 開始,
CCLabelTTF, CCLabelBMFont and CCLabelAtlas 改用 Label 取代,
將原本的程式碼改用這一行取代,
然後將字型複製到資料夾 MyGame/Resources/fonts 底下。

auto label = Label::createWithTTF("Hello World", "fonts/arial.ttf", 24);

重新建置確認一下,沒有任何警告訊息,雖然只是個人的小小堅持,
但是就怕長久習慣警告的出現,對於真正的警告出現時,就有可能忽略他,
所以還是調整了一下。

下一篇: Cocos2d-x 3.2 - Chapter 2 - How to Add a sprite

參考資料:
Cocos2d-x
http://www.cocos2d-x.org/

How To Start A New Game (New Version for v3.0 rc1)
https://github.com/chukong/cocos-docs/blob/master/manual/framework/native/getting-started/v3.0/how-to-start-a-new-game/en.md

How to create a new game (Old Version for cocos2d-x v3.0-alpha0 ~ v3.0 beta2)
http://www.cocos2d-x.org/wiki/How_to_create_a_multi-platform_project_in_one_command_line

Step by Step Cocos2dxSimpleGame Series (Old Version for cocos2d-x v2.x)
http://www.cocos2d-x.org/wiki/Step_by_Step_Cocos2dxSimpleGame_Series

2014年9月7日 星期日

Visual Studio 2013 IIS Express remote access (遠端存取)

在使用 Visual Studio 開發 Web 專案時,因為客戶使用 iPad Mini 為操作界面,
雖然 Chrome 擁有 Device Mode & Mobile Emulation 功能,可以滿足大部份的視覺模擬。
但是在一些細微的視覺差異以及在硬體上,還是只能在實體機上面呈現。

然而,預設 Visual Studio Web 專案啟動時,使用的 IIS Express 是只能本地存取的 (localhost access only),所以我們只能一再的將修正後的程式部署到開發環境中的 IIS Server,在 iPad 上確認是否符合預期,如果不是則再重覆上面的動作,實在是很累人。

所以,決定上網尋找一下,能不能讓 Visual Studio 2013 IIS Express 支援遠端存取 (Remote Access),答案是可以!下面是修改步驟。

專案 > 屬性 > Web 頁面中,有個 專案 URL,原本是 localhost:54926 (54926 是隨機 port 號),改為 127.0.0.123:54926 ( 127.0.0.123 是電腦的 IP,或是 domain 也行)。

如果改完之後直接啟動,會出現

Bad Request - Invalid Hostname / HTTP Error 400. The request hostname is invalid.

這是正常的,還需要修改 IIS Express  設定,開啟這個檔案

%USERPROFILE%\My Documents\IISExpress\config\applicationhost.config

找到像這樣的設定:

<site name="WebSiteTest" id="1" serverAutoStart="true">
    <application path="/">
        <virtualDirectory path="/" physicalPath="E:\Project\WebSiteTest" />
    </application>
    <bindings>
        <binding protocol="http" bindingInformation="*:54926:localhost" />
    </bindings>
</site>

將上述中的 bindingInformation="*:54926:localhost" 改為 bindingInformation="*:54926:127.0.0.123"

重新啟動後,就可以看到網站,這時候就可以遠端存取了!

Reference
Connecting to Visual Studio debugging IIS Express server over the lan

Using Custom Domains With IIS Express

Allowing remote access to your IIS Express service

2014年8月7日 星期四

AngularJS - angular-ui-router 實現 Nested Views 及 Multiple Views

在試著使用 AngularJS 實作 Kuroneko Idle Game 時遇到了問題,
ngRoute 不支持 巢狀 View 及多重 View 的實現。
幸好在 Google 上找到了救兵 ui-router,以下是兩種寫法的差別。

ngRoute 寫法:
app.js config:
index.html:
ui-router 寫法:
app.js config:
index.html:
main.html (新增):
這麼一來就完成了巢狀 View 的實作。

Reference
GitHub - angular-ui/ui-router

2014年8月5日 星期二

C# StyleCop 忽略特定檔案名稱

忽略特定檔案名稱

今天遇到一個問題,編譯檔案後進行 StyleCop 檢查時出現:
TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs(1,1)
TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs(1,1)
TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs(1,1)

看起來是自動產生的檔案,但是卻會造成 StyleCop 檢查失敗,
這時候可以手動加上 StyleCop 忽略檔案規則。

到 StyleCop 安裝目錄底下 (預設安裝路徑是 C:\Program Files (x86)\StyleCop 4.7),
使用文字編輯器開啟 Settings.StyleCop 檔案。

檔案內容預設如下:

<StyleCopSettings Version="4.3">
  <GlobalSettings>
    <CollectionProperty Name="DeprecatedWords">
      <Value>preprocessor,pre-processor</Value>
      <Value>shortlived,short-lived</Value>
    </CollectionProperty>
  </GlobalSettings>
  <Parsers>
    <Parser ParserId="StyleCop.CSharp.CsParser">
      <ParserSettings>
        <CollectionProperty Name="GeneratedFileFilters">
          <Value>\.g\.cs$</Value>
          <Value>\.generated\.cs$</Value>
          <Value>\.g\.i\.cs$</Value>
        </CollectionProperty>
      </ParserSettings>
    </Parser>
  </Parsers>
  <Analyzers>
    <Analyzer AnalyzerId="StyleCop.CSharp.NamingRules">
      <AnalyzerSettings>
        <CollectionProperty Name="Hungarian">
          <Value>as</Value>
          <Value>do</Value>
          <Value>id</Value>
          <Value>if</Value>
          <Value>in</Value>
          <Value>is</Value>
          <Value>my</Value>
          <Value>no</Value>
          <Value>on</Value>
          <Value>to</Value>
          <Value>ui</Value>
        </CollectionProperty>
      </AnalyzerSettings>
    </Analyzer>
  </Analyzers>
</StyleCopSettings>

找到其中一段 CollectionProperty ,預設已經有三行設定,
新增一行,如下:

          <Value>\.g\.cs$</Value>
          <Value>\.generated\.cs$</Value>
          <Value>\.g\.i\.cs$</Value>
          <Value>TemporaryGeneratedFile_.*\.cs$</Value>

存檔後,重新編譯一次專案,OK,沒有錯誤訊息了。


補充,如果想要忽略 *.pb.cs 這樣的規則,
加入下列這一行:

          <Value>\.pb\.cs$</Value>


Reference
TemporaryGeneratedFile_[guid] in /obj/debug breaking build

設定 Chrome Canary 設為預設瀏覽器

本來就有使用 Chrome 當主要瀏覽器,
所以當我安裝了 Chrome Canary 之後,
發現設定頁無法將 Chrome Canary 設定為預設瀏覽器,

顯示訊息為:
這是您第二次安裝「Google Chrome」,您無法將它設定為預設瀏覽器。

想說第二次安裝同樣是 Chrome 系列的瀏覽器,覺得這樣蠻正常的。



過了一陣子,當我重灌電腦之後,
直接選擇 Chrome Canary 來安裝,卻也是同樣的狀況,
這樣就不對了吧。

上網查了之後,才知道 Canary 這個版本會有這個限制,聽說沒有打算要處理。
幸好,可以透過註冊檔 (Regiest) 來設定。
可以到這個網頁 Make Google Chrome Canary the Default Web Browser 來下載,
最底下有個 Download REG File (Manual) ,下載解壓縮後,
用文字編輯器開啟 Registry.reg 找出 YourUsernameHere 文字,
並且用自己的使用者名稱取代,有三個地方,
改完存檔後,直接點擊檔案執行,完成。

2014年7月25日 星期五

C# StyleCop System using directives must be placed before all other using directives.

一般我們的專案會像這樣,使用了很多的 using 參考。
這時候我們就會使用 Visual Stdio 內建的功能,對 Using 進行整理。
右鍵 > 組合管理 Using > 移除和排序


移除和排序後的樣子,很方便對吧!

 但是呢?StyleCop 出來抱怨了,
「System using directives must be placed before all other using directives.」。
也就是說,所有 System 相關的 using 必須放在最前面。


從前面的圖片可以看的出來,SocketLibaray 比 System 的字母順序還前面,所以排在 System 的前面了。
這樣我們就不能用 Visual Stdio 內建的排序了嗎?只能手動調整了嗎?
放心,其實 Visual Stdio 是有這個設定的,在功能選單內,
選項 > 文字編輯器 > C# > 進階 > 組合管理 Using > 排序 Using 時先放置 'System' 指示詞
將這個選項打勾,然後按下確定。



接著再對剛剛的 using 做一次排序,
噹噹!依照我們希望的順序,System 在前面了喔!
這麼一來 StyleCop 也不會報錯了呢。