零打碎敲學Android 二 —做個拼圖遊戲吧
阿新 • • 發佈:2018-12-21
Android千好萬好,唯獨模擬器不是太好,在不更換舊有硬體的前提下,使用Android模擬器通常會遭遇效率問題,況且在logcat下面除錯,也始終不如開發桌面遊戲時那麼直觀。有沒有什麼辦法,能夠解決這一問題呢?
其實很容易做到。
Android首先是一個精簡的Linux平臺,其次才是一個手機系統,Java在PC上可以做到的事情,Android不但可以做到,而且能以近乎一致的手段做到。事實上,如果有人故意通過封裝抹殺Android與PC上Java應用差異性的話,任何Java遊戲,都可以在很少更改程式碼(或者完全不更改程式碼)的情況下移植到Android之上。
比如,筆者下面提供的這個拼圖遊戲示例,就可以在幾乎不改變程式結構(部分相關類需要替換,不過可以利用正則自動完成)的前提下,執行在Android上。
PC版原始碼(框架為LGame-Simple-0.2.0):
[java] view plain copy print?- package org.loon.game.simple.test;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.Image;
- import java.awt.event.KeyEvent;
- import java.awt.event.MouseEvent;
- import org.loon.framework.game.simple.GameScene;
- import org.loon.framework.game.simple.core.Deploy;
- import org.loon.framework.game.simple.core.Screen;
- import org.loon.framework.game.simple.utils.GraphicsUtils;
- /**
- *
- * Copyright 2008
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- *
- * @project loonframework
- * @author chenpeng
- * @email:[email protected]
- * @version 0.1
- */
- publicclass ScreenTest1 extends Screen {
- private Image imageBack, tmp_imageBack, imageForward;
- private Graphics tmp_graphics;
- privateint blocks[];
- privateboolean isEvent;
- privateint count, rs, cs, row, col, width, height;
- public ScreenTest1(String file1, String file2, int row, int col) {
- this.col = col;
- this.row = row;
- this.imageBack = GraphicsUtils.loadImage(file1);
- this.width = imageBack.getWidth(null);
- this.height = imageBack.getHeight(null);
- this.rs = width / row;
- this.cs = height / col;
- this.tmp_imageBack = GraphicsUtils
- .createImage(width, height + cs, true);
- this.tmp_graphics = tmp_imageBack.getGraphics();
- this.count = col * row;
- this.blocks = newint[count];
- this.imageForward = GraphicsUtils.loadImage(file2);
- for (int i = 0; i < count; i++) {
- blocks[i] = i;
- }
- rndBlocks();
- }
- /**
- * 複製拼圖中圖片塊
- *
- * @param x1
- * @param y1
- * @param x2
- * @param y2
- */
- privatevoid copy(int x1, int y1, int x2, int y2) {
- tmp_graphics.copyArea(x1 * rs, y1 * cs, rs, cs, (x2 - x1) * rs,
- (y2 - y1) * cs);
- }
- /**
- * 隨機生成拼圖內容
- *
- */
- privatevoid rndBlocks() {
- tmp_graphics.drawImage(imageBack, 0, 0, null);
- for (int i = 0; i < (count * row); i++) {
- int x1 = (int) ((double) row * Math.random());
- int y1 = (int) ((double) col * Math.random());
- int x2 = (int) ((double) row * Math.random());
- int y2 = (int) ((double) col * Math.random());
- copy(x1, y1, 0, col);
- copy(x2, y2, x1, y1);
- copy(0, col, x2, y2);
- int j1 = blocks[y1 * row + x1];
- blocks[y1 * row + x1] = blocks[y2 * row + x2];
- blocks[y2 * row + x2] = j1;
- }
- }
- /**
- * 點選滑鼠
- */
- publicvoid leftClick(MouseEvent e) {
- if (isEvent) {
- return;
- }
- int x = e.getX() / rs;
- int y = e.getY() / cs;
- copy(0, 0, 0, col);
- copy(x, y, 0, 0);
- copy(0, col, x, y);
- int no = blocks[0];
- blocks[0] = blocks[y * row + x];
- blocks[y * row + x] = no;
- int index;
- for (index = 0; index < count; index++) {
- if (blocks[index] != index) {
- break;
- }
- }
- if (index == count) {
- isEvent = true;
- }
- return;
- }
- publicvoid draw(Graphics2D g) {
- if (!isEvent) {
- g.drawImage(tmp_imageBack, 0, 0, null);
- for (int i = 0; i < row; i++) {
- for (int j = 0; j < col; j++)
- g.drawRect(i * rs, j * cs, rs, cs);
- }
- }
- if (isEvent && imageForward != null) {
- g.drawImage(imageBack, 0, 0, null);
- g.drawImage(imageForward, 0, 0, null);
- tmp_graphics.dispose();
- }
- }
- publicboolean isEvent() {
- return isEvent;
- }
- publicvoid setEvent(boolean isEvent) {
- this.isEvent = isEvent;
- }
- publicvoid middleClick(MouseEvent e) {
- }
- publicvoid onKey(KeyEvent e) {
- }
- publicvoid onKeyUp(KeyEvent e) {
- }
- publicvoid rightClick(MouseEvent e) {
- }
- publicstaticvoid main(String[] args) {
- GameScene frame = new GameScene("拼圖", 320, 480);
- Deploy deploy = frame.getDeploy();
- deploy.setScreen(new ScreenTest1("images/backimage1.jpg",
- "images/over.png", 4, 4));
- deploy.setShowFPS(true);
- deploy.setLogo(false);
- deploy.setFPS(100);
- deploy.mainLoop();
- frame.showFrame();
- }
- }
Android版原始碼(框架為LAGame-Simple-prototype):
[java] view plain copy print?- package org.loon.framework.android.game;
- import android.view.KeyEvent;
- import android.view.MotionEvent;
- /**
- *
- * Copyright 2008 - 2009
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- *
- * @project loonframework
- * @author chenpeng
- * @email <a title="" href="http://hi.baidu.com/ceponline" mce_href="http://hi.baidu.com/ceponline" target="_blank">ceponline</a>@yahoo.com.cn
- * @version 0.1.0
- */
- publicclass ScreenTest1 extends LAScreen {
- private LAImage imageBack, tmp_imageBack, imageForward;
- private LAGraphics tmp_graphics;
- privateint blocks[];
- privateboolean isEvent;
- privateint count, rs, cs, row, col, width, height;
- public ScreenTest1(String file1, String file2, int row, int col) {
- this.col = col;
- this.row = row;
- this.imageBack = getLAImage(file1);
- this.width = imageBack.getWidth();
- this.height = imageBack.getHeight();
- this.rs = width / row;
- this.cs = height / col;
- this.tmp_imageBack = new LAImage(width, height + cs);
- this.tmp_graphics = tmp_imageBack.getLAGraphics();
- this.count = col * row;
- this.blocks = newint[count];
- this.imageForward = getLAImage(file2);
- for (int i = 0; i < count; i++) {
- blocks[i] = i;
- }
- rndBlocks();
- }
- /**
- * 複製拼圖中圖片塊
- *
- * @param x1
- * @param y1
- * @param x2
- * @param y2
- */
- privatevoid copy(int x1, int y1, int x2, int y2) {
- tmp_graphics.copyArea(x1 * rs, y1 * cs, rs, cs, (x2 - x1) * rs,
- (y2 - y1) * cs);
- }
- /**
- * 隨機生成拼圖內容
- *
- */
- privatevoid rndBlocks() {
- tmp_graphics.drawImage(imageBack, 0, 0);
- for (int i = 0; i < (count * row); i++) {
- int x1 = (int) ((double) row * Math.random());
- int y1 = (int) ((double) col * Math.random());
- int x2 = (int) ((double) row * Math.random());
- int y2 = (int) ((double) col * Math.random());
- copy(x1, y1, 0, col);
- copy(x2, y2, x1, y1);
- copy(0, col, x2, y2);
- int j1 = blocks[y1 * row + x1];
- blocks[y1 * row + x1] = blocks[y2 * row + x2];
- blocks[y2 * row + x2] = j1;
- }
- }
- /**
- * 點選觸控式螢幕
- */
- publicboolean onTouchDown(MotionEvent e) {
- if (isEvent) {
- return isEvent;
- }
- int x = (int) (e.getX() / rs);
- int y = (int) (e.getY() / cs);
- copy(0, 0, 0, col);
- copy(x, y, 0, 0);
- copy(0, col, x, y);
- int no = blocks[0];
- blocks[0] = blocks[y * row + x];
- blocks[y * row + x] = no;
- int index;
- for (index = 0; index < count; index++) {
- if (blocks[index] != index) {
- break;
- }
- }
- if (index == count) {
- isEvent = true;
- }
- return isEvent;
- }
- /**
- * 繪製拼圖
- */
- publicvoid draw(LAGraphics g) {
- if (!isEvent) {
- g.drawImage(tmp_imageBack, 0, 0);
- for (int i = 0; i < row; i++) {
- for (int j = 0; j < col; j++)
- g.drawRect(i * rs, j * cs, rs, cs);
- }
- }
- if (isEvent && imageForward != null) {
- g.drawImage(imageBack, 0, 0);
- g.drawImage(imageForward, 0, 0);
- tmp_graphics.dispose();
- }
- }
- publicboolean isEvent() {
- return isEvent;
- }
- publicvoid setEvent(boolean isEvent) {
- this.isEvent = isEvent;
- }
- publicboolean onKeyDown(int keyCode, KeyEvent e) {
- returnfalse;
- }
- publicboolean onKeyUp(int keyCode, KeyEvent e) {
- returnfalse;
- }
- publicboolean onTouchMove(MotionEvent e) {
- returnfalse;
- }
- publicboolean onTouchUp(MotionEvent e) {
- returnfalse;
- }
- }
- package org.loon.framework.android.game;
- import android.app.Activity;
- import android.os.Bundle;
- /**
- *
- * Copyright 2008 - 2009
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- *
- * @project loonframework
- * @author chenpeng
- * @email <a title="" href="http://hi.baidu.com/ceponline" mce_href="http://hi.baidu.com/ceponline" target="_blank">ceponline</a>@yahoo.com.cn
- * @version 0.1.0
- */
- publicclass Main extends Activity {
- private LAGameView view;
- publicvoid onCreate(Bundle icicle) {
- super.onCreate(icicle);
- view = new LAGameView(this);
- view.setScreen(new ScreenTest1("backimage1.jpg",
- "over.png", 4, 4));
- view.setShowFPS(true);
- view.mainLoop();
- }
- protectedvoid onPause() {
- if (view != null) {
- view.setRunning(false);
- }
- super.onPause();
- }
- protectedvoid onStop() {
- if (view != null) {
- view.setRunning(false);
- }
- super.onStop();
- }
- }
Android遊戲與Java桌面遊戲在本質上不存在任何區別,邏輯實現更可以完全一致。通過示例我們看到,把一個以LGame-Simple框架開發的Java桌面遊戲移植到Android上居然是如此簡單。
事實上,未來的Android版LGame-Simple,函式實現將與PC版保持一致,對於差異性程式碼,筆者也將提供相互轉換的輔助工具。
如果您正在以LGame-Simple開發Java遊戲,那麼恭喜您,至多到今年12月底,它也將可以同時執行在Android上了。