Add configurable game flow, finish punching, and audio cues

This commit is contained in:
2026-03-23 19:35:17 +08:00
parent 3b4b3ee3ec
commit 48159be900
23 changed files with 1620 additions and 68 deletions

View File

@@ -97,8 +97,18 @@ Page({
panelTimerText: '00:00:00',
panelMileageText: '0m',
panelDistanceValueText: '108',
panelProgressText: '0/14',
panelProgressText: '0/0',
gameSessionStatus: 'idle',
panelSpeedValueText: '0',
punchButtonText: '打点',
punchButtonEnabled: false,
punchHintText: '等待进入检查点范围',
punchFeedbackVisible: false,
punchFeedbackText: '',
punchFeedbackTone: 'neutral',
contentCardVisible: false,
contentCardTitle: '',
contentCardBody: '',
compassTicks: buildCompassTicks(),
compassLabels: buildCompassLabels(),
...buildSideButtonVisibility('left'),
@@ -124,8 +134,18 @@ Page({
panelTimerText: '00:00:00',
panelMileageText: '0m',
panelDistanceValueText: '108',
panelProgressText: '0/14',
panelProgressText: '0/0',
gameSessionStatus: 'idle',
panelSpeedValueText: '0',
punchButtonText: '打点',
punchButtonEnabled: false,
punchHintText: '等待进入检查点范围',
punchFeedbackVisible: false,
punchFeedbackText: '',
punchFeedbackTone: 'neutral',
contentCardVisible: false,
contentCardTitle: '',
contentCardBody: '',
compassTicks: buildCompassTicks(),
compassLabels: buildCompassLabels(),
...buildSideButtonVisibility('left'),
@@ -311,6 +331,30 @@ Page({
}
},
handleStartGame() {
if (mapEngine) {
mapEngine.handleStartGame()
}
},
handleOverlayTouch() {},
handlePunchAction() {
if (!this.data.punchButtonEnabled) {
return
}
if (mapEngine) {
mapEngine.handlePunchAction()
}
},
handleCloseContentCard() {
if (mapEngine) {
mapEngine.closeContentCard()
}
},
handleCycleSideButtons() {
this.setData(buildSideButtonVisibility(getNextSideButtonMode(this.data.sideButtonMode)))
},
@@ -378,6 +422,9 @@ Page({

View File

@@ -23,6 +23,15 @@
<view class="map-stage__crosshair"></view>
<view class="game-punch-hint" wx:if="{{punchHintText}}">{{punchHintText}}</view>
<view class="game-punch-feedback game-punch-feedback--{{punchFeedbackTone}}" wx:if="{{punchFeedbackVisible}}">{{punchFeedbackText}}</view>
<view class="game-content-card" wx:if="{{contentCardVisible}}" bindtap="handleCloseContentCard">
<view class="game-content-card__title">{{contentCardTitle}}</view>
<view class="game-content-card__body">{{contentCardBody}}</view>
<view class="game-content-card__hint">点击关闭</view>
</view>
<view class="map-stage__overlay">
<view class="map-stage__bottom">
<view class="compass-widget">
@@ -87,6 +96,14 @@
<cover-view class="map-side-button"><cover-view class="map-side-button__text">USER</cover-view></cover-view>
</cover-view>
<cover-view class="map-punch-button {{punchButtonEnabled ? 'map-punch-button--active' : ''}}" wx:if="{{!showDebugPanel}}" bindtap="handlePunchAction">
<cover-view class="map-punch-button__text">{{punchButtonText}}</cover-view>
</cover-view>
<cover-view class="screen-button-layer screen-button-layer--start-left" wx:if="{{!showDebugPanel && showBottomDebugButton && gameSessionStatus === 'idle'}}" bindtap="handleStartGame">
<cover-view class="screen-button-layer__text screen-button-layer__text--start">开始</cover-view>
</cover-view>
<cover-view class="screen-button-layer screen-button-layer--bottom-left" wx:if="{{!showDebugPanel && showBottomDebugButton}}" bindtap="handleToggleDebugPanel">
<cover-view class="screen-button-layer__icon">
<cover-view class="screen-button-layer__line"></cover-view>
@@ -111,7 +128,9 @@
<view class="race-panel__grid">
<view class="race-panel__cell race-panel__cell--action">
<view class="race-panel__play"></view>
<view class="race-panel__action-button"><!-- status only -->
<view class="race-panel__action-button-text">{{punchButtonText}}</view>
</view>
</view>
<view class="race-panel__cell race-panel__cell--timer">
<text class="race-panel__timer">{{panelTimerText}}</text>
@@ -291,3 +310,5 @@

View File

@@ -189,6 +189,23 @@
bottom: 244rpx;
}
.screen-button-layer--start-left {
left: 24rpx;
bottom: 378rpx;
min-height: 96rpx;
padding: 0 18rpx;
background: rgba(255, 226, 88, 0.96);
box-shadow: 0 14rpx 36rpx rgba(120, 89, 0, 0.2), 0 0 0 3rpx rgba(255, 246, 186, 0.38);
}
.screen-button-layer__text--start {
margin-top: 0;
font-size: 30rpx;
font-weight: 800;
color: #6d4b00;
letter-spacing: 2rpx;
}
.map-side-toggle {
position: absolute;
left: 24rpx;
@@ -685,6 +702,36 @@
right: 0;
bottom: 0;
}
.map-punch-button {
position: absolute;
right: 24rpx;
bottom: 244rpx;
width: 92rpx;
height: 92rpx;
border-radius: 50%;
background: rgba(78, 92, 106, 0.82);
box-shadow: 0 12rpx 28rpx rgba(22, 34, 46, 0.22), inset 0 0 0 2rpx rgba(255, 255, 255, 0.08);
z-index: 18;
}
.map-punch-button__text {
font-size: 20rpx;
line-height: 92rpx;
font-weight: 800;
text-align: center;
color: rgba(236, 241, 246, 0.88);
}
.map-punch-button--active {
background: rgba(92, 255, 237, 0.96);
box-shadow: 0 0 0 5rpx rgba(149, 255, 244, 0.18), 0 0 30rpx rgba(92, 255, 237, 0.5);
animation: punch-button-ready 1s ease-in-out infinite;
}
.map-punch-button--active .map-punch-button__text {
color: #064d46;
}
.race-panel__line {
position: absolute;
@@ -979,6 +1026,139 @@
.game-punch-hint {
position: absolute;
left: 50%;
bottom: 280rpx;
transform: translateX(-50%);
max-width: 72vw;
padding: 14rpx 24rpx;
border-radius: 999rpx;
background: rgba(18, 33, 24, 0.78);
color: #f7fbf2;
font-size: 24rpx;
line-height: 1.2;
text-align: center;
z-index: 16;
pointer-events: none;
}
.game-punch-feedback {
position: absolute;
left: 50%;
top: 18%;
transform: translateX(-50%);
min-width: 240rpx;
padding: 20rpx 28rpx;
border-radius: 24rpx;
color: #ffffff;
font-size: 24rpx;
font-weight: 700;
text-align: center;
box-shadow: 0 16rpx 36rpx rgba(0, 0, 0, 0.18);
z-index: 17;
pointer-events: none;
}
.game-punch-feedback--neutral {
background: rgba(27, 109, 189, 0.92);
}
.game-punch-feedback--success {
background: rgba(37, 134, 88, 0.94);
}
.game-punch-feedback--warning {
background: rgba(196, 117, 18, 0.94);
}
.game-content-card {
position: absolute;
left: 50%;
top: 26%;
width: 440rpx;
max-width: calc(100vw - 72rpx);
transform: translateX(-50%);
padding: 28rpx 28rpx 24rpx;
border-radius: 28rpx;
background: rgba(248, 251, 244, 0.96);
box-shadow: 0 18rpx 48rpx rgba(22, 48, 32, 0.18);
box-sizing: border-box;
z-index: 17;
}
.game-content-card__title {
font-size: 34rpx;
line-height: 1.2;
font-weight: 700;
color: #163020;
}
.game-content-card__body {
margin-top: 12rpx;
font-size: 24rpx;
line-height: 1.5;
color: #45624b;
}
.game-content-card__hint {
margin-top: 16rpx;
font-size: 20rpx;
color: #809284;
}
.race-panel__action-button {
display: flex;
align-items: center;
justify-content: center;
min-width: 116rpx;
min-height: 72rpx;
padding: 0 20rpx;
border-radius: 999rpx;
background: rgba(78, 92, 106, 0.54);
border: 2rpx solid rgba(210, 220, 228, 0.18);
box-sizing: border-box;
box-shadow: inset 0 0 0 2rpx rgba(255, 255, 255, 0.06);
}
.race-panel__action-button--active {
background: rgba(255, 226, 88, 0.98);
border-color: rgba(255, 247, 194, 0.98);
box-shadow: 0 0 0 4rpx rgba(255, 241, 158, 0.18), 0 0 28rpx rgba(255, 239, 122, 0.42);
animation: punch-button-ready 1s ease-in-out infinite;
}
.race-panel__action-button-text {
font-size: 24rpx;
line-height: 1;
font-weight: 700;
color: rgba(236, 241, 246, 0.86);
}
.race-panel__action-button--active .race-panel__action-button-text {
color: #775000;
}
@keyframes punch-button-ready {
0% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(255, 241, 158, 0.22), 0 0 18rpx rgba(255, 239, 122, 0.28);
}
50% {
transform: scale(1.06);
box-shadow: 0 0 0 8rpx rgba(255, 241, 158, 0.08), 0 0 34rpx rgba(255, 239, 122, 0.52);
}
100% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(255, 241, 158, 0.22), 0 0 18rpx rgba(255, 239, 122, 0.28);
}
}