Files
dkala-front/public/tower_game-master/src/block.js
T
2026-02-07 15:31:22 +03:30

251 lines
7.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
getMoveDownValue,
getLandBlockVelocity,
getSwingBlockVelocity,
touchEventHandler,
addSuccessCount,
addFailedCount,
addScore
} from './utils'
import * as constant from './constant'
const checkCollision = (block, line) => {
// 0 goon 1 drop 2 rotate left 3 rotate right 4 ok 5 perfect
if (block.y + block.height >= line.y) {
if (block.x < line.x - block.calWidth || block.x > line.collisionX + block.calWidth) {
return 1
}
if (block.x < line.x) {
return 2
}
if (block.x > line.collisionX) {
return 3
}
if (block.x > line.x + (block.calWidth * 0.8) && block.x < line.x + (block.calWidth * 1.2)) {
// -10% +10%
return 5
}
return 4
}
return 0
}
const swing = (instance, engine, time) => {
const ropeHeight = engine.getVariable(constant.ropeHeight)
if (instance.status !== constant.swing) return
const i = instance
const initialAngle = engine.getVariable(constant.initialAngle)
i.angle = initialAngle *
getSwingBlockVelocity(engine, time)
i.weightX = i.x +
(Math.sin(i.angle) * ropeHeight)
i.weightY = i.y +
(Math.cos(i.angle) * ropeHeight)
}
const checkBlockOut = (instance, engine) => {
if (instance.status === constant.rotateLeft) {
// 左转 要等右上角消失才算消失
if (instance.y - instance.width >= engine.height) {
instance.visible = false
instance.status = constant.out
addFailedCount(engine)
}
} else if (instance.y >= engine.height) {
instance.visible = false
instance.status = constant.out
addFailedCount(engine)
}
}
export const blockAction = (instance, engine, time) => {
const i = instance
const ropeHeight = engine.getVariable(constant.ropeHeight)
if (!i.visible) {
return
}
if (!i.ready) {
i.ready = true
i.status = constant.swing
instance.updateWidth(engine.getVariable(constant.blockWidth))
instance.updateHeight(engine.getVariable(constant.blockHeight))
instance.x = engine.width / 2
instance.y = ropeHeight * -1.5
}
const line = engine.getInstance('line')
switch (i.status) {
case constant.swing:
engine.getTimeMovement(
constant.hookDownMovement,
[[instance.y, instance.y + ropeHeight]],
(value) => {
instance.y = value
},
{
name: 'block'
}
)
swing(instance, engine, time)
break
case constant.beforeDrop:
i.x = instance.weightX - instance.calWidth
i.y = instance.weightY + (0.3 * instance.height) // add rope height
i.rotate = 0
i.ay = engine.pixelsPerFrame(0.0003 * engine.height) // acceleration of gravity
i.startDropTime = time
i.status = constant.drop
break
case constant.drop:
const deltaTime = time - i.startDropTime
i.startDropTime = time
i.vy += i.ay * deltaTime
i.y += (i.vy * deltaTime) + (0.5 * i.ay * (deltaTime ** 2))
const collision = checkCollision(instance, line)
const blockY = line.y - instance.height
const calRotate = (ins) => {
ins.originOutwardAngle = Math.atan(ins.height / ins.outwardOffset)
ins.originHypotenuse = Math.sqrt((ins.height ** 2)
+ (ins.outwardOffset ** 2))
engine.playAudio('rotate')
}
switch (collision) {
case 1:
checkBlockOut(instance, engine)
break
case 2:
i.status = constant.rotateLeft
instance.y = blockY
instance.outwardOffset = (line.x + instance.calWidth) - instance.x
calRotate(instance)
break
case 3:
i.status = constant.rotateRight
instance.y = blockY
instance.outwardOffset = (line.collisionX + instance.calWidth) - instance.x
calRotate(instance)
break
case 4:
case 5:
i.status = constant.land
const lastSuccessCount = engine.getVariable(constant.successCount)
addSuccessCount(engine)
engine.setTimeMovement(constant.moveDownMovement, 500)
if (lastSuccessCount === 10 || lastSuccessCount === 15) {
engine.setTimeMovement(constant.lightningMovement, 150)
}
instance.y = blockY
line.y = blockY
line.x = i.x - i.calWidth
line.collisionX = line.x + i.width
// 作弊检测 超出左边或右边13
const cheatWidth = i.width * 0.3
if (i.x > engine.width - (cheatWidth * 2)
|| i.x < -cheatWidth) {
engine.setVariable(constant.hardMode, true)
}
if (collision === 5) {
instance.perfect = true
addScore(engine, true)
engine.playAudio('drop-perfect')
} else {
addScore(engine)
engine.playAudio('drop')
}
break
default:
break
}
break
case constant.land:
engine.getTimeMovement(
constant.moveDownMovement,
[[instance.y, instance.y + (getMoveDownValue(engine, { pixelsPerFrame: s => s / 2 }))]],
(value) => {
if (!instance.visible) return
instance.y = value
if (instance.y > engine.height) {
instance.visible = false
}
},
{
name: instance.name
}
)
instance.x += getLandBlockVelocity(engine, time)
break
case constant.rotateLeft:
case constant.rotateRight:
const isRight = i.status === constant.rotateRight
const rotateSpeed = engine.pixelsPerFrame(Math.PI * 4)
const isShouldFall = isRight ? instance.rotate > 1.3 : instance.rotate < -1.3// 75度
const leftFix = isRight ? 1 : -1
if (isShouldFall) {
instance.rotate += (rotateSpeed / 8) * leftFix
instance.y += engine.pixelsPerFrame(engine.height * 0.7)
instance.x += engine.pixelsPerFrame(engine.width * 0.3) * leftFix
} else {
let rotateRatio = (instance.calWidth - instance.outwardOffset)
/ instance.calWidth
rotateRatio = rotateRatio > 0.5 ? rotateRatio : 0.5
instance.rotate += rotateSpeed * rotateRatio * leftFix
const angle = instance.originOutwardAngle + instance.rotate
const rotateAxisX = isRight ? line.collisionX + instance.calWidth
: line.x + instance.calWidth
const rotateAxisY = line.y
instance.x = rotateAxisX -
(Math.cos(angle) * instance.originHypotenuse)
instance.y = rotateAxisY -
(Math.sin(angle) * instance.originHypotenuse)
}
checkBlockOut(instance, engine)
break
default:
break
}
}
const drawSwingBlock = (instance, engine) => {
const bl = engine.getImg('blockRope')
engine.ctx.drawImage(
bl, instance.weightX - instance.calWidth
, instance.weightY
, instance.width, instance.height * 1.3
)
const leftX = instance.weightX - instance.calWidth
engine.debugLineY(leftX)
}
const drawBlock = (instance, engine) => {
const { perfect } = instance
const bl = engine.getImg(perfect ? 'block-perfect' : 'block')
engine.ctx.drawImage(bl, instance.x, instance.y, instance.width, instance.height)
}
const drawRotatedBlock = (instance, engine) => {
const { ctx } = engine
ctx.save()
ctx.translate(instance.x, instance.y)
ctx.rotate(instance.rotate)
ctx.translate(-instance.x, -instance.y)
drawBlock(instance, engine)
ctx.restore()
}
export const blockPainter = (instance, engine) => {
const { status } = instance
switch (status) {
case constant.swing:
drawSwingBlock(instance, engine)
break
case constant.drop:
case constant.land:
drawBlock(instance, engine)
break
case constant.rotateLeft:
case constant.rotateRight:
drawRotatedBlock(instance, engine)
break
default:
break
}
}