进化轮3项:敌机铆钉纹理/扫雷抛光亮面/金苹果成熟度红晕
Browse files- minesweeper.html +16 -1
- snake.html +16 -0
- star-shooter.html +13 -0
minesweeper.html
CHANGED
|
@@ -151,6 +151,11 @@ const MS_RUST=new Image(); let MS_RUST_OK=false;
|
|
| 151 |
MS_RUST.onload=()=>{ MS_RUST_OK=true; };
|
| 152 |
MS_RUST.onerror=()=>{ MS_RUST_OK=false; };
|
| 153 |
MS_RUST.src='art/ms-rust.webp';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
/* 数字格开盖铜粉碎屑贴图(纯表现层,加载失败自动跳过) */
|
| 155 |
const MS_COPF=new Image(); let MS_COPF_OK=false;
|
| 156 |
MS_COPF.onload=()=>{ MS_COPF_OK=true; };
|
|
@@ -314,7 +319,7 @@ function reset(){
|
|
| 314 |
G.board=[];
|
| 315 |
for(let y=0;y<G.rows;y++){
|
| 316 |
const row=[];
|
| 317 |
-
for(let x=0;x<G.cols;x++) row.push({mine:false,open:false,flag:false,n:0,dead:false,rust:Math.random()<0.2?(1+Math.floor(Math.random()*4)):0,warmth:(Math.random()*3)|0});
|
| 318 |
G.board.push(row);
|
| 319 |
}
|
| 320 |
G.state='playing'; G.paused=false; G.started=false;
|
|
@@ -651,6 +656,13 @@ function draw(){
|
|
| 651 |
ctx.drawImage(MS_RUST,-G.cell/2,-G.cell/2,G.cell,G.cell);
|
| 652 |
ctx.restore();
|
| 653 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 654 |
if(c.flag) drawFlagIcon(px,py,flagPopScale(c),flagWave(c));
|
| 655 |
}
|
| 656 |
ctx.strokeStyle='rgba(255,200,120,.14)';
|
|
@@ -1094,6 +1106,9 @@ window.__ms={G:G,
|
|
| 1094 |
craterDraws(){ return window.__craterDraws||0; },
|
| 1095 |
openRivetDraws(){ return window.__openRivetDraws||0; },
|
| 1096 |
warmthDraws(){ return window.__warmthDraws||0; },
|
|
|
|
|
|
|
|
|
|
| 1097 |
flagAt(x,y){ flagCell(x,y); const c=G.board[y][x]; return !!(c&&c.flag); },
|
| 1098 |
flagAge(x,y){ const c=G.board[y][x]; return c&&c.flagT?(performance.now()-c.flagT):-1; }
|
| 1099 |
};
|
|
|
|
| 151 |
MS_RUST.onload=()=>{ MS_RUST_OK=true; };
|
| 152 |
MS_RUST.onerror=()=>{ MS_RUST_OK=false; };
|
| 153 |
MS_RUST.src='art/ms-rust.webp';
|
| 154 |
+
/* 未翻开格抛光亮面贴图:每局随机约8%的铆钉盖顶部叠加抛光亮斑(纯表现层:常被踩踏磨亮的盖子,与锈斑/色温差异化叠加;加载失败自动跳过,不改逻辑) */
|
| 155 |
+
const MS_SHINE=new Image(); let MS_SHINE_OK=false;
|
| 156 |
+
MS_SHINE.onload=()=>{ MS_SHINE_OK=true; };
|
| 157 |
+
MS_SHINE.onerror=()=>{ MS_SHINE_OK=false; };
|
| 158 |
+
MS_SHINE.src='art/ms-shine.webp';
|
| 159 |
/* 数字格开盖铜粉碎屑贴图(纯表现层,加载失败自动跳过) */
|
| 160 |
const MS_COPF=new Image(); let MS_COPF_OK=false;
|
| 161 |
MS_COPF.onload=()=>{ MS_COPF_OK=true; };
|
|
|
|
| 319 |
G.board=[];
|
| 320 |
for(let y=0;y<G.rows;y++){
|
| 321 |
const row=[];
|
| 322 |
+
for(let x=0;x<G.cols;x++) row.push({mine:false,open:false,flag:false,n:0,dead:false,rust:Math.random()<0.2?(1+Math.floor(Math.random()*4)):0,warmth:(Math.random()*3)|0,shine:Math.random()<0.08?1:0});
|
| 323 |
G.board.push(row);
|
| 324 |
}
|
| 325 |
G.state='playing'; G.paused=false; G.started=false;
|
|
|
|
| 656 |
ctx.drawImage(MS_RUST,-G.cell/2,-G.cell/2,G.cell,G.cell);
|
| 657 |
ctx.restore();
|
| 658 |
}
|
| 659 |
+
/* 磨光亮面(纯表现层:约8%的未翻开格铆钉盖顶部叠加抛光亮斑,与锈斑/色温差异化叠加,不改逻辑) */
|
| 660 |
+
if(c.shine&&MS_SHINE_OK&&MS_SHINE.naturalWidth){
|
| 661 |
+
ctx.save(); ctx.globalAlpha=0.75;
|
| 662 |
+
ctx.drawImage(MS_SHINE,px+0.5,py+0.5,G.cell-1,G.cell-1);
|
| 663 |
+
ctx.restore();
|
| 664 |
+
window.__shineDraws=(window.__shineDraws||0)+1; // 探针:抛光亮面确实绘制
|
| 665 |
+
}
|
| 666 |
if(c.flag) drawFlagIcon(px,py,flagPopScale(c),flagWave(c));
|
| 667 |
}
|
| 668 |
ctx.strokeStyle='rgba(255,200,120,.14)';
|
|
|
|
| 1106 |
craterDraws(){ return window.__craterDraws||0; },
|
| 1107 |
openRivetDraws(){ return window.__openRivetDraws||0; },
|
| 1108 |
warmthDraws(){ return window.__warmthDraws||0; },
|
| 1109 |
+
shineOk(){ return MS_SHINE_OK&&MS_SHINE.naturalWidth>0; },
|
| 1110 |
+
shineDraws(){ return window.__shineDraws||0; },
|
| 1111 |
+
shineCount(){ let n=0; for(const r of G.board) for(const c of r) if(c.shine) n++; return n; },
|
| 1112 |
flagAt(x,y){ flagCell(x,y); const c=G.board[y][x]; return !!(c&&c.flag); },
|
| 1113 |
flagAge(x,y){ const c=G.board[y][x]; return c&&c.flagT?(performance.now()-c.flagT):-1; }
|
| 1114 |
};
|
snake.html
CHANGED
|
@@ -149,6 +149,11 @@ const SN_GOLDPATCH=new Image(); let SN_GOLDPATCH_OK=false;
|
|
| 149 |
SN_GOLDPATCH.onload=()=>{ SN_GOLDPATCH_OK=true; };
|
| 150 |
SN_GOLDPATCH.onerror=()=>{ SN_GOLDPATCH_OK=false; };
|
| 151 |
SN_GOLDPATCH.src='art/sn-goldpatch.webp';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
/* 金苹果果蒂叶贴图(纯表现层:金苹果顶部叠加果蒂叶贴图、随苹果脉冲同呼吸,加载失败跳过、红果不画;不改玩法/碰撞) */
|
| 153 |
const SN_LEAF=new Image(); let SN_LEAF_OK=false;
|
| 154 |
SN_LEAF.onload=()=>{ SN_LEAF_OK=true; };
|
|
@@ -284,6 +289,7 @@ function spawnFood(){
|
|
| 284 |
if(!free.length){ G.food=null; return; }
|
| 285 |
G.food=free[(Math.random()*free.length)|0];
|
| 286 |
G.food.gold=Math.random()<0.18; // 金苹果:纯表现层视觉变体,得分/速度/碰撞完全不变
|
|
|
|
| 287 |
/* 新食物涟漪提示(纯表现层:刷新处扩散小光圈 0.6 秒后消退,不改玩法/碰撞) */
|
| 288 |
const cx0=OX+G.food.x*CELL+CELL/2, cy0=OY+G.food.y*CELL+CELL/2;
|
| 289 |
rings.push({x:cx0,y:cy0,r:4,maxR:CELL*1.35,t:0,life:0.6,c:G.food.gold?'255,215,106':'255,255,220'});
|
|
@@ -537,6 +543,13 @@ function draw(){
|
|
| 537 |
}
|
| 538 |
const s=CELL*1.7*pulse*(gold?1.1:1.0);
|
| 539 |
ctx.drawImage(_appleImg,fx+CELL/2-s/2,fy+CELL/2-s/2,s,s);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 540 |
if(gold) window.__snakeGoldDraws=(window.__snakeGoldDraws||0)+1; // 探针:金苹果确实绘制
|
| 541 |
if(gold&&SN_LEAF_OK&&SN_LEAF.naturalWidth){ // 果蒂叶(纯表现层:金苹果顶部叶贴图,随苹果脉冲同呼吸+微摆;加载失败跳过,不改玩法/碰撞)
|
| 542 |
const ls=CELL*1.05;
|
|
@@ -952,6 +965,9 @@ window.__snake={G:G,
|
|
| 952 |
leafOk(){ return SN_LEAF_OK&&SN_LEAF.naturalWidth>0; },
|
| 953 |
leafDraws(){ return window.__snakeLeafDraws||0; },
|
| 954 |
foodShadowDraws(){ return window.__snakeFoodShadowDraws||0; },
|
|
|
|
|
|
|
|
|
|
| 955 |
foodGold(){ return !!(G.food&&G.food.gold); },
|
| 956 |
score(){ return G.score; },
|
| 957 |
state(){ return G.state; }
|
|
|
|
| 149 |
SN_GOLDPATCH.onload=()=>{ SN_GOLDPATCH_OK=true; };
|
| 150 |
SN_GOLDPATCH.onerror=()=>{ SN_GOLDPATCH_OK=false; };
|
| 151 |
SN_GOLDPATCH.src='art/sn-goldpatch.webp';
|
| 152 |
+
/* 金苹果成熟度红晕(纯表现层:存活越久果面红晕越重(20秒封顶),成熟度图像化;加载失败跳过,不改玩法/碰撞) */
|
| 153 |
+
const SN_BLUSH=new Image(); let SN_BLUSH_OK=false;
|
| 154 |
+
SN_BLUSH.onload=()=>{ SN_BLUSH_OK=true; };
|
| 155 |
+
SN_BLUSH.onerror=()=>{ SN_BLUSH_OK=false; };
|
| 156 |
+
SN_BLUSH.src='art/sn-blush.webp';
|
| 157 |
/* 金苹果果蒂叶贴图(纯表现层:金苹果顶部叠加果蒂叶贴图、随苹果脉冲同呼吸,加载失败跳过、红果不画;不改玩法/碰撞) */
|
| 158 |
const SN_LEAF=new Image(); let SN_LEAF_OK=false;
|
| 159 |
SN_LEAF.onload=()=>{ SN_LEAF_OK=true; };
|
|
|
|
| 289 |
if(!free.length){ G.food=null; return; }
|
| 290 |
G.food=free[(Math.random()*free.length)|0];
|
| 291 |
G.food.gold=Math.random()<0.18; // 金苹果:纯表现层视觉变体,得分/速度/碰撞完全不变
|
| 292 |
+
G.food.bornT=performance.now(); // 食物出生时间(纯表现层:金苹果成熟度红晕计时)
|
| 293 |
/* 新食物涟漪提示(纯表现层:刷新处扩散小光圈 0.6 秒后消退,不改玩法/碰撞) */
|
| 294 |
const cx0=OX+G.food.x*CELL+CELL/2, cy0=OY+G.food.y*CELL+CELL/2;
|
| 295 |
rings.push({x:cx0,y:cy0,r:4,maxR:CELL*1.35,t:0,life:0.6,c:G.food.gold?'255,215,106':'255,255,220'});
|
|
|
|
| 543 |
}
|
| 544 |
const s=CELL*1.7*pulse*(gold?1.1:1.0);
|
| 545 |
ctx.drawImage(_appleImg,fx+CELL/2-s/2,fy+CELL/2-s/2,s,s);
|
| 546 |
+
if(gold&&SN_BLUSH_OK&&SN_BLUSH.naturalWidth){ // 金苹果成熟度红晕(纯表现层:存活越久红晕越重、20秒封顶,与金色草皮光斑/光环叠加不冲突;红果不画;加载失败跳过,不改玩法/碰撞)
|
| 547 |
+
const mat=Math.min(1,(performance.now()-((G.food&&G.food.bornT)||performance.now()))/20000);
|
| 548 |
+
ctx.save(); ctx.globalAlpha=(0.15+0.65*mat).toFixed(2);
|
| 549 |
+
ctx.drawImage(SN_BLUSH,fx+CELL/2-s/2,fy+CELL/2-s/2,s,s);
|
| 550 |
+
ctx.restore();
|
| 551 |
+
window.__snakeBlushDraws=(window.__snakeBlushDraws||0)+1; // 探针:成熟度红晕确实绘制
|
| 552 |
+
}
|
| 553 |
if(gold) window.__snakeGoldDraws=(window.__snakeGoldDraws||0)+1; // 探针:金苹果确实绘制
|
| 554 |
if(gold&&SN_LEAF_OK&&SN_LEAF.naturalWidth){ // 果蒂叶(纯表现层:金苹果顶部叶贴图,随苹果脉冲同呼吸+微摆;加载失败跳过,不改玩法/碰撞)
|
| 555 |
const ls=CELL*1.05;
|
|
|
|
| 965 |
leafOk(){ return SN_LEAF_OK&&SN_LEAF.naturalWidth>0; },
|
| 966 |
leafDraws(){ return window.__snakeLeafDraws||0; },
|
| 967 |
foodShadowDraws(){ return window.__snakeFoodShadowDraws||0; },
|
| 968 |
+
blushOk(){ return SN_BLUSH_OK&&SN_BLUSH.naturalWidth>0; },
|
| 969 |
+
blushDraws(){ return window.__snakeBlushDraws||0; },
|
| 970 |
+
blushMat(){ if(!(G.food&&G.food.gold)) return -1; return Math.min(1,(performance.now()-((G.food&&G.food.bornT)||performance.now()))/20000); },
|
| 971 |
foodGold(){ return !!(G.food&&G.food.gold); },
|
| 972 |
score(){ return G.score; },
|
| 973 |
state(){ return G.state; }
|
star-shooter.html
CHANGED
|
@@ -324,7 +324,9 @@ for (const k of ['ship', 'diver', 'weaver', 'tank', 'elite', 'boss']) {
|
|
| 324 |
function sprReady(k) { const i = SPR[k]; return !!(i && i.complete && i.naturalWidth > 0); }
|
| 325 |
const dmgTex=new Image(); dmgTex.src='art/ss-damage.webp'; // 敌机受损焦痕贴图(加载失败自动跳过)
|
| 326 |
const enemyFlameTex=new Image(); enemyFlameTex.src='art/ss-enemy-flame.webp'; // 敌机尾焰贴图(绯红/橙、与玩家青白尾焰敌我区分,加载失败自动跳过)
|
|
|
|
| 327 |
window.__enemyFlameDraws=0; // 敌机尾焰绘制计数(纯表现层探针)
|
|
|
|
| 328 |
window.__dmgTex=dmgTex;
|
| 329 |
const smokeTex=new Image(); smokeTex.src='art/ss-smoke.webp'; // 玩家飞船受损机翼焦烟贴图(加载失败自动跳过)
|
| 330 |
window.__smokeTex=smokeTex; window.__smokeDraws=0;
|
|
@@ -841,6 +843,14 @@ function drawEnemy(e) {
|
|
| 841 |
if (e.type === 'elite') ctx.rotate(e.t * 0.5); // 保持原旋转感
|
| 842 |
else if (e.type === 'boss') ctx.rotate(Math.sin(e.t * 0.8) * 0.1);
|
| 843 |
ctx.drawImage(SPR[e.type], -S / 2, -S / 2, S, S);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 844 |
if (e.flash > 0) { // 受击闪白
|
| 845 |
ctx.globalAlpha = 0.45;
|
| 846 |
ctx.fillStyle = '#ffffff';
|
|
@@ -1481,6 +1491,9 @@ window.gameDebug = {
|
|
| 1481 |
return !!b;
|
| 1482 |
},
|
| 1483 |
bossLowWarned: () => { const b = enemies.find((e) => e.type === 'boss'); return b ? !!b.lowWarned : null; },
|
|
|
|
|
|
|
|
|
|
| 1484 |
killEliteForProbe: () => { // 探针用:生成一只精英怪并立即击破,验证残骸生成
|
| 1485 |
spawnEnemy('elite');
|
| 1486 |
const e = enemies[enemies.length - 1];
|
|
|
|
| 324 |
function sprReady(k) { const i = SPR[k]; return !!(i && i.complete && i.naturalWidth > 0); }
|
| 325 |
const dmgTex=new Image(); dmgTex.src='art/ss-damage.webp'; // 敌机受损焦痕贴图(加载失败自动跳过)
|
| 326 |
const enemyFlameTex=new Image(); enemyFlameTex.src='art/ss-enemy-flame.webp'; // 敌机尾焰贴图(绯红/橙、与玩家青白尾焰敌我区分,加载失败自动跳过)
|
| 327 |
+
const rivetTex=new Image(); rivetTex.src='art/ss-rivets.webp'; // 敌机装甲铆钉/焊缝纹理(纯表现层:5 种敌机装甲精灵叠加铆钉纹理差异化,与焦痕/尾焰叠加不冲突,加载失败跳过,不改伤害/血量)
|
| 328 |
window.__enemyFlameDraws=0; // 敌机尾焰绘制计数(纯表现层探针)
|
| 329 |
+
window.__rivetTex=rivetTex; window.__rivetDraws=0; // 敌机装甲铆钉绘制计数(纯表现层探针)
|
| 330 |
window.__dmgTex=dmgTex;
|
| 331 |
const smokeTex=new Image(); smokeTex.src='art/ss-smoke.webp'; // 玩家飞船受损机翼焦烟贴图(加载失败自动跳过)
|
| 332 |
window.__smokeTex=smokeTex; window.__smokeDraws=0;
|
|
|
|
| 843 |
if (e.type === 'elite') ctx.rotate(e.t * 0.5); // 保持原旋转感
|
| 844 |
else if (e.type === 'boss') ctx.rotate(Math.sin(e.t * 0.8) * 0.1);
|
| 845 |
ctx.drawImage(SPR[e.type], -S / 2, -S / 2, S, S);
|
| 846 |
+
if (rivetTex.complete && rivetTex.naturalWidth) { // 装甲铆钉纹理:纯表现层,每种敌机固定旋转角差异,与焦痕层叠加不冲突,加载失败跳过
|
| 847 |
+
ctx.save();
|
| 848 |
+
ctx.globalAlpha = 0.55;
|
| 849 |
+
ctx.rotate({diver:0,weaver:0.6,tank:1.2,elite:1.8,boss:2.4}[e.type]||0);
|
| 850 |
+
ctx.drawImage(rivetTex, -S / 2, -S / 2, S, S);
|
| 851 |
+
ctx.restore();
|
| 852 |
+
window.__rivetDraws++;
|
| 853 |
+
}
|
| 854 |
if (e.flash > 0) { // 受击闪白
|
| 855 |
ctx.globalAlpha = 0.45;
|
| 856 |
ctx.fillStyle = '#ffffff';
|
|
|
|
| 1491 |
return !!b;
|
| 1492 |
},
|
| 1493 |
bossLowWarned: () => { const b = enemies.find((e) => e.type === 'boss'); return b ? !!b.lowWarned : null; },
|
| 1494 |
+
spawnAllTypes: () => { ['diver','weaver','tank','elite','boss'].forEach(spawnEnemy); }, // 探针用:5 种敌机各生成一只(验证铆钉纹理差异化)
|
| 1495 |
+
rivetTexOk: () => rivetTex.complete && rivetTex.naturalWidth > 0,
|
| 1496 |
+
rivetDraws: () => window.__rivetDraws,
|
| 1497 |
killEliteForProbe: () => { // 探针用:生成一只精英怪并立即击破,验证残骸生成
|
| 1498 |
spawnEnemy('elite');
|
| 1499 |
const e = enemies[enemies.length - 1];
|