-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
states.js
203 lines (183 loc) · 6.12 KB
/
states.js
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
import { List } from 'immutable';
import store from '../store';
import { want, isClear, isOver } from '../unit/';
import actions from '../actions';
import { speeds, blankLine, blankMatrix, clearPoints, eachLines } from '../unit/const';
import { music } from '../unit/music';
const getStartMatrix = (startLines) => { // 生成startLines
const getLine = (min, max) => { // 返回标亮个数在min~max之间一行方块, (包含边界)
const count = parseInt((((max - min) + 1) * Math.random()) + min, 10);
const line = [];
for (let i = 0; i < count; i++) { // 插入高亮
line.push(1);
}
for (let i = 0, len = 10 - count; i < len; i++) { // 在随机位置插入灰色
const index = parseInt(((line.length + 1) * Math.random()), 10);
line.splice(index, 0, 0);
}
return List(line);
};
let startMatrix = List([]);
for (let i = 0; i < startLines; i++) {
if (i <= 2) { // 0-3
startMatrix = startMatrix.push(getLine(5, 8));
} else if (i <= 6) { // 4-6
startMatrix = startMatrix.push(getLine(4, 9));
} else { // 7-9
startMatrix = startMatrix.push(getLine(3, 9));
}
}
for (let i = 0, len = 20 - startLines; i < len; i++) { // 插入上部分的灰色
startMatrix = startMatrix.unshift(List(blankLine));
}
return startMatrix;
};
const states = {
// 自动下落setTimeout变量
fallInterval: null,
// 游戏开始
start: () => {
if (music.start) {
music.start();
}
const state = store.getState();
states.dispatchPoints(0);
store.dispatch(actions.speedRun(state.get('speedStart')));
const startLines = state.get('startLines');
const startMatrix = getStartMatrix(startLines);
store.dispatch(actions.matrix(startMatrix));
store.dispatch(actions.moveBlock({ type: state.get('next') }));
store.dispatch(actions.nextBlock());
states.auto();
},
// 自动下落
auto: (timeout) => {
const out = (timeout < 0 ? 0 : timeout);
let state = store.getState();
let cur = state.get('cur');
const fall = () => {
state = store.getState();
cur = state.get('cur');
const next = cur.fall();
if (want(next, state.get('matrix'))) {
store.dispatch(actions.moveBlock(next));
states.fallInterval = setTimeout(fall, speeds[state.get('speedRun') - 1]);
} else {
let matrix = state.get('matrix');
const shape = cur && cur.shape;
const xy = cur && cur.xy;
shape.forEach((m, k1) => (
m.forEach((n, k2) => {
if (n && xy.get(0) + k1 >= 0) { // 竖坐标可以为负
let line = matrix.get(xy.get(0) + k1);
line = line.set(xy.get(1) + k2, 1);
matrix = matrix.set(xy.get(0) + k1, line);
}
})
));
states.nextAround(matrix);
}
};
clearTimeout(states.fallInterval);
states.fallInterval = setTimeout(fall,
out === undefined ? speeds[state.get('speedRun') - 1] : out);
},
// 一个方块结束, 触发下一个
nextAround: (matrix, stopDownTrigger) => {
clearTimeout(states.fallInterval);
store.dispatch(actions.lock(true));
store.dispatch(actions.matrix(matrix));
if (typeof stopDownTrigger === 'function') {
stopDownTrigger();
}
const addPoints = (store.getState().get('points') + 10) +
((store.getState().get('speedRun') - 1) * 2); // 速度越快, 得分越高
states.dispatchPoints(addPoints);
if (isClear(matrix)) {
if (music.clear) {
music.clear();
}
return;
}
if (isOver(matrix)) {
if (music.gameover) {
music.gameover();
}
states.overStart();
return;
}
setTimeout(() => {
store.dispatch(actions.lock(false));
store.dispatch(actions.moveBlock({ type: store.getState().get('next') }));
store.dispatch(actions.nextBlock());
states.auto();
}, 100);
},
// 页面焦点变换
focus: (isFocus) => {
store.dispatch(actions.focus(isFocus));
if (!isFocus) {
clearTimeout(states.fallInterval);
return;
}
const state = store.getState();
if (state.get('cur') && !state.get('reset') && !state.get('pause')) {
states.auto();
}
},
// 暂停
pause: (isPause) => {
store.dispatch(actions.pause(isPause));
if (isPause) {
clearTimeout(states.fallInterval);
return;
}
states.auto();
},
// 消除行
clearLines: (matrix, lines) => {
const state = store.getState();
let newMatrix = matrix;
lines.forEach(n => {
newMatrix = newMatrix.splice(n, 1);
newMatrix = newMatrix.unshift(List(blankLine));
});
store.dispatch(actions.matrix(newMatrix));
store.dispatch(actions.moveBlock({ type: state.get('next') }));
store.dispatch(actions.nextBlock());
states.auto();
store.dispatch(actions.lock(false));
const clearLines = state.get('clearLines') + lines.length;
store.dispatch(actions.clearLines(clearLines)); // 更新消除行
const addPoints = store.getState().get('points') +
clearPoints[lines.length - 1]; // 一次消除的行越多, 加分越多
states.dispatchPoints(addPoints);
const speedAdd = Math.floor(clearLines / eachLines); // 消除行数, 增加对应速度
let speedNow = state.get('speedStart') + speedAdd;
speedNow = speedNow > 6 ? 6 : speedNow;
store.dispatch(actions.speedRun(speedNow));
},
// 游戏结束, 触发动画
overStart: () => {
clearTimeout(states.fallInterval);
store.dispatch(actions.lock(true));
store.dispatch(actions.reset(true));
store.dispatch(actions.pause(false));
},
// 游戏结束动画完成
overEnd: () => {
store.dispatch(actions.matrix(blankMatrix));
store.dispatch(actions.moveBlock({ reset: true }));
store.dispatch(actions.reset(false));
store.dispatch(actions.lock(false));
store.dispatch(actions.clearLines(0));
},
// 写入分数
dispatchPoints: (point) => { // 写入分数, 同时判断是否创造最高分
store.dispatch(actions.points(point));
if (point > 0 && point > store.getState().get('max')) {
store.dispatch(actions.max(point));
}
},
};
export default states;