Java로 첫 번째 Android 게임을 작성하는 방법

작가: John Stephens
창조 날짜: 1 1 월 2021
업데이트 날짜: 19 할 수있다 2024
Anonim
Java로 첫 번째 Android 게임을 작성하는 방법
동영상: Java로 첫 번째 Android 게임을 작성하는 방법

콘텐츠


Android 용 게임을 만드는 방법에는 여러 가지가 있으며 한 가지 중요한 방법은 Java를 사용하여 Android Studio에서 처음부터 새로 만드는 방법입니다. 이를 통해 게임의 모양과 동작 방식을 최대한 제어 할 수 있으며, 프로세스는 앱의 스플래시 화면을 만들 든, 아니면 원하는 다른 시나리오에서도 사용할 수있는 기술을 가르쳐줍니다. 애니메이션을 추가하십시오. 이를 염두에두고이 튜토리얼에서는 Android Studio 및 Java를 사용하여 간단한 2D 게임을 만드는 방법을 보여줍니다. 따라하고 싶다면 Github에서 모든 코드와 리소스를 찾을 수 있습니다.

설정

게임을 만들려면 게임 루프, 스레드 및 캔버스와 같은 몇 가지 특정 개념을 처리해야합니다. 우선 Android Studio를 시작하십시오. 설치하지 않은 경우 설치 과정을 거치는 Android Studio에 대한 전체 소개를 확인하십시오. 이제 새 프로젝트를 시작하고 '빈 활동'템플릿을 선택하십시오. 이 게임은 물론 FAB 버튼과 같은 요소가 필요하지 않습니다.

가장 먼저하고 싶은 일은 AppCompatActivity활동. 이는 작업 표시 줄 기능을 사용하지 않음을 의미합니다.

마찬가지로 게임을 전체 화면으로 만들고 싶습니다. setContentView ()를 호출하기 전에 다음 코드를 onCreate ()에 추가하십시오.

getWindow (). setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); this.requestWindowFeature (Window.FEATURE_NO_TITLE);

일부 코드를 작성하고 빨간색으로 밑줄이 표시되면 클래스를 가져와야 할 수도 있습니다. 즉, 특정 문장을 사용하고 사용 가능하게하려면 Android Studio에 알려야합니다. 밑줄이 그어진 단어의 아무 곳이나 클릭 한 다음 Alt + Enter를 누르면 자동으로 완료됩니다!


게임 뷰 만들기

버튼, 이미지 및 레이블과 같은보기의 레이아웃을 정의하기 위해 XML 스크립트를 사용하는 앱에 익숙 할 수 있습니다. 이것이 라인입니다 setContentView 우리를 위해하고 있습니다.

다시 말하지만 이것은 브라우저 창이나 스크롤 리사이클 뷰가 필요하지 않은 게임입니다. 그 대신 캔버스를 대신 표시하려고합니다. Android Studio에서 캔버스는 예술에서와 동일합니다. 캔버스는 우리가 그릴 수있는 매체입니다.

따라서 해당 줄을 다음과 같이 변경하십시오.

setContentView (새로운 GameView (this))

이 부분은 다시 빨간색 밑줄로 표시됩니다. 그러나 지금 Alt + Enter를 누르면 수업을 가져올 수있는 옵션이 없습니다. 대신, 당신은 옵션이 있습니다 몹시 떠들어 대다 수업. 다시 말해, 캔버스에서 어떤 일을할지 정의 할 클래스를 만들려고합니다. 바로 기성품보기 만 표시하는 대신 화면에 그릴 수 있습니다.

왼쪽의 계층 구조에서 패키지 이름을 마우스 오른쪽 버튼으로 클릭하고 신규> 수업. 이제 수업을 만들 수있는 창이 표시되며 전화 할 것입니다. GameView. 수퍼 클래스에서 다음과 같이 작성하십시오. android.view.SurfaceView 이는 클래스가 SurfaceView에서 메서드 (기능)를 상속한다는 의미입니다.

인터페이스 상자에 android.view.SurfaceHolder.Callback. 다른 클래스와 마찬가지로 이제 생성자를 만들어야합니다. 이 코드를 사용하십시오 :


개인 MainThread 스레드; 공개 GameView (컨텍스트 컨텍스트) {super (context); getHolder (). addCallback (this); }

클래스가 새로운 객체 (이 경우 표면)를 만들기 위해 호출 될 때마다 생성자를 실행하고 새로운 표면을 만듭니다. ‘super’행은 수퍼 클래스를 호출하며이 경우 SurfaceView입니다.

콜백을 추가하면 이벤트를 가로 챌 수 있습니다.

이제 몇 가지 방법을 재정의하십시오.

@ 공개 void surfaceChanged (SurfaceHolder 홀더, int 형식, int 너비, int 높이) 무시 {} @ 공개 void surfaceCreated (SurfaceHolder 홀더) 재정의 {} @Public void surfaceCreates (SurfaceHolder holder) 재정의 {}

이것들은 기본적으로 수퍼 클래스 (SurfaceView)의 메소드를 오버라이드 (따라서 이름) 할 수있게합니다. 이제 코드에 더 이상 빨간색 밑줄이 없어야합니다. 좋은.

방금 새 클래스를 만들었고이를 참조 할 때마다 게임이 그려 질 캔버스를 만듭니다. 수업 몹시 떠들어 대다 우리는 하나 더 필요합니다.

스레드 만들기

우리의 새로운 수업은 메인 스레드. 그리고 그 임무는 스레드를 만드는 것입니다. 스레드는 기본적으로 병렬 코드와 동시에 실행될 수있는 병렬 코드와 같습니다. 본관 코드의 일부. 한 번에 많은 스레드를 실행할 수 있으므로 엄격한 순서를 지키지 않고 동시에 작업을 수행 할 수 있습니다. 게임이 많은 경우에도 매끄럽게 실행되도록해야하기 때문에 이는 게임에 중요합니다.

이전과 마찬가지로 새 수업을 만들면 이번에는 수업이 확장됩니다. . 생성자에서 우리는 단지 감독자(). 그것이 바로 수퍼 클래스이며 스레드이며 우리를 위해 모든 노력을 기울일 수 있습니다. 이것은 그냥 전화를 설거지하는 프로그램을 만드는 것과 같습니다 세탁기().

이 클래스가 호출되면 주요 작업의 파생물로 실행되는 별도의 스레드가 생성됩니다. 그리고 그것은 이리 GameView를 만들고 싶습니다. 즉, GameView 클래스도 참조해야하며 캔버스가 포함 된 SurfaceHolder도 사용하고 있습니다. 따라서 캔버스가 표면이면 SurfaceHolder가 이젤입니다. 그리고 GameView가이 모든 것을 하나로 모았습니다.

전체 내용은 다음과 같아야합니다.

공용 클래스 MainThread는 스레드를 확장합니다. {private SurfaceHolder surfaceHolder; 개인 GameView gameView; 공개 MainThread (SurfaceHolder surfaceHolder, GameView gameView) {super (); this.surfaceHolder = surfaceHolder; this.gameView = gameView; }}

쇼트 이제 GameView와 스레드가 생겼습니다!

게임 루프 만들기

이제 게임을 만드는 데 필요한 원자재가 있지만 아무 일도 일어나지 않습니다. 게임 루프가 시작되는 곳입니다. 기본적으로, 이것은 화면을 그리기 전에 빙글 빙글 이동하고 입력 및 변수를 확인하는 코드 루프입니다. 우리의 목표는 가능한 한 일관성을 유지하여 프레임 속도에 끊김이나 딸꾹질이 없도록하는 것입니다.

지금은 여전히 메인 스레드 클래스와 수퍼 클래스의 메소드를 재정의하겠습니다. 이건 운영.

그리고 이것은 다음과 같이 조금갑니다 :

@Override public void run () {while (실행 중) {canvas = null; 시도 {canvas = this.surfaceHolder.lockCanvas (); synchronized (surfaceHolder) {this.gameView.update (); this.gameView.draw (canvas); }} catch (Exception e) {} finally {if (canvas! = null) {try {surfaceHolder.unlockCanvasAndPost (canvas); } catch (예외 e) {e.printStackTrace (); }}}}}

밑줄이 많이 표시되므로 변수와 참조를 더 추가해야합니다. 맨 위로 돌아가서 다음을 추가하십시오.

개인 SurfaceHolder surfaceHolder; 개인 GameView gameView; 개인 부울 실행; 공개 정적 캔버스 캔버스;

Canvas를 가져와야합니다. 캔버스는 우리가 실제로 그릴 것입니다. ‘lockCanvas’는 캔버스를 그릴 수 있도록 본질적으로 동결하기 때문에 중요합니다. 그렇지 않으면 한 번에 여러 개의 스레드를 시도 할 수 있기 때문에 중요합니다. 캔버스를 편집하려면 먼저 캔버스를 편집해야합니다. 자물쇠 캔버스.

업데이트는 우리가 만들 방법이며 나중에 재미있는 일이 일어날 곳입니다.

그만큼 시험 잡기 반면에 캔버스가 준비되지 않은 경우 발생할 수있는 예외 (오류)를 기꺼이 처리하려고 시도한다는 것을 보여주는 Java의 요구 사항 일뿐입니다.

마지막으로, 필요할 때 스레드를 시작할 수 있기를 원합니다. 이를 위해서는 모션을 설정할 수있는 다른 방법이 필요합니다. 그게 달리는 변수는 for입니다 (부울은 참 또는 거짓 인 변수 유형 임). 이 방법을 메인 스레드 수업:

public void setRunning (boolean isRunning) {running = isRunning; }

하지만이 시점에서 여전히 강조해야 할 것은 최신 정보. 아직 업데이트 방법을 만들지 않았기 때문입니다. 다시 들어와 GameView 이제 메소드를 추가하십시오.

공공 무효 업데이트 () {}

우리는 또한 스타트 실! 우리는 이것을 우리의 surfaceCreated 방법:

@void public void surfaceCreated (SurfaceHolder holder) 재정의 {thread.setRunning (true); thread.start (); }

또한 표면이 파괴 될 때 실을 멈춰야합니다. 당신이 짐작할 수 있듯이, 우리는 이것을 표면 파괴 방법. 그러나 실제로 스레드를 중지하기 위해 여러 번 시도 할 수 있으므로이를 루프에 넣고 사용하겠습니다. 시험 잡기 다시. 이렇게 :

@ 공공 void void 재정의 surfaceDestroyed (SurfaceHolder holder) {boolean retry = true; while (재시도) {try {thread.setRunning (false); thread.join (); } catch (InterruptedException e) {e.printStackTrace (); } 재시도 = 거짓; }}

마지막으로 생성자로 가서 스레드의 새 인스턴스를 만들어야합니다. 그렇지 않으면 두려운 널 포인터 예외가 발생합니다! 그런 다음 GameView를 포커스 가능하게 만들어 이벤트를 처리 할 수 ​​있습니다.

스레드 = 새로운 MainThread (getHolder (),이); setFocusable (true);

지금 당신은 할 수 있습니다 마침내 실제로 이것을 테스트하십시오! 맞습니다, 달리기를 클릭하면 할까요 실제로 오류없이 실행됩니다. 날아갈 준비를하세요!

빈 화면입니다. 그 모든 코드. 빈 화면. 그러나 이것은 빈 화면입니다 기회. 이벤트를 처리하기 위해 게임 루프로 표면을 가동했습니다. 이제 남은 것은 일이 일어나게하는 것입니다. 지금까지 튜토리얼의 모든 내용을 따르지 않아도 상관 없습니다. 요점은이 코드를 단순히 재활용하여 영광스러운 게임을 시작할 수 있다는 것입니다!

그래픽하기

자, 이제 빈 화면을 그릴 수 있습니다. 그냥해야합니다. 다행히도 그게 간단한 부분입니다. 우리의 draw 메소드를 재정의하기 만하면됩니다. GameView 수업 후 예쁜 그림을 추가하십시오.

@ 공공 무효 그리기 무시 (캔버스 캔버스) {super.draw (canvas); if (canvas! = null) {canvas.drawColor (Color.WHITE); 페인트 페인트 = new Paint (); paint.setColor (Color.rgb (250, 0, 0)); canvas.drawRect (100, 100, 200, 200, 페인트); }}

이것을 실행하면 흰색 화면의 왼쪽 상단에 빨간색 사각형이 생깁니다. 이것은 확실히 개선입니다.

이론적 으로이 방법을 사용하여 게임 전체를 거의 만들 수 있습니다. onTouchEvent 입력을 처리하는 것이 좋지만 문제를 해결하는 데 좋은 방법은 아닙니다. 루프 안에 새로운 페인트를 넣으면 작업 속도가 크게 느려지고 다른 곳에 넣더라도 너무 많은 코드를 추가하면 무승부 방법은 추악하고 따르기가 어려울 것입니다.

대신, 자신의 클래스로 게임 오브젝트를 처리하는 것이 훨씬 더 합리적입니다. 캐릭터를 보여주는 것으로 시작하겠습니다.이 수업은 캐릭터 스파이트. 계속 진행하십시오.

이 클래스는 캔버스에 스프라이트를 그릴 것입니다.

공개 클래스 CharacterSprite {개인 비트 맵 이미지; 공개 CharacterSprite (비트 맵 bmp) {image = bmp; } public void draw (캔버스 캔버스) {canvas.drawBitmap (image, 100, 100, null); }}

이제 이것을 사용하려면 먼저 비트 맵을로드 한 다음 클래스를 호출해야합니다. GameView. 에 참조 추가 개인 CharacterSprite characterSprite 그런 다음 surfaceCreated 방법, 라인을 추가하십시오 :

characterSprite = 새로운 CharacterSprite (BitmapFactory.decodeResource (getResources (), R.drawable.avdgreen));

보시다시피,로드중인 비트 맵은 리소스에 저장되며 avdgreen (이전 게임에서 온 것)이라고합니다. 이제 비트 맵을 새 클래스에 전달하기 만하면됩니다. 무승부 방법 :

characterSprite.draw (캔버스);

이제 실행을 클릭하면 그래픽이 화면에 나타납니다! 이것은 BeeBoo입니다. 나는 학교 교과서에 그를 그렸습니다.

이 작은 사람을 움직이게하려면 어떻게해야합니까? 단순 : 우리는 그의 위치에 대한 x 및 y 변수를 만든 다음이 값을 최신 정보 방법.

참조를 추가하십시오. 캐릭터 스파이트 그런 다음 비트 맵을 x, y. 여기에 업데이트 방법을 만들고 지금 시도해 보겠습니다.

y ++;

게임 루프가 실행될 때마다 캐릭터가 화면 아래로 이동합니다. 생각해 내다, 와이 좌표는 위에서부터 측정되므로 0 화면 상단입니다. 물론 우리는 최신 정보 방법 캐릭터 스파이트 ~로부터 최신 정보 방법 GameView.

다시 재생을 누르면 이미지가 화면에서 천천히 아래로 내려 오는 것을 볼 수 있습니다. 우리는 아직 게임 상을 수상하지는 않았지만 시작입니다!

좋아, 물건을 만들기 위해 약간 더 흥미로운 것은 여기에‘탄력성 공’코드를 놓는 것입니다. 이렇게하면 오래된 Windows 화면 보호기처럼 화면 가장자리에서 그래픽이 튀어 오릅니다. 이상하게 최면적인 것들을 알고 있습니다.

공공 무효 업데이트 () {x + = xVelocity; y + = y 벨로 시티; if ((x & gt; screenWidth-image.getWidth ()) || (x & lt; 0)) {xVelocity = xVelocity * -1; } if ((y & gt; screenHeight-image.getHeight ()) || (y & lt; 0)) {yVelocity = yVelocity * -1; }}

다음 변수도 정의해야합니다.

private int xVelocity = 10; 개인 int yVelocity = 5; private int screenWidth = Resources.getSystem (). getDisplayMetrics (). widthPixels; private int screenHeight = Resources.getSystem (). getDisplayMetrics (). heightPixels;

최적화

있다 많은 플레이어 입력 처리, 이미지 스케일링, 화면에서 한 번에 많은 캐릭터 이동을 관리하는 데 이르기까지 여기에서 더 자세히 알아볼 수 있습니다. 지금 캐릭터가 튀는 소리가 있지만 자세히 보면 약간의 말더듬이 있습니다. 끔찍한 것은 아니지만 육안으로 볼 수 있다는 사실은 경고 신호입니다. 속도는 물리적 장치와 비교하여 에뮬레이터에서 많이 다릅니다. 이제 당신이있을 때 무슨 일이 일어날 지 상상 한 번에 화면에 계속!

이 문제에 대한 몇 가지 해결책이 있습니다. 내가 시작하고 싶은 것은 개인 정수를 만드는 것입니다. 메인 스레드 그리고 그것을 부르십시오 targetFPS. 값은 60입니다.이 속도로 게임을 실행하려고 노력하고 그 동안 게임이 제대로 작동하는지 확인하려고합니다. 이를 위해 개인 더블도 원합니다 averageFPS.

또한 업데이트 할 것입니다 운영 각 게임 루프가 얼마나 오래 걸리는지 측정하는 방법 중지 해당 게임이 targetFPS보다 앞서 있으면 일시적으로 반복됩니다. 그런 다음 얼마나 오래 계산합니까 지금 가져 와서 인쇄해서 로그에서 볼 수 있습니다.

@Override public void run () {long startTime; 오랜 시간; 긴 대기 시간; 긴 totalTime = 0; int frameCount = 0; 긴 targetTime = 1000 / targetFPS; while (실행 중) {startTime = System.nanoTime (); 캔버스 = null; 시도 {canvas = this.surfaceHolder.lockCanvas (); synchronized (surfaceHolder) {this.gameView.update (); this.gameView.draw (canvas); }} catch (Exception e) {} finally {if (canvas! = null) {try {surfaceHolder.unlockCanvasAndPost (canvas); } catch (예외 e) {e.printStackTrace (); }}} timeMillis = (System.nanoTime ()-startTime) / 1000000; waitTime = targetTime-timeMillis; 시도 {this.sleep (waitTime); } catch (예외 e) {} totalTime + = System.nanoTime ()-startTime; frameCount ++; if (frameCount == targetFPS) {averageFPS = 1000 / ((totalTime / frameCount) / 1000000); frameCount = 0; totalTime = 0; System.out.println (평균 FPS); }}}

이제 우리 게임은 FPS를 60으로 고정하려고 시도하고 있으며 일반적으로 최신 장치에서 상당히 안정적인 58-62 FPS를 측정합니다. 에뮬레이터에서는 다른 결과를 얻을 수 있습니다.

60에서 30으로 변경하고 어떻게되는지보십시오. 게임이 느려지고 할까요 이제 logcat에서 30을 읽으십시오.

결산 생각

성능을 최적화하기 위해 할 수있는 다른 일도 있습니다. 여기 주제에 대한 훌륭한 블로그 게시물이 있습니다. 루프 내에서 Paint 또는 비트 맵의 ​​새 인스턴스를 만들지 말고 모든 초기화를 수행하십시오. 외부 게임이 시작되기 전에.

다음 히트 안드로이드 게임을 만들 계획이라면 확실히 요즘 더 쉽고 효율적인 방법입니다. 그러나 캔버스에 그릴 수있는 유스 케이스 시나리오는 여전히 존재하며 레퍼토리에 추가하는 것이 매우 유용한 기술입니다. 이 안내서가 어느 정도 도움이 되었기를 바랍니다. 다가오는 코딩 벤처에서 행운을 빕니다.

다음 것Java 초보자 가이드

업데이트 : 2019 년 6 월 13 일 오전 11시 28 분 (ET) : LG 대변인이 상황을 명확히하기 위해. LG에 따르면이 회사는 Qualcomm의 5G 칩 공급이 중단 될 것으로 예상하지 않습니다. 실제로, 6 월 30 일까지 합의가 있는지 여부는 "공급 계약과는 관계가 없습니다."...

LG는 신속한 안드로이드 버전 업데이트로 알려진 적이 없다. 작년에 Android 9는 8 월에 기기에 출시되기 시작했지만 LG 사용자는 9 개월이 지난 후에야 안정적인 공개 버전을 보지 못했습니다.LG는 이번에 이전의 단점을 보완하려고 노력하고있다. 오늘은 한국에서 Android 10 공개 미리보기 프로그램의 시작을 발표합니다. LG는 연말까지 공식 업데...

우리는 당신에게 추천합니다