Cách viết trò chơi Android đầu tiên của bạn bằng Java

Tác Giả: John Stephens
Ngày Sáng TạO: 1 Tháng MộT 2021
CậP NhậT Ngày Tháng: 8 Có Thể 2024
Anonim
Cách viết trò chơi Android đầu tiên của bạn bằng Java - ỨNg DụNg
Cách viết trò chơi Android đầu tiên của bạn bằng Java - ỨNg DụNg

NộI Dung


Có rất nhiều cách để tạo trò chơi cho Android và một cách quan trọng là làm từ đầu trong Android Studio với Java. Điều này cho phép bạn kiểm soát tối đa cách bạn muốn trò chơi của mình trông và hành xử và quy trình sẽ dạy cho bạn các kỹ năng bạn có thể sử dụng trong một loạt các tình huống khác - cho dù bạn đang tạo màn hình giật gân cho ứng dụng hay bạn chỉ muốn thêm một số hình ảnh động. Với ý nghĩ đó, hướng dẫn này sẽ chỉ cho bạn cách tạo một trò chơi 2D đơn giản bằng Android Studio và Java. Bạn có thể tìm thấy tất cả mã và tài nguyên tại Github nếu bạn muốn theo dõi cùng.

Đang cài đặt

Để tạo trò chơi của chúng tôi, chúng tôi sẽ cần phải xử lý một vài khái niệm cụ thể: vòng lặp trò chơi, chủ đề và khung vẽ. Để bắt đầu, hãy khởi động Android Studio. Nếu bạn không cài đặt nó thì hãy xem phần giới thiệu đầy đủ của chúng tôi về Android Studio, phần tiếp theo quá trình cài đặt. Bây giờ bắt đầu một dự án mới và đảm bảo bạn chọn mẫu ‘rỗng Activity Activity. Đây là một trò chơi, nên dĩ nhiên bạn không cần các yếu tố như nút FAB làm phức tạp vấn đề.


Điều đầu tiên bạn muốn làm là thay đổi AppCompatActivity đến Hoạt động. Điều này có nghĩa là chúng tôi đã thắng được sử dụng các tính năng của thanh hành động.

Tương tự, chúng tôi cũng muốn làm cho trò chơi của chúng tôi toàn màn hình. Thêm mã sau vào onCreate () trước lệnh gọi đến setContentView ():

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

Lưu ý rằng nếu bạn viết ra một số mã và nó được gạch chân màu đỏ, điều đó có thể có nghĩa là bạn cần nhập một lớp. Nói cách khác, bạn cần nói với Android Studio rằng bạn muốn sử dụng một số câu lệnh nhất định và làm cho chúng có sẵn. Nếu bạn chỉ cần nhấp vào bất cứ nơi nào trên từ được gạch chân và sau đó nhấn Alt + Enter, thì điều đó sẽ tự động được thực hiện cho bạn!


Tạo chế độ xem trò chơi của bạn

Bạn có thể được sử dụng cho các ứng dụng sử dụng tập lệnh XML để xác định bố cục của các chế độ xem như nút, hình ảnh và nhãn. Đây là những gì dòng setContentView đang làm cho chúng tôi.

Nhưng một lần nữa, đây là một trò chơi có nghĩa là nó không cần phải có cửa sổ trình duyệt hoặc cuộn các chế độ xem tái chế. Thay vào đó, chúng tôi muốn hiển thị một bức tranh thay thế. Trong Android Studio, một khung vẽ giống như trong nghệ thuật: đó là một phương tiện mà chúng ta có thể vẽ.

Vì vậy, thay đổi dòng đó để đọc như vậy:

setContentView (GameView mới (này))

Bạn sẽ thấy rằng điều này một lần nữa được gạch chân màu đỏ. Nhưng hiện nay nếu bạn nhấn Alt + Enter, bạn không có tùy chọn để nhập lớp. Thay vào đó, bạn có tùy chọn để tạo nên một lớp học. Nói cách khác, chúng tôi sắp sửa tạo ra lớp của riêng mình để xác định những gì sẽ đi trên khung vẽ. Đây là những gì sẽ cho phép chúng ta vẽ lên màn hình, thay vì chỉ hiển thị các chế độ xem sẵn sàng.

Vì vậy, nhấp chuột phải vào tên gói trong phân cấp của bạn ở bên trái và chọn Mới> Lớp. Bây giờ bạn sẽ được trình bày với một cửa sổ để tạo lớp của bạn và bạn sẽ gọi nó là GameView. Trong SuperClass, viết: android.view.SurfaceView có nghĩa là lớp sẽ kế thừa các phương thức - khả năng của nó - từ SurfaceView.

Trong hộp Giao diện, bạn sẽ viết android.view.SurfaceHolder.Callback. Như với bất kỳ lớp nào, bây giờ chúng ta cần tạo hàm tạo của chúng ta. Sử dụng mã này:

chủ đề MainThread riêng tư; GameView công khai (Bối cảnh bối cảnh) {super (bối cảnh); getHolder (). addCallback (này); }

Mỗi khi lớp của chúng ta được gọi để tạo một đối tượng mới (trong trường hợp này là bề mặt của chúng ta), nó sẽ chạy hàm tạo và nó sẽ tạo ra một bề mặt mới. Dòng super siêu cấp gọi siêu lớp và trong trường hợp của chúng tôi, đó là SurfaceView.

Bằng cách thêm Callback, chúng tôi có thể chặn các sự kiện.

Bây giờ ghi đè một số phương thức:

@Override void void voidChanged (Giá đỡ SurfaceHolder, định dạng int, int width, int height) {} @Override void void voidCreated (SurfaceHolder giữ)

Về cơ bản, chúng cho phép chúng ta ghi đè các phương thức (do đó là tên) trong siêu lớp (SurfaceView). Bây giờ bạn sẽ không có gạch chân màu đỏ trong mã của bạn. Tốt đẹp.

Bạn vừa tạo một lớp mới và mỗi lần chúng tôi đề cập đến nó, nó sẽ xây dựng khung vẽ cho trò chơi của bạn để vẽ lên. Các lớp học tạo nên đối tượng và chúng ta cần thêm một.

Tạo chủ đề

Lớp học mới của chúng tôi sẽ được gọi Chính. Và công việc của nó sẽ là tạo ra một chủ đề. Một luồng về cơ bản giống như một nhánh mã song song có thể chạy đồng thời cùng với chủ yếu một phần của mã của bạn. Bạn có thể có rất nhiều luồng chạy cùng một lúc, do đó cho phép mọi thứ xảy ra đồng thời thay vì tuân thủ một trình tự nghiêm ngặt. Điều này rất quan trọng đối với một trò chơi, bởi vì chúng ta cần đảm bảo rằng nó tiếp tục chạy trơn tru, ngay cả khi có nhiều thứ đang diễn ra.

Tạo lớp mới của bạn giống như bạn đã làm trước đây và lần này nó sẽ mở rộng Chủ đề. Trong constructor, chúng tôi sẽ gọi siêu(). Hãy nhớ rằng, siêu hạng đó, đó là Thread, và có thể làm tất cả những công việc nặng nhọc cho chúng ta. Điều này giống như tạo ra một chương trình để rửa chén đĩa mà chỉ cần gọi may giặt().

Khi lớp này được gọi, nó sẽ tạo ra một luồng riêng chạy như một nhánh của điều chính. Và nó từ đây mà chúng tôi muốn tạo GameView của chúng tôi. Điều đó có nghĩa là chúng ta cũng cần tham chiếu lớp GameView và chúng tôi cũng sử dụng SurfaceHolder có chứa canvas. Vì vậy, nếu khung vẽ là bề mặt, SurfaceHolder là giá vẽ. Và GameView là thứ đặt tất cả lại với nhau.

Điều đầy đủ sẽ trông như vậy:

lớp công khai MainThread mở rộng Thread {private SurfaceHolder SurfaceHolder; trò chơi GameView riêng; công khai MainThread (SurfaceHolder SurfaceHolder, GameView gameView) {super (); this.surfaceHolder = SurfaceHolder; this.gameView = gameView; }}

Schweet. Bây giờ chúng ta có một GameView và một chủ đề!

Tạo vòng lặp trò chơi

Bây giờ chúng tôi có các nguyên liệu thô cần thiết để tạo ra trò chơi của mình, nhưng không có gì xảy ra. Đây là nơi mà vòng lặp trò chơi xuất hiện. Về cơ bản, đây là một vòng mã đi vòng tròn và kiểm tra các đầu vào và biến trước khi vẽ màn hình. Mục đích của chúng tôi là làm cho điều này phù hợp nhất có thể, để không có sự tắc nghẽn hay trục trặc trong khung hình, mà tôi sẽ khám phá một chút sau đó.

Cho đến bây giờ, chúng tôi vẫn còn trong Chính class và chúng tôi sẽ ghi đè một phương thức từ lớp cha. Cái này là chạy.

Và nó đi một chút gì đó như thế này:

@Override công khai void run () {while (đang chạy) {canvas = null; thử {canvas = this.surfaceHolder.lockCanvas (); đã đồng bộ hóa (SurfaceHolder) {this.gameView.update (); this.gameView.draw (canvas); }} Catch (Exception e) {} cuối cùng {if (canvas! = null) {thử {SurfaceHolder.unlockCanvasAndPost (canvas); } Catch (Ngoại lệ e) {e.printStackTrace (); }}}}}

Bạn có thể thấy rất nhiều gạch chân, vì vậy chúng tôi cần thêm một số biến và tham chiếu. Quay trở lại đầu trang và thêm:

SurfaceHolder riêngHolder; trò chơi GameView riêng; boolean riêng chạy; vải canvas tĩnh công cộng;

Nhớ nhập Canvas. Canvas là thứ chúng ta thực sự sẽ vẽ. Đối với ‘lockCanvas, điều này rất quan trọng vì về cơ bản nó đóng băng khung vẽ để cho phép chúng ta vẽ lên nó. Điều đó rất quan trọng bởi vì nếu không, bạn có thể có nhiều luồng cố gắng vẽ lên nó cùng một lúc. Chỉ cần biết rằng để chỉnh sửa canvas, trước tiên bạn phải Khóa tấm bạt.

Cập nhật là một phương pháp mà chúng tôi sẽ tạo ra và đây là nơi những điều thú vị sẽ xảy ra sau này.

Các thử bắt lấy trong khi đó chỉ đơn giản là các yêu cầu của Java cho thấy chúng tôi sẵn sàng thử và xử lý các trường hợp ngoại lệ (lỗi) có thể xảy ra nếu khung vẽ sẵn sàng, v.v.

Cuối cùng, chúng tôi muốn có thể bắt đầu chuỗi của chúng tôi khi chúng tôi cần nó. Để làm điều này, chúng tôi sẽ cần một phương pháp khác ở đây cho phép chúng tôi thiết lập mọi thứ theo chuyển động. Đó là những gì đang chạy biến là for (lưu ý rằng Boolean là một loại biến chỉ đúng hoặc sai). Thêm phương thức này vào Chính lớp học:

công khai void setRasty (boolean isRucky) {running = isRasty; }

Nhưng tại thời điểm này, một điều vẫn nên được làm nổi bật và đó cập nhật. Điều này là do chúng tôi đã tạo ra phương pháp cập nhật. Vì vậy, quay trở lại vào GameView và bây giờ thêm phương thức.

cập nhật khoảng trống công khai () {}

Chúng ta cũng cần phải khởi đầu chủ đề! Chúng tôi sẽ làm điều này trong bề mặt phương pháp:

@Override void void voidCreated (SurfaceHolder giữ) {thread.setRasty (true); thread.start (); }

Chúng ta cũng cần dừng luồng khi bề mặt bị phá hủy. Như bạn có thể đoán, chúng tôi xử lý việc này trong bề mặt phương pháp. Nhưng vì thực sự có thể mất nhiều nỗ lực để ngăn chặn một chuỗi, chúng tôi sẽ đưa nó vào vòng lặp và sử dụng thử bắt lấy lần nữa. Thích như vậy:

@Override void void voidDestroyed (người giữ SurfaceHolder) {boolean retry = true; while (thử lại) {thử {thread.setRasty (false); chủ đề.join (); } Catch (Interrupttedception e) {e.printStackTrace (); } thử lại = sai; }}

Và cuối cùng, đi đến hàm tạo và đảm bảo tạo phiên bản mới của luồng của bạn, nếu không, bạn sẽ nhận được ngoại lệ con trỏ null đáng sợ! Và sau đó chúng tôi sẽ làm cho GameView có thể tập trung, có nghĩa là nó có thể xử lý các sự kiện.

chủ đề = new MainThread (getHolder (), cái này); setF Focusable (true);

Bây giờ bạn có thể cuối cùng Thực sự kiểm tra điều này! Đúng vậy, nhấp vào chạy và nó Nên Thực sự chạy mà không có lỗi. Chuẩn bị để được thổi bay đi!

Nó từ chối nó một số màn hình trống! Tất cả mã đó. Đối với một màn hình trống. Nhưng, đây là một màn hình trống của cơ hội. Bạn đã có bề mặt và chạy với một vòng lặp trò chơi để xử lý các sự kiện. Bây giờ tất cả những gì còn lại là làm cho mọi thứ xảy ra. Nó thậm chí không quan trọng nếu bạn đã làm theo mọi thứ trong hướng dẫn cho đến thời điểm này. Điểm là, bạn chỉ có thể tái chế mã này để bắt đầu tạo ra các trò chơi vinh quang!

Làm đồ họa

Phải, bây giờ chúng ta có một màn hình trống để vẽ, tất cả những gì chúng ta cần làm là vẽ lên nó. May mắn thay, đó là phần đơn giản. Tất cả bạn cần làm là ghi đè phương thức vẽ trong của chúng tôi GameView lớp và sau đó thêm một số hình ảnh đẹp:

@Override void void draw (Canvas canvas) {super.draw (canvas); if (canvas! = null) {canvas.drawColor (Color.WHITE); Sơn sơn = sơn mới (); paint.setColor (Color.rgb (250, 0, 0)); canvas.drawRect (100, 100, 200, 200, sơn); }}

Chạy cái này và bây giờ bạn sẽ có một hình vuông màu đỏ khá đẹp ở phía trên bên trái của màn hình màu trắng. Đây chắc chắn là một cải tiến.

Về mặt lý thuyết bạn có thể tạo ra khá nhiều toàn bộ trò chơi của mình bằng cách dán nó vào bên trong phương thức này (và ghi đè onTouchEvent để xử lý đầu vào) nhưng đó sẽ là một cách cực kỳ tốt để làm mọi thứ. Đặt Paint mới bên trong vòng lặp của chúng tôi sẽ làm mọi thứ chậm lại đáng kể và ngay cả khi chúng tôi đặt nó ở nơi khác, thêm quá nhiều mã vào vẽ tranh phương pháp sẽ trở nên xấu xí và khó theo dõi.

Thay vào đó, nó có ý nghĩa hơn nhiều để xử lý các đối tượng trò chơi với các lớp riêng của chúng. Chúng tôi sẽ bắt đầu với một nhân vật thể hiện một nhân vật và lớp này sẽ được gọi Ký tự. Đi trước và làm điều đó.

Lớp này sẽ vẽ một sprite lên khung vẽ và sẽ trông như vậy

lớp công khai CharacterSprite {hình ảnh Bitmap riêng tư; công khai CharacterSprite (Bitmap bmp) {image = bmp; } vẽ void void công khai (Canvas canvas) {canvas.drawBitmap (hình ảnh, 100, 100, null); }}

Bây giờ để sử dụng cái này, bạn sẽ cần phải tải bitmap trước và sau đó gọi lớp từ GameView. Thêm một tham chiếu đến private characterSprite characterSprite và sau đó trong bề mặt phương thức, thêm dòng:

characterSprite = new CharacterSprite (BitmapFactory.decodeResource (getResource (), R.drawable.avdgreen));

Như bạn có thể thấy, bitmap mà chúng tôi đang tải được lưu trữ trong các tài nguyên và được gọi là avdgreen (nó là từ một trò chơi trước đó). Bây giờ tất cả những gì bạn cần làm là chuyển bitmap đó sang lớp mới trong vẽ tranh phương pháp với:

characterSprite.draw (canvas);

Bây giờ bấm vào chạy và bạn sẽ thấy đồ họa của bạn xuất hiện trên màn hình của bạn! Đây là BeeBoo. Tôi đã từng vẽ anh ấy trong sách giáo khoa của trường tôi.

Điều gì nếu chúng ta muốn làm cho anh chàng nhỏ bé này di chuyển? Đơn giản: chúng ta chỉ cần tạo các biến x và y cho các vị trí của mình và sau đó thay đổi các giá trị này trong một cập nhật phương pháp.

Vì vậy, thêm các tài liệu tham khảo cho của bạn Ký tự và sau đó vẽ bitmap của bạn tại x, y. Tạo phương thức cập nhật tại đây và bây giờ chúng tôi sẽ thử:

y ++;

Mỗi khi vòng lặp trò chơi chạy, chúng tôi sẽ di chuyển nhân vật xuống màn hình. Nhớ lại, y tọa độ được đo từ trên xuống 0 là đỉnh của màn hình. Tất nhiên chúng ta cần gọi cập nhật phương pháp trong Ký tự từ cập nhật phương pháp trong GameView.

Nhấn play một lần nữa và bây giờ bạn sẽ thấy rằng hình ảnh của bạn từ từ theo dõi màn hình. Chúng tôi không thể giành được bất kỳ giải thưởng trò chơi nào nhưng đó là một sự khởi đầu!

Được rồi, để làm cho mọi thứ khinh bỉ Thú vị hơn, tôi sẽ bỏ một số mã bóng bouncy bóng ở đây. Điều này sẽ làm cho đồ họa của chúng tôi nảy xung quanh màn hình ra khỏi các cạnh, giống như các trình bảo vệ màn hình Windows cũ. Bạn biết đấy, những người thôi miên kỳ lạ.

cập nhật void công khai () {x + = xVelocity; y + = yVelocity; if ((x & gt; screenWidth - image.getWidth ()) || (x & lt; 0)) {xVelocity = xVelocity * -1; } if ((y & gt; screenHeight - image.getHeight ()) || (y & lt; 0)) {yVelocity = yVelocity * -1; }}

Bạn cũng sẽ cần xác định các biến này:

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

Tối ưu hóa

nhiều nhiều hơn để đi sâu vào đây, từ việc xử lý dữ liệu đầu vào của người chơi, đến thu nhỏ hình ảnh, đến việc quản lý có rất nhiều nhân vật di chuyển xung quanh màn hình cùng một lúc. Ngay bây giờ, nhân vật đang nảy nhưng nếu bạn nhìn rất kỹ thì có chút nói lắp. Nó không khủng khiếp nhưng thực tế là bạn có thể nhìn thấy nó bằng mắt thường là một dấu hiệu cảnh báo. Tốc độ cũng thay đổi rất nhiều trên trình giả lập so với thiết bị vật lý. Bây giờ hãy tưởng tượng những gì xảy ra khi bạn có tấn diễn ra trên màn hình cùng một lúc!

Có một vài giải pháp cho vấn đề này. Những gì tôi muốn làm để bắt đầu, là tạo một số nguyên riêng tư trong Chính và gọi nó mục tiêu FPS. Điều này sẽ có giá trị là 60.Tôi sẽ cố gắng để trò chơi của mình chạy với tốc độ này và trong khi đó, tôi sẽ kiểm tra để đảm bảo rằng nó sẽ hoạt động. Cho rằng, tôi cũng muốn một đôi riêng gọi là trung bìnhFPS.

Tôi cũng sẽ cập nhật chạy phương pháp để đo thời gian mỗi vòng lặp trò chơi diễn ra trong bao lâu tạm ngừng trò chơi đó lặp lại tạm thời nếu nó đi trước TargetFPS. Chúng tôi sẽ tính toán sau bao lâu hiện nay lấy và sau đó in nó để chúng ta có thể nhìn thấy nó trong nhật ký.

@Override void void run () {long startTime; thời gian dàiMillis; thời gian chờ đợi lâu; tổng thời gian dài = 0; int khungCount = 0; thời gian dài đích = 1000 / targetFPS; while (đang chạy) {startTime = System.nanoTime (); vải = null; thử {canvas = this.surfaceHolder.lockCanvas (); đã đồng bộ hóa (SurfaceHolder) {this.gameView.update (); this.gameView.draw (canvas); }} Catch (Exception e) {} cuối cùng {if (canvas! = null) {thử {SurfaceHolder.unlockCanvasAndPost (canvas); } Catch (Ngoại lệ e) {e.printStackTrace (); }}} timeMillis = (System.nanoTime () - startTime) / 1000000; WaitTime = targetTime - timeMillis; thử {this.s ngủ (WaitTime); } Catch (Exception e) {} TotalTime + = System.nanoTime () - startTime; frameCount ++; if (frameCount == targetFPS) {AverageFPS = 1000 / ((TotalTime / frameCount) / 1000000); khungCount = 0; tổng thời gian = 0; System.out.println (AverageFPS); }}}

Bây giờ trò chơi của chúng tôi đang cố gắng khóa nó FPS FPS thành 60 và bạn sẽ thấy rằng nó thường đo 58-62 FPS khá ổn định trên một thiết bị hiện đại. Trên trình giả lập mặc dù bạn có thể nhận được một kết quả khác.

Hãy thử thay đổi 60 đến 30 và xem điều gì sẽ xảy ra. Trò chơi chậm lại và nó Nên bây giờ đọc 30 trong logcat của bạn.

Bớt tư tưởng

Có một số điều khác chúng ta có thể làm để tối ưu hóa hiệu suất quá. Có một bài viết tuyệt vời trên blog về chủ đề này. Cố gắng kiềm chế không bao giờ tạo phiên bản mới của Paint hoặc bitmap trong vòng lặp và thực hiện tất cả việc khởi tạo ở ngoài trước khi trò chơi bắt đầu

Nếu bạn có kế hoạch tạo ra trò chơi Android đình đám tiếp theo thì sẽ có chắc chắn những cách dễ dàng và hiệu quả hơn để đi về nó những ngày này. Nhưng chắc chắn vẫn còn những tình huống sử dụng để có thể vẽ lên một bức tranh và đó là một kỹ năng rất hữu ích để thêm vào tiết mục của bạn. Tôi hy vọng hướng dẫn này đã giúp ích phần nào và chúc bạn may mắn nhất trong các dự án mã hóa sắp tới!

Kế tiếpHướng dẫn dành cho người mới bắt đầu với Java

Có hàng ngàn ứng dụng trong Cửa hàng Google Play, nhiều ứng dụng cạnh tranh trực tiếp với các dịch vụ của Google. Một phát hiện gần đây cho thấy Google có thể k...

Nuôi con rất tốn kém, ở đó không còn nghi ngờ gì nữa. Khi bạn là cha mẹ, bạn không ngừng tìm kiếm bất kỳ cách nào bạn có thể có thể tiế...

Cho BạN