123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- <template>
- <div style="position: relative;">
- <canvas id="tetris1" width="320" height="620" style="border: 1px #ccc solid" tabindex="0"/>
- <div style="position: absolute;top: 0;left: 350px;">
- <p>{{view?view.score:0}}</p>
- <el-button @click="reset" type="primary">重新开始</el-button>
- </div>
- </div>
- </template>
- <script lang="ts">
- import { Component, Vue } from "vue-property-decorator";
- import { SCanvasView, SColor, SPainter, STextAlign } from "@persagy-web/draw/lib";
- class TetrisView extends SCanvasView {
-
- gridMap = Array(20)
- .fill(null)
- .map(() => Array(10).fill(0));
-
- boxType = Number(Math.floor(Math.random() * 7));
-
- dir = Number(Math.floor(Math.random() * 4));
-
- currRow = 0;
-
- currCol = 3;
-
- lastTime = Date.now();
-
- score = 0;
-
- isGameOver = false;
-
- 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],
- ]
- ];
-
- private _scoreList = [100, 300, 600, 1000];
-
- constructor(id: string) {
- super(id);
-
- this.init();
- }
-
- init(): void {
-
- for (let r = 0; r < 20; r++) {
-
- for (let c = 0; c < 10; c++) {
-
- this.gridMap[r][c] = 0;
- }
- }
-
- this.newFallBox();
-
- this.score = 0;
-
- this.isGameOver = false;
- }
-
- onKeyDown(event: KeyboardEvent): void {
-
- if (this.isGameOver) {
- return;
- }
- if (event.code == "KeyW") {
-
- if (!this.checkCollide(this.boxType, (this.dir + 1) % 4, this.currRow, this.currCol)) {
-
- this.dir = (this.dir + 1) % 4;
- }
- } else if (event.code == "KeyA") {
-
- if (!this.checkCollide(this.boxType,this.dir, this.currRow, this.currCol - 1)) {
-
- this.currCol--;
- }
- } else if (event.code == "KeyD") {
-
- if (!this.checkCollide(this.boxType,this.dir, this.currRow, this.currCol + 1)) {
-
- this.currCol++;
- }
- } else if (event.code == "KeyS") {
-
- this.fallBox();
- }
-
- this.update();
- }
-
- onDraw(canvas: SPainter): void {
-
- canvas.clearRect(0, 0, this.width, this.height);
-
- this.drawGridMap(canvas);
-
- if (this.isGameOver) {
-
- canvas.brush.color = SColor.Blue;
- canvas.font.size = 40;
- canvas.font.textAlign = STextAlign.Center;
- if (Date.now() % 1000 > 500) {
- canvas.drawText("Game Over", 160, 300);
- }
-
- this.update();
- return;
- }
-
- this.drawFallBox(canvas);
-
- if (Date.now() - this.lastTime > 500) {
-
- this.fallBox();
- this.lastTime = Date.now();
- }
-
- this.update();
- }
-
- private drawGridMap(canvas: SPainter): void {
-
- for (let r = 0; r < 20; r++) {
-
- for (let c = 0; c < 10; c++) {
-
- this.drawGird(canvas, this.gridMap[r][c], r, c);
- }
- }
- }
-
- private drawFallBox(canvas: SPainter): void {
-
- for (let r = 0; r < 4; r++) {
-
- for (let c = 0; c < 4; c++) {
-
- this.drawGird(canvas, this.box[this.boxType * 4 + this.dir][r][c], this.currRow + r, this.currCol + c);
- }
- }
- }
-
- private fallBox(): void {
-
- if (!this.checkCollide(this.boxType,this.dir, this.currRow + 1, this.currCol)) {
-
- this.currRow++;
- this.update();
- return;
- }
-
- this.boxIntoMap();
-
- if (this.currRow <= -1) {
-
- this.isGameOver = true;
- this.update();
- return;
- }
-
- const rows = this.removeFullRow();
-
- if (rows > 0) {
- this.score += this._scoreList[rows - 1];
- }
-
- this.newFallBox();
- }
-
- private drawGird(canvas: SPainter, type: number, row: number, col: number): void {
-
- if (type != 0) {
-
- canvas.pen.color = SColor.Transparent;
- canvas.brush.color = SColor.Red;
- canvas.drawRect(col * 30 + 11, row * 30 + 11, 28, 28);
- }
- }
-
- private checkCollide(type: number, dir: number, row: number, col: number): boolean {
-
- for (let r = 0; r < 4; r++) {
- const r1 = row + r;
-
- for (let c = 0; c < 4; c++) {
- const c1 = col + c;
- if (this.box[this.boxType * 4 + dir][r][c] != 0) {
-
- if (c1 < 0 || c1 >= 10 || r1 >= 20) {
- return true;
- }
-
- if (r1 > 0 && this.gridMap[row + r][col + c] != 0) {
- return true;
- }
- }
- }
- }
-
- return false;
- }
-
- private boxIntoMap() {
-
- for (let r = 0; r < 4; r++) {
- const r1 = this.currRow + r;
-
- for (let c = 0; c < 4; c++) {
- const g = this.box[this.boxType * 4 + this.dir][r][c]
- const c1 = this.currCol + c;
-
- if (g != 0) {
-
- if (c1 < 0 || c1 >= 10 || r1 < 0 || r1 >= 20) {
- continue;
- }
-
- this.gridMap[r1][c1] = g;
- }
- }
- }
- }
-
- private newFallBox() {
-
- this.currCol = 3;
- this.currRow = -3;
-
- this.boxType = Number(Math.floor(Math.random() * 7));
- this.dir = Number(Math.floor(Math.random() * 4));
- }
-
- private removeFullRow(): number {
-
- let count = 0;
-
- for (let r = 0; r < 20; r++) {
-
- let isRemove = true;
-
- for (let c = 0; c < 10; c++) {
-
- if (this.gridMap[r][c] == 0) {
- isRemove = false
- break;
- }
- }
-
- if (isRemove) {
-
- this.gridMap.splice(r,1);
- this.gridMap.unshift(Array(10).fill(0));
-
- count++;
- }
- }
-
- return count
- }
- }
- @Component
- export default class Tetris1 extends Vue {
-
- view: TetrisView | null = null;
-
- mounted(): void {
- this.view = new TetrisView("tetris1");
- document.getElementById("tetris1")!!.focus();
- }
-
- reset(): void {
-
- this.view!!.init();
- document.getElementById("tetris1")!!.focus();
- }
- }
- </script>
|