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
'기술자료 > Android' 카테고리의 다른 글
유용한 팁 모음 사이트.. (1) | 2010.08.23 |
---|---|
자작 FTP 프로그램 (7) | 2010.08.13 |
자작 환율정보 플그램 (3) | 2010.08.13 |
Download Android 1.5 NDK(Native Development Kit) (4) | 2009.09.11 |
윈도우에서 안드로이드 소스 다운로드 받기 (0) | 2009.09.11 |