sample研究之snake

贪吃蛇实现的原理:根据屏幕的宽高,根据贪吃蛇的节点高度,将屏幕分割成二维网格,在网格中通过组合显示不同的图片颜色,来构成蛇的身体,要吃的苹果,以及墙壁。
收获:1.学习建立自定义的View类
一.详细分解:
1.TileView类:该类继承自View类。主要实现加载贪吃蛇画面的基本元素,比如根据屏幕宽高计算出应将画面分割成的二维网格数。其中tile是其中最小的元素。
主要方法:


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mXTileCount = (int) Math.floor(w / mTileSize);//tile在x轴的数量
mYTileCount = (int) Math.floor(h / mTileSize);//tile在y轴的数量

mXOffset = ((w - (mTileSize * mXTileCount)) / 2);//tile相对x轴偏移量
mYOffset = ((h - (mTileSize * mYTileCount)) / 2);//tile相对y轴偏移量

mTileGrid = new int[mXTileCount][mYTileCount];//二维网格
clearTiles();
}

该方法重载了View类中的方法,通过传入的屏幕宽高参数,计算可以将屏幕x.y轴分为多少个网格。


@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int x = 0; x < mXTileCount; x += 1) {
for (int y = 0; y < mYTileCount; y += 1) {
if (mTileGrid[x][y] > 0) {
canvas.drawBitmap(mTileArray[mTileGrid[x][y]],
mXOffset + x * mTileSize,
mYOffset + y * mTileSize,
mPaint);
}
}
}

}

画图,将屏幕根据二维网格数进行分割

2.SnakeView类:为TileView的子类,实现贪吃蛇游戏画面初始化、方向键控制、记分、切换到其他程序是游戏参数的保存等。

private void initSnakeView() {
setFocusable(true);

Resources r = this.getContext().getResources();

resetTiles(4);
loadTile(RED_STAR, r.getDrawable(R.drawable.redstar));
loadTile(YELLOW_STAR, r.getDrawable(R.drawable.yellowstar));
loadTile(GREEN_STAR, r.getDrawable(R.drawable.greenstar));

}


初始化贪吃蛇画面


private void initNewGame() {
mSnakeTrail.clear();
mAppleList.clear();

// For now we're just going to load up a short default eastbound snake
// that's just turned north


mSnakeTrail.add(new Coordinate(7, 7));
mSnakeTrail.add(new Coordinate(6, 7));
mSnakeTrail.add(new Coordinate(5, 7));
mSnakeTrail.add(new Coordinate(4, 7));
mSnakeTrail.add(new Coordinate(3, 7));
mSnakeTrail.add(new Coordinate(2, 7));
mNextDirection = NORTH;

// Two apples to start with
addRandomApple();
addRandomApple();

mMoveDelay = 600;
mScore = 0;
}


新建一个游戏


private void updateWalls() {
for (int x = 0; x < mXTileCount; x++) {
setTile(GREEN_STAR, x, 0);
setTile(GREEN_STAR, x, mYTileCount - 1);
}
for (int y = 1; y < mYTileCount - 1; y++) {
setTile(GREEN_STAR, 0, y);
setTile(GREEN_STAR, mXTileCount - 1, y);
}
}

画墙


private void updateSnake() {
boolean growSnake = false;

// grab the snake by the head
Coordinate head = mSnakeTrail.get(0);
Coordinate newHead = new Coordinate(1, 1);

mDirection = mNextDirection;

switch (mDirection) {
case EAST: {
newHead = new Coordinate(head.x + 1, head.y);
break;
}
case WEST: {
newHead = new Coordinate(head.x - 1, head.y);
break;
}
case NORTH: {
newHead = new Coordinate(head.x, head.y - 1);
break;
}
case SOUTH: {
newHead = new Coordinate(head.x, head.y + 1);
break;
}
}

// Collision detection
// For now we have a 1-square wall around the entire arena
if ((newHead.x < 1) || (newHead.y < 1) || (newHead.x > mXTileCount - 2)
|| (newHead.y > mYTileCount - 2)) {
setMode(LOSE);
return;

}

// Look for collisions with itself
int snakelength = mSnakeTrail.size();
for (int snakeindex = 0; snakeindex < snakelength; snakeindex++) {
Coordinate c = mSnakeTrail.get(snakeindex);
if (c.equals(newHead)) {
setMode(LOSE);
return;
}
}

// Look for apples
int applecount = mAppleList.size();
for (int appleindex = 0; appleindex < applecount; appleindex++) {
Coordinate c = mAppleList.get(appleindex);
if (c.equals(newHead)) {
mAppleList.remove(c);
addRandomApple();

mScore++;
mMoveDelay *= 0.9;

growSnake = true;
}
}

// push a new head onto the ArrayList and pull off the tail
mSnakeTrail.add(0, newHead);
// except if we want the snake to grow
if (!growSnake) {
mSnakeTrail.remove(mSnakeTrail.size() - 1);
}

int index = 0;
for (Coordinate c : mSnakeTrail) {
if (index == 0) {
setTile(YELLOW_STAR, c.x, c.y);
} else {
setTile(RED_STAR, c.x, c.y);
}
index++;
}

}

画蛇


private void updateApples() {
for (Coordinate c : mAppleList) {
setTile(YELLOW_STAR, c.x, c.y);
}
}

画苹果


public Bundle saveState() {
Bundle map = new Bundle();

map.putIntArray("mAppleList", coordArrayListToArray(mAppleList));
map.putInt("mDirection", Integer.valueOf(mDirection));
map.putInt("mNextDirection", Integer.valueOf(mNextDirection));
map.putLong("mMoveDelay", Long.valueOf(mMoveDelay));
map.putLong("mScore", Long.valueOf(mScore));
map.putIntArray("mSnakeTrail", coordArrayListToArray(mSnakeTrail));

return map;
}

保存数据


public void restoreState(Bundle icicle) {
setMode(PAUSE);

mAppleList = coordArrayToArrayList(icicle.getIntArray("mAppleList"));
mDirection = icicle.getInt("mDirection");
mNextDirection = icicle.getInt("mNextDirection");
mMoveDelay = icicle.getLong("mMoveDelay");
mScore = icicle.getLong("mScore");
mSnakeTrail = coordArrayToArrayList(icicle.getIntArray("mSnakeTrail"));
}

重新加载数据

3.Snake-activty类
这个类比较简单,就不做记录了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值