Add event-driven gameplay feedback framework

This commit is contained in:
2026-03-24 09:03:27 +08:00
parent 48159be900
commit 2c03d1a702
20 changed files with 1718 additions and 64 deletions

View File

@@ -72,6 +72,40 @@
transform: translateY(-50%);
}
.map-stage__map-pulse {
position: absolute;
width: 44rpx;
height: 44rpx;
margin-left: -22rpx;
margin-top: -22rpx;
border-radius: 50%;
pointer-events: none;
z-index: 6;
}
.map-stage__map-pulse--control {
animation: map-pulse-control 0.82s ease-out 1;
}
.map-stage__map-pulse--ready {
animation: map-pulse-ready 0.72s ease-out 1;
}
.map-stage__map-pulse--finish {
animation: map-pulse-finish 0.82s ease-out 1;
}
.map-stage__stage-fx {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 5;
}
.map-stage__stage-fx--finish {
animation: stage-fx-finish 0.76s ease-out 1;
}
.map-stage__overlay {
position: absolute;
inset: 0;
@@ -732,6 +766,16 @@
color: #064d46;
}
.map-punch-button--fx-ready-a,
.map-punch-button--fx-ready-b {
animation: punch-button-burst 0.92s ease-out 1;
}
.map-punch-button--fx-warning-a,
.map-punch-button--fx-warning-b {
animation: punch-button-warning 0.56s ease-in-out 1;
}
.race-panel__line {
position: absolute;
@@ -1076,6 +1120,18 @@
background: rgba(196, 117, 18, 0.94);
}
.game-punch-feedback--fx-pop {
animation: feedback-toast-pop 0.42s ease-out;
}
.game-punch-feedback--fx-success {
animation: feedback-toast-success 0.58s ease-out;
}
.game-punch-feedback--fx-warning {
animation: feedback-toast-warning 0.56s ease-out;
}
.game-content-card {
position: absolute;
left: 50%;
@@ -1111,6 +1167,14 @@
color: #809284;
}
.game-content-card--fx-pop {
animation: content-card-pop 0.5s cubic-bezier(0.18, 0.88, 0.2, 1);
}
.game-content-card--fx-finish {
animation: content-card-finish 0.68s cubic-bezier(0.18, 0.88, 0.2, 1);
}
.race-panel__action-button {
display: flex;
align-items: center;
@@ -1162,3 +1226,191 @@
@keyframes punch-button-burst {
0% {
transform: scale(1);
box-shadow: 0 12rpx 28rpx rgba(22, 34, 46, 0.22);
}
34% {
transform: scale(1.12);
box-shadow: 0 0 0 9rpx rgba(149, 255, 244, 0.18), 0 0 34rpx rgba(92, 255, 237, 0.58);
}
100% {
transform: scale(1);
box-shadow: 0 12rpx 28rpx rgba(22, 34, 46, 0.22);
}
}
@keyframes punch-button-warning {
0%, 100% {
transform: translateX(0);
}
20% {
transform: translateX(-6rpx) scale(1.02);
}
40% {
transform: translateX(6rpx) scale(1.04);
}
60% {
transform: translateX(-4rpx) scale(1.02);
}
80% {
transform: translateX(4rpx);
}
}
@keyframes feedback-toast-pop {
0% {
opacity: 0;
transform: translateX(-50%) translateY(18rpx) scale(0.88);
}
100% {
opacity: 1;
transform: translateX(-50%) translateY(0) scale(1);
}
}
@keyframes feedback-toast-success {
0% {
opacity: 0;
transform: translateX(-50%) translateY(18rpx) scale(0.88);
}
55% {
opacity: 1;
transform: translateX(-50%) translateY(-6rpx) scale(1.04);
}
100% {
opacity: 1;
transform: translateX(-50%) translateY(0) scale(1);
}
}
@keyframes feedback-toast-warning {
0% {
opacity: 0;
transform: translateX(-50%) translateY(12rpx) scale(0.92);
}
30% {
opacity: 1;
transform: translateX(calc(-50% - 6rpx)) translateY(0) scale(1.02);
}
60% {
transform: translateX(calc(-50% + 6rpx)) translateY(0) scale(1.02);
}
100% {
opacity: 1;
transform: translateX(-50%) translateY(0) scale(1);
}
}
@keyframes content-card-pop {
0% {
opacity: 0;
transform: translateX(-50%) translateY(30rpx) scale(0.92);
}
100% {
opacity: 1;
transform: translateX(-50%) translateY(0) scale(1);
}
}
@keyframes content-card-finish {
0% {
opacity: 0;
transform: translateX(-50%) translateY(34rpx) scale(0.9);
box-shadow: 0 18rpx 48rpx rgba(22, 48, 32, 0.18);
}
45% {
opacity: 1;
transform: translateX(-50%) translateY(-6rpx) scale(1.03);
box-shadow: 0 0 0 6rpx rgba(255, 232, 147, 0.18), 0 22rpx 52rpx rgba(22, 48, 32, 0.2);
}
100% {
opacity: 1;
transform: translateX(-50%) translateY(0) scale(1);
box-shadow: 0 18rpx 48rpx rgba(22, 48, 32, 0.18);
}
}
@keyframes map-pulse-control {
0% {
opacity: 0.94;
transform: scale(0.28);
border: 6rpx solid rgba(92, 255, 237, 0.98);
box-shadow: 0 0 0 0 rgba(92, 255, 237, 0.42);
}
70% {
opacity: 0.32;
transform: scale(3.4);
border: 4rpx solid rgba(92, 255, 237, 0.52);
box-shadow: 0 0 0 10rpx rgba(92, 255, 237, 0.08);
}
100% {
opacity: 0;
transform: scale(4.1);
border: 2rpx solid rgba(92, 255, 237, 0);
box-shadow: 0 0 0 0 rgba(92, 255, 237, 0);
}
}
@keyframes map-pulse-ready {
0% {
opacity: 0.92;
transform: scale(0.22);
border: 5rpx solid rgba(255, 248, 184, 0.98);
box-shadow: 0 0 0 0 rgba(255, 248, 184, 0.28);
}
68% {
opacity: 0.22;
transform: scale(2.4);
border: 3rpx solid rgba(255, 248, 184, 0.46);
box-shadow: 0 0 0 8rpx rgba(255, 248, 184, 0.08);
}
100% {
opacity: 0;
transform: scale(3);
border: 2rpx solid rgba(255, 248, 184, 0);
box-shadow: 0 0 0 0 rgba(255, 248, 184, 0);
}
}
@keyframes map-pulse-finish {
0% {
opacity: 0.98;
transform: scale(0.24);
border: 6rpx solid rgba(255, 231, 117, 1);
box-shadow: 0 0 0 0 rgba(255, 231, 117, 0.46);
}
48% {
opacity: 0.52;
transform: scale(3.8);
border: 4rpx solid rgba(255, 231, 117, 0.72);
box-shadow: 0 0 0 14rpx rgba(255, 231, 117, 0.14);
}
100% {
opacity: 0;
transform: scale(4.8);
border: 2rpx solid rgba(255, 231, 117, 0);
box-shadow: 0 0 0 0 rgba(255, 231, 117, 0);
}
}
@keyframes stage-fx-finish {
0% {
opacity: 0;
background: radial-gradient(circle at 50% 50%, rgba(255, 241, 168, 0.22) 0%, rgba(255, 241, 168, 0.08) 28%, rgba(255, 255, 255, 0) 62%);
backdrop-filter: brightness(1);
}
24% {
opacity: 1;
background: radial-gradient(circle at 50% 50%, rgba(255, 241, 168, 0.34) 0%, rgba(255, 241, 168, 0.14) 32%, rgba(255, 255, 255, 0.04) 74%);
backdrop-filter: brightness(1.08);
}
100% {
opacity: 0;
background: radial-gradient(circle at 50% 50%, rgba(255, 241, 168, 0) 0%, rgba(255, 241, 168, 0) 100%);
backdrop-filter: brightness(1);
}
}