Commit f807008f authored by 董政锦's avatar 董政锦

style: game3 的 h5 样式马位置、道具位置、道具碰到位置、苹果蒙层宽度调整;

parent f8b7ee46
...@@ -193,14 +193,18 @@ defineExpose({ ...@@ -193,14 +193,18 @@ defineExpose({
} }
.modal-container { .modal-container {
position: absolute; /* position:fixed + 显式 100vw/100vh 确保在 iOS Safari 中全屏蒙层,
inset: 0; 避免因父级 overflow:hidden / transform:scale 导致 inset:0 计算异常 */
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 10; z-index: 10;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-color: rgba(0, 0, 0, 0.6); background-color: rgba(0, 0, 0, 0.6);
/* pointer-events: none; */
} }
.game-rule-fade-enter-active, .game-rule-fade-enter-active,
......
This diff is collapsed.
...@@ -26,8 +26,26 @@ const HORSE_BOTTOM_PCT = 19.11; ...@@ -26,8 +26,26 @@ const HORSE_BOTTOM_PCT = 19.11;
const ITEM_SIZE = 80; const ITEM_SIZE = 80;
const GAME_DURATION = 60; const GAME_DURATION = 60;
const LEFT_LANE_X = 170; // 设计基准跑道 X 位置(750px 设计稿下的值,窄屏设备上会自动居中偏移)
const RIGHT_LANE_X = 470; const DESIGN_LEFT_LANE_X = 150;
const DESIGN_RIGHT_LANE_X = 500;
// 运行时根据视口计算的真实 X 位置(适配不同屏幕宽度)
const leftLaneX = ref(DESIGN_LEFT_LANE_X);
const rightLaneX = ref(DESIGN_RIGHT_LANE_X);
/** 按视口宽度计算 750px 设计区域在 content-bg 中的居中偏移 */
const updateLanePositions = () => {
const vw = window.visualViewport?.width ?? window.innerWidth;
const vh = window.visualViewport?.height ?? window.innerHeight;
// MobileStage contain 模式下 scale = min(scaleX, scaleY),手机通常由高度决定
const scaleY = vh / 1624;
if (!scaleY || scaleY <= 0) return;
const stageViewportWidth = vw / scaleY;
const offset = Math.max(0, (stageViewportWidth - 750) / 2);
leftLaneX.value = DESIGN_LEFT_LANE_X + offset;
rightLaneX.value = DESIGN_RIGHT_LANE_X + offset;
};
// ========== 马帧 ========== // ========== 马帧 ==========
const HORSE_FRAME_COUNT = 21; const HORSE_FRAME_COUNT = 21;
...@@ -63,20 +81,20 @@ preloadFrames(bomFrames); ...@@ -63,20 +81,20 @@ preloadFrames(bomFrames);
const horseLane = ref<'left' | 'right'>('left'); const horseLane = ref<'left' | 'right'>('left');
const horseFrameIndex = ref(0); const horseFrameIndex = ref(0);
const horseX = ref(LEFT_LANE_X); const horseX = ref(leftLaneX.value);
const horseTargetX = ref(LEFT_LANE_X); const horseTargetX = ref(leftLaneX.value);
const switchToLeft = () => { const switchToLeft = () => {
if (horseLane.value !== 'left') { if (horseLane.value !== 'left') {
horseLane.value = 'left'; horseLane.value = 'left';
horseTargetX.value = LEFT_LANE_X; horseTargetX.value = leftLaneX.value;
} }
}; };
const switchToRight = () => { const switchToRight = () => {
if (horseLane.value !== 'right') { if (horseLane.value !== 'right') {
horseLane.value = 'right'; horseLane.value = 'right';
horseTargetX.value = RIGHT_LANE_X; horseTargetX.value = rightLaneX.value;
} }
}; };
...@@ -183,7 +201,7 @@ function generateNewItem() { ...@@ -183,7 +201,7 @@ function generateNewItem() {
if (!props.isDivDescVisible) return; if (!props.isDivDescVisible) return;
const seed = Date.now() + itemIdCounter; const seed = Date.now() + itemIdCounter;
const kind: ItemKind = seededRandom(seed) < 0.55 ? 'coin' : 'bomb'; const kind: ItemKind = seededRandom(seed) < 0.75 ? 'coin' : 'bomb';
// 概率分配车道,但避免与前一个同车道道具太近 // 概率分配车道,但避免与前一个同车道道具太近
let lane: 'left' | 'right' = seededRandom(seed + 1000) < 0.5 ? 'left' : 'right'; let lane: 'left' | 'right' = seededRandom(seed + 1000) < 0.5 ? 'left' : 'right';
...@@ -244,7 +262,7 @@ const checkCollisions = () => { ...@@ -244,7 +262,7 @@ const checkCollisions = () => {
for (const item of roadItems.value) { for (const item of roadItems.value) {
if (item.collected || item.colliding) continue; if (item.collected || item.colliding) continue;
const itemX = item.lane === 'left' ? LEFT_LANE_X : RIGHT_LANE_X; const itemX = item.lane === 'left' ? leftLaneX.value : rightLaneX.value;
// item.y 已经是屏幕坐标(content-bg 内),无需加 roadOffset // item.y 已经是屏幕坐标(content-bg 内),无需加 roadOffset
const itemCenterX = itemX + ITEM_SIZE / 2; const itemCenterX = itemX + ITEM_SIZE / 2;
const itemCenterY = item.y + ITEM_SIZE / 2; const itemCenterY = item.y + ITEM_SIZE / 2;
...@@ -278,7 +296,7 @@ const playCollectEffect = (item: RoadItem, x: number, y: number) => { ...@@ -278,7 +296,7 @@ const playCollectEffect = (item: RoadItem, x: number, y: number) => {
const frameDuration = 1000 / totalFrames; const frameDuration = 1000 / totalFrames;
// 碰撞动画(大幅放大尺寸,x 往右偏移让动画居中于视觉碰撞点) // 碰撞动画(大幅放大尺寸,x 往右偏移让动画居中于视觉碰撞点)
effectAnims.value.push({ id: animId, kind: item.kind, frame: 0, x: x + 40, y }); effectAnims.value.push({ id: animId, kind: item.kind, frame: 0, x: x + 65, y });
let frameIdx = 0; let frameIdx = 0;
const tick = () => { const tick = () => {
...@@ -297,7 +315,7 @@ const playCollectEffect = (item: RoadItem, x: number, y: number) => { ...@@ -297,7 +315,7 @@ const playCollectEffect = (item: RoadItem, x: number, y: number) => {
const effectId = ++scoreEffectIdSeq; const effectId = ++scoreEffectIdSeq;
scoreEffects.value.push({ scoreEffects.value.push({
id: effectId, id: effectId,
x: x + ITEM_SIZE / 2, x: x + ITEM_SIZE / 2 + 25,
y: y, y: y,
score: delta, score: delta,
}); });
...@@ -377,6 +395,12 @@ const stopMainLoop = () => { ...@@ -377,6 +395,12 @@ const stopMainLoop = () => {
// ========== 生命周期 ========== // ========== 生命周期 ==========
onMounted(() => { onMounted(() => {
window.addEventListener('keydown', handleKeydown); window.addEventListener('keydown', handleKeydown);
window.addEventListener('resize', updateLanePositions);
window.visualViewport?.addEventListener('resize', updateLanePositions);
updateLanePositions();
// 初始化马匹在左侧跑道(使用计算后的实际 X 位置)
horseX.value = leftLaneX.value;
horseTargetX.value = leftLaneX.value;
nextTick(() => { nextTick(() => {
startRoadScroll(); startRoadScroll();
startMainLoop(); startMainLoop();
...@@ -386,6 +410,8 @@ onMounted(() => { ...@@ -386,6 +410,8 @@ onMounted(() => {
onBeforeUnmount(() => { onBeforeUnmount(() => {
window.removeEventListener('keydown', handleKeydown); window.removeEventListener('keydown', handleKeydown);
window.removeEventListener('resize', updateLanePositions);
window.visualViewport?.removeEventListener('resize', updateLanePositions);
stopRoadScroll(); stopRoadScroll();
stopMainLoop(); stopMainLoop();
stopItemGen(); stopItemGen();
...@@ -405,6 +431,9 @@ watch(() => props.isDivDescVisible, (visible) => { ...@@ -405,6 +431,9 @@ watch(() => props.isDivDescVisible, (visible) => {
scoreEffects.value = []; scoreEffects.value = [];
roadOffset.value = 0; roadOffset.value = 0;
gameElapsed.value = 0; gameElapsed.value = 0;
updateLanePositions();
horseX.value = leftLaneX.value;
horseTargetX.value = leftLaneX.value;
startRoadScroll(); startRoadScroll();
startMainLoop(); startMainLoop();
scheduleNextItem(); scheduleNextItem();
...@@ -582,18 +611,21 @@ watch(() => props.isDivDescVisible, (visible) => { ...@@ -582,18 +611,21 @@ watch(() => props.isDivDescVisible, (visible) => {
.road-item { .road-item {
position: absolute; position: absolute;
width: 80px; /* width: 80px;
height: 80px; height: 80px; */
width: 77px;
height: 96px;
z-index: 5; z-index: 5;
pointer-events: none; pointer-events: none;
} }
.item-lane-left { .item-lane-left {
left: 170px; /* 当 content-bg 宽于 750px 设计稿时,自动居中 750px 游戏区域 */
left: calc((var(--stage-viewport-width, 750px) - 750px) / 2 + 170px);
} }
.item-lane-right { .item-lane-right {
left: 470px; left: calc((var(--stage-viewport-width, 750px) - 750px) / 2 + 520px);
} }
.effect-anim { .effect-anim {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment