TortoiseGit 설치 디렉토리에 포함된 TortoiseGitProc.exe를 사용하면, 커맨드 프롬프트 혹은 타 스크립트 언어에서 TortoiseGit의 특정 기능을 실행하는 것이 가능하다.



1. 로그 보기


TortoiseGitProc /command:log /path:"작업 디렉토리 경로"


하지만 위 방법으로 로그창을 띄울 경우, 아직 fetch만 되고 아직 pull 되지 않은 로그를 보려면 왼쪽 위의 레퍼런스명을 누르고 선택된 레퍼런스를 변경해줘야 한다.


로그창을 띄울 때부터 레퍼런스가 변경되어 있기를 원하면, 아래와 같이 /endrev 옵션을 사용하여 적용할 레퍼런스를 지정하면 된다.


TortoiseGitProc /command:log /path:"작업 디렉토리 경로" /endrev:remotes/origin/head


추가) /endrev: 뒤에 들어가는 내용은 달라질 수 있으므로 수동으로 변경했을 때 실제로 나오는 내용으로 입력한다.



2. Commit

TortoiseGitProc /command:commit /path:"작업 디렉토리 경로"


3. Pull

TortoiseGitProc /command:pull /path:"작업 디렉토리 경로"


4. Push

TortoiseGitProc /command:push /path:"작업 디렉토리 경로"


이 외에도 더 많은 기능들이 실행 가능하지만, 자세한 내용은 Help 파일의 Automating TortoiseGit 파트를 참고하도록 하자.


테스트 버전 : TortoiseGit 1.8.8.0


,

start cmd /c 명령어


-> 실행한 커맨드가 종료되면 새로운 cmd 창도 종료된다



start cmd /k 명령어


-> 실행한 커맨드가 종료되도 새로운 cmd 창이 종료되지 않는다


,

./change_dir.sh


위와 같이 일반적인 방법으로 shell script를 실행하고 스크립트 내에서 cd 명령을 사용하면, 스크립트를 종료했을 때 현재 디렉토리는 원래대로 돌아와있다.


스크립트 내에서 변경한 현재 디렉토리가 유지되도록 하려면 아래와 같은 방법으로 실행해야 한다.


. change_dir.sh


대체적인 방법으로 .bashrc 파일 상에 alias를 등록하여 사용하는 방법도 있다.


alias change_dir='cd /path-to-dir'


,

Vertical BoxSizer에서 가로로 꽉 차게 컨트롤 추가하는 방법입니다.


class MyFrame(wx.Frame):

    def __init__(self):
        ...
        sizer = wx.BoxSizer(wx.VERTICAL)
        button = wx.Button(self, label = "Button 1", size = (-1, 50))
        sizer.Add(button, 0, wx.EXPAND | wx.ALL)
        ...


,



테스트 환경


  • 윈도우 7 (32비트)




기본 프로그램들


기본적인 안드로이드 앱 개발 환경(NDK 제외)은 구축되어있는 것으로 가정한다.


  • JDK (8u20)
  • Android ADT bundle + SDK (23.02, 20140702)




프로그램 버전 및 다운로드


1.  Cocos2d-x 2.2.5


2. Android NDK Revision 10


3. Cygwin (Cygwin DLL 1.7.32)





프로그램 설치



1. Cocos2d-x 2.2.5 / Android NDK


    • 원하는 위치에 압축을 푼다


2. Cygwin


    • setup-x86.exe (혹은  setup-x86_64.exe)를 실행하여 설치를 진행한다. 설치 과정 중 나머지는 default로 하여도 무방하나, 패키지 선택시 Devel 항목 밑에 make 패키지 옆에 Skip을 눌러 최신 버전이 표시되어 해당 패키지가 설치되도록 한다.



    • 설치 후, setup-x86.exe을 다시 실행하여 설치된 항목을 확인해보면, 아래와 같이 관련 패키지가 함께 설치되어 있는 것을 볼 수 있다.






환경 설정


  • NDK_ROOT 환경 변수를 추가하고, 압축 푼 Android NDK의 루트 경로(파일들이 존재하는 경로)를 그 값으로 입력한다.


-> 환경 변수 설정하는 방법







HelloCpp 샘플 프로그램 실행



1. 버그 수정


Cocos2d-x를 윈도우에서 빌드하다보면, 주 개발 환경이 Mac OS로 맞춰져있는 탓으로 보이는 몇가지 문제가 발생한다. 다음은 그 문제점 해결을 위한 작업이다.


<Cocos2d-x 설치 경로>/samples/Cpp/HelloCpp/proj.android 밑에 build_native.sh 파일을 텍스트 편집기로 열고, 마지막에 다음 명령을 추가한다.


chmod 777 -R "$APP_ANDROID_ROOT"/assets



이 작업을 하지 않는다면?




2. C++ 코드 컴파일


1) Cygwin을 실행 후, <Cocos2d-x 설치 경로>/samples/Cpp/HelloCpp/proj.android로 이동한다.

cd <Cocos2d-x 설치 경로>/samples/Cpp/HelloCpp/proj.android



2) build_native.sh를 실행한다.


./build_native.sh


이 과정을 통해, 앱 코드Cocos2d-x 라이브러리 코드 모두 빌드되며, <Cocos2d-x 설치 경로>/samples/Cpp/HelloCpp/Resouces 밑에 있는 리소스 파일들이 <안드로이드 프로젝트 폴더>/assets로 복사된다.



3. 안드로이드 앱 빌드


1) Eclipse를 실행한다.


2) 다음 두 위치에서 프로젝트를 import한다.


<Cocos2d-x 설치 경로>/cocos2dx/platform/android/java

<Cocos2d-x 설치 경로>/samples/Cpp/HelloCpp/proj.android



3) HellopCpp 프로젝트의 속성을 열고, C/C++ Build 항목을 선택하고, build command의 내용을 cmd로 바꿔준다.



관련 에러: Cannot run program "bash": Launching failed



4) libcocos2dx -> HelloCpp 프로젝트 순으로 빌드한다.


5) 빌드된 앱을 실행하면 다음과 같은 샘플 프로그램을 볼 수 있다. 애뮬레이터(AVD)에서 실행할 경우에, 애뮬레이터 속성 중 Use Host GPU 옵션이 켜져있어야 한다.







[참고] Cocos2d-x 샘플 프로그램의 폴더 구조


,

프로그램 버전 및 다운로드

  1.  Cocos2d-x 2.2.5


    다운로드 : http://www.cocos2d-x.org/download


    -> Download v2.2.5 버튼을 눌러 다운로드한다


  2. Visual C++ 2010 express


    다운로드 : http://www.visualstudio.com/ko-kr/downloads/download-visual-studio-vs#DownloadFamilies_4





프로그램 설치

  1. Cocos2d-x 2.2.5


    -> 원하는 위치에 압축을 푼다


 
  2. Visual C++ 2010 express


    -> vc_web.exe를 실행하여 설치를 진행한다





샘플 프로그램 실행


  1. Visual C++ 2010 express를 실행한다
 
  2. 파일 - 열기 - 프로젝트/솔루션 메뉴를 선택한 뒤, 다음 위치의 솔루션 파일을 연다
 
    -> cocos2d-x-2.2.5\cocos2d-win32.vc2010.sln


  3. 왼쪽 솔루션 탐색기에서 HelloCpp 프로젝트(가장 기본적인 내용이 들어있는 샘플 프로젝트이다)를 오른쪽 클릭 후, '시작 프로젝트로 설정'을 선택한다.
 
  4. HelloCpp 프로젝트를 오른쪽 클릭 후, 빌드를 실행한다. (나머지 라이브러리들은 종속성에 따라 자동 빌드된다)

※ 빌드 중 "COFF로 변환하는 동안 오류가 발생했습니다" 에러가 발생할 경우, HelloCpp 프로젝트 속성 페이지에 들어가서, 구성 속성 -> 매니페스트 도구 -> 입력 및 출력 밑에 있는 매니페스트 포함 항목을 아니오로 바꾼다.



  5. 디버그 - 디버그 시작을 선택하거나, Ctrl+F5를 누르면, 아래와 같은 샘플 프로그램이 실행되는 것을 볼 수 있다.



 
  6. HelloCpp 프로젝트 대신에 TestCpp 프로젝트를 선택하면 Cocos2d가 지원하는 좀더 많은 기능이 들어간 샘플 프로그램을 볼 수 있다.



,

import pygame
from pygame.locals import *
from Box2D import *
from Box2D.b2 import *

SCREEN_WD = 640
SCREEN_HT = 480
TARGET_FPS = 60
PPM = 20.0

screen = pygame.display.set_mode((SCREEN_WD, SCREEN_HT), 0, 32)
pygame.display.set_caption("PyBox2D_Example")
clock = pygame.time.Clock()

world = b2World(gravity = (0, 0), doSleep = True)

ground1BodyDef = b2BodyDef()
ground1BodyDef.position.Set(0, 0)
ground1Body = world.CreateBody(ground1BodyDef)
ground1Shape = b2PolygonShape()
ground1Shape.SetAsBox(50, 1)
ground1Body.CreateFixture(shape = ground1Shape)

box1BodyDef = b2BodyDef()
box1BodyDef.type = b2_dynamicBody
box1BodyDef.position.Set(16, 20)
box1Body = world.CreateBody(box1BodyDef)
box1Shape = b2PolygonShape()
box1Shape.SetAsBox(1, 1)
box1FixtureDef = b2FixtureDef()
box1FixtureDef.shape = box1Shape
box1FixtureDef.density = 1
box1FixtureDef.friction = 0.3
box1Body.CreateFixture(box1FixtureDef)

box2BodyDef = b2BodyDef()
box2BodyDef.type = b2_dynamicBody
box2BodyDef.position.Set(16, 15)
box2Body = world.CreateBody(box2BodyDef)
box2Shape = b2PolygonShape()
box2Shape.SetAsBox(1, 1)
box2FixtureDef = b2FixtureDef()
box2FixtureDef.shape = box2Shape
box2FixtureDef.density = 1
box2FixtureDef.friction = 0.3
box2Body.CreateFixture(box2FixtureDef)

jointDef = b2PrismaticJointDef()
worldAxis = b2Vec2(0, 1.0)
jointDef.Initialize(box1Body, box2Body, box1Body.worldCenter, worldAxis)
jointDef.lowerTranslation = -5.0
jointDef.upperTranslation = 2.5
jointDef.enableLimit = True
jointDef.maxMotorForce = 1.0
jointDef.motorSpeed = 0
jointDef.enableMotor = True
prismaticJoint = world.CreateJoint(jointDef)

timeStep = 1.0 / 60
velIters = 10
posIters = 10

colors = {
    staticBody  : (255,255,255,255),
    dynamicBody : (127,127,127,255),
}

def my_draw_polygon(polygon, body, fixture):
    vertices=[(body.transform*v)*PPM for v in polygon.vertices]
    vertices=[(v[0], SCREEN_HT-v[1]) for v in vertices]
    pygame.draw.polygon(screen, colors[body.type], vertices)
polygonShape.draw=my_draw_polygon

def my_draw_circle(circle, body, fixture):
    position=body.transform*circle.pos*PPM
    position=(position[0], SCREEN_HT-position[1])
    pygame.draw.circle(screen, colors[body.type], [int(x) for x in position], int(circle.radius*PPM))
circleShape.draw=my_draw_circle

prismaticJoint.__SetMotorSpeed(15)

running = True
while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
            continue
        if event.type == KEYDOWN and event.key == K_ESCAPE:
            running = False
            continue

    screen.fill((0, 0, 0, 0))

    for body in world.bodies:
        for fixture in body.fixtures:
            fixture.shape.draw(body, fixture)
                     
    world.Step(timeStep, velIters, posIters)
    pygame.display.flip()
    clock.tick(TARGET_FPS)

pygame.quit()
print("done")


[Python] pyBox2D 사용 예제 - 9. Prismatic Joint

Prismatic Joint는 두개의 body를 가변 가능한 길이로 연결하는데, 마치 유압 실린더와 같은 역활을 합니다.


아래의 코드로 가동 범위를 설정한 후에,

jointDef.lowerTranslation = -5.0
jointDef.upperTranslation = 2.5
jointDef.enableLimit = True


움직일 속도를 세팅합니다.

prismaticJoint.__SetMotorSpeed(15)


,

import pygame
from pygame.locals import *
from Box2D import *
from Box2D.b2 import *

SCREEN_WD = 640
SCREEN_HT = 480
TARGET_FPS = 60
PPM = 20.0

screen = pygame.display.set_mode((SCREEN_WD, SCREEN_HT), 0, 32)
pygame.display.set_caption("PyBox2D_Example")
clock = pygame.time.Clock()

world = b2World(gravity = (0, 0), doSleep = True)

ground1BodyDef = b2BodyDef()
ground1BodyDef.position.Set(0, 0)
ground1Body = world.CreateBody(ground1BodyDef)
ground1Shape = b2PolygonShape()
ground1Shape.SetAsBox(50, 1)
ground1Body.CreateFixture(shape = ground1Shape)

box1BodyDef = b2BodyDef()
box1BodyDef.type = b2_dynamicBody
box1BodyDef.position.Set(16, 12)
box1Body = world.CreateBody(box1BodyDef)
box1Shape = b2PolygonShape()
box1Shape.SetAsBox(4, 0.25)
box1FixtureDef = b2FixtureDef()
box1FixtureDef.shape = box1Shape
box1FixtureDef.density = 1
box1FixtureDef.friction = 0.3
box1FixtureDef.categoryBits = 0x02
box1FixtureDef.maskBits = 0x04
box1Body.CreateFixture(box1FixtureDef)

circle1BodyDef = b2BodyDef()
circle1BodyDef.type = b2_dynamicBody
circle1BodyDef.position.Set(16, 12)
circle1Body = world.CreateBody(circle1BodyDef)
circle1Shape = b2CircleShape()
circle1Shape.radius = 1
circle1FixtureDef = b2FixtureDef()
circle1FixtureDef.shape = circle1Shape
circle1FixtureDef.density = 1
circle1FixtureDef.friction = 0.3
circle1FixtureDef.categoryBits = 0x04
circle1FixtureDef.maskBits = 0x02
circle1Body.CreateFixture(circle1FixtureDef)

jointDef = b2RevoluteJointDef()
jointDef.Initialize(box1Body, circle1Body, circle1Body.worldCenter)
jointDef.collideConnected = False
jointDef.lowerAngle = 0
jointDef.upperAngle = 0
jointDef.enableLimit = False
jointDef.maxMotorTorque = 10
jointDef.motorToque = 0
jointDef.motorSpeed = 0
jointDef.enableMotor = True
revoluteJoint = world.CreateJoint(jointDef)
print(revoluteJoint)

timeStep = 1.0 / 60
velIters = 10
posIters = 10

colors = {
    staticBody  : (255,255,255,255),
    dynamicBody : (127,127,127,255),
}

def my_draw_polygon(polygon, body, fixture):
    vertices=[(body.transform*v)*PPM for v in polygon.vertices]
    vertices=[(v[0], SCREEN_HT-v[1]) for v in vertices]
    pygame.draw.polygon(screen, colors[body.type], vertices)
polygonShape.draw=my_draw_polygon

def my_draw_circle(circle, body, fixture):
    position=body.transform*circle.pos*PPM
    position=(position[0], SCREEN_HT-position[1])
    pygame.draw.circle(screen, colors[body.type], [int(x) for x in position], int(circle.radius*PPM))
circleShape.draw=my_draw_circle

revoluteJoint.__SetMotorSpeed(15)

running = True
while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
            continue
        if event.type == KEYDOWN and event.key == K_ESCAPE:
            running = False
            continue

    screen.fill((0, 0, 0, 0))

    for body in world.bodies:
        for fixture in body.fixtures:
            fixture.shape.draw(body, fixture)
                     
    world.Step(timeStep, velIters, posIters)
    pygame.display.flip()
    clock.tick(TARGET_FPS)

pygame.quit()
print("done")


[Python] pyBox2D 사용 예제 - 8. Revolute Joint



Revolute Joint는 하나의 축을 중심으로 두개의 body 사이에 회전 운동을 가능하게 하는 연결입니다.


위 코드는 사각형과 원을 revolute joint로 연결한 후에, 사각형을 일정한 속도로 회전하도록 하는 예제 코드입니다.


,