<template>
  <div id="main_box" ref="main_box">
    <canvas id="myCanvas1" class="can" ref="can1"></canvas>
    <canvas id="myCanvas2" class="can" ref="can2"></canvas>
    <a href="javascript:void(0)" @click="loginGame" id="login_btn" ref="login_btn">开始游戏</a>
    <div id="score" ref="score_div">{{ scoreText }}</div>
    <div id="game_title" ref="game_title">方&nbsp;块&nbsp;跳&nbsp;跃</div>
    <div id="state" ref="state_div">{{ stateText }}</div>
    <span id="square_main" ref="square_main"></span>
    <div id="colorChangeTime_div" ref="colorChangeTime_div">{{ colorChangeTimeText }}</div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { clearInterval, clearTimeout, setInterval, setTimeout } from 'worker-timers';
const changeTimeArrays: any = ["10", "9", "8", "7", "6", "5", "4", "3", "2", "1", "color change!"];
const squareColor: any = ["#FF6688", "#00FF00", "#3399FF", "#FFDAB9", "blueviolet"];

const can1: any = ref(null);
const can2: any = ref(null);
const ctx1: any = ref(null);
const ctx2: any = ref(null);
const canWidth: any = ref(820);
const canHeight: any = ref(640);
const maxWidth: any = ref(820);
const maxHeight: any = ref(640);
const beginGame: any = ref(false);
const gameOver: any = ref(true);
const score: any = ref(0);
const scoreText: any = ref('得分:0');
const stateText: any = ref('');
const colorChangeTimeText: any = ref();
let backrgound: any = ref(null);
let squares: any = ref(null);
let mySquare: any = ref(null);
let beginAnim: any = ref(null);
let lastTime: any = ref(null);
let changeColorTime: any = ref(null);
let loop: any = ref(null);

const changeColorindex: any = ref(0);
const totalSpeed: any = ref(3);
const isStep: any = ref(false);
const colorChangeTimeW: any = ref(0);
const AnimPX: any = ref([]);
const AnimPY: any = ref([]);
const jump_count: any = ref(0);
let square_main: any = ref(null);
let game_title: any = ref(null);
let main_box: any = ref(null);
let login_btn: any = ref(null);
let colorChangeTime_div: any = ref(null);
let state_div: any = ref(null);
let score_div: any = ref(null);

function init() {
  score.value = 0;
  beginGame.value = false;
  gameOver.value = false;
  isStep.value = false;

  lastTime.value = Date.now();
  ctx1.value = can1.value.getContext("2d");
  ctx2.value = can2.value.getContext("2d");
  if (maxWidth.value != canWidth.value) {
    canWidth.value = maxWidth.value;
  }
  if (maxHeight.value != canHeight.value) {
    canHeight.value = maxHeight.value;
  }


  main_box.value.style.width = canWidth.value + "px";
  main_box.value.style.height = canHeight.value + "px";

  can1.value.width = canWidth.value;
  can2.value.width = canWidth.value;
  can1.value.height = canHeight.value;
  can2.value.height = canHeight.value;

  // 模拟 slideDown 效果
  game_title.value.style.display = "block";
  game_title.value.style.height = "0";
  game_title.value.style.overflow = "hidden";
  setTimeout(() => {
    game_title.value.style.height = "auto";
  }, 0);

  // 模拟 delay 和 slideToggle 效果
  setTimeout(() => {
    login_btn.value.style.display = "block";
    login_btn.value.style.height = "0";
    login_btn.value.style.overflow = "hidden";
    setTimeout(() => {
      login_btn.value.style.height = "auto";
    }, 10);
  }, 500);

  colorChangeTimeW.value = (canHeight.value > canWidth.value ? canWidth.value : canHeight.value) * 0.5;
  colorChangeTime_div.value.style.width = colorChangeTimeW * 1.6 + "px";
  colorChangeTime_div.value.style.height = colorChangeTimeW * 0.5 + "px";
  colorChangeTime_div.value.style.marginLeft = -colorChangeTimeW * 0.8 + "px";
  colorChangeTime_div.value.style.lineHeight = colorChangeTimeW * 0.5 + "px";
  colorChangeTime_div.value.style.fontSize = colorChangeTimeW * 0.3 + "px";

  backrgound.value = new backgroundObj();
  backrgound.value.init();

  squares.value = new squareObj();
  squares.value.init();

  mySquare.value = new mySquareObj();
  mySquare.value.init();

  beginAnim.value = new beginAnimObj();
  beginAnim.value.init();
}

function restartInit() {
  AnimPX.value = new Array();
  AnimPY.value = new Array();
  changeColorindex.value = 0;
  jump_count.value = 0;

  // 隐藏元素
  colorChangeTime_div.value.style.display = "none";
  score_div.value.style.display = "none";

  // 初始化动画
  beginAnim.value.init();

  // 设置游戏状态
  beginGame.value = false;
  gameOver.value = true;
  lastTime.value = Date.now();

  // 设置游戏标题
  game_title.value.innerHTML = "方&nbsp;块&nbsp;跳&nbsp;跃";

  // 显示游戏标题（模拟slideDown效果）
  game_title.value.style.display = "block";
  game_title.value.style.height = "0";
  game_title.value.style.overflow = "hidden";
  setTimeout(() => {
    game_title.value.style.height = "auto";
  }, 0);

  // 延迟显示登录按钮（模拟delay和slideToggle效果）
  setTimeout(() => {
    login_btn.value.style.display = "block";
    login_btn.value.style.height = "0";
    login_btn.value.style.overflow = "hidden";
    setTimeout(() => {
      login_btn.value.style.height = "auto";
    }, 10);
  }, 500);

  // 设置登录按钮文本
  login_btn.value.innerHTML = "再来一次";

  // 显示状态（模拟slideDown效果）
  state_div.value.style.display = "block";
  state_div.value.style.height = "0";
  state_div.value.style.overflow = "hidden";
  setTimeout(() => {
    state_div.value.style.height = "auto";
  }, 500);

  // 设置状态文本
  state_div.value.innerHTML = "游戏结束，得分：" + Math.floor(score.value);
}

function game() {
  init();
  loop.value = setInterval(gameloop, 20);
}
function restart() {
  // 调用初始化方法
  backrgound.value.init();
  squares.value.init();
  mySquare.value.init();

  // 更新时间戳
  lastTime.value = Date.now();

  // 隐藏元素
  state_div.value.style.display = "none";
  game_title.value.style.display = "none";
  login_btn.value.style.display = "none";

  // 显示分数
  score_div.value.style.display = "block";

  // 重置分数和速度
  score.value = 0;
  totalSpeed.value = 3;
}
function gameloop() {
  backrgound.value.draw();
  ctx2.value.clearRect(0, 0, canWidth.value, canHeight.value);
  ctx2.value.save();

  if (beginAnim.value.isLive && Date.now() - lastTime.value > 1000) {
    beginAnim.value.draw();
  }

  if (beginGame.value && !gameOver.value) {
    scoreText.value = `得分:${Math.floor(score.value)}`;
    addSpeed();
    squares.value.draw();
    mySquare.value.draw();
    squaresToMy();

    // 添加点击事件监听器
    main_box.value.addEventListener("click", function () {
      mySquare.value.jump();
    });
  } else if (gameOver.value && !beginGame.value) {
    // 这里可以添加游戏结束时的逻辑
  }

  ctx2.value.restore();
}
function loginGame() {
  changeColorTime.value = Date.now();

  // 显示颜色变化时间div
  colorChangeTime_div.value.style.display = "block";

  // 随机设置颜色
  const randomColor =
    squareColor[Math.floor(Math.random() * squareColor.length)];
  colorChangeTime_div.value.style.color = randomColor;

  // 设置颜色变化时间div的内容
  colorChangeTime_div.value.innerHTML = "" + changeTimeArrays[changeColorindex.value];

  if (!gameOver.value && !beginGame.value) {
    // 显示分数，隐藏游戏标题和方块
    score_div.value.style.display = "block";
    game_title.value.style.display = "none";
    square_main.value.style.display = "none";

    // 设置游戏状态
    beginGame.value = true;

    // 隐藏登录按钮
    login_btn.value.style.display = "none";
  } else if (gameOver.value && !beginGame.value) {
    // 重新开始游戏
    restart();

    // 更新游戏状态
    gameOver.value = false;
    beginGame.value = true;
  }

  // 设置动画状态
  beginAnim.value.isLive = false;

  // 隐藏方块
  square_main.value.style.display = "none";
}
function addSpeed() {
  totalSpeed.value += 0.04 * 0.05;
  score.value += 0.04;
}
function squaresToMy() {
  for (var i = 0; i < squares.value.num; i++) {
    if (squares.value.isLive[i]) {
      if (squares.value.color[i] != mySquare.value.color) {
        if (mySquare.value.isLive) {
          if (
            ((mySquare.value.x + mySquare.value.l - 1 > squares.value.x[i] &&
              mySquare.value.x + mySquare.value.l - 1 < squares.value.x[i] + squares.value.w[i] &&
              mySquare.value.x + mySquare.value.l - 30 > squares.value.x[i] &&
              mySquare.value.x + mySquare.value.l - 30 <
              squares.value.x[i] + squares.value.w[i]) ||
              (mySquare.value.x > squares.value.x[i] &&
                mySquare.value.x + 10 < squares.value.x[i] + squares.value.w[i] &&
                mySquare.value.x + 10 > squares.value.x[i] &&
                mySquare.value.x + 10 < squares.value.x[i] + squares.value.w[i])) &&
            mySquare.value.y + mySquare.value.l > squares.value.y[i] &&
            mySquare.value.y + mySquare.value.l < squares.value.y[i] + squares.value.h[i]
          ) {
            mySquare.value.y = squares.value.y[i] - mySquare.value.l;
            mySquare.value.toVSpeed = -totalSpeed.value * 0.2;
            mySquare.value.toDownSpeed = 0;
            jump_count.value = 0;
          }
          if (
            mySquare.value.x + mySquare.value.l > squares.value.x[i] &&
            mySquare.value.x + mySquare.value.l < squares.value.x[i] + squares.value.w[i] &&
            mySquare.value.y + mySquare.value.l > squares.value.y[i] &&
            mySquare.value.y + mySquare.value.l < squares.value.y[i] + squares.value.h[i]
          ) {
            mySquare.value.x = squares.value.x[i] - mySquare.value.l;
          }
        }
      }
    }
  }
}

function jump() {
  mySquare.value.jump();
}

//暴露给父组件用
defineExpose({
  loginGame,
  jump
});

//背景
class backgroundObj {
  x:any;
  y:any;
  w:any;
  h:any;
  isLive:any;
  num:any;
  constructor() {
    this.x = [];
    this.y = [];
    this.w = [];
    this.h = [];
    this.isLive = [];
    this.num = 3;
  }

  init() {
    for (let i = 0; i < this.num; i++) {
      this.x[i] =
        i === 0
          ? canWidth.value * 0.1 * Math.random()
          : this.x[i - 1] +
          this.w[i - 1] +
          canWidth.value * 0.2 * i * Math.random();

      this.w[i] = canWidth.value * 0.08 + canHeight.value * Math.random() * 0.3;
      this.h[i] = canHeight.value * 0.08 + canWidth.value * Math.random() * 0.3;
      this.y[i] = canHeight.value * 0.2 * Math.random();
      this.isLive[i] = true;
    }
  }

  cloudBorn() {
    for (let i = 0; i < this.num; i++) {
      if (!this.isLive[i]) {
        this.w[i] = canWidth.value * 0.08 + canWidth.value * Math.random() * 0.3;
        this.h[i] = canHeight.value * 0.08 + canHeight.value * Math.random() * 0.3;
        this.y[i] = canHeight.value * 0.2 * Math.random();

        this.x[i] = i === 0 ? canWidth.value : canWidth.value + i * this.w[i - 1];

        this.isLive[i] = true;
      }
    }
  }

  draw() {
    ctx1.value.clearRect(0, 0, canWidth.value, canHeight.value);
    ctx1.value.save();

    for (let i = 0; i < this.num; i++) {
      if (!this.isLive[i]) continue;

      this.x[i] -= 0.1 * totalSpeed.value;
      const maxSize = Math.max(this.h[i], this.w[i]) * 0.15;
      const smallSize = Math.max(this.h[i], this.w[i]) * 0.1;

      // 绘制云朵的各个部分
      const cloudParts = [
        { x: 0.4, y: 0.1, size: maxSize },
        { x: 0.1, y: 0.2, size: maxSize },
        { x: 0.6, y: 0.25, size: maxSize },
        { x: 0.5, y: 0.3, size: maxSize },
        { x: 0.65, y: 0.22, size: maxSize },
        { x: 0.2, y: 0.35, size: maxSize },
        { x: 0.35, y: 0.35, size: smallSize },
        { x: 0.3, y: 0.1, size: maxSize },
      ];

      ctx1.value.fillStyle = "#ffffff";
      cloudParts.forEach((part) => {
        ctx1.value.beginPath();
        ctx1.value.arc(
          this.x[i] + this.w[i] * part.x,
          this.y[i] + this.h[i] * part.y,
          part.size,
          0,
          Math.PI * 2
        );
        ctx1.value.fill();
        ctx1.value.closePath();
      });

      if (this.x[i] + this.w[i] < 0) {
        this.isLive[i] = false;
      }
    }

    ctx1.value.restore();
    this.cloudBorn();
  }
}

//底下方块
class squareObj {
  num:any;
  x:any;
  y:any;
  w:any;
  h:any;
  color:any;
  isLive:any;
  constructor() {
    this.num = 12;
    this.x = [];
    this.y = [];
    this.w = [];
    this.h = [];
    this.color = [];
    this.isLive = [];
  }

  init() {
    let repeatColorCount = 0;

    for (let i = 0; i < this.num; i++) {
      // Random color selection with constraints
      this.color[i] = this.getRandomColor(i, repeatColorCount);

      // Position and size initialization
      if (i === 0) {
        this.x[i] = 0;
      } else {
        this.x[i] = this.x[i - 1] + this.w[i - 1] + 1;
      }

      this.h[i] = canHeight.value * 0.3 + canHeight.value * 0.25 * Math.random();
      this.w[i] = canWidth.value * 0.15 + canWidth.value * 0.06 * Math.random();
      this.y[i] = canHeight.value - this.h[i];
      this.isLive[i] = true;

      // Update repeat color count
      repeatColorCount =
        this.color[i] === this.color[i - 1] ? repeatColorCount + 1 : 0;

      // Handle consecutive colors
      if (repeatColorCount > 1) {
        this.adjustColor(i);
      }
    }
  }

  getRandomColor(i: any, repeatColorCount: any) {
    const randomIndex = Math.floor(Math.random() * squareColor.length);
    let color = squareColor[randomIndex];

    // For the first element, check against last element
    if (i === 0 && color === this.color[this.num - 1]) {
      const lastColorIndex = squareColor.indexOf(
        this.color[this.num - 1]
      );
      color =
        squareColor[
        (lastColorIndex - 1 + squareColor.length) % squareColor.length
        ];
    }
    // For other elements, check against previous element
    else if (
      i > 0 &&
      color === this.color[i - 1] &&
      repeatColorCount > 1
    ) {
      const currentColorIndex = squareColor.indexOf(color);
      color = squareColor[(currentColorIndex + 1) % squareColor.length];
    }

    return color;
  }

  adjustColor(i: any) {
    if (i === 0) {
      const lastColorIndex = squareColor.indexOf(
        this.color[this.num - 1]
      );
      this.color[i] =
        squareColor[
        (lastColorIndex - 1 + squareColor.length) % squareColor.length
        ];
    } else {
      const currentColorIndex = squareColor.indexOf(this.color[i]);
      this.color[i] =
        squareColor[(currentColorIndex + 1) % squareColor.length];
    }
  }

  squareBorn() {
    const maxX = Math.max(
      ...this.x.map((val:any, idx:any) => val + (this.w[idx] || 0))
    );
    const maxI = this.x.indexOf(
      maxX - (this.w[this.x.indexOf(maxX)] || 0)
    );

    for (let i = 0; i < this.num; i++) {
      if (!this.isLive[i]) {
        this.x[i] = maxX + 1;
        this.h[i] = canHeight.value * 0.25 + canHeight.value * 0.35 * Math.random();
        this.w[i] = canWidth.value * 0.14 + canWidth.value * 0.1 * Math.random();
        this.y[i] = canHeight.value - this.h[i];

        let repeatColorCount = 0;
        if (i === 0 && this.isLive[this.num - 1]) {
          this.color[i] = this.getRandomColorForBorn(
            this.num - 1,
            repeatColorCount
          );
        } else if (i > 0 && this.isLive[i - 1]) {
          this.color[i] = this.getRandomColorForBorn(
            i - 1,
            repeatColorCount
          );
        }

        this.isLive[i] = true;
        return;
      }
    }
  }

  getRandomColorForBorn(prevIndex: any, repeatColorCount: any) {
    const randomIndex = Math.floor(Math.random() * 3);
    let color = squareColor[randomIndex];

    if (color === this.color[prevIndex] && repeatColorCount > 1) {
      const currentColorIndex = squareColor.indexOf(color);
      color = squareColor[(currentColorIndex + 1) % squareColor.length];
    }

    return color;
  }

  draw() {
    for (let i = 0; i < this.num; i++) {
      if (this.isLive[i]) {
        ctx2.value.fillStyle = this.color[i];
        ctx2.value.beginPath();
        ctx2.value.fillRect(this.x[i], this.y[i], this.w[i], this.h[i]);
        ctx2.value.fill();
        ctx2.value.closePath();
        this.x[i] -= totalSpeed.value;
      }

      if (this.x[i] + this.w[i] < 0) {
        this.isLive[i] = false;
      }
    }

    this.squareBorn();
  }
}

//我的方块
class mySquareObj {
  x:any;
  y:any;
  isLive:any;
  l:any;
  color:any;
  toDownSpeed:any;
  toVSpeed:any;
  constructor() {
    this.x;
    this.y;
    this.isLive; // 生命状态
    this.l = 40; // 正方形边长
    this.color;
    this.toDownSpeed = 0; // 垂直方向速度
    this.toVSpeed = 0; // 水平方向速度
  }

  init() {
    this.isLive = true;
    this.x = 0;
    this.y = 0;
    this.l = 40;
    this.toDownSpeed = 0;
    this.toVSpeed = 0;
    this.color = squareColor[0];
  }

  jump() {
    if (this.isLive) {
      this.toDownSpeed = -15;
      this.toVSpeed = 2;
      jump_count.value++;
      if (this.x + this.l > canWidth.value) {
        this.x = canWidth.value - this.l;
      }
    }
  }

  toDown() {
    if (this.isLive) {
      this.toDownSpeed += 9.8 * 1 * 0.06;
      this.y += this.toDownSpeed;
      this.x += this.toVSpeed;
      if (this.y + this.l > canHeight.value) {
        this.isLive = false;
      }
    }
  }

  draw() {
    if (this.isLive) {
      const now = Date.now();
      if (now - changeColorTime.value > 1000) {
        changeColorindex.value = ++changeColorindex.value % changeTimeArrays.length;
        const strColor =
          "" +
          squareColor[Math.floor(Math.random() * squareColor.length)];


        // 设置颜色和内容
        colorChangeTime_div.value.style.color = strColor;
        colorChangeTime_div.value.textContent =
          "" + changeTimeArrays[changeColorindex.value];

        if (changeColorindex.value === 10) {
          colorChangeTime_div.value.style.fontSize =
            colorChangeTimeW * 0.15 + "px";
          this.color = strColor;
        } else {
          colorChangeTime_div.value.style.fontSize =
            colorChangeTimeW * 0.3 + "px";
        }

        changeColorTime.value = now;
      }
      ctx2.value.fillStyle = this.color + "";
      ctx2.value.rect(this.x, this.y, this.l, this.l);
      ctx2.value.fill();
      ctx2.value.lineWidth = 3;
      ctx2.value.radiusX = 3;

      ctx2.value.strokeStyle = "#ffffff";
      ctx2.value.stroke();
      if (this.x < -100) {
        this.isLive = false;
      }
    } else {
      restartInit();
    }
    this.toDown();
  }
}

//动画
class beginAnimObj {
  x:any;
  y:any;
  isLive:any;
  l:any;
  color:any;
  toDownSpeed:any;
  toVSpeed:any;
  constructor() {
    this.x;
    this.y;
    this.isLive;
    this.l = 40; // 正方形边长
    this.color;
    this.toDownSpeed = 0; // 垂直方向速度
    this.toVSpeed = canWidth.value * 0.021; // 水平方向速度
  }

  init() {
    this.isLive = true;
    this.x = 0;
    this.y = 0;
    this.toDownSpeed = 0;
    this.toVSpeed = canWidth.value * 0.021;
    this.color = squareColor[0];
  }

  jump() {
    if (this.isLive) {
      this.toDownSpeed = -this.toDownSpeed;
      this.toVSpeed = canWidth.value * 0.021 * 0.5;
      jump_count.value++;
      if (this.x + this.l > canWidth.value) {
        this.x = canWidth.value - this.l;
      }
      this.x += this.toVSpeed;
      if (this.toVSpeed + 2 < 3) {
        this.toVSpeed += 1;
      }
    }
  }

  toDown() {
    if (this.isLive) {
      this.toDownSpeed += 9.8 * 1 * 0.06;
      this.y += this.toDownSpeed;
      this.x += this.toVSpeed;
      if (this.y > canHeight.value) {
        this.isLive = false;
      }
    }
  }

  draw() {
    if (this.isLive) {

      square_main.value.style.display = "block";
      square_main.value.style.left = this.x + "px";
      square_main.value.style.top = this.y + "px";

      if (
        this.y + this.l > canHeight.value * 0.35 &&
        this.x + this.l * 0.5 < canWidth.value * 0.5 + 120 &&
        this.x + this.l * 0.5 > canWidth.value * 0.5 - 120
      ) {
        this.jump();
        game_title.value.innerHTML =
          "方&nbsp;块&nbsp;<i style='font-size: 46px;color:#FF6688;'>跳&nbsp;</i>跃";
      }

      ctx2.value.restore();
      this.toDown();
    } else {
      square_main.value.style.display = "none";
    }
  }
}



onMounted(() => {
  game();
});

onBeforeUnmount(() => {
  clearInterval(loop.value);
});
</script>

<style scoped>
* {
  padding: 0px;
  margin: 0px;
}

a {
  text-decoration: none;
  list-style: none;
  color: rgb(0, 0, 0);
}

#main_box {
  margin: 0px auto;
  width: 420px;
  height: 580px;
  background: skyblue;
  position: relative;
  overflow: hidden;
}

.can {
  position: absolute;
  top: 0px;
  left: 0px;
}

#score {
  width: auto;
  height: 40px;
  font-size: 22px;
  color: #7fffd4;
  position: absolute;
  top: 10px;
  left: 10px;
  display: none;
}

#game_title {
  display: none;
  position: absolute;
  width: 240px;
  height: 80px;
  line-height: 80px;
  text-align: center;
  top: 35%;
  left: 50%;
  margin-left: -120px;
  font-size: 42px;
  font-family: "century gothic";
  font-weight: bolder;
  text-shadow: 4px 3px 2px black;
  color: #fff;
}

#login_btn {
  display: none;
  position: absolute;
  bottom: 100px;
  left: 50%;
  width: 100px;
  height: 40px;
  margin-left: -50px;
  line-height: 40px;
  text-align: center;
  border-radius: 12px;
  border: 2px solid #ffffff;
  font-size: 18px;
  color: #000000;
  font-weight: normal;
  background: peachpuff;
}

#login_btn:hover {
  color: #fff;
}

#login_btn:active {
  background: #ffffff;
  color: #000000;
}

#square_main {
  width: 40px;
  height: 40px;
  position: absolute;
  top: 0px;
  left: 0px;
  border: 2px solid #ffffff;
  display: none;
  background: #ff6688;
}

#state {
  width: 280px;
  height: 60px;
  font-size: 18px;
  font-weight: bolder;
  text-shadow: #fdf5e6;
  color: blueviolet;
  font-family: "arial narrow";
  position: absolute;
  top: 45%;
  left: 50%;
  line-height: 60px;
  text-align: center;
  margin-left: -140px;
  display: none;
}

#colorChangeTime_div {
  width: 200px;
  height: 50px;
  line-height: 50px;
  position: absolute;
  text-align: center;
  top: 3%;
  left: 50%;
  display: none;
  color: #ffffff;
  font-size: 40px;
}
</style>