|
@@ -9,522 +9,512 @@
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts">
|
|
|
- import { Component, Vue } from "vue-property-decorator";
|
|
|
- import { v1 as uuid } from "uuid";
|
|
|
- import { SCanvasView, SColor, SPainter, STextAlign } from "@persagy-web/draw/lib";
|
|
|
+import { Component, Vue } from "vue-property-decorator";
|
|
|
+import { v1 as uuid } from "uuid";
|
|
|
+import { SCanvasView, SColor, SPainter, STextAlign } from "@persagy-web/draw/lib";
|
|
|
+
|
|
|
+/**
|
|
|
+ * 俄罗斯方块视图
|
|
|
+ *
|
|
|
+ * @author 郝建龙 <haojianlong@sagacloud.com>
|
|
|
+ */
|
|
|
+class TestView extends SCanvasView {
|
|
|
+ /** 背景表示数组 */
|
|
|
+ map: number[][] = [];
|
|
|
+ /** 方块类型索引 0-6 */
|
|
|
+ boxType: number = Number(Math.floor(Math.random() * 7));
|
|
|
+ /** 方块变形索引 0-3 */
|
|
|
+ dir: number = Number(Math.floor(Math.random() * 4));
|
|
|
+ /** 所有方块集合 */
|
|
|
+ box: number[][][] = [
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [1, 1, 1, 1],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [1, 1, 1, 1],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [1, 1, 0, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 0, 1, 1],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 1, 1],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [1, 1, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [1, 1, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 1, 1],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [1, 1, 1, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 1, 1, 1],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 1, 1, 1],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ [1, 1, 1, 0],
|
|
|
+ [0, 1, 0, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ],
|
|
|
+ [
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 1, 1, 0],
|
|
|
+ [0, 0, 1, 0],
|
|
|
+ [0, 0, 0, 0],
|
|
|
+ ]
|
|
|
+ ];
|
|
|
+ /** 方块初始位置x坐标 */
|
|
|
+ x = 5;
|
|
|
+ /** 方块初始位置y坐标 */
|
|
|
+ y = 0;
|
|
|
+ /** 记录上次刷新时间 */
|
|
|
+ t = Date.now();
|
|
|
+ /** 是否游戏结束 */
|
|
|
+ gameOver: boolean = false;
|
|
|
+ /** 方块颜色 */
|
|
|
+ boxColor: SColor = new SColor();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构造函数
|
|
|
+ *
|
|
|
+ * @param id canvas DOM id
|
|
|
+ */
|
|
|
+ constructor(id: string) {
|
|
|
+ super(id);
|
|
|
+ this.initMap();
|
|
|
+ this.initColor();
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
- * 俄罗斯方块视图
|
|
|
+ * 键盘按下事件
|
|
|
*
|
|
|
- * @author 郝建龙
|
|
|
- * */
|
|
|
- class TestView extends SCanvasView {
|
|
|
- /** 背景表示数组 */
|
|
|
- map: number[][] = [];
|
|
|
- /** 方块类型索引 */
|
|
|
- boxType: number = Number(Math.floor(Math.random() * 7)); // 0-6
|
|
|
- /** 方块变形索引 */
|
|
|
- dir: number = Number(Math.floor(Math.random() * 4)); // 0-3
|
|
|
- /** 所有方块集合 */
|
|
|
- box: number[][][] = [
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [1, 1, 1, 1],
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- [1, 1, 1, 1],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [1, 1, 0, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 0, 1, 1],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 1, 1],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [1, 1, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- [1, 1, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 1, 1],
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [1, 1, 1, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 1, 1, 1],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 1, 1, 1],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 0, 0],
|
|
|
- [1, 1, 1, 0],
|
|
|
- [0, 1, 0, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ],
|
|
|
- [
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 1, 1, 0],
|
|
|
- [0, 0, 1, 0],
|
|
|
- [0, 0, 0, 0],
|
|
|
- ]
|
|
|
- ];
|
|
|
- /** 方块初始位置x坐标 */
|
|
|
- x = 5;
|
|
|
- /** 方块初始位置y坐标 */
|
|
|
- y = 0;
|
|
|
- /** 记录上次刷新时间 */
|
|
|
- t = Date.now();
|
|
|
- /** 是否游戏结束 */
|
|
|
- gameOver: boolean = false;
|
|
|
- /** 方块颜色 */
|
|
|
- boxColor: SColor = new SColor();
|
|
|
-
|
|
|
- /**
|
|
|
- * 构造函数
|
|
|
- *
|
|
|
- * @param id canvas DOM id
|
|
|
- */
|
|
|
- constructor(id: string) {
|
|
|
- super(id);
|
|
|
- this.initMap();
|
|
|
- this.initColor();
|
|
|
+ * @param event 事件对象
|
|
|
+ */
|
|
|
+ onKeyDown(event: KeyboardEvent): void {
|
|
|
+ if (this.gameOver) { // 游戏结束
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 键盘按下事件
|
|
|
- *
|
|
|
- * @param event 事件对象
|
|
|
- */
|
|
|
- onKeyDown(event: KeyboardEvent): void {
|
|
|
- //游戏结束
|
|
|
- if (this.gameOver) {
|
|
|
- return;
|
|
|
+ if (event.code == "KeyW") { // 按键 w
|
|
|
+ if (!this.checkKnocked(this.x, this.y, (this.dir + 1) % 4)) { // 检查变形后是否碰撞
|
|
|
+ this.dir = (this.dir + 1) % 4;
|
|
|
}
|
|
|
-
|
|
|
- if (event.code == "KeyW") {
|
|
|
- //检查变形后是否碰撞
|
|
|
- if (!this.checkKnocked(this.x, this.y, (this.dir + 1) % 4)) {
|
|
|
- this.dir = (this.dir + 1) % 4;
|
|
|
- }
|
|
|
- } else if (event.code == "KeyA") {
|
|
|
- //检查左移后是否碰撞
|
|
|
- if (!this.checkKnocked(this.x - 1, this.y, this.dir)) {
|
|
|
- this.x--;
|
|
|
- }
|
|
|
- } else if (event.code == "KeyD") {
|
|
|
- //检查右移后是否碰撞
|
|
|
- if (!this.checkKnocked(this.x + 1, this.y, this.dir)) {
|
|
|
- this.x++;
|
|
|
- }
|
|
|
- } else if (event.code == "KeyS") {
|
|
|
- //检查下移后是否碰撞
|
|
|
- if (!this.checkKnocked(this.x, this.y + 1, this.dir)) {
|
|
|
- this.y++;
|
|
|
- } else {
|
|
|
- this.fullMap();
|
|
|
- }
|
|
|
+ } else if (event.code == "KeyA") { // 按键 a
|
|
|
+ if (!this.checkKnocked(this.x - 1, this.y, this.dir)) { // 检查左移后是否碰撞
|
|
|
+ this.x--;
|
|
|
+ }
|
|
|
+ } else if (event.code == "KeyD") { // 按键 d
|
|
|
+ if (!this.checkKnocked(this.x + 1, this.y, this.dir)) { // 检查右移后是否碰撞
|
|
|
+ this.x++;
|
|
|
+ }
|
|
|
+ } else if (event.code == "KeyS") { // 按键 s
|
|
|
+ if (!this.checkKnocked(this.x, this.y + 1, this.dir)) { // 检查下移后是否碰撞
|
|
|
+ this.y++;
|
|
|
+ } else {
|
|
|
+ this.fillMap();
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ this.update();
|
|
|
+ }
|
|
|
|
|
|
- this.update();
|
|
|
+ /**
|
|
|
+ * Item 绘制操作
|
|
|
+ *
|
|
|
+ * @param painter 绘制对象
|
|
|
+ */
|
|
|
+ onDraw(painter: SPainter): void {
|
|
|
+
|
|
|
+ if (this.gameOver) { // 游戏结束绘制文字
|
|
|
+ painter.brush.color = SColor.Blue;
|
|
|
+ painter.font.size = 20;
|
|
|
+ painter.font.textAlign = STextAlign.Center;
|
|
|
+ painter.drawText("GAME OVER", 180, 30);
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Item 绘制操作
|
|
|
- *
|
|
|
- * @param painter 绘制对象
|
|
|
- */
|
|
|
- onDraw(painter: SPainter): void {
|
|
|
- //游戏结束绘制文字
|
|
|
- if (this.gameOver) {
|
|
|
- painter.brush.color = SColor.Blue;
|
|
|
- painter.font.size = 20;
|
|
|
- painter.font.textAlign = STextAlign.Center;
|
|
|
- painter.drawText("GAME OVER", 180, 30);
|
|
|
- return;
|
|
|
- }
|
|
|
+ painter.clearRect(0, 0, this.width, this.height);
|
|
|
|
|
|
- painter.clearRect(0, 0, this.width, this.height);
|
|
|
-
|
|
|
- painter.pen.color = new SColor("#0bc0ff");
|
|
|
- painter.brush.color = new SColor("#2accc7");
|
|
|
- this.drawMap(painter);
|
|
|
-
|
|
|
- painter.pen.color = this.boxColor;
|
|
|
- painter.brush.color = this.boxColor;
|
|
|
- //绘制图形
|
|
|
- this.drawBox(painter);
|
|
|
- //下落速度,下移一格
|
|
|
- if (Date.now() - this.t > 500) {
|
|
|
- //下移是否碰撞
|
|
|
- if (!this.checkKnocked(this.x, this.y + 1, this.dir)) {
|
|
|
- this.y++;
|
|
|
- } else {
|
|
|
- this.fullMap();
|
|
|
- }
|
|
|
- this.t = Date.now();
|
|
|
+ painter.pen.color = new SColor("#0bc0ff");
|
|
|
+ painter.brush.color = new SColor("#2accc7");
|
|
|
+ this.drawMap(painter);
|
|
|
+
|
|
|
+ painter.pen.color = this.boxColor;
|
|
|
+ painter.brush.color = this.boxColor;
|
|
|
+ // 绘制图形
|
|
|
+ this.drawBox(painter);
|
|
|
+
|
|
|
+
|
|
|
+ if (Date.now() - this.t > 500) { // 下落速度,下移一格
|
|
|
+ if (!this.checkKnocked(this.x, this.y + 1, this.dir)) { // 下移是否碰撞
|
|
|
+ this.y++;
|
|
|
+ } else {
|
|
|
+ this.fillMap();
|
|
|
}
|
|
|
- this.update();
|
|
|
+ this.t = Date.now();
|
|
|
}
|
|
|
+ this.update();
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 初始化背景
|
|
|
- */
|
|
|
- initMap(): void {
|
|
|
- this.gameOver = false;
|
|
|
- this.map = [];
|
|
|
- //循环行数
|
|
|
- for (let row = 0; row < 22; row++) {
|
|
|
- const m1: number[] = [];
|
|
|
- //循环列数
|
|
|
- for (let col = 0; col < 14; col++) {
|
|
|
- //左侧,右侧,底部补充两个格
|
|
|
- if (row > 19 || col < 2 || col > 11) {
|
|
|
- //-1代表左右填充
|
|
|
- m1.push(-1);
|
|
|
- } else {
|
|
|
- m1.push(0);
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 初始化背景
|
|
|
+ */
|
|
|
+ initMap(): void {
|
|
|
+ this.gameOver = false;
|
|
|
+ this.map = [];
|
|
|
+ for (let row = 0; row < 22; row++) { // 循环行数
|
|
|
+ const m1: number[] = [];
|
|
|
+ for (let col = 0; col < 14; col++) { // 循环列数
|
|
|
+ if (row > 19 || col < 2 || col > 11) { // 左侧,右侧,底部补充两个格
|
|
|
+ // -1 代表左右填充
|
|
|
+ m1.push(-1);
|
|
|
+ } else {
|
|
|
+ m1.push(0);
|
|
|
}
|
|
|
- this.map.push(m1);
|
|
|
}
|
|
|
+ this.map.push(m1);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 初始化方块形状
|
|
|
- */
|
|
|
- initBox(): void {
|
|
|
- this.x = 5;
|
|
|
- this.y = 0;
|
|
|
- this.boxType = Number(Math.floor(Math.random() * 7));
|
|
|
- this.dir = Number(Math.floor(Math.random() * 4));
|
|
|
- this.initColor();
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 初始化方块形状
|
|
|
+ */
|
|
|
+ initBox(): void {
|
|
|
+ this.x = 5;
|
|
|
+ this.y = 0;
|
|
|
+ this.boxType = Number(Math.floor(Math.random() * 7));
|
|
|
+ this.dir = Number(Math.floor(Math.random() * 4));
|
|
|
+ this.initColor();
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 初始化方块颜色
|
|
|
- */
|
|
|
- initColor(): void {
|
|
|
- const a = Number(Math.floor(Math.random() * 128));
|
|
|
- const b = Number(Math.floor(Math.random() * 128));
|
|
|
- const c = Number(Math.floor(Math.random() * 128));
|
|
|
- this.boxColor = new SColor(a, b, c);
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 初始化方块颜色
|
|
|
+ */
|
|
|
+ initColor(): void {
|
|
|
+ const a = Number(Math.floor(Math.random() * 128));
|
|
|
+ const b = Number(Math.floor(Math.random() * 128));
|
|
|
+ const c = Number(Math.floor(Math.random() * 128));
|
|
|
+ this.boxColor = new SColor(a, b, c);
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 绘制背景
|
|
|
- *
|
|
|
- * @param painter 绘制对象
|
|
|
- */
|
|
|
- private drawMap(painter: SPainter): void {
|
|
|
- //行数
|
|
|
- for (let row = 0; row < 22; row++) {
|
|
|
- //列数
|
|
|
- for (let col = 0; col < 14; col++) {
|
|
|
- this.drawShape(painter, row, col, this.map[row][col]);
|
|
|
- // if (n == 0) {
|
|
|
- // painter.drawRect(col * 30 + 11 - 60, row * 30 + 11, 28, 28);
|
|
|
- // }
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 绘制背景
|
|
|
+ *
|
|
|
+ * @param painter 绘制对象
|
|
|
+ */
|
|
|
+ private drawMap(painter: SPainter): void {
|
|
|
+ for (let row = 0; row < 22; row++) { // 行数
|
|
|
+ for (let col = 0; col < 14; col++) { // 列数
|
|
|
+ this.drawShape(painter, row, col, this.map[row][col]);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 绘制实体图形
|
|
|
- *
|
|
|
- * @param painter 绘制对象
|
|
|
- * @param row 行
|
|
|
- * @param col 列
|
|
|
- * @param type 图类型
|
|
|
- */
|
|
|
- private drawShape(painter: SPainter, row: number, col: number, type: number): void {
|
|
|
- const x = col * 30 + 11 - 60;
|
|
|
- const y = row * 30 + 11;
|
|
|
- //类型判断,0为空白,-1填充
|
|
|
- switch (type) {
|
|
|
- case 0:
|
|
|
- break;
|
|
|
- case -1:
|
|
|
- painter.drawRoundRect(x, y, 28, 28, 6);
|
|
|
- break;
|
|
|
- default:
|
|
|
- painter.drawRoundRect(x, y, 28, 28, 6);
|
|
|
- break;
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 绘制实体图形
|
|
|
+ *
|
|
|
+ * @param painter 绘制对象
|
|
|
+ * @param row 行
|
|
|
+ * @param col 列
|
|
|
+ * @param type 图类型
|
|
|
+ */
|
|
|
+ private drawShape(painter: SPainter, row: number, col: number, type: number): void {
|
|
|
+ const x = col * 30 + 11 - 60;
|
|
|
+ const y = row * 30 + 11;
|
|
|
+
|
|
|
+ switch (type) { // 类型判断
|
|
|
+ case 0: // 空白
|
|
|
+ break;
|
|
|
+
|
|
|
+ case -1: // 边界
|
|
|
+ painter.drawRoundRect(x, y, 28, 28, 6);
|
|
|
+ break;
|
|
|
+
|
|
|
+ default: // 填充
|
|
|
+ painter.drawRoundRect(x, y, 28, 28, 6);
|
|
|
+ break;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 绘制方块
|
|
|
- *
|
|
|
- * @param painter 绘制对象
|
|
|
- */
|
|
|
- private drawBox(painter: SPainter): void {
|
|
|
- //绘制图形行数
|
|
|
- for (let row = 0; row < 4; row++) {
|
|
|
- //绘制图形列数
|
|
|
- for (let col = 0; col < 4; col++) {
|
|
|
- this.drawShape(painter, row + this.y, col + this.x, this.box[this.boxType * 4 + this.dir][row][col]);
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 绘制方块
|
|
|
+ *
|
|
|
+ * @param painter 绘制对象
|
|
|
+ */
|
|
|
+ private drawBox(painter: SPainter): void {
|
|
|
+ for (let row = 0; row < 4; row++) { // 绘制图形行数
|
|
|
+ for (let col = 0; col < 4; col++) { // 绘制图形列数
|
|
|
+ this.drawShape(painter, row + this.y, col + this.x, this.box[this.boxType * 4 + this.dir][row][col]);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 是否碰撞
|
|
|
- *
|
|
|
- * @param x x坐标
|
|
|
- * @param y y坐标
|
|
|
- * @param dir 方块变形索引
|
|
|
- * @return 是否碰撞
|
|
|
- */
|
|
|
- private checkKnocked(x: number, y: number, dir: number): boolean {
|
|
|
- //绘制图形行数
|
|
|
- for (let row = 0; row < 4; row++) {
|
|
|
- //绘制图形列数
|
|
|
- for (let col = 0; col < 4; col++) {
|
|
|
- //判断是否重合,每种图形四个一组,四种变形的某种变形,不为零表示绘制(确定方块),坐标转换,背景图中绘制
|
|
|
- if (this.box[this.boxType * 4 + dir][row][col] != 0 && this.map[y + row][x + col] != 0) {
|
|
|
- return true;
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 是否碰撞
|
|
|
+ *
|
|
|
+ * @param x x 坐标
|
|
|
+ * @param y y 坐标
|
|
|
+ * @param dir 方块变形索引
|
|
|
+ * @return 是否碰撞
|
|
|
+ */
|
|
|
+ private checkKnocked(x: number, y: number, dir: number): boolean {
|
|
|
+ for (let row = 0; row < 4; row++) { // 绘制图形行数
|
|
|
+ for (let col = 0; col < 4; col++) { // 绘制图形列数
|
|
|
+ // 判断是否重合,每种图形四个一组,四种变形的某种变形,不为零表示绘制(确定方块),坐标转换,背景图中绘制
|
|
|
+ if (this.box[this.boxType * 4 + dir][row][col] != 0 && this.map[y + row][x + col] != 0) {
|
|
|
+ return true;
|
|
|
}
|
|
|
}
|
|
|
- return false;
|
|
|
}
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 将方块合到背景中
|
|
|
- */
|
|
|
- private fullMap(): void {
|
|
|
- //遍历图形的行数
|
|
|
- for (let row = 0; row < 4; row++) {
|
|
|
- //遍历图形的列数
|
|
|
- for (let col = 0; col < 4; col++) {
|
|
|
- //判断图形绘制,填充至背景中
|
|
|
- if (this.box[this.boxType * 4 + this.dir][row][col] == 1) {
|
|
|
- this.map[this.y + row][this.x + col] = 1;
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 将方块合到背景中
|
|
|
+ */
|
|
|
+ private fillMap(): void {
|
|
|
+ for (let row = 0; row < 4; row++) { // 遍历图形的行数
|
|
|
+ for (let col = 0; col < 4; col++) { // 遍历图形的列数
|
|
|
+ if (this.box[this.boxType * 4 + this.dir][row][col] == 1) { // 判断图形绘制
|
|
|
+ // 填充至背景中
|
|
|
+ this.map[this.y + row][this.x + col] = 1;
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- this.initBox();
|
|
|
- //判断背景上的图形与初始化图形是否重合
|
|
|
- if (this.checkKnocked(this.x, this.y, this.dir)) {
|
|
|
- //游戏结束
|
|
|
- this.gameOver = true;
|
|
|
- }
|
|
|
-
|
|
|
- this.remove();
|
|
|
+ this.initBox();
|
|
|
+ if (this.checkKnocked(this.x, this.y, this.dir)) { // 判断背景上的图形与初始化图形是否重合
|
|
|
+ //游戏结束
|
|
|
+ this.gameOver = true;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 消除满行
|
|
|
- */
|
|
|
- private remove(): void {
|
|
|
- //消除行数
|
|
|
- let removeCount = 0;
|
|
|
- //循环行数,不包含底部填充2行
|
|
|
- for (let row = 0; row < 20; row++) {
|
|
|
- //消除标记,true 是
|
|
|
- let flag = true;
|
|
|
- //
|
|
|
- // for (let col = 0; col < 14; col++) {
|
|
|
- // if (this.map[row][col] == 0) {
|
|
|
- // flag = false;
|
|
|
- // break;
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- //若当前行有一个空格,则不消除
|
|
|
- for (let col = 2; col < 12; col++) {
|
|
|
- if (this.map[row][col] == 0) {
|
|
|
- flag = false;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
+ this.remove();
|
|
|
+ }
|
|
|
|
|
|
- if (flag) {
|
|
|
- this.map.splice(row, 1);
|
|
|
- //顶部加一行空行
|
|
|
- this.map.unshift(this.randomRow(10, 0));
|
|
|
- removeCount++;
|
|
|
+ /**
|
|
|
+ * 消除满行
|
|
|
+ */
|
|
|
+ private remove(): void {
|
|
|
+ //消除行数
|
|
|
+ let removeCount = 0;
|
|
|
+ //循环行数,不包含底部填充2行
|
|
|
+ for (let row = 0; row < 20; row++) {
|
|
|
+ //消除标记,true 是
|
|
|
+ let flag = true;
|
|
|
+ //若当前行有一个空格,则不消除
|
|
|
+ for (let col = 2; col < 12; col++) {
|
|
|
+ if (this.map[row][col] == 0) { // 存在空格
|
|
|
+ flag = false;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
- //记录消除行数
|
|
|
- if (removeCount > 0) {
|
|
|
- this.$emit("score", removeCount);
|
|
|
- //删除行
|
|
|
- this.map.shift();
|
|
|
- //底部随机产生一行
|
|
|
- this.map.splice(19, 0, this.randomRow());
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- /**
|
|
|
- * 随机数组生成
|
|
|
- *
|
|
|
- * @return 数组
|
|
|
- */
|
|
|
- private randomRow(len: number = 10, num: number = 2): number[] {
|
|
|
- let array = new Array(len + 4).fill(-1);
|
|
|
- //生成随机数,循环不包含左右填充格
|
|
|
- for (let i = 2; i < array.length - 2; i++) {
|
|
|
- array[i] = Math.floor(num * Math.random());
|
|
|
+ if (flag) { // 标记删除
|
|
|
+ this.map.splice(row, 1);
|
|
|
+ //顶部加一行空行
|
|
|
+ this.map.unshift(this.randomRow(10, 0));
|
|
|
+ removeCount++;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- return array;
|
|
|
+ if (removeCount > 0) { // 记录消除行数
|
|
|
+ this.$emit("score", removeCount);
|
|
|
+ // 删除行
|
|
|
+ this.map.shift();
|
|
|
+ // 底部随机产生一行
|
|
|
+ this.map.splice(19, 0, this.randomRow());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- @Component
|
|
|
- export default class ElsfkCanvas extends Vue {
|
|
|
- id: string = uuid();
|
|
|
- scoreList: number[] = [100, 300, 600, 1000];
|
|
|
- score: number = 0;
|
|
|
- view: TestView | undefined = undefined;
|
|
|
-
|
|
|
- mounted(): void {
|
|
|
- this.view = new TestView(this.id);
|
|
|
- this.view.connect("score", this, this.changeScore);
|
|
|
- document.getElementById(this.id)!!.focus();
|
|
|
+ /**
|
|
|
+ * 随机数组生成
|
|
|
+ *
|
|
|
+ * @return 数组
|
|
|
+ */
|
|
|
+ private randomRow(len: number = 10, num: number = 2): number[] {
|
|
|
+ let array = new Array(len + 4).fill(-1);
|
|
|
+ // 生成随机数,循环不包含左右填充格
|
|
|
+ for (let i = 2; i < array.length - 2; i++) {
|
|
|
+ array[i] = Math.floor(num * Math.random());
|
|
|
}
|
|
|
|
|
|
- changeScore(v: SCanvasView, count: number[]) {
|
|
|
- //根据消除行数判断分值
|
|
|
- this.score += this.scoreList[count[0] - 1];
|
|
|
- }
|
|
|
+ return array;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- reset() {
|
|
|
- this.view!!.initMap();
|
|
|
- this.view!!.initBox();
|
|
|
- this.score = 0;
|
|
|
- this.view!!.update();
|
|
|
- document.getElementById(this.id)!!.focus();
|
|
|
- }
|
|
|
+@Component
|
|
|
+export default class ElsfkCanvas extends Vue {
|
|
|
+ /** 图 id */
|
|
|
+ id: string = uuid();
|
|
|
+ /** 记分数组列表 */
|
|
|
+ scoreList: number[] = [100, 300, 600, 1000];
|
|
|
+ /** 记分分数 */
|
|
|
+ score: number = 0;
|
|
|
+ /** 实例化 view */
|
|
|
+ view: TestView | undefined = undefined;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 页面挂载
|
|
|
+ */
|
|
|
+ mounted(): void {
|
|
|
+ this.view = new TestView(this.id);
|
|
|
+ this.view.connect("score", this, this.changeScore);
|
|
|
+ document.getElementById(this.id)!!.focus();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分值展示
|
|
|
+ *
|
|
|
+ * @param v canvas 视图对象
|
|
|
+ * @param count 计数分值
|
|
|
+ */
|
|
|
+ changeScore(v: SCanvasView, count: number[]) {
|
|
|
+ //根据消除行数判断分值
|
|
|
+ this.score += this.scoreList[count[0] - 1];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重置操作
|
|
|
+ */
|
|
|
+ reset() {
|
|
|
+ this.view!!.initMap();
|
|
|
+ this.view!!.initBox();
|
|
|
+ this.score = 0;
|
|
|
+ this.view!!.update();
|
|
|
+ document.getElementById(this.id)!!.focus();
|
|
|
}
|
|
|
+}
|
|
|
</script>
|