wangfukang 3 days ago
parent
commit
95422c0cfc
  1. 183
      package1/planet/adventure.vue

183
package1/planet/adventure.vue

@ -433,11 +433,11 @@
]
},
hell: {
layerCounts: [36, 30, 24],
layerCounts: [52, 40, 28],
zones: [
{ x: 58, y: 18, cols: 6, gapX: 86, gapY: 82, offsetX: 0, offsetY: 0, stagger: 4 },
{ x: 102, y: 58, cols: 5, gapX: 86, gapY: 82, offsetX: 0, offsetY: 0, stagger: 4 },
{ x: 144, y: 98, cols: 4, gapX: 86, gapY: 82, offsetX: 0, offsetY: 0, stagger: 4 }
{ x: 44, y: 14, cols: 7, gapX: 76, gapY: 72, offsetX: 0, offsetY: 0, stagger: 4 },
{ x: 72, y: 42, cols: 6, gapX: 76, gapY: 72, offsetX: 0, offsetY: 0, stagger: 4 },
{ x: 34, y: 18, cols: 7, gapX: 76, gapY: 88, offsetX: 0, offsetY: 0, stagger: 0 }
]
}
}
@ -450,6 +450,7 @@
card.trap = false
card.keyCard = false
card.garbage = false
card.openingSafe = false
})
const bottom = this.seededShuffle(cards.filter(card => card.layer === 0), seed + '_bottom')
const middle = this.seededShuffle(cards.filter(card => card.layer === 1), seed + '_middle')
@ -459,7 +460,7 @@
const midOuter = this.seededShuffle(middle.filter(card => !this.isCenterCard(card)), seed + '_mid_outer')
const assigned = {}
const groupCount = Math.floor((cards.length - 6) / 3)
const trapCount = Math.max(10,Math.ceil(groupCount*0.5))
const trapCount = Math.max(20,Math.ceil(groupCount*0.62))
for (let group = 0; group < groupCount; group++) {
const icon = icons[group % icons.length]
let chosen = []
@ -543,8 +544,7 @@
})
},
shouldBuildTrapLayout() {
const rand = this.seededRandom((this.roundSeed || this.levelSeed()) + '_win_rate')
return rand() < 0.85
return true
},
applyTrapLayout(cards) {
this.cards = cards
@ -558,49 +558,168 @@
if (!candidates.length) return
const rand = this.seededRandom((this.roundSeed || this.levelSeed()) + '_trap_layout')
this.shuffleWithRandom(candidates, rand)
const trapIcons = candidates.slice(0, Math.min(candidates.length, 12 + Math.floor(rand() * 5)))
const trapIcons = candidates.slice(0, Math.min(candidates.length, 8 + Math.floor(rand() * 2)))
trapIcons.forEach((targetIcon, trapIndex) => {
const group = iconMap[targetIcon].slice(0, 3)
const group = this.seededShuffle(iconMap[targetIcon].slice(), (this.roundSeed || this.levelSeed()) + '_trap_icon_' + trapIndex).slice(0, 3)
if (group.length < 3) return
const key = group[0]
const pair = group.slice(1, 3)
this.placeDeepKeyCard(key, trapIndex, rand)
this.exposePairEarly(pair, trapIndex)
this.placeDeepKeyCard(key, trapIndex, rand)
this.buildCoverChain(key, cards, trapIndex, rand)
})
this.exposeOpeningCombos(cards, candidates, rand)
this.tightenOpeningPressure(cards, rand)
},
placeDeepKeyCard(card, index, rand) {
card.layer = 0
card.keyCard = true
card.trap = true
card.x = 170 + Math.floor(rand() * 200)
card.y = 130 + Math.floor(rand() * 300)
card.order = 20 + index
card.x = 188 + Math.floor(rand() * 150)
card.y = 150 + Math.floor(rand() * 250)
card.style = `left:${card.x}rpx;top:${card.y}rpx;z-index:${this.cardZIndex(card)};`
this.refreshCardState()
},
exposePairEarly(pair, index) {
const baseX = 56 + (index % 5) * 84
const baseY = 18 + Math.floor(index / 5) * 76
const slots = [
{ x: 34, y: 16 }, { x: 138, y: 16 }, { x: 242, y: 16 }, { x: 346, y: 16 }, { x: 450, y: 16 },
{ x: 34, y: 114 }, { x: 138, y: 114 }, { x: 242, y: 114 }, { x: 346, y: 114 }, { x: 450, y: 114 },
{ x: 34, y: 314 }, { x: 138, y: 314 }, { x: 242, y: 314 }, { x: 346, y: 314 }, { x: 450, y: 314 },
{ x: 34, y: 412 }, { x: 138, y: 412 }, { x: 242, y: 412 }, { x: 346, y: 412 }, { x: 450, y: 412 }
]
const first = slots[index % 10]
const second = slots[index % 10 + 10]
pair.forEach((card, i) => {
card.layer = 2
card.order = 900 + index * 4 + i
card.trap = true
card.x = baseX + i * 8
card.y = baseY + i * 58
card.x = i === 0 ? first.x : second.x
card.y = i === 0 ? first.y : second.y
card.style = `left:${card.x}rpx;top:${card.y}rpx;z-index:${this.cardZIndex(card)};`
})
this.refreshCardState()
},
exposeOpeningCombos(cards, candidates, rand) {
const slots = [
{ x: 38, y: 16 }, { x: 122, y: 16 }, { x: 206, y: 16 },
{ x: 310, y: 16 }, { x: 394, y: 16 }, { x: 478, y: 16 },
{ x: 38, y: 118 }, { x: 122, y: 118 }, { x: 206, y: 118 },
{ x: 310, y: 118 }, { x: 394, y: 118 }, { x: 478, y: 118 },
{ x: 38, y: 408 }, { x: 122, y: 408 }, { x: 206, y: 408 }
]
const safeIcons = candidates.slice(-4)
let slotIndex = 0
safeIcons.forEach((icon, groupIndex) => {
const group = cards.filter(card => card.icon === icon && !card.garbage && !card.keyCard && !card.trap).slice(0, 3)
if (group.length < 3 || slotIndex + 2 >= slots.length) return
group.forEach(card => {
const slot = slots[slotIndex++]
card.layer = 2
card.trap = false
card.keyCard = false
card.openingSafe = true
card.order = 1100 + groupIndex * 8 + slotIndex
card.x = slot.x + Math.floor(rand() * 4)
card.y = slot.y + Math.floor(rand() * 4)
card.style = `left:${card.x}rpx;top:${card.y}rpx;z-index:${this.cardZIndex(card)};`
})
})
this.refreshCardState()
},
buildCoverChain(key, cards, index, rand) {
const covers = cards.filter(card => {
return card.id !== key.id && !card.garbage && !card.keyCard && !card.trap && card.layer > 0
return card.id !== key.id && !card.garbage && !card.keyCard && !card.trap && !card.openingSafe && card.layer > 0
})
this.shuffleWithRandom(covers, rand)
const count = 5 + (index % 3)
const count = 7 + (index % 3)
const offsets = [
{ x: 0, y: 0 },
{ x: 8, y: 8 },
{ x: -8, y: 10 },
{ x: 10, y: -8 },
{ x: -10, y: -6 },
{ x: 2, y: 14 },
{ x: 14, y: 2 },
{ x: -14, y: 4 },
{ x: 4, y: -14 },
{ x: -4, y: 16 },
{ x: 16, y: -4 },
{ x: -16, y: -2 }
]
for (let i = 0; i < count && i < covers.length; i++) {
const cover = covers[i]
cover.layer = i % 2 === 0 ? 1 : 2
cover.x = key.x + (i % 2 === 0 ? 14 : -14) + Math.floor(rand() * 10)
cover.y = key.y + (i % 3 === 0 ? 14 : -14) + Math.floor(rand() * 10)
const offset = offsets[i % offsets.length]
cover.layer = i < 5 ? 1 : 2
cover.order = 520 + index * 28 + i
cover.x = key.x + offset.x + Math.floor(rand() * 5)
cover.y = key.y + offset.y + Math.floor(rand() * 5)
cover.style = `left:${cover.x}rpx;top:${cover.y}rpx;z-index:${this.cardZIndex(cover)};`
}
this.refreshCardState()
},
tightenOpeningPressure(cards, rand) {
let buryIndex = 0
for (let round = 0; round < 3; round++) {
this.refreshCardState()
const visibleMap = {}
cards.forEach(card => {
if (card.removed || card.selected || card.coverDepth > 0 || this.isGarbageIcon(card.icon)) return
if (!visibleMap[card.icon]) visibleMap[card.icon] = []
visibleMap[card.icon].push(card)
})
let changed = false
Object.keys(visibleMap).forEach(icon => {
const list = visibleMap[icon].sort((a, b) => {
if (a.openingSafe !== b.openingSafe) return a.openingSafe ? -1 : 1
if (a.trap !== b.trap) return a.trap ? -1 : 1
return this.getRealZ(b) - this.getRealZ(a)
})
const keepCount = list.some(card => card.openingSafe) ? 3 : (list.some(card => !card.trap) ? 3 : 2)
list.slice(keepCount).forEach(card => {
changed = true
this.buryOpeningCard(card, cards, buryIndex++, rand)
})
})
if (!changed) break
}
this.refreshCardState()
const visible = cards.filter(card => !card.removed && !card.selected && card.coverDepth === 0 && !this.isGarbageIcon(card.icon) && !card.openingSafe)
visible
.sort((a, b) => {
if (a.trap !== b.trap) return a.trap ? -1 : 1
return this.getRealZ(b) - this.getRealZ(a)
})
.slice(30)
.forEach(card => {
this.buryOpeningCard(card, cards, buryIndex++, rand)
})
this.refreshCardState()
},
buryOpeningCard(card, cards, index, rand) {
card.layer = 0
card.trap = true
card.keyCard = true
card.order = 40 + index
card.x = 170 + (index % 5) * 44 + Math.floor(rand() * 10)
card.y = 150 + Math.floor(index / 5) * 54 + Math.floor(rand() * 12)
card.style = `left:${card.x}rpx;top:${card.y}rpx;z-index:${this.cardZIndex(card)};`
this.buildCoverChain(card, cards, 20 + index, rand)
if (this.coverCount(card, cards) < 3) {
this.forceCoverBuriedCard(card, cards, index, rand)
}
},
forceCoverBuriedCard(card, cards, index, rand) {
const covers = cards.filter(item => {
return item.id !== card.id && !item.garbage && !item.keyCard && !item.trap && !item.openingSafe && item.layer > 0
})
this.shuffleWithRandom(covers, rand)
for (let i = 0; i < 3 && i < covers.length; i++) {
const cover = covers[i]
cover.layer = i === 0 ? 1 : 2
cover.order = 980 + index * 8 + i
cover.x = card.x + (i === 0 ? 0 : (i === 1 ? 12 : -12)) + Math.floor(rand() * 4)
cover.y = card.y + (i === 0 ? 0 : (i === 1 ? 10 : -10)) + Math.floor(rand() * 4)
cover.style = `left:${cover.x}rpx;top:${cover.y}rpx;z-index:${this.cardZIndex(cover)};`
}
this.refreshCardState()
@ -664,7 +783,7 @@
coverCount(card, cards) {
return cards.filter(other => {
if (other.id === card.id || this.getRealZ(other) <= this.getRealZ(card)) return false
return this.isOverlap(card, other)
return this.covers(other, card)
}).length
},
isGarbageIcon(icon) {
@ -676,7 +795,7 @@
isBlockedIn(card, list) {
return list.some(other => {
if (other.id === card.id || this.getRealZ(other) <= this.getRealZ(card)) return false
return this.isOverlap(card, other)
return this.covers(other, card)
})
},
isOverlap(a, b) {
@ -690,6 +809,13 @@
overlapY >= minAxis &&
(overlapX * overlapY) >= size * size * minAreaRatio
},
// upper lower
covers(upper, lower) {
const size = 76
const overlapX = Math.min(upper.x + size, lower.x + size) - Math.max(upper.x, lower.x)
const overlapY = Math.min(upper.y + size, lower.y + size) - Math.max(upper.y, lower.y)
return overlapX >= 10 && overlapY >= 10
},
getRealZ(card) {
return (card.layer || 0) * 1000 + (card.order || 0)
},
@ -719,7 +845,7 @@
card.locked = !card.removed && !card.selected && depth > 0
card.coverDepth = depth
card.displayState = depth === 0 ? 'top' : (depth === 1 ? 'middle' : 'deep')
card.renderIcon = card.displayState === 'deep' ? '' : (card.displayIcon || this.displayIcon(card.icon))
card.renderIcon = card.displayState === 'deep' ? '?' : (card.displayIcon || this.displayIcon(card.icon))
card.className = [
depth === 0 ? 'active' : '',
depth === 1 ? 'locked' : '',
@ -733,7 +859,7 @@
return this.cards.filter(other => {
if (other.id === card.id) return false
if (other.removed || other.selected) return false
return this.getRealZ(other) > this.getRealZ(card) && this.isOverlap(card, other)
return this.getRealZ(other) > this.getRealZ(card) && this.covers(other, card)
}).length
},
pickCard(id) {
@ -1008,10 +1134,9 @@
.tile text { font-size: 42rpx; }
.tile .debug-layer { position: absolute; right: 6rpx; bottom: 4rpx; font-size: 16rpx; color: #8AA09C; line-height: 1; }
.tile.active { background: #fff; box-shadow: 0 12rpx 24rpx rgba(66,99,94,0.14); }
.tile.locked { opacity: .45; filter: grayscale(100%); background: #F3F6F5; box-shadow: 0 6rpx 14rpx rgba(66,99,94,0.08); pointer-events: none; }
.tile.hidden-card { opacity: .32; background: #fff; border-radius: 22rpx; box-shadow: none; color: #BFC9D4; pointer-events: none; }
.tile.hidden-card text:first-child { display: none; }
.tile.hidden-card::after { content: '?'; font-size: 36rpx; color: #BFC9D4; }
.tile.locked { opacity: .45; filter: grayscale(100%); background: #F3F6F5; box-shadow: 0 6rpx 14rpx rgba(66,99,94,0.08); }
.tile.hidden-card { opacity: .32; background: #fff; border-radius: 22rpx; box-shadow: none; color: #BFC9D4; }
.tile.hidden-card text:first-child { display: block; font-size: 36rpx; color: #BFC9D4; }
.tile.selected { opacity: 0; transform: scale(.5); pointer-events: none; }
.slot-wrap { margin-top: 24rpx; }
.slot-title { color: #6B817D; font-size: 24rpx; margin-bottom: 14rpx; }

Loading…
Cancel
Save