星空练习


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
public class StarField {
private static final int TILES_NORMAL = 1;
private static final int TILES_LARGE = 5;
private static final int TILES_HUGE = 7;
private static final float AMMOUNT_FEW = 3f;
private static final float AMMOUNT_NORMAL = 2f;
private static final float AMMOUNT_LOTS = 0.2f;
Paint mPaintFill = new Paint();
Paint mPaintStar = new Paint();
Paint mPaintText = new Paint();
private String TAG = getClass().getSimpleName();
private SurfaceHolder surfaceHolder;
private boolean mVisible = true;
private Handler mHandler = new Handler();
private int mWidth, mHeight, xWidth;
private int mOffsetSpan;
private int mOffset = 1;
private int mTiles = TILES_NORMAL;
private int mDirection = Stars.RIGHT;
private float mAmmount = AMMOUNT_FEW;
private Stars[] stars;
private boolean firstTime = true;
private Runnable mDraw = new Runnable() {
@Override
public void run() {
drawFrame();
}
};
public StarField(SurfaceHolder surfaceHolder, int mWidth, int mHeight) {
this.surfaceHolder = surfaceHolder;
this.mWidth = mWidth;
this.mHeight = mHeight;
//背景画笔
mPaintFill.setStyle(Paint.Style.FILL);
mPaintFill.setColor(Color.BLACK);
//星星画笔
mPaintStar.setStyle(Paint.Style.FILL);
mPaintStar.setColor(Color.WHITE);
//抗锯齿
mPaintStar.setAntiAlias(true);
}
public void start() {
drawFrame();
}
public void stop() {
mVisible = false;
//移除runnable,停止动画
mHandler.removeCallbacks(mDraw);
}
private void updateXWidthAndOffsetSpan() {
//屏幕宽*1
xWidth = mWidth * mTiles;
//0
mOffsetSpan = mWidth * (mTiles - 1);
}
private void drawFrame() {
Canvas c = null;
if (firstTime) {
firstTime = false;
updateXWidthAndOffsetSpan();
try {
c = surfaceHolder.lockCanvas();
if (c != null) {
//画出背景
c.drawRect(0, 0, mWidth, mHeight, mPaintFill);
}
} finally {
if (c != null) surfaceHolder.unlockCanvasAndPost(c);
c = null;
}
//大小,速度,数量,宽,高
Stars far = new Stars(1f, 1f, Math.round(3 * mAmmount), xWidth, mHeight);
Stars middle = new Stars(2.1f, 1.5f, Math.round(5 * mAmmount), xWidth, mHeight);
Stars near = new Stars(2.9f, 2.5f, Math.round(7 * mAmmount), xWidth, mHeight);
Stars close = new Stars(4f, 15f, Math.round(40 * mAmmount), xWidth, mHeight);
stars = new Stars[]{far, middle, near, close};
int steps = mWidth * 2;
//计算所有类型的星星数据
for (Stars star : stars) {
//计算出每一颗星星轨迹
for (int i = 0; i < steps; i++) {
star.step(mDirection);
}
}
}
try {
c = surfaceHolder.lockCanvas();
if (c != null) {
c.drawRect(0, 0, mWidth, mHeight, mPaintFill);
for (Stars star : stars) {
star.step(mDirection);
star.draw(c, mWidth, mOffset, mPaintStar);
}
}
} finally {
if (c != null) surfaceHolder.unlockCanvasAndPost(c);
}
mHandler.removeCallbacks(mDraw);
if (mVisible) {
mHandler.postDelayed(mDraw, 40);
}
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
public class Stars {
public static final int LEFT = 0;
public static final int RIGHT = 1;
public static final int RANDOM = 2;
private final ArrayList<Pos> poss;
private final ArrayList<Pos> old;
private float size;
private float speed;
private int number;
private Random r = new Random();
private int mWidth, mHeight;
public Stars(float size, float speed, int number, int width, int height) {
this.size = size;
this.speed = speed;
this.number = number;
mWidth = width;
mHeight = height;
poss = new ArrayList<Stars.Pos>();
old = new ArrayList<Stars.Pos>();
}
public void step(int direction) {
if (r.nextInt(number) == 0) {
int size = old.size();
if (size > 0) {
poss.add(old.remove(size - 1));
} else {
if (direction == RANDOM) {
direction = r.nextInt(RANDOM); // Random direction
}
poss.add(new Pos(-1, 0, direction));
}
}
int width = mWidth;
int height = mHeight;
synchronized (poss) {
Iterator<Pos> itr = poss.iterator();
while (itr.hasNext()) {
Pos pos = itr.next();
switch (pos.mDirection) {
case RIGHT:
if (pos.x > width) {
pos.x = -1;
old.add(pos);
itr.remove();
continue;
}
if (pos.x < 0) {
pos.x = 0;
pos.y = r.nextInt() % height;
}
break;
case LEFT:
if (pos.x < 0) {
pos.x = mWidth + 1;
old.add(pos);
itr.remove();
continue;
}
if (pos.x > mWidth) {
pos.x = mWidth;
pos.y = r.nextInt() % height;
}
break;
}
pos.updatePos(speed);
}
}
}
public void draw(Canvas c, int width, int offset, Paint p) {
for (Pos pos : poss) {
if (pos.x + size > offset && pos.x < offset + width) {
c.drawRect(pos.x - offset, pos.y, pos.x - offset + size, pos.y + size, p);
}
}
}
//记录星星位置信息
private static class Pos {
private float x, y;
private int mDirection;
public Pos(float x, float y, int direction) {
this.x = x;
this.y = y;
mDirection = direction;
}
//更新坐标
public void updatePos(float move) {
switch (mDirection) {
case RIGHT:
x += move;
break;
case LEFT:
x -= move;
break;
}
}
}
}

使用:

1
2
StarField starField = new StarField(surfaceView.getHolder(),w,h);
starField.start();