سورس بازی NPuzzle در اندروید
چهارشنبه 16 فروردین 1396در این مقاله می خواهیم یک بازی ساده و زیبا را به نام پازل آموزش دهیم بازی به این صورت است که شما دو تصویر دارید و می توانید این عکس ها را جا به جا نمایید و از راست به چپ و یا از چپ به راست بالا به پایین و یا پایین به بالا حرکت دهید تا تصویر درست در بیاید.
این بازی 7 لایه ی layout دارد
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/scoreView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/scoreText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="22dp" android:text="@string/scoreText"/> <TextView android:id="@+id/numMoves" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="22dp" android:text="@string/score"/> </LinearLayout>
این لایه شماره امتیاز و تعداد حرکات پازل را توضیح می دهد.
و 8 تا کلاس جاوا دارد که یکی از آن ها را به اختصار توضیح می دهیم:
مثلا کلاس زیر برای شروع بازی توقف بازی و حرکت تصاویر بین سطر ها و ستون ها است که به صورت زیر است:
/********************************************** * GamePlay - the presentation of the game * * * * Author: Jacky, Chen * * * * Last Modified: Feb, 18th, 2012 * * * * Version: 1.0 * * * **********************************************/ package com.qqending.npuzzle; import android.app.Activity; import android.view.Menu; import android.view.LayoutInflater; import android.view.MenuInflater; import android.view.MenuItem; import android.content.Intent; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.RelativeLayout.LayoutParams; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.graphics.BitmapFactory; import android.util.Log; import android.os.Bundle; import android.net.Uri; import java.io.InputStream; import java.io.FileNotFoundException; public class GamePlay extends Activity { protected static final int BASE_ID = 10; private final int ERROR = -1; private final int SCREEN_PADDING = 100; private GameController gc; private int screenWidth; private int screenHeight; private int dimension; private Bitmap scaledImg; private int tileWidth; private int tileHeight; private boolean clickable = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //create a game controller which would be the intermediate layer gc = new GameController(this); //get the height and the width of the screen screenWidth = this.getResources().getDisplayMetrics().widthPixels; screenHeight = this.getResources().getDisplayMetrics().heightPixels; //get the selected image and scales it to a proper size Intent i = this.getIntent(); int imageId = i.getIntExtra("imageId", ERROR); if(imageId != ERROR) { scaledImg = scaleBitmap(imageId); } else { scaledImg = scaleBitmap(i.getData()); } //start the game gc.start(); } @Override protected void onPause() { gc.saveGame(); super.onPause(); } @Override public void onBackPressed() { gc.changeImage(); } //create the puzzle public void createPuzzle(int[] config, int dimension, boolean clickable) { RelativeLayout root = (RelativeLayout) findViewById(R.id.root_layout); //remove the old views root.removeAllViews(); this.dimension = dimension; this.clickable = clickable; //get the tile size from the scaled image tileWidth = scaledImg.getWidth() / dimension; tileHeight = scaledImg.getHeight() / dimension; //add rows to the root LinearLayout for(int i = 0; i < dimension; i++) { root.addView(createRow(config,i)); } root.addView(createScoreBoard(root)); } //create a row of tiles and each row is a LinearLayout itself private LinearLayout createRow(int[] config, int row) { LayoutInflater inflater = LayoutInflater.from(this); LinearLayout newRow = (LinearLayout) inflater.inflate(R.layout.puzzle_row, null); newRow.setId(BASE_ID - 1 - row); if(row != 0) { final LayoutParams p = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); p.addRule(RelativeLayout.BELOW, BASE_ID - row); p.addRule(RelativeLayout.ALIGN_LEFT, BASE_ID - row); newRow.setLayoutParams(p); } int id, index; //create corresponding numbers of tiles //and add them to the row for(int i = 0; i < dimension; i++) { index = row * dimension + i; id = config[index]; newRow.addView(createTile(id)); } return newRow; } //crop the image and set it on a tile private ImageView createTile(int id) { //inflate a tile layout from the xml file LayoutInflater inflater = LayoutInflater.from(this); ImageView imgView = (ImageView) inflater.inflate(R.layout.puzzle_tile, null); if(id == 0) { setBlankTile(imgView); } else { setNormalTile(imgView,id); } return imgView; } //overloaded method, used to update the view private ImageView createTile(int id, Drawable drawable) { //inflate a tile layout from the xml file LayoutInflater inflater = LayoutInflater.from(this); ImageView imgView = (ImageView) inflater.inflate(R.layout.puzzle_tile, null); imgView.setId(id); imgView.setImageDrawable(drawable); if(id != BASE_ID) { imgView.setOnClickListener(gc); } return imgView; } private void setNormalTile(ImageView imgView, int id) { Bitmap content = null; //set the id of the tile //id starts from BASE_ID and increase by 1 //when a new tile is created imgView.setId(id + BASE_ID); //array index starts from 0 but our ids starts from 1 //so id need to be decrement by 1 id--; //calculate the pivot of the cropping int row = id / dimension; int col = id - row * dimension; //create a cropped bitmap and the set it on the view try { content = Bitmap.createBitmap(scaledImg, col * tileWidth, row * tileHeight, tileWidth, tileHeight); } catch (OutOfMemoryError e) { Log.e("Npuzzle","GamePlay:OutOfMemory:setNormalTile"); new ErrorAlertDialog(this).show(); } imgView.setImageBitmap(content); if(clickable) { imgView.setOnClickListener(gc); } } private void setBlankTile(ImageView imgView) { Bitmap content = null; imgView.setId(BASE_ID); try { //create and scales the blank tile image Bitmap origin = BitmapFactory.decodeResource(this.getResources(), R.drawable.blanktile); content = Bitmap.createScaledBitmap(origin, tileWidth, tileHeight, false); origin.recycle(); } catch (OutOfMemoryError e) { Log.e("Npuzzle","GamePlay:OutOfMemory:setBlankTile"); new ErrorAlertDialog(this).show(); } //set the image and set it to not clickable imgView.setImageBitmap(content); imgView.setClickable(false); } private LinearLayout createScoreBoard(RelativeLayout root) { //inflate a scoreBoard layout from the xml file LayoutInflater inflater = LayoutInflater.from(this); LinearLayout scoreView = (LinearLayout) inflater.inflate(R.layout.scoreview, null); final LayoutParams p = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); if(screenWidth > screenHeight) { p.addRule(RelativeLayout.ALIGN_TOP, BASE_ID - 1); p.addRule(RelativeLayout.RIGHT_OF, BASE_ID - 1); } else { p.addRule(RelativeLayout.ALIGN_PARENT_TOP); p.addRule(RelativeLayout.ALIGN_RIGHT, BASE_ID - 1); root.setIgnoreGravity(R.id.scoreView); } scoreView.setLayoutParams(p); return scoreView; } //return the smaller one of the two //if they are equal then return the second one private double getMin(double x, double y) { double result = x; if(Double.compare(y, x) <= 0) { result = y; } return result; } //pass in the image id and return a scaled bitmap of the original bitmap private Bitmap scaleBitmap(int id) { Bitmap scaledImg = null; try { //get the image from it's id that got passed in Bitmap origin = BitmapFactory.decodeResource(this.getResources(), id); scaledImg = createScaledBitmap(origin); } catch (OutOfMemoryError e) { Log.e("Npuzzle","GamePlay:OutOfMemory:scaledBitmap " + "image id is " + id); new ErrorAlertDialog(this).show(); } return scaledImg; } private Bitmap scaleBitmap(Uri uri) { Bitmap scaledImg = null; try { InputStream imageStream = getContentResolver().openInputStream(uri); Bitmap origin = BitmapFactory.decodeStream(imageStream); scaledImg = createScaledBitmap(origin); } catch (OutOfMemoryError oe) { Log.e("Npuzzle","GamePlay:OutOfMemory:scaledBitmap " + "image uri is " + uri); new ErrorAlertDialog(this).show(); } catch (FileNotFoundException fe) { Log.e("Npuzzle","GamePlay:FileNotFound:scaledBitmap " + "image uri is " + uri); new ErrorAlertDialog(this).show(); } return scaledImg; } private Bitmap createScaledBitmap(Bitmap origin) throws OutOfMemoryError { Bitmap scaledImg = null; //get the height and the width of that image int imageWidth = origin.getWidth(); int imageHeight = origin.getHeight(); //compute the ratio of image to the screen //and pick the smaller one as the scaling ratio //so that image would fit the screen correctly double ratio1 = (double)screenWidth / imageWidth; double ratio2 = (double)screenHeight / imageHeight; double ratio = getMin(ratio1,ratio2); //set paddings so that the image wouldn't full fill the entire screen int scaledWidth = (int) (imageWidth * ratio) - SCREEN_PADDING; int scaledHeight = (int) ((imageHeight - SCREEN_PADDING) * ratio); //get she scaled image and recycle the original one scaledImg = Bitmap.createScaledBitmap(origin, scaledWidth, scaledHeight, false); origin.recycle(); return scaledImg; } //swap the blank tile with the tapped tile public void updateLayout(int id) { ImageView blank = (ImageView) findViewById(BASE_ID); ImageView tile = (ImageView) findViewById(id); LinearLayout blankParent = (LinearLayout)blank.getParent(); LinearLayout tileParent = (LinearLayout)tile.getParent(); int blankPosition = blankParent.indexOfChild(blank); int tilePosition = tileParent.indexOfChild(tile); Drawable blankDrawable = blank.getDrawable(); Drawable tileDrawable = tile.getDrawable(); blankParent.removeViewAt(blankPosition); blankParent.addView(createTile(id,tileDrawable),blankPosition); tileParent.removeViewAt(tilePosition); tileParent.addView(createTile(BASE_ID,blankDrawable),tilePosition); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu_layout, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.easy: gc.changeDifficulty(GameController.EASY); break; case R.id.medium: gc.changeDifficulty(GameController.MEDIUM); break; case R.id.hard: gc.changeDifficulty(GameController.HARD); break; case R.id.shuffle: gc.shuffle(); break; case R.id.restart: gc.start(); break; case R.id.change_puzzle: gc.changeImage(); break; default: } return true; } }
خروجی کار به صورت زیر است:
- Android
- 2k بازدید
- 5 تشکر