본문 바로가기
기술자료/Android

안드로이드 개발어플 서비스~~~~ 테트리스 수정본~!!

by 알 수 없는 사용자 2010. 11. 26.
728x90
반응형

테트리스 수정본입니다.
에뮬에서만 개발하다보니..
쿼티 키패드 위주로 생각했었는데..
터치로만 된게 더 많더군요..
에뮬보다는 실제 안드로이드 폰에서 어떻게 사용될지 파악해서 만드는게 더 중요한듯 합니다.
안드로이드 버전도 중요하고요.
무조건 2.2 버전보다는 아직 2.1버전을 쓰고 있는 안드로이드폰이 있으니..
어떤버전에 맞춰야하는지도 생각을 해야겠네요.

이 테트리스는 2주간 안드로이드 공부해보다가 sdk 공개 플래폼에서 snake 게임을 참고로
만들어본건데.. 좀 허접하긴 합니다 ㅋㅋ
디자인도 영 엉망이라..
플젝트 끝나고 심심해서 예전에 공부하면서 만들었던거 걍 수정해봤네요..
이 프로그램을 실행하기 위해선 이미지 2개가 필요합니다.


중요~~!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
여긴 파일전송이 막혀 있어서 ㅎㅎ
res/drawable 폴더에 width, height 24픽셀되는 이미지 파일을
block.png, tile.png 만들어서 넣어주기만 하면 됩니다.
이거 하다가 하나 하다 말았는데 ㅋㅋ
sqlite3 이용해서 획득한 점수 이름과 점수 및 날짜, 시간 기록할려고 했었는데
하다 말았네요 ㅎㅎ
밑에 있는 ftp 프로그램의 db adapter 사용해서 만들어보면 괜찮을듯 합니다.

테트리스가 라이센스가 있어서 마켓 그런곳에는 못올릴테니..(맞나? -_-?)
걍 공부용으로만 쓰세욤~




개발시 참고 자료
android sdk의 snake 게임
win api 1권의 테트리스게임




/*********************************
AndroidManifest.xml
*********************************/
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.btb.tetris"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".AndroTetris"
                  android:label="@string/app_name"
                  android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>


</manifest> 



/*********************************
string.xml
*********************************/
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, AndroTetris!</string>
    <string name="app_name">Andro Tetris</string>
    <string name="tetris_layout_text_text"></string>
<string name="tetris_layout_text_score"></string>
</resources>



/*********************************
attrs.xml
*********************************/
<resources>
<declare-styleable name="TileView">
<attr name="tileSize" format="integer" />
</declare-styleable>
</resources>



/*********************************
main.xml
*********************************/
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
<com.btb.tetris.AndroTetrisView
        android:id="@+id/tetris"
android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        tileSize="12"/>
<TextView
   android:id="@+id/score"
   android:text="@string/tetris_layout_text_score"
   android:visibility="visible"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_centerInParent="true"
   android:textColor="#ff8888ff"
   android:textSize="24sp"/>
    <RelativeLayout
        android:layout_width="fill_parent"
android:layout_height="fill_parent" >

<TextView
   android:id="@+id/text"
   android:text="@string/tetris_layout_text_text"
   android:visibility="visible"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_centerInParent="true"
   android:gravity="center_horizontal"
   android:textColor="#ff8888ff"
   android:textSize="24sp"/>
    </RelativeLayout>
<LinearLayout 
android:id="@+id/control" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:visibility="invisible">
<Button 
android:text="←" 
android:id="@+id/btnLeft" 
android:layout_width="80dip" 
android:layout_height="wrap_content" />
<Button 
android:text="↑" 
android:id="@+id/btnUp" 
android:layout_width="80dip" 
android:layout_height="wrap_content" />
<Button 
android:text="→" 
android:id="@+id/btnRight" 
android:layout_width="80dip" 
android:layout_height="wrap_content" />
<Button 
android:text="↓" 
android:id="@+id/btnDown" 
android:layout_width="80dip" 
android:layout_height="wrap_content" />
</LinearLayout>
</FrameLayout>





/*********************************
AndroTetris.java
*********************************/
package com.btb.tetris;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class AndroTetris extends Activity {
    /** Called when the activity is first created. */
private AndroTetrisView mTetrisView;
private static String STATE_KEY = "tetris-view";
private static final int TetrisDialog = 1;
private static final int ScoreDialog = 2;
private static final int START_MENU_ID = Menu.FIRST;
    private static final int SCORE_MENU_ID = Menu.FIRST + 1;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mTetrisView = (AndroTetrisView)findViewById(R.id.tetris);
        mTetrisView.setScoreView((TextView) findViewById(R.id.score));
        mTetrisView.setTextView((TextView) findViewById(R.id.text));
        mTetrisView.setControlView((LinearLayout) findViewById(R.id.control));
        mTetrisView.setLeft((Button) findViewById(R.id.btnLeft));
        mTetrisView.setRight((Button) findViewById(R.id.btnRight));
        mTetrisView.setUp((Button) findViewById(R.id.btnUp));
        mTetrisView.setDown((Button) findViewById(R.id.btnDown));
        
        if(savedInstanceState == null){
         mTetrisView.setMode(AndroTetrisView.READY);
        } else {
         Bundle map = savedInstanceState.getBundle(STATE_KEY);
            if (map != null) {
                //mTetrisView.restoreState(map);
            } else {
                mTetrisView.setMode(AndroTetrisView.PAUSE);
            }
        }
    }

@Override
public void onBackPressed() {
// TODO Auto-generated method stub
if(mTetrisView.returnMode() == mTetrisView.RUNNING)
mTetrisView.setMode(mTetrisView.PAUSE);
showDialog(TetrisDialog);
//super.onBackPressed();
}

@Override
protected Dialog onCreateDialog(int id) {
// TODO Auto-generated method stub
if(id==TetrisDialog){
Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Andro Tetris")
.setMessage("Are you sure exit??")
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
finish();
}
})
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
/*if(mTetrisView.returnMode()==mTetrisView.PAUSE)
mTetrisView.setMode(mTetrisView.RUNNING);*/
}
})
.setIcon(R.drawable.icon)
.create()
.show();
}else if(id==ScoreDialog){
List<String> temp = new ArrayList<String>();
temp.add("red");
temp.add("green");
temp.add("blue");
temp.add("blue");
temp.add("blue");
temp.add("blue");
temp.add("blue");
temp.add("blue");
temp.add("blue");
temp.add("blue");
temp.add("blue");
String [] items = temp.toArray(new String[temp.size()]);
     
Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Tetris Score")
.setItems(items, null)
.setPositiveButton(android.R.string.ok, null)
.setIcon(R.drawable.icon)
.create()
.show();
}
return super.onCreateDialog(id);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
menu.add(0, START_MENU_ID, 0, "Start");
menu.add(0, SCORE_MENU_ID, 0, "Score");
return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
return super.onPrepareOptionsMenu(menu);
}

@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
// TODO Auto-generated method stub
switch(item.getItemId()){
case START_MENU_ID:
if(mTetrisView.returnMode()==mTetrisView.READY || mTetrisView.returnMode()==mTetrisView.LOSE){
mTetrisView.initNewGame();
mTetrisView.setMode(mTetrisView.RUNNING);
mTetrisView.update();
}
mTetrisView.setMode(mTetrisView.RUNNING);
return true;
case SCORE_MENU_ID:
mTetrisView.setMode(mTetrisView.PAUSE);
showDialog(ScoreDialog);
return true;
}
return super.onMenuItemSelected(featureId, item);
}
}




/*********************************
AndroTetrisView.java
*********************************/
package com.btb.tetris;

import java.util.Random;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class AndroTetrisView extends View implements OnClickListener{

private RefreshHandler mRedrawHandler = new RefreshHandler();
public class RefreshHandler extends Handler {

@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
AndroTetrisView.this.update();
AndroTetrisView.this.invalidate();
}
public void sleep(long delayMillis){
this.removeMessages(0);
sendMessageDelayed(obtainMessage(0), delayMillis);
}
}
protected static int mTileSize;
protected static int mXTileCount;
protected static int mYTileCount;
protected static int mXOffset;
protected static int mYOffset;
protected Bitmap[] mTileArray;
public int[][] mTileGrid;
public int[][] board;
private final Paint mPaint = new Paint();
private int mMode = READY;
    public static final int PAUSE = 0;
    public static final int READY = 1;
    public static final int RUNNING = 2;
    public static final int LOSE = 3;
private static final int RED_STAR = 1;
    private static final int BLACK_STAR = 2;

    private TextView mScoreText;
    private TextView mStatusText;
    private LinearLayout mControl;
        
    private long mMoveDelay = 1500;
    
    public int nx = 0;
    public int ny = 0;
    public int brick = 0;
    public int rot = 0;
    public int trot = 0;
    public int nbrick = 0;
    public int score = 0;
    public int bricknum = 0;
    public static Random RNG = new Random();
    
    public static int [][][] shape = {
{{0,0,1,0,2,0,-1,0},{0,0,0,1,0,-1,0,-2},{0,0,1,0,2,0,-1,0},{0,0,0,1,0,-1,0,-2}},
{{0,0,1,0,0,1,1,1},{0,0,1,0,0,1,1,1},{0,0,1,0,0,1,1,1},{0,0,1,0,0,1,1,1}},
{{0,0,-1,0,0,-1,1,-1},{0,0,0,1,-1,0,-1,-1},{0,0,-1,0,0,-1,1,-1},{0,0,0,1,-1,0,-1,-1}},
{{0,0,-1,-1,0,-1,1,0},{0,0,-1,0,-1,1,0,-1},{0,0,-1,-1,0,-1,1,0},{0,0,-1,0,-1,1,0,-1}},
{{0,0,-1,0,1,0,-1,-1},{0,0,0,-1,0,1,-1,1},{0,0,-1,0,1,0,1,1},{0,0,0,-1,0,1,1,-1}},
{{0,0,1,0,-1,0,1,-1},{0,0,0,1,0,-1,-1,-1},{0,0,1,0,-1,0,-1,1},{0,0,0,-1,0,1,1,1}},
{{0,0,-1,0,1,0,0,1},{0,0,0,-1,0,1,1,0},{0,0,-1,0,1,0,0,-1},{0,0,-1,0,0,-1,0,1}},
{{0,0,0,0,0,-1,1,0},{0,0,0,0,-1,0,0,-1},{0,0,0,0,0,1,-1,0},{0,0,0,0,0,1,1,0}}
};
    
    public static final int EMPTY = 1;
    public static final int BRICK = 2;
    public static final int WALL = 3;
    
    private Button mLeft;
    private Button mRight;
    private Button mUp;
    private Button mDown;
public AndroTetrisView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);
mTileSize = a.getInt(R.styleable.TileView_tileSize, 22);
initTetrisView();
}

public AndroTetrisView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);
mTileSize = a.getInt(R.styleable.TileView_tileSize, 22);
initTetrisView();
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
int i,j,x,y;
if(mMode==RUNNING){
for(x=1; x<mXTileCount-1; x++){
for(y=4; y<mYTileCount-3; y++){
setTile(0, x, y);
}
}
for(x=0; x<mXTileCount; x++){
setBoard(BLACK_STAR, x, 3);
setBoard(BLACK_STAR, x, mYTileCount-3);
}
for(y=3; y<mYTileCount-3; y++){
setBoard(BLACK_STAR, 0, y);
setBoard(BLACK_STAR, mXTileCount-1, y);
}
j=0;
for(i=0; i<4; i++){
x = shape[brick][rot][j++];
y = shape[brick][rot][j++];
setTile(RED_STAR, nx+x, ny+y);
}
}
for(x=0; x<mXTileCount; x+=1){
for(y=0; y<mYTileCount-1; y+=1){
if(board[x][y]==1) mTileGrid[x][y]=1;
if(mTileGrid[x][y]>0){
canvas.drawBitmap(mTileArray[mTileGrid[x][y]],
mXOffset+x*mTileSize,
mYOffset+y*mTileSize,
mPaint);
}
}
}
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
mXTileCount = (int)Math.floor(w/mTileSize);
mYTileCount = (int)Math.floor(h/mTileSize);
mXOffset = ((w-(mTileSize*mXTileCount))/2);
mYOffset = ((h-(mTileSize*mYTileCount))/2);
mTileGrid = new int[mXTileCount][mYTileCount];
board = new int[mXTileCount][mYTileCount];
for(int x=0; x<mXTileCount; x++){
for(int y=0; y<mYTileCount; y++){
mTileGrid[x][y] = 0;
board[x][y] = 0;
}
}
clearTiles();
//super.onSizeChanged(w, h, oldw, oldh);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
/*if(mMode==READY){
initNewGame();
setMode(RUNNING);
update();
}*/
return super.onTouchEvent(event);
}

private void initTetrisView(){
setFocusable(true);
Resources r = this.getContext().getResources();
resetTiles(3);
loadTile(RED_STAR, r.getDrawable(R.drawable.block));
loadTile(BLACK_STAR, r.getDrawable(R.drawable.tile));
}
public void resetTiles(int tilecount){
mTileArray = new Bitmap[tilecount];
}
public void loadTile(int key, Drawable tile){
Bitmap bitmap = Bitmap.createBitmap(mTileSize, mTileSize, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
tile.setBounds(0, 0, mTileSize, mTileSize);
tile.draw(canvas);
mTileArray[key] = bitmap;
}
public void setTile(int tileindex, int x, int y){
mTileGrid[x][y] = tileindex;
}
public void setBoard(int boardindex, int x, int y){
board[x][y] = boardindex;
}
public void clearTiles(){
for(int x=0; x<mXTileCount; x++){
for(int y=0; y<mYTileCount; y++){
setTile(0, x, y);
}
}
}
public void clearBoard(){
for(int x=0; x<mXTileCount; x++){
for(int y=0; y<mYTileCount; y++){
setBoard(0, x, y);
}
}
}
public void setScoreView(TextView newView){
mScoreText = newView;
}
public void setTextView(TextView newView){
mStatusText = newView;
}
public void setControlView(LinearLayout newView){
mControl = newView;
}
public void setLeft(Button newView){
mLeft = newView;
}
public void setRight(Button newView){
mRight = newView;
}
public void setUp(Button newView){
mUp = newView;
}
public void setDown(Button newView){
mDown = newView;
}

public void setMode(int newMode){
int oldMode = mMode;
mMode = newMode;
if(newMode==RUNNING & oldMode!=RUNNING){
mStatusText.setVisibility(View.INVISIBLE);
update();
return;
}
Resources res = getContext().getResources();
CharSequence str = " ";
if(newMode == READY){
str = res.getText(R.string.app_name);
}
mStatusText.setText(str);
mStatusText.setVisibility(View.VISIBLE);
}
public void update(){
if(mMode==RUNNING){
//clearTiles();
//updateWalls();
updateTetris();
}
mRedrawHandler.sleep(mMoveDelay);
}
private void updateWalls(){
for(int x=0; x<mXTileCount; x++){
setTile(BLACK_STAR, x, 3);
setTile(BLACK_STAR, x, mYTileCount-3);
setBoard(BLACK_STAR, x, 3);
setBoard(BLACK_STAR, x, mYTileCount-3);
}
for(int y=3; y<mYTileCount-3; y++){
setTile(BLACK_STAR, 0, y);
setTile(BLACK_STAR, mXTileCount-1, y);
setBoard(BLACK_STAR, 0, y);
setBoard(BLACK_STAR, mXTileCount-1, y);
}
}
public void initNewGame() {
clearTiles();
updateWalls();
clearBoard();
nbrick = RNG.nextInt(8);
MakeNewBrick();
int i, j;
for(i=0, j=0; i<4; i++){
board[10+shape[nbrick][0][j++]][1+shape[nbrick][0][j++]] = 1;
}
//mMoveDelay = 1500;
mStatusText.setVisibility(View.INVISIBLE);
String str = "점수 : 0";
CharSequence temp = str;
mScoreText.setText(temp);
mScoreText.setVisibility(View.VISIBLE);
mControl.setVisibility(View.VISIBLE);
//mLeft = (Button) findViewById(R.id.btnLeft);
mLeft.setOnClickListener(this);
//mRight = (Button) findViewById(R.id.btnRight);
mRight.setOnClickListener(this);
//mUp = (Button) findViewById(R.id.btnUp);
mUp.setOnClickListener(this);
//mDown = (Button) findViewById(R.id.btnDown);
mDown.setOnClickListener(this);
    }
public void MakeNewBrick(){
boolean state = false;
if(mMode==RUNNING){
state = true;
}
int i, j, z;
if(state){
for(i=0, j=0; i<4; i++){
z = j;
setBoard(0, 10+shape[nbrick][0][z++], 1+shape[nbrick][0][z++]);
setTile(0, 10+shape[nbrick][0][j++], 1+shape[nbrick][0][j++]);
}
}
bricknum++;
brick = nbrick;
nbrick = RNG.nextInt(8);
nx = 6;
ny = 5;
rot = 0;

if(state){
for(i=0, j=0; i<4; i++){
board[10+shape[nbrick][0][j++]][1+shape[nbrick][0][j++]] = 1;
}
}
if(GetAround(nx, ny, brick, rot)!=0){
setMode(LOSE);
CharSequence str = "GAME OVER";
mStatusText.setText(str);
mStatusText.setVisibility(View.VISIBLE);
mLeft.setClickable(false);
mRight.setClickable(false);
mUp.setClickable(false);
mDown.setClickable(false);
}
}
public int updateTetris(){
if(GetAround(nx, ny+1, brick, rot)!=0){
TestFull();
MakeNewBrick();
return 0;
}else{
ny++;
}
invalidate();
return 1;
}
public int GetAround(int x, int y, int b, int r){
int i, j, k=0;
j = 0;
for(i=0; i<4; i++){
k = max(k, board[x+shape[b][r][j++]][y+shape[b][r][j++]]);
}
return k;
}
public int max(int a, int b){
int k;
if(a>b) k = a;
else k = b;
return k;
}
public void TestFull(){
int i, j, x, y, ty;
int count=0;
int[] arScore = {0, 1, 3, 8, 20};
j = 0;
for(i=0; i<4; i++){
board[nx+shape[brick][rot][j++]][ny+shape[brick][rot][j++]] = 1;
}
brick = -1;
for(y=4; y<mYTileCount-3; y++){
for(x=1; x<mXTileCount-1; x++){
if(board[x][y] == 0) break;
}
if(x==mXTileCount-1){
count++;
for(ty=y; ty>4; ty--){
for(x=1; x<mXTileCount-1; x++){
board[x][ty] = board[x][ty-1];
}
}
mRedrawHandler.sleep(300);
mMoveDelay-=10;
}
}
score += arScore[count];
String str = "점수 : ";
str = str + score;
CharSequence temp = str;
mScoreText.setText(temp);
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(brick==-1) return;
if(v==mUp){
/*if(mMode==READY | mMode==LOSE){
initNewGame();
setMode(RUNNING);
update();
return;
}else if(mMode==PAUSE){
setMode(RUNNING);
update();
return;
}else*/ if(mMode==RUNNING){
trot = (rot==3?0:rot+1);
if(GetAround(nx, ny, brick, trot)==0){
rot = trot;
invalidate();
}
return;
}
return;
}else if(v==mLeft){
if(mMode==RUNNING){
if(GetAround(nx-1, ny, brick, rot)==0) {
nx--;
invalidate();
}
}
return;
}else if(v==mRight){
if(mMode==RUNNING){
if(GetAround(nx+1, ny, brick, rot)==0) {
nx++;
invalidate();
}
}
return;
}else if(v==mDown){
if(mMode==RUNNING){
while(updateTetris()==1){};
}
return;
}
}
public int returnMode(){
return mMode;
}
}






728x90