編輯:Android開發實例
引言
程序猿們,是否還在為你的老板辛辛苦苦的打工而拿著微薄的薪水呢,還是不知道如何用自己的應用或游戲來賺錢呢!
在這裡IQuick將教您如何同過自己的應用來賺取自己的第一桶金!
你是說自己的應用還沒有做出來?
不,在這裡已經為你提供好了一個完整的游戲應用了,在文章的下面有源碼的地址哦。你只要稍做修改就可以變成一個完全屬於自己的應用了,比如將4*4換成5*5,甚至是其它的。如果你實在是慵懶至極的話,你只要將本應用的包名及廣告換成自己的,就可以上傳到市場上輕輕松松賺取自己的第一桶金了。
如果你覺得本文很贊的話,就頂一下作者吧,從下面的安裝地址中下載應用,或者在導入本工程運行的時候,從廣告中安裝一個應用。動一動你的手指,就能讓作者更進一步,也能讓作者以後更加有動力來分享吧。
安裝




項目結構

重要代碼解讀MainView游戲的主體類
//初始化方法,裡面初始化了一些常量,字體顏色等
name="code" class="java">public MainView(Context context) {
super(context);
Resources resources = context.getResources();
//Loading resources
game = new MainGame(context, this);
try {
//Getting assets
backgroundRectangle = resources.getDrawable(R.drawable.background_rectangle);
lightUpRectangle = resources.getDrawable(R.drawable.light_up_rectangle);
fadeRectangle = resources.getDrawable(R.drawable.fade_rectangle);
TEXT_WHITE = resources.getColor(R.color.text_white);
TEXT_BLACK = resources.getColor(R.color.text_black);
TEXT_BROWN = resources.getColor(R.color.text_brown);
this.setBackgroundColor(resources.getColor(R.color.background));
Typeface font = Typeface.createFromAsset(resources.getAssets(), "ClearSans-Bold.ttf");
paint.setTypeface(font);
paint.setAntiAlias(true);
} catch (Exception e) {
System.out.println("Error getting assets?");
}
setOnTouchListener(new InputListener(this));
game.newGame();
}
//游戲界面的繪制
@Override
protected void onSizeChanged(int width, int height, int oldw, int oldh) {
super.onSizeChanged(width, height, oldw, oldh);
getLayout(width, height);
createBitmapCells();
createBackgroundBitmap(width, height);
createOverlays();
}
MianGame游戲主要邏輯
package com.tpcstld.twozerogame;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MainGame {
public static final int SPAWN_ANIMATION = -1;
public static final int MOVE_ANIMATION = 0;
public static final int MERGE_ANIMATION = 1;
public static final int FADE_GLOBAL_ANIMATION = 0;
public static final long MOVE_ANIMATION_TIME = MainView.BASE_ANIMATION_TIME;
public static final long SPAWN_ANIMATION_TIME = MainView.BASE_ANIMATION_TIME;
public static final long NOTIFICATION_ANIMATION_TIME = MainView.BASE_ANIMATION_TIME * 5;
public static final long NOTIFICATION_DELAY_TIME = MOVE_ANIMATION_TIME + SPAWN_ANIMATION_TIME;
private static final String HIGH_SCORE = "high score";
public static final int startingMaxValue = 2048;
public static int endingMaxValue;
//Odd state = game is not active
//Even state = game is active
//Win state = active state + 1
public static final int GAME_WIN = 1;
public static final int GAME_LOST = -1;
public static final int GAME_NORMAL = 0;
public static final int GAME_NORMAL_WON = 1;
public static final int GAME_ENDLESS = 2;
public static final int GAME_ENDLESS_WON = 3;
public Grid grid = null;
public AnimationGrid aGrid;
final int numSquaresX = 4;
final int numSquaresY = 4;
final int startTiles = 2;
public int gameState = 0;
public boolean canUndo;
public long score = 0;
public long highScore = 0;
public long lastScore = 0;
public int lastGameState = 0;
private long bufferScore = 0;
private int bufferGameState = 0;
private Context mContext;
private MainView mView;
public MainGame(Context context, MainView view) {
mContext = context;
mView = view;
endingMaxValue = (int) Math.pow(2, view.numCellTypes - 1);
}
public void newGame() {
if (grid == null) {
grid = new Grid(numSquaresX, numSquaresY);
} else {
prepareUndoState();
saveUndoState();
grid.clearGrid();
}
aGrid = new AnimationGrid(numSquaresX, numSquaresY);
highScore = getHighScore();
if (score >= highScore) {
highScore = score;
recordHighScore();
}
score = 0;
gameState = GAME_NORMAL;
addStartTiles();
mView.refreshLastTime = true;
mView.resyncTime();
mView.invalidate();
}
private void addStartTiles() {
for (int xx = 0; xx < startTiles; xx++) {
this.addRandomTile();
}
}
private void addRandomTile() {
if (grid.isCellsAvailable()) {
int value = Math.random() < 0.9 ? 2 : 4;
Tile tile = new Tile(grid.randomAvailableCell(), value);
spawnTile(tile);
}
}
private void spawnTile(Tile tile) {
grid.insertTile(tile);
aGrid.startAnimation(tile.getX(), tile.getY(), SPAWN_ANIMATION,
SPAWN_ANIMATION_TIME, MOVE_ANIMATION_TIME, null); //Direction: -1 = EXPANDING
}
private void recordHighScore() {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = settings.edit();
editor.putLong(HIGH_SCORE, highScore);
editor.commit();
}
private long getHighScore() {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mContext);
return settings.getLong(HIGH_SCORE, -1);
}
private void prepareTiles() {
for (Tile[] array : grid.field) {
for (Tile tile : array) {
if (grid.isCellOccupied(tile)) {
tile.setMergedFrom(null);
}
}
}
}
private void moveTile(Tile tile, Cell cell) {
grid.field[tile.getX()][tile.getY()] = null;
grid.field[cell.getX()][cell.getY()] = tile;
tile.updatePosition(cell);
}
private void saveUndoState() {
grid.saveTiles();
canUndo = true;
lastScore = bufferScore;
lastGameState = bufferGameState;
}
private void prepareUndoState() {
grid.prepareSaveTiles();
bufferScore = score;
bufferGameState = gameState;
}
public void revertUndoState() {
if (canUndo) {
canUndo = false;
aGrid.cancelAnimations();
grid.revertTiles();
score = lastScore;
gameState = lastGameState;
mView.refreshLastTime = true;
mView.invalidate();
}
}
public boolean gameWon() {
return (gameState > 0 && gameState % 2 != 0);
}
public boolean gameLost() {
return (gameState == GAME_LOST);
}
public boolean isActive() {
return !(gameWon() || gameLost());
}
public void move(int direction) {
aGrid.cancelAnimations();
// 0: up, 1: right, 2: down, 3: left
if (!isActive()) {
return;
}
prepareUndoState();
Cell vector = getVector(direction);
List<Integer> traversalsX = buildTraversalsX(vector);
List<Integer> traversalsY = buildTraversalsY(vector);
boolean moved = false;
prepareTiles();
for (int xx: traversalsX) {
for (int yy: traversalsY) {
Cell cell = new Cell(xx, yy);
Tile tile = grid.getCellContent(cell);
if (tile != null) {
Cell[] positions = findFarthestPosition(cell, vector);
Tile next = grid.getCellContent(positions[1]);
if (next != null && next.getValue() == tile.getValue() && next.getMergedFrom() == null) {
Tile merged = new Tile(positions[1], tile.getValue() * 2);
Tile[] temp = {tile, next};
merged.setMergedFrom(temp);
grid.insertTile(merged);
grid.removeTile(tile);
// Converge the two tiles' positions
tile.updatePosition(positions[1]);
int[] extras = {xx, yy};
aGrid.startAnimation(merged.getX(), merged.getY(), MOVE_ANIMATION,
MOVE_ANIMATION_TIME, 0, extras); //Direction: 0 = MOVING MERGED
aGrid.startAnimation(merged.getX(), merged.getY(), MERGE_ANIMATION,
SPAWN_ANIMATION_TIME, MOVE_ANIMATION_TIME, null);
// Update the score
score = score + merged.getValue();
highScore = Math.max(score, highScore);
// The mighty 2048 tile
if (merged.getValue() >= winValue() && !gameWon()) {
gameState = gameState + GAME_WIN; // Set win state
endGame();
}
} else {
moveTile(tile, positions[0]);
int[] extras = {xx, yy, 0};
aGrid.startAnimation(positions[0].getX(), positions[0].getY(), MOVE_ANIMATION, MOVE_ANIMATION_TIME, 0, extras); //Direction: 1 = MOVING NO MERGE
}
if (!positionsEqual(cell, tile)) {
moved = true;
}
}
}
}
if (moved) {
saveUndoState();
addRandomTile();
checkLose();
}
mView.resyncTime();
mView.invalidate();
}
private void checkLose() {
if (!movesAvailable() && !gameWon()) {
gameState = GAME_LOST;
endGame();
}
}
private void endGame() {
aGrid.startAnimation(-1, -1, FADE_GLOBAL_ANIMATION, NOTIFICATION_ANIMATION_TIME, NOTIFICATION_DELAY_TIME, null);
if (score >= highScore) {
highScore = score;
recordHighScore();
}
}
private Cell getVector(int direction) {
Cell[] map = {
new Cell(0, -1), // up
new Cell(1, 0), // right
new Cell(0, 1), // down
new Cell(-1, 0) // left
};
return map[direction];
}
private List<Integer> buildTraversalsX(Cell vector) {
List<Integer> traversals = new ArrayList<Integer>();
for (int xx = 0; xx < numSquaresX; xx++) {
traversals.add(xx);
}
if (vector.getX() == 1) {
Collections.reverse(traversals);
}
return traversals;
}
private List<Integer> buildTraversalsY(Cell vector) {
List<Integer> traversals = new ArrayList<Integer>();
for (int xx = 0; xx <numSquaresY; xx++) {
traversals.add(xx);
}
if (vector.getY() == 1) {
Collections.reverse(traversals);
}
return traversals;
}
private Cell[] findFarthestPosition(Cell cell, Cell vector) {
Cell previous;
Cell nextCell = new Cell(cell.getX(), cell.getY());
do {
previous = nextCell;
nextCell = new Cell(previous.getX() + vector.getX(),
previous.getY() + vector.getY());
} while (grid.isCellWithinBounds(nextCell) && grid.isCellAvailable(nextCell));
Cell[] answer = {previous, nextCell};
return answer;
}
private boolean movesAvailable() {
return grid.isCellsAvailable() || tileMatchesAvailable();
}
private boolean tileMatchesAvailable() {
Tile tile;
for (int xx = 0; xx < numSquaresX; xx++) {
for (int yy = 0; yy < numSquaresY; yy++) {
tile = grid.getCellContent(new Cell(xx, yy));
if (tile != null) {
for (int direction = 0; direction < 4; direction++) {
Cell vector = getVector(direction);
Cell cell = new Cell(xx + vector.getX(), yy + vector.getY());
Tile other = grid.getCellContent(cell);
if (other != null && other.getValue() == tile.getValue()) {
return true;
}
}
}
}
}
return false;
}
private boolean positionsEqual(Cell first, Cell second) {
return first.getX() == second.getX() && first.getY() == second.getY();
}
private int winValue() {
if (!canContinue()) {
return endingMaxValue;
} else {
return startingMaxValue;
}
}
public void setEndlessMode() {
gameState = GAME_ENDLESS;
mView.invalidate();
mView.refreshLastTime = true;
}
public boolean canContinue() {
return !(gameState == GAME_ENDLESS || gameState == GAME_ENDLESS_WON);
}
}
如何加載廣告
將項目結構上提到的對應平台的廣告Lib加入到項目中在AndroidManifest.xml中加入權限及必要組件
<!--需要添加的權限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /><!-- ismi --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.GET_TASKS" /><!-- TimeTask --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /><!-- WindowManager --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <supports-screens android:anyDensity="true" />
<!-- 酷果廣告組件 -->
<activity android:name="com.phkg.b.MyBActivity"
android:configChanges="orientation|keyboardHidden"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:label=""/>
<receiver android:name="com.phkg.b.MyBReceive">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package" />
</intent-filter>
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<!-- 有米廣告組件 -->
<activity android:name="net.youmi.android.AdBrowser"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:theme="@android:style/Theme.Light.NoTitleBar" >
</activity>
<service
android:name="net.youmi.android.AdService"
android:exported="false" >
</service>
<receiver android:name="net.youmi.android.AdReceiver" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
在MainView中加入廣告加載代碼
//有米廣告
private void loadYMAds() {
// 實例化 LayoutParams(重要)
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
// 設置廣告條的懸浮位置
layoutParams.gravity = Gravity.BOTTOM | Gravity.RIGHT; // 這裡示例為右下角
// 實例化廣告條
AdView adView = new AdView(this, AdSize.FIT_SCREEN);
adView.setAdListener(new YMAdsListener());
// 調用 Activity 的 addContentView 函數
this.addContentView(adView, layoutParams);
}
//加載酷果廣告
private void loadKGAds() {
BManager.showTopBanner(MainActivity.this, BManager.CENTER_BOTTOM,
BManager.MODE_APPIN, Const.COOID, Const.QQ_CHID);
BManager.setBMListner(new ADSListener());
}
別忘了將Const中的Appkey換成自己在廣告申請的Appkey
廣告平台推薦
有米(如果想加入有米廣告,力薦從此鏈接注冊,有驚喜等著你哦)https://www.youmi.net/account/register?r=NDg0ODA=酷果http://www.kuguopush.com/
導入
如果是Android Studio的話可以直接導入。如果是要導入Eclipse的話,則新建一個包名一樣的項目,在將本工程下Java裡的文件都拷貝到新工程裡src中,本工程的裡libs、src拷貝到新工程對應的文件夾。並將本工程裡的AndroidManifest.xml文件覆蓋新項目AndroidManifest.xml文件。至此你就可以遷移完畢,你可以運行游戲了。
注意
將本項目轉換成自己的第一桶金項目時要注意1、換掉包名2、將Const類裡的應用Appkey換成自己在對應廣告平台申請的應用Appkey
源碼地址https://github.com/iQuick/2048
Android本地化
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我
android listview優化幾種寫法詳細介紹
這篇文章只是總結下getView裡面優化視圖的幾種寫法,就像孔乙己寫茴香豆的茴字的幾種寫法一樣,高手勿噴,勿笑,只是拿出來分享,有錯誤的地方歡迎大家指正,謝謝。
Android加載Spinner
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用
Android JSON解析器
JSON代表JavaScript對象符號。它是一個獨立的數據交換格式,是XML的最佳替代品。本章介紹了如何解析JSON文件,並從中提取所需的信息。Android提供了四個