wangfukang 4 days ago
parent
commit
ee32770ba2
  1. 78
      package1/planet/adventure.vue

78
package1/planet/adventure.vue

@ -88,6 +88,7 @@
:style="card.style" :style="card.style"
@tap="pickCard(card)"> @tap="pickCard(card)">
<text>{{card.displayIcon}}</text> <text>{{card.displayIcon}}</text>
<text class="debug-layer">{{card.layer}}</text>
</view> </view>
</view> </view>
@ -162,8 +163,8 @@
cards: [], cards: [],
slots: [], slots: [],
slotLimit: 7, slotLimit: 7,
timeLimit: 150, timeLimit: 300,
timeLeft: 150, timeLeft: 300,
timer: null, timer: null,
roundSeed: '', roundSeed: '',
moveCount: 0, moveCount: 0,
@ -199,7 +200,9 @@
return Math.max(16, Math.min(100, Math.round((mine.score || 0) * 100 / top.score))) return Math.max(16, Math.min(100, Math.round((mine.score || 0) * 100 / top.score)))
}, },
visibleCards() { visibleCards() {
return this.cards.filter(item => !item.removed && !item.selected) return this.cards
.filter(item => !item.removed && !item.selected)
.sort((a,b)=>this.cardZIndex(a)-this.cardZIndex(b))
}, },
remainingCount() { remainingCount() {
return this.cards.filter(item => !item.removed && !item.selected).length return this.cards.filter(item => !item.removed && !item.selected).length
@ -225,7 +228,7 @@
return cells return cells
}, },
timerText() { timerText() {
return this.playing ? `${this.timeLeft}s` : '150s限时' return this.playing ? `${this.timeLeft}s` : '300s限时'
}, },
timerPercent() { timerPercent() {
return Math.max(0, Math.min(100, Math.round(this.timeLeft * 100 / this.timeLimit))) return Math.max(0, Math.min(100, Math.round(this.timeLeft * 100 / this.timeLimit)))
@ -240,7 +243,7 @@
if (!this.playing) return '开始后进入倒计时' if (!this.playing) return '开始后进入倒计时'
if (this.timeLeft <= 30) return '最后冲刺,槽位别满' if (this.timeLeft <= 30) return '最后冲刺,槽位别满'
if (this.timeLeft <= 60) return '时间紧张,加快决策' if (this.timeLeft <= 60) return '时间紧张,加快决策'
return '150秒内完成助推' return '300秒内完成助推'
}, },
riskText() { riskText() {
if (this.slots.length >= this.slotLimit - 1) return '危险:差1格就满' if (this.slots.length >= this.slotLimit - 1) return '危险:差1格就满'
@ -274,7 +277,7 @@
const elapsed = Math.floor((Date.now() - this.startTs) / 1000) const elapsed = Math.floor((Date.now() - this.startTs) / 1000)
this.timeLeft = Math.max(0, this.timeLimit - elapsed) this.timeLeft = Math.max(0, this.timeLimit - elapsed)
if (this.timeLeft <= 0) { if (this.timeLeft <= 0) {
this.failLevel('时间到了', '超过150秒,本关失败。不消耗次数,调整顺序再来一次。') this.failLevel('时间到了', '超过300秒,本关失败。不消耗次数,调整顺序再来一次。')
} else { } else {
this.startTimer(false) this.startTimer(false)
} }
@ -356,6 +359,9 @@
if (this.shouldBuildTrapLayout()) { if (this.shouldBuildTrapLayout()) {
this.applyTrapLayout(cards) this.applyTrapLayout(cards)
} }
if (!this.validateTileCounts(cards)) {
this.repairTileCounts(cards, icons, garbageIcons)
}
this.cards = cards this.cards = cards
this.slots = [] this.slots = []
this.moveCount = 0 this.moveCount = 0
@ -481,6 +487,7 @@
assigned[card.id] = true assigned[card.id] = true
}) })
} }
this.cards = cards
this.repositionKeyCovers(cards, seed) this.repositionKeyCovers(cards, seed)
const freeCards = cards.filter(card => !assigned[card.id]) const freeCards = cards.filter(card => !assigned[card.id])
const garbageCards = this.seededShuffle(freeCards.slice(), seed + '_garbage').slice(0, 6) const garbageCards = this.seededShuffle(freeCards.slice(), seed + '_garbage').slice(0, 6)
@ -511,11 +518,36 @@
}) })
return positions return positions
}, },
validateTileCounts(cards) {
const counts = {}
cards.forEach(card => {
if (!card.icon) return
counts[card.icon] = (counts[card.icon] || 0) + 1
})
return Object.keys(counts).every(icon => {
const unit = this.isGarbageIcon(icon) ? 2 : 3
return counts[icon] % unit === 0
})
},
repairTileCounts(cards, icons, garbageIcons) {
const sorted = cards.slice().sort((a, b) => this.cardZIndex(a) - this.cardZIndex(b))
sorted.forEach((card, index) => {
if (index < 6) {
card.icon = garbageIcons[Math.floor(index / 2) % garbageIcons.length]
card.garbage = true
} else {
card.icon = icons[Math.floor((index - 6) / 3) % icons.length]
card.garbage = false
}
card.displayIcon = this.displayIcon(card.icon)
})
},
shouldBuildTrapLayout() { shouldBuildTrapLayout() {
const rand = this.seededRandom((this.roundSeed || this.levelSeed()) + '_win_rate') const rand = this.seededRandom((this.roundSeed || this.levelSeed()) + '_win_rate')
return rand() < 0.5 return rand() < 0.5
}, },
applyTrapLayout(cards) { applyTrapLayout(cards) {
this.cards = cards
const iconMap = {} const iconMap = {}
cards.forEach(card => { cards.forEach(card => {
if (this.isGarbageIcon(card.icon)) return if (this.isGarbageIcon(card.icon)) return
@ -544,6 +576,7 @@
card.x = 180 + Math.floor(rand() * 180) card.x = 180 + Math.floor(rand() * 180)
card.y = 140 + Math.floor(rand() * 260) card.y = 140 + Math.floor(rand() * 260)
card.style = `left:${card.x}rpx;top:${card.y}rpx;z-index:${this.cardZIndex(card)};` card.style = `left:${card.x}rpx;top:${card.y}rpx;z-index:${this.cardZIndex(card)};`
this.refreshCardState()
}, },
exposePairEarly(pair, index) { exposePairEarly(pair, index) {
const baseX = 66 + (index % 4) * 100 const baseX = 66 + (index % 4) * 100
@ -555,6 +588,7 @@
card.y = baseY + i * 58 card.y = baseY + i * 58
card.style = `left:${card.x}rpx;top:${card.y}rpx;z-index:${this.cardZIndex(card)};` card.style = `left:${card.x}rpx;top:${card.y}rpx;z-index:${this.cardZIndex(card)};`
}) })
this.refreshCardState()
}, },
buildCoverChain(key, cards, index, rand) { buildCoverChain(key, cards, index, rand) {
const covers = cards.filter(card => { const covers = cards.filter(card => {
@ -569,6 +603,7 @@
cover.y = key.y + (i < 2 ? 16 : -16) + Math.floor(rand() * 10) cover.y = key.y + (i < 2 ? 16 : -16) + Math.floor(rand() * 10)
cover.style = `left:${cover.x}rpx;top:${cover.y}rpx;z-index:${this.cardZIndex(cover)};` cover.style = `left:${cover.x}rpx;top:${cover.y}rpx;z-index:${this.cardZIndex(cover)};`
} }
this.refreshCardState()
}, },
repositionKeyCovers(cards, seed) { repositionKeyCovers(cards, seed) {
const rand = this.seededRandom(seed + '_cover') const rand = this.seededRandom(seed + '_cover')
@ -583,6 +618,7 @@
cover.style = `left:${cover.x}rpx;top:${cover.y}rpx;z-index:${this.cardZIndex(cover)};` cover.style = `left:${cover.x}rpx;top:${cover.y}rpx;z-index:${this.cardZIndex(cover)};`
} }
}) })
this.refreshCardState()
}, },
takeNext(pool, assigned) { takeNext(pool, assigned) {
while (pool.length) { while (pool.length) {
@ -627,7 +663,7 @@
}, },
coverCount(card, cards) { coverCount(card, cards) {
return cards.filter(other => { return cards.filter(other => {
if (other.id === card.id || other.layer <= card.layer) return false if (other.id === card.id || this.getRealZ(other) <= this.getRealZ(card)) return false
return this.isOverlap(card, other) return this.isOverlap(card, other)
}).length }).length
}, },
@ -639,15 +675,24 @@
}, },
isBlockedIn(card, list) { isBlockedIn(card, list) {
return list.some(other => { return list.some(other => {
if (other.id === card.id || other.layer <= card.layer) return false if (other.id === card.id || this.getRealZ(other) <= this.getRealZ(card)) return false
return this.isOverlap(card, other) return this.isOverlap(card, other)
}) })
}, },
isOverlap(a, b) { isOverlap(a, b) {
return Math.abs(a.x - b.x) < 82 && Math.abs(a.y - b.y) < 82 const size = 76
return !(
a.x + size <= b.x ||
b.x + size <= a.x ||
a.y + size <= b.y ||
b.y + size <= a.y
)
},
getRealZ(card) {
return (card.layer || 0) * 1000 + (card.order || 0)
}, },
cardZIndex(card) { cardZIndex(card) {
return (card.layer || 0) * 100 + (card.order || 0) + 1 return this.getRealZ(card) + 1
}, },
normalizeCards(icons) { normalizeCards(icons) {
this.cards.forEach((card, index) => { this.cards.forEach((card, index) => {
@ -683,8 +728,9 @@
return return
} }
this.refreshCardState() this.refreshCardState()
if (card.removed || card.selected || card.locked || this.isLocked(card)) { const lockedNow = this.isLocked(card)
this.tui.toast('这张还被压住,先消上面的牌') if (card.removed || card.selected || lockedNow) {
this.tui.toast('这张卡被压住了')
return return
} }
if (this.slots.length >= this.slotLimit) return if (this.slots.length >= this.slotLimit) return
@ -713,7 +759,7 @@
const elapsed = Math.floor((Date.now() - this.startTs) / 1000) const elapsed = Math.floor((Date.now() - this.startTs) / 1000)
this.timeLeft = Math.max(0, this.timeLimit - elapsed) this.timeLeft = Math.max(0, this.timeLimit - elapsed)
if (this.timeLeft <= 0) { if (this.timeLeft <= 0) {
this.failLevel('时间到了', '超过150秒,本关失败。不消耗次数,调整顺序再来一次。') this.failLevel('时间到了', '超过300秒,本关失败。不消耗次数,调整顺序再来一次。')
} }
}, 1000) }, 1000)
}, },
@ -752,8 +798,9 @@
}, },
isLocked(card) { isLocked(card) {
return this.cards.some(other => { return this.cards.some(other => {
if (other.removed || other.selected || other.layer <= card.layer) return false if (other.id === card.id) return false
return this.isOverlap(card, other) if (other.removed || other.selected) return false
return this.getRealZ(other) > this.getRealZ(card) && this.isOverlap(card, other)
}) })
}, },
finishClear() { finishClear() {
@ -943,6 +990,7 @@
.board { margin-top: 22rpx; height: 620rpx; border-radius: 36rpx; background: linear-gradient(155deg, rgba(234,248,255,0.9), rgba(255,248,222,0.72)); position: relative; overflow: hidden; z-index: 1; } .board { margin-top: 22rpx; height: 620rpx; border-radius: 36rpx; background: linear-gradient(155deg, rgba(234,248,255,0.9), rgba(255,248,222,0.72)); position: relative; overflow: hidden; z-index: 1; }
.tile { position: absolute; width: 76rpx; height: 76rpx; border-radius: 22rpx; background: #fff; display: flex; align-items: center; justify-content: center; box-shadow: 0 10rpx 22rpx rgba(66,99,94,0.12); border: 2rpx solid rgba(255,255,255,0.9); transition: transform .12s ease, opacity .12s ease; } .tile { position: absolute; width: 76rpx; height: 76rpx; border-radius: 22rpx; background: #fff; display: flex; align-items: center; justify-content: center; box-shadow: 0 10rpx 22rpx rgba(66,99,94,0.12); border: 2rpx solid rgba(255,255,255,0.9); transition: transform .12s ease, opacity .12s ease; }
.tile text { font-size: 42rpx; } .tile text { font-size: 42rpx; }
.tile .debug-layer { position: absolute; right: 6rpx; bottom: 4rpx; font-size: 16rpx; color: #8AA09C; line-height: 1; }
.tile.locked { .tile.locked {
opacity: .42; opacity: .42;
pointer-events: none; pointer-events: none;

Loading…
Cancel
Save