2016년 12월 11일 일요일

블로그 이전.

2015년 7월 23일 목요일

좋은 글



그대가 서 있는 곳에서,
그대가 가진 것으로,
그대가 할 수 있는
최선의 일을 하라.
-루즈벨트

2015년 7월 16일 목요일

Visual Studio Extensions_Code Maid

Explain.
Visual Sutdio Extensions 프로그램중
Code Maid에 대해 정리.
Join Line, Sort Line ,Code CleanUp, Code space 등의 기능 제공.
설치방법 및 대표적인 기능 정리 예정...

Visual Studio_Hot key


Explain.
Visual Studio Hot key list
자주쓰는 내용 Bold


Rename : Ctrl + R, R
Extract Method : Ctrl + R , M
Extract Interface : Ctrl + R, I

Quick Resolve : Ctrl + .
Navigator : Ctrl + ,
Find All Reference : Shift + F12
Class View : Ctrl + Shift + C
Auto Document : Ctrl + K + D

Comment Selection : Ctrl + K + C
UnComment Selection : Ctrl + K + U

Go to : Ctrl + G

2015년 6월 21일 일요일

C#_Naver Search API 활용 소스


AnalysisEngine.
class AnalysisEngine
{
    public enum Step
    {
        WEB,
        IN,
        CAFE,
        BLOG
    }

    const string NAVER_OPENAPI_KEY = "InputYourNaverAPIKey";
    const string NAVER_OPENAPI_URL = "http://openapi.naver.com/search?";
    const int NAVER_SEARCH_COUNT = 100;

    string keyword;
    string url;
    string blog;
    string cafe;

    public AnalysisEngine(string keyword, string url, string blog, string cafe)
    {
        this.keyword = keyword;
        this.url = url;
        this.blog = blog;
        this.cafe = cafe;
    }

    public void Analysis()
    {
        AnalysisResult result = new AnalysisResult();
        

        result.webRank = AnalysisProccess(Step.WEB, url);
        result.blogRank = AnalysisProccess(Step.BLOG, blog);
        result.cafeRank = AnalysisProccess(Step.CAFE, cafe);

        Console.WriteLine("0 = 100위안에 없음.");
        Console.WriteLine("네이버 웹문서 분석 결과 : " + result.webRank);
        Console.WriteLine("네이버 블로그 분석 결과 : " + result.blogRank);
        Console.WriteLine("네이버 카페 분석 결과 : " + result.cafeRank);

        Console.ReadLine();
    }

    int AnalysisProccess(Step step, string target)
    {
        string html = AnalysisTools.GetHTML(CreateURL(step));

        XmlDocument doc = new XmlDocument();
        doc.LoadXml(html);

        int rank = 0;

        foreach (XmlNode node in doc.SelectNodes("rss/channel/item/link"))
        {
            string realURL = GetRealURL(node.InnerText);

            if (realURL.Length > target.Length)
                realURL = realURL.Substring(0, target.Length);

            Console.WriteLine(realURL);

            ++rank;
            if (target == realURL)
            {
                return rank;
            }
        }

        return 0;
    }

    string CreateURL(Step step)
    {
        string target = "";
        switch (step)
        {
            case Step.WEB: target = "webkr";
                break;
            case Step.IN: target = "in";
                break;
            case Step.CAFE: target = "cafearticle";
                break;
            case Step.BLOG: target = "blog";
                break;
            default:
                break;
        }

        return string.Format("{0}key={1}&query={2}&display={4}&start=1&target={3}", NAVER_OPENAPI_URL, NAVER_OPENAPI_KEY, keyword, target, NAVER_SEARCH_COUNT);

    }

    /*
    Naver API를 활용하여 url주소를 획득 할 시
    실주소가 아닌 API 로 맵핑된 가상주소를 제공 해주기 때문에
    직접 리다이렉트 주소를 획득하여 반영 하기위한 함수.
    */

    string GetRealURL(string url) 
    {
        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
        webRequest.AllowAutoRedirect = false;

        webRequest.Timeout = 10000;           
        webRequest.Method = "HEAD";

        HttpWebResponse webResponse;
        string uriString = string.Empty;

        using (webResponse = (HttpWebResponse)webRequest.GetResponse())
        {
            if ((int)webResponse.StatusCode >= 300 && (int)webResponse.StatusCode <= 399)
            {
                uriString = webResponse.Headers["Location"];
                webResponse.Close();
            }
        }

        return uriString;
    }
}

AnalysisResult
class AnalysisResult
{
    public int webRank;
    public int cafeRank;
    public int blogRank;
}

AnalysisTool
class AnalysisTools
{
    public static string GetHTML(string url)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();

        if (response.StatusCode == HttpStatusCode.OK)
        {
            Stream receiveStream = response.GetResponseStream();
            StreamReader readStream = null;

            if (response.CharacterSet == null)
            {
                readStream = new StreamReader(receiveStream);
            }
            else
            {
                readStream = new StreamReader(receiveStream, Encoding.UTF8);
            }

            string data = readStream.ReadToEnd();

            response.Close();
            readStream.Close();

            return data;
        }

        return string.Empty;
    }
    
}

Main
class Program
{
    static string keyword = ""; //키워드
    static string homepage = ""; //홈페이지 주소
    static string blog = ""; //블로그 주소
    static string cafe = ""; //카페 주소


    static void Main(string[] args)
    {

        AnalysisEngine engine = new AnalysisEngine(
            keyword , 
            homepage, 
            blog,
            cafe);

        engine.Analysis();

        
    }
}

2015년 6월 2일 화요일

Unity_코루틴 함수를 활용한 Lerp함수 활용 using IEnumerator with Lerp

Explain.

Unity Coroutine 함수를 활용한 Object의 Lerp(선형보간)운동 구현구현
가장 심플하게 구현한 예제.
C#의 Generic , Reflection을 활용하여 기능 확장 가능.

Code.
IEnumerator moveCoroutine(float duration, Vector3 end)
{
 WaitEndOfFrame wait = new WaitEndOfFrame();

 Vector3 start = transform.position;
 float elapsed = 0.0f;

 while(elapsed < duration){
  elapsed += Time.deltatime;
  transform.position = Vector3.Lerp(start,end elapsed / duration);
  yield return wait;
 }

 transform.position = end;
}

IEnumerator colorCoroutine(float duration, Color start, Color end)
{
 WaitEndOfFrame wait += new WaitEndOfFrame();

 float elapsed = 0.0f;

 while(elapsed < duration){
  elapsed = Time.deltaTime;
  renderer.material.color  = Color.Lerp(start,end elapsed / duration);
  yield return wait;
 }

 renderer.material.color = end;
}

2015년 5월 14일 목요일

Game Open Source_3-Match Puzzle 형식의 게임 소스



예전에 만들어둔 3-Match형식(애니팡) 소스를 Github에 올려둔게 있어서 포스팅.


References.
Github.
PlayStore.

C#_Naver Search API 활용 예제


Explain.
C#환경 에서 네이버 오픈 검색 API 를 활용하는 예제.

Input - 키워드(검색값), 페이지(URL)
Output - 네이버 노출 순위

Environment.
Visual Studio 2015 Comunity.
Naver Search API KEY


Logic flow.
1. Input / Keyword, Home Page URL
2. WebRequest를 활용하여 네이버 오픈 API에 request 요청 후 respawn 데이터 저장.
3. 2.의 respawn 데이터 네이버 노출 순위 검색.

소스 코드

Result.














소스 코드

2015년 4월 15일 수요일

Finite State Machine for CSharp_Step2. 활용 예제

Explain.
게임 제작시 MainFrame(MainManager, GameManager 등)에서 FSM을 구현하는 방법 정리


MainFrame.cs
class MainFrame
{
    public enum State
    {
        Game,
        Lobby
    }

    FiniteStateMachine<MainFrame, State> FSM;
    
    LobbyState stateLobby = new LobbyState();
    GameState stateGame = new GameState();

    void Awake()
    {
        FSM = new FiniteStateMachine<MainFrame, State>(this);
        FSM.AddState(stateLobby);
        FSM.AddState(stateGame);

        FSM.ChangeState(stateLobby); // 시작시 stateLobby State
    }
}
LobbyState.cs
class LobbyState : FiniteState<MainFrame, MainFrame.State>
{
    public override void SetEntity(MainFrame entity)
    {
        base.SetEntity(entity);
    }
    public override void Enter()
    {
        base.Enter();
        //게임 입장시 이벤트 구현부
    }
    public override void Excute()
    {
        base.Excute();
        //게임 실행시 이벤트 구현부
    }
    public override void Exit()
    {
        base.Exit();
        //게임 퇴장시 이벤트 구현부
    }

    public override MainFrame.State _StateID
    {
        get
        {
            return MainFrame.State.Game;
        }
    }
}
GameState.cs
class GameState : FiniteState<MainFrame, MainFrame.State>
{
    public override void SetEntity(MainFrame entity)
    {
        base.SetEntity(entity);
    }
    public override void Enter()
    {
        base.Enter();
        //게임 입장시 이벤트 구현부
    }
    public override void Excute()
    {
        base.Excute();
        //게임 실행시 이벤트 구현부
    }
    public override void Exit()
    {
        base.Exit();
        //게임 퇴장시 이벤트 구현부
    }

    public override MainFrame.State _StateID
    {
        get
        {
            return MainFrame.State.Game;
        }
    }
}

Finite State Machine for CSharp_Step1. FSM 구현

Explain. 
유한 상태 기계라고 하며, 특정한 Input(event) 에 따라 해당하는 state(output)으로 변화하는 방법론. 다양한 분야(특히 게임)에 사용되어 지고있으며 상태에 변화에 따른 이벤트를 발생시킬수있으므로 좀더 유연한 로직을 구성할수있다. 이전에 게임 제작시 사용했던 현재도 사용하고있는 FSM에 대해 정리. 스크립트 설명의경우 주석으로 진행.

Step. 
1. FiniteStateMachine 구현
2. 간단한 사용법

FSM 구현

Summary.
 IState ( FiniteState의 명세를 담은 Interface )
 FiniteState ( State 클래스 )
 FiniteStateMachine ( FSM 클래스 )

IState.cs

interface IState<T>
{
    
    void Enter();
    void Excute();
    void Exit();

    T _StateID
    {
        get;
    }
}

FiniteState.cs
class FiniteState<T, U> : IState<U>
{
    protected T entity;

    public virtual void SetEntity(T entity)
    {
        this.entity = entity;
    }

    public virtual void Enter()
    {
        Console.WriteLine(typeof(T).ToString() + "Enter");
    }

    public virtual void Excute()
    {
        Console.WriteLine(typeof(T).ToString() + "Excute");
    }

    public virtual void Exit()
    {
        Console.WriteLine(typeof(T).ToString() + "Exite");
    }

    public virtual U _StateID
    {
        get
        {
            throw new ArgumentException("Exception");
        }
    }

}

FiniteStateMachine.cs
class FiniteStateMachine<T, U>
{
    private T entity; // State의 주체가 되는 class

    private Dictionary<U, FiniteState<T, U>> stateDic; // 전체 State

    private FiniteState<T, U> currentState; // 현재 상태
    private FiniteState<T, U> previousState; // 이전 상태

    /// <summary>
    /// 생성자
    /// </summary>
    /// <param name="entity">주체 class</param>
    public FiniteStateMachine(T entity)
    {
        this.entity = entity;
        stateDic = new Dictionary<U, FiniteState<T, U>>();
    }

    public void ExcuteState()
    {
        if (currentState != null) currentState.Excute();
    }

    public void ChangeState(FiniteState<T, U> nextState)
    {
        if (currentState == nextState) return;

        if(currentState != null)
        {
            currentState.Exit();
            previousState = currentState;
        }

        currentState = nextState;

        currentState.Enter();
    }

    public void ChangeState(U stateID)
    {
        try
        {
            FiniteState<T, U> state = stateDic[stateID];
            ChangeState(state);
        }
        catch(KeyNotFoundException)
        {
            // exception 처리
        }
    }

    //이전 state로 상태 되돌리기
    public void RevertState()
    {
        if (previousState != null)
            ChangeState(previousState);
    }

    public void AddState(FiniteState<T, U> state)
    {
        if (state == null) return;
        state.SetEntity(entity);
        stateDic.Add(state._StateID, state);
    }

    public void RemoveState(FiniteState<T, U> state)
    {
        stateDic.Remove(state._StateID);
    }
}

2015년 4월 8일 수요일

Visual Stduio2013에 Boost Library 설치하기.



Summary.
 - Boost Library란? C++ STL에 포함되기전 철저한 리뷰를 거쳐 실험적인 라이브러리. 매우 광대한 영역을 품고있으며 실제로 C++ STL 표준에 많은 부분이 포함되어지기도한다.
때문에, C++ 표준에 영향을 미치기도 한다.

Environment.
 - Visual Studio 2013 Ultimate.
 - Window 7 professional 64bit.

Step.
 - 1. boost Library 다운로드 , 압축해제
 - 2. Boost Lib 빌드
 - 3. VS2013 property에 lib 추가.


How to used?.
1. boost Library 다운로드 , 압축해제
  boost 홈페이지에 접속하여 boost lib 압축파일을 다운로드 한뒤
아무곳에나 압축해제하여 위치시킨다.

2.Boost Lib 빌드

  • 압축 해제된 폴더내의 bootstrap.bat 배치파일을 실행한다.
  • 그후 cmd를 실행한뒤 해당 폴더로 이동하고 b2파일을 실행하여 컴파일 한다.
    • b2 toolset=msvc-12.0 --build-type=complete --abbreviate-paths architecture=x86 address-model=32 install -j4
      • b2 : build boost
      • msvs-12.0 : vs version
      • j4 : 4 cores for parallel compilation 사용
  • 이후 20~30분 정도의 빌드 시간을 거친 뒤 header 파일 및 lib 파일이 생성 된다.
    • 경로 : C:\Boost
3. VS2013 property에 lib 추가.

Project Properties 창을 선택한뒤.

Include Directories 에 C:\Boost\include 폴더를 포함시킨다.




Reference.
 - How to use boost in visual studio

More.
 - 이후 boost 헤더파일을 포함시키면서 코딩을 진행하면 된다. 다만 link 단계에서의 종속성이 요구되는 부분을 사용할경우 따로 설정해야하는 부분이 있으니 기억해두고 진행한다.(레퍼런스 참고) 

2015년 2월 11일 수요일

Android Push Server_ Step1.AWS 계정생성 및 AWS EC2 Instance 생성.


Explain.
 - 이번에 푸쉬서버 구현 진행중 AWS 회원가입시 FreeTier 권한으로 1년간 무료로 AWS를 사용할수있는점을 발견해서 진행. 자세한내용은 AWS 홈페이지 참고. 한글어도 일부 지원하는것으로 보이고 계속 번역 진행중인것으로 보여짐.(굿)
 - 회원가입의경우 한글어로 폼을 지원하기때문에 따로 정리하지는 않았습니다.


1.회원가입후 로그인시 볼수있는 AWS서비스 화면
EC2를 활용하여 서버구현을 진행할것이므로 EC2를 선택한다.

2. 그후 인스턴스를 추가해야되기때문에 좌측에 인스턴스 클릭.

3. 현재 실행중인 인스턴스들을 보여주는 창이나오는데
상단의 Launch Instance를 선택

4. OS 선택. Amazon Linux를 선택하여 진행.(다른운영체제를 선택하셔도 무방합니다.)

5. Instance type을 선택하는 부분인데 free tier용 타입(t2.micro) 선택
후 Next

6. 이후 서버관련 셋팅(과금과 관련된 부분은 안건드시는게 좋습니다.^^;)
딱히 따로 셋팅이 필요없으신분은
디폴트로 놔두시고 Launch 하셔도 무방합니다.

여기까지 진행하신경우 3번의 화면에서 생성된 인스턴스의 상태와 정보를 볼수있습니다.
다음포스팅에서는 AWS에 LAMP 환경 구축하는것을 진행.

Android Push Server_ AWS 를 활용한 안드로이드 푸쉬 서버 구현.



Summary.
 -AWS(Amazon Web Services) EC2를 활용하여 안드로이드 푸쉬서버 구현 내용 정리.

Server.
 -EC2(Amazon Linux) + Apche + php + mysql 로 구성.(LAMP)

Step.
 1. AWS 계정생성 및 AWS EC2 Instance 생성.
 2. EC2 Instance 셋팅 및 LAMP 환경 셋팅.
 3. 안드로이드 푸쉬 서버 구현.
 4. 안드로이드 푸쉬 클라이언트(apk) 생성 및 테스트.

Environment.
 - Window 7
 - Eclips
 - Sublime Text 3 SFTP
 - Filezlia
 - Putty

2015년 1월 29일 목요일

C#.HtmlLoader_HtmlAgilityPack을활용하여 Web에서 Html 데이터 받아오는법.

Summary.
  -C#환경(.net)에서 사용할수있는 HtmlAgilityPack을 활용하여 Web에서 Html데이터 받아오는 코드.

Requirements.
 -HtmlAgilityPack Library
   : VS 내의 NuGet Pakage Manager를 통해 설치할수 있다.


Code.
class HtmlLoader
{
    public enum State
    {
        Working,
        End
    }

    string mURL;
    HtmlDocument mDocument;
    State mState;
    Action mCallback;
    Encoding mEncoding;

    public HtmlLoader(string url, Encoding enc , Action callback)
    {
        this.mURL = url;
        this.mState = State.End;
        this.mCallback = callback;
        this.mEncoding = enc;
    }

    //새로운 스레드를 생성하여 실행.
    public void LoadWithThread()
    {
        if (mState == State.Working) return;

        Thread thraed = new Thread(new ThreadStart(LoadHtml));
        thraed.Start();

    }
    
    //호출한 스레드상에서 바로 실행.
    public void Load()
    {
        if (mState == State.Working) return;
        LoadHtml();
        
    }

    void LoadHtml()
    {
        mState = State.Working;

        mDocument = new HtmlDocument();
        HtmlWeb website = new HtmlWeb();
        StreamReader reader = new StreamReader(WebRequest.Create(mURL).GetResponse().GetResponseStream(), mEncoding);   

        mDocument.Load(reader);

        mCallback();
        mState = State.End;
    }
    
    public HtmlDocument _Document
    {
        get { return mDocument; }
    }
}
Use.
string url = textBox1.Text;

loader = new HtmlLoader(url,
    Encoding.GetEncoding("euc-kr"),
    new Action(() => 
        System.IO.File.WriteAllText("web.txt", loader._Document.DocumentNode.InnerText)
));
loader.LoadWithThread();
이후 생성되는 web.txt파일을 확인할수있다.

2014년 11월 6일 목요일

Unity_IOS 에서 Screen Capture한 이미지를 Social.framework를 활용하여 공유하는 방법정리.

Explain.


IOS 에서 Screen Capture한 이미지를 Social.framework를 활용하여 공유하는 방법정리.


Sequence.


1. Application.CaptureScreenShot() 으로 캡쳐진행.

2. 위의 이미지를 가지고 IOS의 social.framwork를 활용하여 쉐어진행.


In Xcode

아래 2파일[SocialHelper.h , mm]을 현재 프로젝트의 Plugin/IOS 위치 시킨다.

SocialHelper.h
#import &ltFoundation/Foundation.h>

@interface SocialHelper : NSObject
{
    
}

+(void)ImageToTwitter:(NSString*)filePath;

+(void)ImageToFaceBook:(NSString*)filePath;

@end

SocialHelper.mm
#import "SocialHelper.h"

#import &ltSocial/Social.h>
#import &ltUIKit/UIKit.h>
#import &ltUnityAppController.h>

#pragma mark - Unity methods

@implementation SocialHelper


+ (void) ImageToTwitter:(NSString *) filePath
{
    UIViewController *rootViewController = [GetAppController() rootViewController];
    UIImage *image = [UIImage imageWithContentsOfFile:filePath];
    
    if([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]){
        SLComposeViewController *mySLComposeSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
        
        [mySLComposeSheet setInitialText:@"Let's Play Together!"];
        [mySLComposeSheet addImage:image];
        [mySLComposeSheet addURL:[NSURL URLWithString:@"https://myurl.com"]];
        [mySLComposeSheet setCompletionHandler:^(SLComposeViewControllerResult result) {
            switch (result) {
                case SLComposeViewControllerResultCancelled:
                    NSLog(@"Twtitter - POST Cancel");
                    break;
                    
                case SLComposeViewControllerResultDone :
                    NSLog(@"Twitter - Post Success");
                    break;
                    
                default:
                    break;
            }
        }];
        [rootViewController presentViewController:mySLComposeSheet animated:YES completion:nil];
    }
}

+ (void) ImageToFaceBook:(NSString *) filePath
{
    UIViewController *rootViewController = [GetAppController() rootViewController];
    UIImage *image = [UIImage imageWithContentsOfFile:filePath];
    
    if([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]){
        SLComposeViewController *mySLComposeSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
        
        [mySLComposeSheet setInitialText:@"Let's Play Together!"];
        [mySLComposeSheet addImage:image];
        [mySLComposeSheet addURL:[NSURL URLWithString:@"https://myurl.com"]];
        [mySLComposeSheet setCompletionHandler:^(SLComposeViewControllerResult result) {
            switch (result) {
                case SLComposeViewControllerResultCancelled:
                    NSLog(@"Facebook - POST Cancel");
                    break;
                    
                case SLComposeViewControllerResultDone :
                    NSLog(@"Facebook - Post Success");
                    break;
                    
                default:
                    break;
            }
        }];
        [rootViewController presentViewController:mySLComposeSheet animated:YES completion:nil];
    }
}

extern "C" {
    void PostImageToTwitter(const char * filePath)
    {
        NSLog(@"Share Iamge Path : %@", [NSString stringWithUTF8String:filePath]);
        [SocialHelper ImageToTwitter:[NSString stringWithUTF8String:filePath]];
    }
    
    void PostImageToFacebook(const char * filePath)
    {
        NSLog(@"Share Iamge Path : %@", [NSString stringWithUTF8String:filePath]);
        [SocialHelper ImageToFaceBook:[NSString stringWithUTF8String:filePath]];
    }
}

@end



In Unity

using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;


public enum SocialType : int
{
    Twitter,
    Facebook
}

public class SocialHelper : MonoBehaviour
{

    public static IEnumerator PostImage(SocialType type)
    {
        string fileName = getCaptureFileName();

        Application.CaptureScreenshot(fileName);

        yield return new WaitForSeconds(1.0f);

        if (type == SocialType.Facebook)
            PostImageToFacebook(string.Format("{0}/{1}", Application.persistentDataPath, fileName));

        if (type == SocialType.Twitter)
            PostImageToTwitter(string.Format("{0}/{1}", Application.persistentDataPath, fileName));
    }

    static string getCaptureFileName()
    {
        return string.Format("capture_{0}.png", System.DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"));
    }



    [DllImport("__Internal")]
    static extern void PostImageToTwitter(string filePath);

    [DllImport("__Internal")]
    static extern void PostImageToFacebook(string filePath);

}

SocialHelper.PostImage(SocialType.Facebook); // 이후 이런식으로 메소드를 호출시 공유가 진행.



Reference.


IOS 에서 Screen Capture한 이미지 Camera Roll에 등록하기.

Social.Framework


2014년 10월 31일 금요일

Unity for IOS_Screen Capture한 이미지 카메라롤 에 등록하기.


Explan.

IOS에서 Application.CaptureScreenShot(path) 메소드를 사용할경우
캡처는 진행되나 해당 app 의 document폴더로 들어가서 카메라 롤에서 확인할수가 없다.
이를 등록해주는 방법 포스팅.


CaptureHelper.h
#import <Foundation/Foundation.h>

@interface CaptureHelper : NSObject

+(CaptureHelper *)sharedInstancs;

@end
CaptureHelper.mm
#import "CaptureHelper.h"

static CaptureHelper * captureHelper = [CaptureHelper sharedInstancs];

@implementation CaptureHelper : NSObject

+ (void)initialize{
    if(captureHelper == nil)
        captureHelper = [[CaptureHelper alloc] init];
}

+ (CaptureHelper *)sharedInstancs{
    return captureHelper;
}

- (id)init{
    if(captureHelper != nil){
        return  captureHelper;
    }
    
    self = [super init];
    if(self){
        captureHelper = self;
    }
    
    return self;
}


- (NSString *)getDocumentDirectory {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    
    return [paths objectAtIndex:0];
}

@end

extern "C"{
    void CaptureToCameraRoll(const char *fileName)
    {
        NSString *file = [NSString stringWithUTF8String:(fileName)];
        NSString *filePath = [[captureHelper getDocumentDirectory] stringByAppendingString:file];
        UIImage *image = [[UIImage alloc] initWithContentsOfFile:filePath];
        
        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
    }
}

위 2개의 파일을 생성후 Plugin/IOS 폴더에 위치 그후

how to used.
[DllImport("__Internal")]
public static extern void CaptureToCameraRoll(String fileName);

// 그이후 스크린 캡처 진행시.

Application.CaptureScreenShot(path);
CaptureToCameraRoll(string.Format("/{0}",path));


이후 카메라롤에서 캡쳐된 이미지를 확인하실수 있다.

2014년 10월 1일 수요일

CSharp_Visual Studio Custom Snippet 적용 시키기. in Visual Studio & Unity

Explain.
Visual Studio를 사용할경우 snippet파일을 직접 만들어서 적용.
Snippet을 적용하여 작업하는 이유는 모든 스크립트의 전체적으로 통일된 디자인을 적용하고 반복되어지는 작업을 최소화 시켜줌.

How to use.
아래처럼 xml형식으로 snippet 파일을 생성후 저장(*.snippet)으로 저장 하여야 한다.
(아래 형식은 제가 사용하는(unity)에서 형식이고 내용은 필요한대로 편집하여 사용하시면됩니다.)
저장경로 : Users\User\Documents\Visual Studio XXXX\Code Snippets\Visual C#\My Code Snippets

그 이후
프로젝트에서 우클릭-> Insert Code Snippet -> My Code Snippet -> 해당 Snippet 선택
해주시면 snippet이 짠 하고 나타나는것을 보실수 있습니다.
ctrl + K + X가 Hotkey이니 애용하시면 될듯합니다. -End.

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>#Classregion</Title>
      <Shortcut>#Classregion</Shortcut>
      <Description>Code snippet for #Classregion</Description>
      <Author>Author Name</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
        <SnippetType>SurroundsWith</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>name</ID>
          <ToolTip>Region name</ToolTip>
          <Default>MyRegion</Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
        <![CDATA[
        #region -------Public Field-------
        $selected$ $end$
        #endregion
    
        #region -------Private Field-------
        $selected$ $end$
        #endregion
    
        #region -------Default Method-------
        $selected$ $end$
        #endregion

        #region -------Public Method-------
        $selected$ $end$
        #endregion
    
        #region -------Private Method-------
        $selected$ $end$
        #endregion
    
        #region -------Property-------
        $selected$ $end$
        #endregion
    ]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

2014년 9월 24일 수요일

Google Play Game Service for Unity In Android_Step2. GPGS Plugin 활용을 위한 Manager Class 생성 & 사용 in Unity


 Explain.
앞서 GPGS활용을위한 셋팅까지 완료한경우
Unity Project에서 GPGS의 기본적은 기능(업적 , 리더보드)를 활용하기위한 Class 생성.
아래 방법은 여러가지 방법중 하나이므로 프로젝트 상황에 맞게끔 구현하여 사용하면 됩니다.


1. Google Game service의 리더보드,업적의 경우 Id값을 기준으로
실행이 이뤄지므로 Developer Console의 업적,리더보드에서
Get Resources를 클릭하여 ID값을 복사

2.위 처럼 텍스트 형식으로 Export하여 복사하여 둡니다.

이후 아래처럼 GPGS Manager Class를 생성한 뒤 Scene에 배치후
이벤트 관련 동작시(게임종료)
업적,리더보드관련 메소드를 호출하여 동작을 확인해 보실수있습니다.
리더보드 , 업적 확인 관련 UI호출은
ShowLeaderBoard, ShowArchievement
메소드를 호출하여 확인가능.
이상으로 GPGS의 기본적인 기능들 활용방법 포스팅 마치겠습니다.


GPGSManager.cs
using UnityEngine;
using System.Collections;
using GooglePlayGames;
using UnityEngine.SocialPlatforms;

public class GPGSManager : MonoBehaviour {

    private static GPGSManager sInstance;

    public static GPGSManager GetInstance
    {
        get
        {
            if(sInstance == null) sInstance = this;

            return sInstance;
        }
    }

    void Start()
    {
        init();
    }

    void init()
    {
        PlayGamesPlatform.DebugLogEnabled = true;

        PlayGamesPlatform.Activate();

        Social.localUser.Authenticate((bool success) =>
        {
            if (success) Debug.Log("Sign in Success");
            else Debug.Log("Sign in Fail");
        });
    }

    public void PostScore(float time)
    {
        Social.ReportScore((long)(time * 1000), IDs.LB, (bool success) => {
            if (success) Debug.Log("Post Success");
            else Debug.Log("Post Fail");
        });
    }

    public void ProgessiveAchievement(AchievementType type, int value)
    {
        if (type == AchievementType.PlayCount)
        {
            //TODO : 업적 상황 달성시 postAchievement(업적ID);
        }

        if(type == AchievementType.PlayTime)
        {
            //TODO : 업적 상황 달성시 postAchievement(업적ID);
        }
    }

    public void ShowLeaderboard()
    {
        Social.ShowLeaderboardUI();
    }

    public void ShowAchievement()
    {
        Social.ShowAchievementsUI();
    }


    private void postAchievement(string key)
    {
        if (PlayerPrefs.GetInt(key) == (int)AchievementState.UNLOCK) return;
        Social.ReportProgress(key, 100, (bool success) => {
            if (success)
            {
                PlayerPrefs.SetInt(key, (int)AchievementState.UNLOCK);
            }
        });
    }
}

// 업적 , 리더보드 ID Class
public class IDs
{
    public const string LB = ""; // 리더보드 ID
    //TODO : 업적 ID 추가.
}

public enum AchievementType
{
    PlayCount,
    PlayTime
}

public enum AchievementState
{
    LOCK,
    UNLOCK
}

2014년 9월 23일 화요일

Google Play Game Service for Unity In Android_Step1. GPGS Plugin 설치후 기본적인 셋팅


Notice.
 - 이전의 포스팅에서의 준비사항이 모두 준비된 상태에서 진행. (준비사항)
 - Developer console사용법등의 기타 방법은 자세하게 정리X


1. GPGS와 연동할 application 등록.
2.Game Service 또한 등록.
3.Game Service 등록시 출력되는 Application ID값 복사.
4.Unity 프로젝트에 Google Play Service Plugin Import후
메뉴바의 Google Play Services -> Android Setup 실행
위에서 복사해둔 ID값 입력 -> Setup 버튼 클릭

5. 이후 다시 Developer Conlose로 돌아와서
Game Service 메뉴의 업적 추가
기본적으로 최소 5개 이상으로 등록
e.g) 점수 xxx 이상 달성
플레이 횟수 x 회 이상 달성 등.

6. 게임에서 사용할 리더보드 또한 등록.
최소 1개 이상.

여기까지 진행했을경우 기본적으로 GPGS Plugin을 활용하여
업적,리더보드 기능을 활용할수 있게끔 셋팅이 완료된 상태이다.
Very Easy..
이후 리더보드,업적 활용법에 대해 정리하겠습니다.

2014년 9월 3일 수요일

Google Play Game Service for Unity In Android_Step0. Index & 준비 사항.



Summary.
 - Anroid & IOS App 작업진행시 각종 게임 관련 기능들을 제공해주는 플랫폼중 
가장 널리 알려진 Google play game service를 Unity에서 활용하는 기본방법 포스팅.
 - GPGS의경우 기본적은 리더보드 , 업적등의 기능 외에도 Multiplay, cloud game save 등의 기능까지 제공해주므로 여러가지 방면으로 유용한 플랫폼.

Requirements.
 - Unity 4.3 이상(only Pro)
 - Android SDK
 - Google Play Services library 4.2.42 이상 (SDK Manager에서 설치 가능)
 - Google Developer 계정(테스트용으로 진행할 App 등록)
 - GPGS Plugin 최신버전 - 다운로드 

Index
 -step 0 : 준비 사항
 -step 1 : GPGS Plugin 설치후 기본적인 요구사항 셋팅
 -step 2 : GPGS Plugin 활용을 위한 Manager Class 생성 후 사용



이번 포스팅은 여기까지 아주 기본적인 기능들면 정리할 생각 추후 멀티플레이 , 클라우드 게임 세이브 등의 기능도 정리 할 예정.