Spine Attachment Off 하는법 (어태치먼트 비활성화)


목적 : 스파인 내부의 일부 장비를 비활성화, 다양항 장비를 교체하는 효과를 낼 수 있다.



this.sprite.skeleton.findSlot('helmet0').setAttachment( null );

이런 방식으로 슬롯을 찾은뒤 어태치먼트를 null 로 설정한다.


setSkinByName을 사용하면 attachment가 다시 설정된다.

벽돌깨기 게임을 만드는 도중 공이 벽에 부딪혔을때 입사각, 반사각이 의도한대로 나오지 않는 현상이 있었다.


friction, restitution수치로 인한 현상이었는데


friction을 0, restitution을 1로 설정하면 의도한 수치대로 나왔다.


Material을 만든다음 각각 Object마다 다른 수치로 적용할수 있지만 이번에는 World의 DefaultMaterial을 수정해서 처리했다.


this.world.defaultContactMaterial.friction = 0;
this.world.defaultContactMaterial.restitution = 1;

이미 만든 world의 수치를 위와같이 변경하면 된다.

'프로그래밍 > JavaScript' 카테고리의 다른 글

Threejs repeat  (0) 2018.07.04
Spine Attachment Off  (0) 2018.06.20
HTML5 휴대폰 터치 처리  (0) 2018.04.12
HTML5 PixiJS, P2 물리엔진 적용 및 충돌 콜백 (collision callback)  (0) 2018.04.11
PIXI.js, box2d 적용  (0) 2018.04.03

Keyword : HTML touch event, input


마우스 클릭, 이동 기준으로 게임 생성후 모바일에서 게임 실행히 마우스 이벤트가 동작하지 않았다.

터치 이벤트로 따로 연결시켜줘야 했었다.

ECMA6 클래스 기준


window.addEventListener("touchstart", this.touchDown.bind(this), false);
window.addEventListener("touchend", this.touchUp.bind(this), false);
window.addEventListener("touchmove", this.touchMove.bind(this), false);

window에서 터치와 관련됨 이벤트는 touchstart, touchend, touchmove가 있다. mousedown, mouseup, mousemove와 같은 개념

바인딩된 함수는 touchDown만 살펴보면

touchDown(event){
this.touches = event.changedTouches;

this.touches[0].pageX, this.touches[0].pageY;
}

event의 changedTouches를 받은뒤

index마다 pageX, pageY를 확인하면 된다. (0번은 맨첫번째 터치, 터치를 여러 손가락으로 동시에 할경우 배열에 더 많이 담긴다.)

'프로그래밍 > JavaScript' 카테고리의 다른 글

Threejs repeat  (0) 2018.07.04
Spine Attachment Off  (0) 2018.06.20
p2 reflection angle (반사각) 설정  (0) 2018.04.13
HTML5 PixiJS, P2 물리엔진 적용 및 충돌 콜백 (collision callback)  (0) 2018.04.11
PIXI.js, box2d 적용  (0) 2018.04.03

Keyword : Pixijs, P2, Collision, Collision Callback, 


Box2D 적용이후 몬스터가 충돌을 감지했을때 HP를 깍으려고 시도했었다.

하지만 Box2D의 물리엔진 콜백 (Contact Listener ?)을 달기가 어려웠었다. (레퍼런스가 C++ 기준, 구현 방식도 원본과 다른상황)

이런 상황이라 엔진은 Box2D에서 P2로 교체했다.

ECMA6 을 이용한 클래스 기반으로 생성중이다.


<script src="library/P2/build/p2.js" type="text/javascript"></script>

index파일에 먼저 p2.js 파일을 포함, 로드시킨다.


this.world = new p2.World({
gravity:[0, 0]
});

this.world.solver.iterations = 20;
this.world.stiffness = 1000000;
this.world.relaxation = 4;
this.world.solver.tolerance = 0.02;
this.world.sleepMode = p2.World.NO_SLEEPING;

이후 world를 생성한다.

Gravity는 중력의 정도를 설정한다. (일반적으로 Y값에 -9.87 적용)

밑의 solver, relaxtion등의 설정은 필수는 아닌 옵션 설정이다.

충돌되기를 원하는 클래스에 Body와 Shape를 만들어 준다.


this.rigidBody = new p2.Body({
mass: 1,
position: [Device.app.screen.width / 2, Device.app.screen.height - 200]
});

유니티와 비슷하게 사용하기 위해 모든 변수명을 RigidBody로 설정

이후 충돌체의 모양을 결정한다.


this.circleShape = new p2.Circle({ radius: 20});
this.circleShape.collisionGroup = Device.PLAYER;
this.circleShape.collisionMask = Device.ENEMY | Device.GROUND;

이 코드의 경우에는 Collider를 원으로 설정했다.

collisionGroup과 collisionMask가 중요한데 이 부분을 설정하지 않는다면 모든 충돌체와 충돌검사를 수행한다.

이번에는 적, 바닥만 충돌처리를 하기 위해 MASK를 두 종류만 설정했다.


this.PLAYER = Math.pow(2, 0);
this.ENEMY = Math.pow(2, 1);
this.GROUND = Math.pow(2, 2);

collisionMask에 사용된 값은 위의 코드와 같이 정의되어 있다. (비트 연산을 수행하기 위해 2의 제곱으로 설정)


this.rigidBody.addShape(this.circleShape);

Shape의 설정이 마무리 됬으면 rigidBody에 AddShape 해준다.


this.world.addBody(rigidBody);

이후 맨처음 생성한 World에 rigidBody를 등록한다.


이렇게 까지 처리하면 화면에서 물체가 충돌되서 서로 반사되는 부분까지 확인이 가능하다. 

(확인이 안된다면 sprite의 x, y 좌표를 Update에서 rigidBody의 x, y 좌표로 업데이트 시켜준다.)


다음 물체끼리 충돌했을때 콜백으로 확인하고 싶다면


this.world.on('beginContact', this.BeginContact.bind(this) ); // << : Collision Callback

world의 on함수에 콜백을 등록한다. (beginContact는 충돌 시작시 콜백해주는 함수)


BeginContact(contact){
// Shape ID 대신 Body의 ID를 이용 (한개의 Body에 여러 Shape가 붙을수 있다.)
if( ( contact.shapeA.collisionGroup & contact.shapeB.collisionMask ) !== 0 && (contact.shapeB.collisionGroup & contact.shapeA.collisionMask) !== 0) // 다른 타입인지 검사
{
if(contact.shapeA.collisionGroup !== Device.GROUND && contact.shapeB.collisionGroup !== Device.GROUND) // 둘다 그라운드가 아닐때
{

contact.bodyA.parent.Collision();
contact.bodyB.parent.Collision();
// console.log("Collision Enemy && Player ");
}
}
}

위의 조건문을 이용해서 collisionGroup, collisionMask를 이용, 충돌하기를 원하는 대상들만 충돌처리를 실행할수 있다.

이벤트를 통해서 특정 함수를 실행해도 되고 

이번 코드의 경우 Body를 생성한뒤 parent에 this를 설정, 부모 클래스의 특정 함수를 실행시키는 방법으로 처리했었다.


이렇게 처리하면 Collision 발생시 특정 함수 실행 가능

'프로그래밍 > JavaScript' 카테고리의 다른 글

Threejs repeat  (0) 2018.07.04
Spine Attachment Off  (0) 2018.06.20
p2 reflection angle (반사각) 설정  (0) 2018.04.13
HTML5 휴대폰 터치 처리  (0) 2018.04.12
PIXI.js, box2d 적용  (0) 2018.04.03

ECMA6 기준으로 클래스에서 현재 물리를 구현중


1. b2CircleDef와 같이 Shape 정의를 먼저한다.


this.ballSd1 = new b2CircleDef();
this.ballSd1.density = 1.0;
this.ballSd1.radius = 20;
this.ballSd1.restitution = 0.2;
this.ballSd1.localPosition.Set(-20, 0);
this.ballSd2 = new b2CircleDef();
this.ballSd2.density = 1.0;
this.ballSd2.radius = 20;
this.ballSd2.restitution = 0.2;
this.ballSd2.localPosition.Set(20, 0);

2. 클래스의 Body에 Shape를 추가한다.

this.circleBd = new b2BodyDef();
this.circleBd.linearDamping = 0.01;
this.circleBd.angularDamping = 0.01;
this.circleBd.AddShape(this.ballSd1);
this.circleBd.AddShape(this.ballSd2);
this.circleBd.position.Set(Device.app.screen.width / 2, Device.app.screen.height / 2 + 100);

3. World에서 Body 생성


this.rigidBody = Device.gamestate.CreateBody(this.circleBd);

4. Sprite의 x, y 좌표는 body의 m_position x, y 를 계속 반영시킨다.

this.sprite.x = this.rigidBody.m_position.x;
this.sprite.y = this.rigidBody.m_position.y;

5. 물체에 힘을 주고 싶다면 SetLinearVelocity, SetAngularVelocity 2개의 방법이 있다.

Angular는 float을 인자로, Linear는 b2Vec (벡터2)를 인자로 받는다.

물체가 일정시간 움직이지 않으면 WakeUp 시켜야 한다. (WakeUp하지 않을경우 m_force는 바뀌지만 반영되지 않음)

this.rigidBody.WakeUp();
this.rigidBody.SetLinearVelocity(new b2Vec2(-100, -200));


유니티 (Unity) 에서 Android Studio 를 통해 최신 Android SDK를 설치, 빌드를 시도하면 빌드 마무리 쯤에 SDK Error가 발생합니다.


해당 문제는 2개의 해결 방법이 있습니다.


1. 안드로이드 SDK 중 tools 다운그레이드 


안드로이드 SDK 설치시 내부에 있는 tools 폴더를 버전 r25.2.5로 설치, 덮어쓰기 하면 정상적으로 빌드가 가능합니다.


2. AndroidManifest 파일 변경


유니티 프로젝트 탭에서 AndroidManifest 파일에 다음과 같은 코드를 추가합니다.


xmlns:tools="http://schemas.android.com/tools"


둘중 한가지 방법을 선택한뒤 정상적으로 빌드되는걸 확인할 수 있습니다.


GoogleVR등 Target API가 26이상일 경우 2번 방법을 추천드립니다.

Unity로 만든 게임을 휴대폰 APK로 빌드해서 실행 해보자.


Unity 설정변경 + NVIDIA Codeworks 에서 받은 파일을 설치, 빌드 할 예정이다.


유니티 메뉴중 File 메뉴 -> Build Settings 를 클릭한다.



빌드 설정을 변경하는 부분이다.


1. Scenes In Build (맨위 창) 에는 게임에 사용될 씬이 모두 있어야 한다. 만약 없다면 씬전환이 이루어 지지 않는다.

2. Platform에서 Android를 클릭한다.

3. 왼쪽 밑의 Switch Platform을 클릭하면 변환이 진행된다. 상당히 오래 걸린다.


만약 안드로이드를 눌렀는데 오른쪽 밑의 화면이 안뜬다면 ?

이 사진처럼 Open Download Page가 있을것이다. (예시는 IOS) Open Download Page클릭 한뒤 설치하면 된다.


변환이 모두 완료됬다면 https://developer.nvidia.com/codeworks-android 사이트로 이동한다.

다음과 같은 창이 뜰텐데 Download 녹색 버튼을 클릭한다.

오른쪽의 DOWNLOADS 밑의 녹색 글씨중 Windows ( 64-bit)를 클릭해서 다운로드 한다. (맥이면 맥으로 다운로드)

이때 NVIDIA 계정이 필요하다.

CodeWorksforAndroid-1R6-windows.z01

CodeWorksforAndroid-1R6-windows.zip

CodeWorksforAndroid-1R6-windows.z02


언제 까지 될진 모르겠는데 첨부파일을 다운로드 해도 된다.



실행하면 다음과 같은 창이 반겨준다. Next > 를 클릭하자.


여기서도 다음 클릭

설치 경로 와 임시 다운로드 경로 (PATH)를 설정해야 하는데 가급적 기본 설정 그대로 두는것을 추천한다. Next > 클릭

다음과 같은 화면이 뜨게 될텐데

어떠한 버전으로 빌드하느냐에 따라 설정이 달라진다.

내 핸드폰은 안드로이드 7.0이고 안드로이드 5.0이상에서만 실행할 생각이기 때문에 5.0 이전 버전은 설치를 안할 예정

설치를 안할 버전은 클릭해서 no action으로 변경해 주면 된다.

no action을 선택하면 다음과 같은 창이 뜨는데 Keep & Apply 클릭해주면 된다.

나는 다음과 같이 설정했다. 5.0이전 버전만 no action으로 선택하고 나머지는 그대로 두었다.


그다음 왼쪽 아래에 있는 Automatically resolve dependency conflicts 에 체크하고 설치하는게 편하다.

체크 안하면 확인확인 엄청 눌러줘야됨

Next 를 누르면 다음과 같은 창이 나온다.

Accept All 한뒤 Accept 버튼 누르면 된다. 어차피 체크 안하면 못씀

다운로드가 시작되면 용량이 상당하다. 전부 설치시 약 11기가를 차지한다고 설명에 나온다.

설치가 완료됬다면 재부팅 하라고 알림이 뜰텐데 재부팅 해주자


재부팅 이후 이제 Unity에서 Path (경로) 설정을 해주자


유니티 Edit 메뉴의 Preferences를 클릭한다.

External Tools 메뉴에 들어가면 SDK, JDK 경로가 빈칸인데 이 부분을 설정할 거다.

SDK 옆의 Brose버튼을 누르면

경로를 변경하지 않고 그대로 설치했다면

C드라이브 -> NVPACK -> android-sdk-windows 폴더를 선택하면 된다.


마찬가지로 JDK 옆의 Browse 버튼을 누른뒤

C드라이브 -> NVPACK -> jdk1.8.0_77 폴더를 선택해 주면 된다.

위 사진처럼 경로가 정상적으로 설정 됬으면 완료이다.


다음은 프로젝트 이름, 조직과 관련된 설정을 할것이다.


유니티 메뉴 File -> Build Settings에서 왼쪽 밑의 "Player Settings..." 버튼을 클릭해 보자.

오른쪽 인스펙터에 다음과 같은 창이 표시될 것이다.

Company Name은 조직명이다.

Product Name은 상품명이다. 일반적으로는 게임 이름이다.


밑의 Identification의 Package Name을 보면 com.Company.ProductName 이렇게 하는게 일반적이다.

(www.naver.com 이런 주소처럼 역순으로 com.회사이름.제품이름 이렇게 서술한다.)

이때 숫자를 맨 앞에 표기하거나 한글을 사용하지 않는다.

스크립트를 만들때 맨앞에 숫자를 사용해서 만들어 봤으면 알겠지만 정상적으로 동작하지 않는다.


Identification안의 메뉴중 Minimum API Level은 이 프로그램이 작동할 최소 버전을 선택하는 것이다.

나는 안드로이드 5.0 롤리팝 부터 지원하도록 5.0을 선택했다

이렇게 했으면 설정은 끝났다.


File -> Build Settings에서 Build 버튼을 클릭한다.

APK 파일명을 뭐로 할지 정해주고 저장을 누르면 빌드를 시작한다.

이 파일을 핸드폰에 넣어준뒤 설치해주면 휴대폰에서 실행할 수 있다.

'기타 > ETC' 카테고리의 다른 글

Unity Gradle Build 에러시  (0) 2018.07.02
API 에러창 띄우기  (0) 2017.04.20
size_t 란 무엇인가? C++  (0) 2017.04.09

자 모든 포트를 사용할수 있게는 했는데

외부와 내부의 연결이 되지 않은 상태이다.

선착장은 준비가 됬는데 뱃길이 뚫리지 않은 상황이라고 생각하면 될듯

그럼 이제 뱃길을 준비해 보자.

// >> : 포트를 열어두면 네트워크 공격이 들어올 수 있다. 자신이 사용할 포트만 연결시키자.


먼저 자신이 사용할 포트의 번호를 정해두는게 좋은데

1 ~ 1000 까지는 특수한 목적으로 사용되고 있다.

1001 ~ 30000내에서 자신이 사용할 포트를 정해보자.

나는 1234, 9090으로 사용했음


밑에 규칙이름 , 내부 IP주소, 외부포트, 내부포트를 설정한뒤 적용을 누르면

위에 3개처럼 등록이 된다.


규칙이름 : 자기가 구분하기 쉽게 설정하면 됨

내부 IP주소 : 현재 컴퓨터의 IP주소, 옆의 현재 접속된 IP 주소 체크하면 자동으로 설정된다.

외부 포트 : 밖에서 연결을 시도할때 사용할 포트번호

내부 포트 : 안에서 연결을 받을때 사용할 포트번호

나같은 경우에는 외부, 내부포트 같게 설정했다.

저렇게 한뒤 적용하면 동작한다.


통신사 공유기를 사용한다면

이런 화면에서 포트포워딩을 할수 있다.


DMZ 설정, 포트포워딩 과정을 끝냈다면 이제는 코딩으로 들어가서 테스트 해볼 시간


게임 프로그래밍을 하거나 다른 프로그램들을 짜다보면 "서버와 연결시켜서 해보고 싶다" 라는 생각을 자주 하게 된다.

나또한 이런 생각을 했었는데 책을 보면서 허겁지겁 했던거 같다.

책을 보면서 따라하기 전에 하드웨어적으로 설정을 해야 인터넷을 통해 서버가 제대로 동작했다. 이것부터 해보자.


먼저 컴퓨터에서 수신, 송신을 할때 다양한 포트를 사용하게 되는데 이때 DMZ가 설정이 안되있으면 연결이 안된다.

DMZ를 먼저 설정해보자.


1 >> : 인터넷 회사 공유기

나같은 경우엔 유플러스 인터넷을 사용하는데 공유기 설정 (보통 주소창에 IP로 입력)창을 들어가면 다음과 같은 화면이 나온다

여기서 밑의 공유기 사진에 >모양 버튼을 누르면 설정으로 진입할수 있다.

여기서 사용되는 패스워드는 대부분 공유기에 스티커로 붙어있다. 밑의 Code는 사진의 알파벳을 그대로 치면 됨

비밀번호를 입력후 들어가면 이런곳이 나온다.

1번째 방법 : 네트워크 설정 -> NAT 설정 -> DMZ 서버 (포트포워딩) 으로 가거나

2번재 방법 : 밑의 녹색 부분의 DMZ 서버의 >아이콘을 눌러서 들어간다.

그럼 이런창이 나오게 되는데

1 : DMZ 사용함을 켜서 자신의 컴퓨터 IP를 입력해 주는 방법이 있고

2 : Super DMZ를 이용해서 설정하는 방법이 있다.

근데 가정용 인터넷은 내부 IP도 유동적으로 잘변하기 때문에 Super DMZ 추천

Super DMZ 하면 이런창이 나오는데 여기서 맥주소 검색을 누른다.

그럼 다음과 같이 공유기에 연결된 기기들이 나오는데 여기서 서버로 돌릴 컴퓨터를 선택해야 한다.

어떻게 찾아야 하나 ??

"프로토콜"을 통해 찾아야 한다. 여기서 프로토콜은 맥주소임 (MAC 주소)

윈도우 + R키를 누른뒤에 cmd 친후 확인을 눌러서 콘솔창을 열어보자


그럼 이런창이 나오는데 여기에 ipconfig/all (사진처럼)를 친뒤 엔터를 누른다.

이런 목록이 엄청 나올텐데 대부분 컴퓨터는 리얼텍 아니면 인텔 LAN이다.

저기서 물리적 주소 (빨간 박스부분)이 "프로토콜"이다.

SuperDMZ 맥주소 검색에서 물리적 주소(MAC주소)가 같은걸 선택해 줘야한다.


내컴퓨터가 인터넷 공유기 + 다른 공유기를 통해서 컴퓨터와 연결된다면 ?

공유기의 MAC주소를 확인해야 한다.

이런식으로 맥주소를 확인해야 한다.

IP주소 쳐서 들어가는 거보다 그냥 공유기 회사 프로그램 깔아서 들어가는게 편함.

이렇게 Super DMZ설정을 하면 인터넷을 통해서 데이터를 주고 받을 준비는 끝났다.


2 >> : 기타 공유기 (IPTIME 등등)

인터넷 회사 공유기에 다른 공유기가 연결되어 있거나

자신의 공유기가 통신사 공유기가 아니라면 좀 다른 연결이 필요하다


이런 메뉴로 들어간뒤에 DMZ 설정을 해줘야 한다. 주소 적는칸 밑에 "현재 접속된 PC의 IP주소로 설정" 체크하면 편하다.


이렇게 하면 "모든 포트를 개방" 하는 "DMZ 설정"이 끝났다.


C++에서 게임을 만들다 보면

버튼을 눌렀을때 특정 행동을 수행해야 할때가 많다.

이때 싱글톤이나 이런거로 다 처리할수는 없기 때문에

Delegate (델리게이트)를 이용해서 처리하는게 좋다.

원래 이개념은 C++의 콜백함수에서 발전된 C#에서 만들어진 내용이다.

UIButton 클래스 위에 iButtonDelegate라는 클래스를 생성했다.

다음은 포인터로 생성했다.

(SYNTHESIZE는 매크로 함수로 사용하고 있는데 여기서는 iButtonDelegate* m_pDelegate를 만든거라고 이해하면 된다.

버튼을 생성할때 이렇게 자기자신의 주소를 넣어준다.

다음 해당 클래스 (cMainGame)에서 OnClick에 대해 이렇게 구현되어 있기 때문에 클릭하게 되면 OK로 바뀌면서 확인이라는 글씨가 출력된다.


요약 

1. OnClick이라는 가상함수를 가진 클래스를 만든다. 파라미터(인자)로 주소를 받게한다.

2. OnClick이라는 함수를 실행했을때 원하는 동작을 해당 클래스에 구현한다.

3. SetDelegate를 통해 자신의 주소를 넘겨주면 된다.

+ Recent posts