안녕하세요. 호랑인 입니다.



이번 포스팅은 쉽습니다. 저번 포스팅이 조금 많은 내용을 우겨넣은 듯한 감이 없지 않아 있었는데, 한 가지 정말 다행인 점은 저 부분은 앞으로 거의 모든 앱을 만드는데에 있어서 필수적이고 공통적인 부분이라는 점입니다.



우선 저번에 만들었던 두개의 함수인 draw( ) 와 update( ) 를 만들어 봅시다.



당장은 draw( ) 부터 만들겠습니다. 업데이트를 할 그림이 우선 있어야 하니까요.




1
2
3
4
5
6
7
8
9
10
    @Override
    public void draw(Canvas canvas){
        super.draw(canvas);
        if(canvas != null){
            canvas.drawColor(Color.WHITE);
            Paint paint = new Paint();
            paint.setColor(Color.rgb(25000));
            canvas.drawRect(00100100, paint);
        }
    }
cs



위의 코드를 넣어봅시다. 코드는 크게 두 가지 역할을 갖고 있습니다.


1. canvas.drawColor(Color.WHITE) 는 배경을 하얗게 칠해줍니다.


2. Paint object를 하나 만들어줍니다. 이는 어떤 object (Rectangle, Circle 등등)에 색을 입힐 때 사용합니다.


3. Paint object에 색을 입력해줍니다. 저는 빨간색을 넣어줬습니다. 색은 rgb (alpha도 추가 가능) 을 넣어줄 수 있습니다.


4. canvas.draw... 까지만 치시면 다양한 함수들과 그 overriding 이 보이실 겁니다. 일단 slide라는 앱은 가장 단순한 앱을 만드는 것이 목적이므로, drawRect 를 씁니다.


drawRect 함수는 왼쪽위의 x, y, 오른쪽 아래의 x, y, 마지막으로 paint object를 input으로 받습니다.




자, 여기까지 하셨으면, 이제 빨간 사각형이 하나 나왔을 것입니다. 이제 이걸 움직여봅시다.



객체를 움직이는 등의 활동을 할 때에 사용하는 것이 바로 update 함수입니다. 이 함수를 통해 이 다음 frame 에서는 어떤 변화가 만들어져야 하는지를 계산합니다.


하.지.만 이 전에 android 에서의 좌표계를 아셔야 합니다.




그림으로 그릴 필요조차 없이 간단합니다. 왼쪽 위가 (0,0) 입니다. 그리고 오른쪽이 +x, 아래쪽이 +y 입니다. 아래쪽이 +y이라는 점이 가끔 헷갈려서 문제가 자주 발생합니다. (혼천의 앱에서 북극성이 아래쪽에 나타났었던 현상이 바로 이 예입니다.)




이제 update 함수를 만들어봅시다.



만들기에 앞서, 이 GameView object에 상자의 위치를 저장할 변수를 만들어 줍시다. 상자의 크기도 말이죠.



1
2
3
4
5
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
 
    private int x;
    private int y;
    private int box_size;
cs



그리고 이들을 초기화 해주어야죠. (생성자에 추가)



1
2
3
4
5
6
7
8
    public GameView(Context context){
        super(context);
        getHolder().addCallback(this);
        thread = new MainThread(getHolder(), this);
 
        x = 0;
        y = 0;
        box_size = 100;
cs




자, 우선 update 함수를 아래와 같이 만들어 봅시다.



1
2
3
4
    public void update(int width, int height){
        x += 1;
        y += 1;
    }
cs



그리고 실행 시켜 보시면, 상자가 오른쪽 아래로 이동할 껍니다.



슬슬 게임 같아 지지 않나요?


----------------------------------------------------------------------------------------



원래 여기에서 마치려 했지만, 조금 더 추가하도록 하겠습니다.



현재 완성된 "게임"을 보면, 뭔가 아쉬운 부분이 딱 보입니다. 바로, 상자가 화면 밖으로 나간 뒤에는 아무것도 없다는 점입니다. 이를 보완해보죠. 단순하게, 튀겨 다니게 하는 걸 만들고, 이번 포스팅을 마치도록 하겠습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
 
    private final int MAX_TOUCH_COUNT = 100000;
    private MainThread thread;
 
    private int x;
    private int y;
    private float vel_x;
    private float vel_y;
    private int box_size;
 
    private int VIEW_WIDTH;
    private int VIEW_HEIGHT;
cs




변수를 조금 추가했습니다. 생성자 초기화도 해주세요 ~!


vel_x, vel_y 는 상자의 x 방향과 y 방향 속도를 저장하는 데에 쓰일 것입니다. 왜냐하면, 튀긴 다음에는 속도가 바귀어야 하기 때문이죠. 한 가지 말씀드리자면, vel_x, vel_y 는 10 정도로 초기화하는 것이 예쁩니다.


VIEW_WIDTH, VIEW_HEIGHT 는 화면 크기를 저장하는데에 사용될 것입니다.



이제, 벽에 튀기는 연산을 해주는 함수를 만들어 봅시다. 직사각형이기 때문에 매우 간단한데요, x 좌표, y 좌표, 상자 크기, WIDTH, HEIGHT 값을 사용해서 다음과 같이 설정해주시면 됩니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public void check_boundary(){
        if(this.x >= this.VIEW_WIDTH-this.box_size){
            this.x = this.VIEW_WIDTH - this.box_size;
            this.vel_x = - this.vel_x;
        }
        if(this.y >= this.VIEW_HEIGHT-this.box_size){
            this.y = this.VIEW_HEIGHT - this.box_size;
            this.vel_y = - this.vel_y;
        }
        if(this.x <= 0){
            this.x = 0;
            this.vel_x = - this.vel_x;
        }
        if(this.y <= 0){
            this.y = 0;
            this.vel_y = - this.vel_y;
        }
    }
cs



내용을 보면, x 나 y 좌표가 0보다 작으면, 왼쪽이나 위의 벽에 부딪힌 것이므로, 속도의 방향을 뒤집고, 그 반대일 때에도 그리하라는 내용입니다. 주의하실 점은 오른쪽과 아래의 벽은 상자의 크기를 고려하셔야 한다는 점입니다.


또한, 이 경우 this. 은 모두 다 빼셔도 문제 없을 것입니다. python 코딩하던 습관이 나와버린 것이니, 무시해주세요.



위의 함수를 update() 함수에서 실행하면 됩니다.



1
2
3
4
5
6
7
    public void update(int width, int height){
        VIEW_WIDTH = width;
        VIEW_HEIGHT = height;
        x += vel_x;
        y += vel_y;
        check_boundary();
    }
cs



위처럼, this. 부분은 생략하셔도 됩니다.



자, 이제 통통 튀어다니는 사각형을 만들었습니다 ! (와아아아아)



이제 곰곰히 생각을 보십쇼. 창의력이 중요해지는 순간입니다. 여러분은 이제 뭘 할 수 있나요?



1. 많은 종류의 다각형을 원하는 크기로 그릴 수 있습니다.


2. 다각형에게 원하는 색을 줄 수 있고, 이를 시간에 따라 바꿀 수 있습니다.


3. 다각형의 크기를 원하는 데로 바꿀 수 있습니다.


4. 다각형의 운동을 변화시킬 수 있으며, 특히나 가장자리와의 충돌을 조절할 수 있습니다.




이것만으로도 거의 모든 것을 만들 수 있습니다. 하지만, 분명히 더 필요한 능력들이 존재합니다.



1. 사용자의 입력을 받을 수가 없습니다. - 터치, 키보드 등


2. 사진을 넣고 싶으면, 이를 다각형으로 그려야 하나요? (당연하지만 아닙니다.)


3. 소리를 넣고 싶습니다.



위의 "하지 못하는 것들" 은 차차 다루겠지만, 보시다시피 이제 남은 것은 상상력 뿐입니다. slide 게임의 미래를 결정하는 것은 당신의 상상력 하나에 모든 것이 걸려 있습니다.



1. 색이 변하는 것을 예쁘게 하고 싶다. 배경색도 같이 변화시켜서 예쁘게 하자. - 요새 뜨는 디자인 좋은 게임들의 기초.


2. 터치를 통해 원하는 방향으로 토스하면서 놀자 - 에어 하키와 같은 게임의 기초, objective를 넣어서 게임성을 더 살릴 수도 있음.


3. 크기를 키우거나, 더 많은 다각형을 쉽게 그리고 놀 수 있게 하자 - 그림판의 기초


4. 이것으로 물건을 부수고, 중력 효과 등을 넣어보자 - 앵그리버드의 기초



등등 여러분은 모든 것을 할 수 있습니다. 대신 좋은 아이디어를 낼 사람, 그림을 그릴 사람 등 많은 사람이 필요로 합니다.



실제로 이 draw() 기능을 어떻게 활용하는지 궁금하시다면 여기로 가주세요.





결론: 창의력이 가장 중요하다. 하지만 인맥이 없으면, 이 또한 부질 없다. 코딩 실력은 그저 부수적인 것일 뿐이다.



감사합니다. 이만 줄이겠습니다.

안녕하세요. 호랑인 입니다.



오늘은 저번에 만든 앱에 블루투스를 연결해 볼 것입니다.



우선, 나중에 안드로이드 개발에 대해 정리할 때에도 말하겠지만, MSDN과 비슷하게 안드로이도 Android Developers 라는 사이트가 존재해서, 이 사이트를 통해 안드로이드 개발에 대한 거의 모든 것을 배울 수 있습니다. 물론 Kotlin과 같은 다른 부수적인 것을 통해 더 쉽고 간편하게, 예쁜 것을 할 수도 있지만, 우선 당장 어떤 동작하는 앱을 만들어야 하는 상황이라면, 정말 그 어떤 기초지식 없이도 시작하실 수 있습니다.



우선 당장 저만 봐도


1. 한번도 자바를 배운적이 없으며 (약간의 함정이 있다면 C#을 독학한 적이 있습니다.)


2. 안드로이드 개발은 Gingerbread 때 (갤럭시 S2가 최신폰이었던 시절...) 한두번 했던 것 이후로 이번이 처음입니다. 그 때 만든 앱이라 해봤자 버튼 누른 횟수만큼 숫자 커지는 앱? 뭔가 당연한 예제 한 두개 만들어 봤었습니다.



그렇기 때문에 이 글을 읽는 모두 안드로이드 앱을 만드는 것을 할 수 있다는 자신감을 가지고 임해주셨으면 좋겠습니다. 앱을 구현하는 코딩은 정말 누구나, 3일 배우면 얼추 할 수 있습니다. 제일 중요한 것은 어떤 앱을 만들지에 대한 구상입니다. 이 구상이 얼마나 참신한가, 얼마나 유익한가, 얼마나 세세한 디테일을 담아내는가가 앱의 품질을 결정합니다. 물론 저처럼 당장 어떤 정해진 일을 수행하기 위한 앱을 만드는 상황이 아니라면 말이죠.



그래서, Android Developers 에서 제공한 블루투스 연결 코드를 우선 그대로 가지고 와 봤습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
private class ConnectThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;
 
    public ConnectThread(BluetoothDevice device) {
        // Use a temporary object that is later assigned to mmSocket,
        // because mmSocket is final
        BluetoothSocket tmp = null;
        mmDevice = device;
 
        // Get a BluetoothSocket to connect with the given BluetoothDevice
        try {
            // MY_UUID is the app's UUID string, also used by the server code
            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
        } catch (IOException e) { }
        mmSocket = tmp;
    }
 
    public void run() {
        // Cancel discovery because it will slow down the connection
        mBluetoothAdapter.cancelDiscovery();
 
        try {
            // Connect the device through the socket. This will block
            // until it succeeds or throws an exception
            mmSocket.connect();
        } catch (IOException connectException) {
            // Unable to connect; close the socket and get out
            try {
                mmSocket.close();
            } catch (IOException closeException) { }
            return;
        }
 
        // Do work to manage the connection (in a separate thread)
        manageConnectedSocket(mmSocket);
    }
 
    /** Will cancel an in-progress connection, and close the socket */
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) { }
    }
}
cs


만약 정말 급하다면, 그냥 이 코드 쓰세요. 어케 쓰는지 감이 1도 안오신다고요? 우선 마음을 차분히 갖고 코드를 봅시다.


우선, Thread 를 Extend 하는, 나만의(?)블루투스 연결 Thread 입니다. 일반적인 Thread와 마찬가지로, 결국 run() 함수를 통해 시행하게 됩니다.



나머지 설명은 사실 전부 주석에 적혀 있습니다. try와 catch문으로 가능한 문제 사항을 훌륭하게 처리해 놓은 코드입니다. 저희가 건들여야 하는 부분은 정말 간단한데요, 보면 마지막에 manageConnectedSocket이란 함수가 호출되었지만, 정의 되지 않았습니다. 저 함수를 정의해서, 원하는 행동을 하게 하면 되는 것입니다.



저는 그래서 ListView에 나타난 페어링된 기기 목록에서 눌린 기기와 연결을 하게 만들었습니다.





연결이 되었습니다. 아래에 뜨는 팝업 메세지는 Toast 라고 하는 것입니다. 이 또한 Android Developers에 잘 설명되어 있으니, 한번 보세요 ^^





위의 페널에서도 K11 이라는 장치와 연결되었다고 나타납니다. 이거 왜 굳이 앱을 통해서 하냐, 그냥 블루투스 설정 들어가서 연결하면 되는 거 아니냐 하실 수 있는데요, 저는 이것을 나중에 브레드보드와 연결할 것이기 때문에 제가 원하는 데로 Stream 을 보낼 수 있는 Socket을 필요로 하기 때문에 이렇게 하는 것입니다. 같은 이유로 사실 이 연결을 통해서는 음악을 실핼시킬 수 없습니다. 음악기기로 연결하는 모드가 따로 있고, 무엇보다 음악 앱으로 들어가는 순간 제 앱은 휴면 모드가 되기 때문에 (물론 막을 수는 있지만) 연결이 끊깁니다.




오늘은 블루투스를 연결했습니다. 다음에는 이제 혼천의와 관련된 일을 이 앱에 할 것입니다. 드디어 본격적인 앱 개발에 들어가겠습니다.

안녕하세요. 호랑인 입니다.



오늘은 간만에 할 숙제가 없어서 프로젝트에 시간을 마음껏 할애할 수 있었습니다.




덕분에 어플리케이션을 만들기 시작했는데요, 이 어플리케이션은 혼천의의 움직임을 제어하는 핵심 부분이 될 것입니다. 크게 하는 일은 3 가지 정도입니다.


1. 아두이노와 휴대폰을 연결한다.

2. 현재의 시간 데이터를 통해 시간축이 얼마나 회전해야 하는지 계산하고, 이를 아두이노에게 송신한다.

3. 원하는 별을 데이터 베이스에서 검색해서 이것의 위치를 아두이노에게 송신한다.



그리하려 가장 기본적인 뼈대를 만들어보았습니다. 사실 안드로이드 어플리케이션을 만들어보는 것이 처음일 뿐더러, java 언어를 사용해보는 것도 처음이라 조금 힘들었지만, 본래 C#을 다뤄봤던 경험 때문인지 java 언어 자체에 의한 힘듦은 조금 덜 했던 것 같습니다.



안드로이드 개발을 위한 정보는 나중에 내용정리 쪽에 따로 포스팅을 할 것 같습니다. 여기는 언제까지나 프로젝트 게시판이기 때문이죠.



가장 먼저 해야 하는 것은 당연히 프로젝트를 만들고, 디자인을 하는 것입니다.






위는 제가 디자인한 앱의 시작 화면입니다. 여백이 많은 이유는 아직 디자인이 다 끝나지 않은 탓입니다.



기본적인 구성은 위와 같고요, 제일 위에 있는 CONNECT 버튼을 사용해서 아두이노와 연결을 할 생각입니다.





그러면, 블루투스를 연결할 수 있게 만들어야 겠죠?





우선 위의 사진처럼 manifest 파일을 통해 블루투스 권한을 줍시다.





그리고 당연히 블루투스가 연결되는 화면을 만들어야 하겠죠? 잘 보시면, 위의 바(bar)에 뒤로가기 모양 아이콘이 있는 것을 볼 수 있는데요, 이는 제가 블루투스를 연결하는 Activity를 Main Activity의 child 로 설정을 했기 때문입니다.


즉, Main Activity와 BlueToothConnection Activity 라는 두 Activity 를 별개가 아닌, Main Activity 아래에 다른 하나가 있게 했다는 것이죠. 따라서, 블루투스 연결 창에서 할일이 다 끝나고 나서 뒤로가기를 누르거나 위에 있는 뒤로가기 버튼을 누르면, 다시 상위에 있는 Main Activity로 이동하게 됩니다.



이렇게 두번째 Activity 에는 페어링 된 기기들의 목록이 뜰것이고, 이를 눌러 연결할 수 있게 만들것입니다.


다음에는 블루투스를 연결해봅시다.


+ Recent posts