aardio版-跳一跳(天气干扰版)源码
By
admin
at 4 天前 • 0人收藏 • 72人看过
aardio版-跳一跳(天气干扰+辅助线)源码
纯Gemini 设计, 我只提了需求

编译好的exe游戏下载:
import win.ui;
import gdip;
import math;
/*DSG{{*/
winform = win.form(text="aardio 跳一跳 (辅助线版)";right=539;bottom=709;bgcolor=0xFFFFFF)
winform.add(
plus={cls="plus";left=0;top=0;right=540;bottom=710;db=1;dl=1;dr=1;dt=1;notify=1;z=1}
)
/*}}*/
// ==========================================
// 1. 游戏配置
// ==========================================
var config = {
blockWidth = 100;
blockHeight = 60;
bodyHeight = 40;
maxPower = 30;
jumpHeight = 150;
minDist = 110;
maxDist = winform.plus.width/2-20;
powerRatio = 10;
cameraSpeed = 0.1; // 镜头跟随平滑度
// 天气配置
cloudCount = 6;
rainCount = 100;
}
var gameState = {
blocks = {};
playerPos = {x=0;y=0};
cameraOffset = {x=0;y=0};
score = 0;
isGameOver = false;
action = "idle";
power = 0;
jumpStartPos = {x=0;y=0};
jumpTargetDist = 0;
jumpDirection = {x=0;y=0};
jumpProgress = 0;
// 天气状态
weather = {
type = "sunny";
items = {};
bgColor = 0;
lightning = { active=false; segments={}; timer=0; flashAlpha=0; duration=0 }
}
}
// ==========================================
// 2. 几何与天气算法
// ==========================================
var getPolyPoints = function(cx, cy, r, sides, angleOffset){
var points = {};
for(i=0; sides-1){
var theta = angleOffset + (i * 2 * math.pi / sides);
table.push(points, cx + r * math.cos(theta));
table.push(points, cy + (r * 0.6) * math.sin(theta));
}
return points;
}
var createLightningBolt = function(){
var segments = {};
var currX = math.random(50, winform.plus.width-50);
var currY = -50;
var segCount = math.random(5, 8);
var stepY = (winform.plus.height * 0.8) / segCount;
for(i=1; segCount){
var nextX = currX + math.random(-80, 80);
var nextY = currY + stepY + math.random(-20, 20);
table.push(segments, {x1=currX; y1=currY; x2=nextX; y2=nextY});
currX, currY = nextX, nextY;
}
return segments;
}
var initWeather = function(){
gameState.weather.items = {};
gameState.weather.lightning = { active=false; segments={}; timer=100; flashAlpha=0; duration=0 };
if(math.random(0,1) == 0){
// ☀️ 晴天
gameState.weather.type = "sunny";
gameState.weather.bgColor = 0xFF87CEEB;
for(i=1; config.cloudCount){
table.push(gameState.weather.items, { x=math.random(-50,450); y=math.random(20,200); speed=math.random(2,5)*0.1; scale=math.random(8,15)*0.1; type="cloud" });
}
} else {
// ⛈️ 雷雨天
gameState.weather.type = "rainy";
gameState.weather.bgColor = 0xFF4B5B6B; // 深蓝灰背景
for(i=1; config.cloudCount){
table.push(gameState.weather.items, { x=math.random(-50,450); y=math.random(20,150); speed=math.random(5,10)*0.1; scale=math.random(8,15)*0.1; type="darkcloud" });
}
for(i=1; config.rainCount){
table.push(gameState.weather.items, { x=math.random(0,450); y=math.random(0,600); speed=math.random(10,20); len=math.random(10,25); type="rain" });
}
}
}
var updateWeather = function(){
var w, h = winform.plus.width, winform.plus.height;
// 更新云雨位置
for(i=1; #gameState.weather.items){
var item = gameState.weather.items[i];
if(item.type == "cloud" || item.type == "darkcloud"){
item.x += item.speed; if(item.x > w + 100) item.x = -100;
} elseif(item.type == "rain"){
item.y += item.speed; if(item.y > h){ item.y = -item.len; item.x = math.random(0, w); }
}
}
// 更新闪电
if(gameState.weather.type == "rainy"){
var ln = gameState.weather.lightning;
if(ln.flashAlpha > 0) ln.flashAlpha -= 10; // 闪光渐隐
if(ln.flashAlpha < 0) ln.flashAlpha = 0;
if(ln.active){ ln.duration--; if(ln.duration <= 0) ln.active = false; }
ln.timer--;
if(ln.timer <= 0){
// 随机触发闪电
if(math.random(1, 100) < 5){
ln.active = true; ln.duration = math.random(3, 6);
ln.segments = createLightningBolt(); ln.flashAlpha = 150;
ln.timer = math.random(100, 300);
}
}
}
}
// ==========================================
// 3. 游戏核心逻辑
// ==========================================
var spawnBlock = function(){
var lastBlock = gameState.blocks[#gameState.blocks];
var newBlock = {};
var types = {"cube", "cylinder", "pentagon"};
newBlock.type = types[math.random(1, 3)];
math.randomize();
var direction = math.random(0, 1);
var distance = math.random(config.minDist, config.maxDist);
if(!lastBlock){ newBlock.x=225; newBlock.y=400; newBlock.type="cube"; }
else {
if(direction==0) { newBlock.x=lastBlock.x-distance*0.8; newBlock.y=lastBlock.y-distance*0.5; }
else { newBlock.x=lastBlock.x+distance*0.8; newBlock.y=lastBlock.y-distance*0.5; }
}
var colors = {0xFFEEEEEE, 0xFFFFE4E1, 0xFF98FB98, 0xFFAFEEEE, 0xFFFFD700};
newBlock.color = colors[math.random(1, #colors)];
if(!lastBlock) newBlock.color = 0xFFFFFFFF;
table.push(gameState.blocks, newBlock);
if(#gameState.blocks > 6) table.remove(gameState.blocks, 1);
}
var initGame = function(){
gameState.blocks = {}; gameState.score = 0; gameState.isGameOver = false;
gameState.action = "idle"; gameState.power = 0; gameState.cameraOffset = {x=0; y=0};
initWeather(); spawnBlock(); spawnBlock();
gameState.playerPos.x = gameState.blocks[1].x; gameState.playerPos.y = gameState.blocks[1].y;
}
var checkLanding = function(){
var px, py = gameState.playerPos.x, gameState.playerPos.y;
for(i=1; #gameState.blocks){
var b = gameState.blocks[i];
if(math.sqrt((px-b.x)**2 + (py-b.y)**2) < (config.blockWidth/2.2)){
if(i==#gameState.blocks){
gameState.score++;
spawnBlock();
gameState.action="idle"; // 立即允许下次操作
} else {
gameState.action="idle";
}
return true;
}
}
return false;
}
// ==========================================
// 4. 渲染绘制
// ==========================================
var drawCloud = function(g, x, y, scale, isDark){
var color = isDark ? 0xAA444444 : 0x88FFFFFF; var brush = gdip.solidBrush(color);
g.fillEllipse(brush, x, y, 50*scale, 50*scale);
g.fillEllipse(brush, x+25*scale, y-20*scale, 60*scale, 60*scale);
g.fillEllipse(brush, x+50*scale, y, 50*scale, 50*scale); brush.delete();
}
var drawCube = function(g, x, y, w, h, bh, color){
var b1=gdip.solidBrush(0xFF999999); g.fillPolygon(b1,{x,y+h/2;x+w/2,y;x+w/2,y+bh;x,y+h/2+bh}); b1.delete();
var b2=gdip.solidBrush(0xFFBBBBBB); g.fillPolygon(b2,{x,y+h/2;x-w/2,y;x-w/2,y+bh;x,y+h/2+bh}); b2.delete();
var bTop=gdip.solidBrush(color); g.fillPolygon(bTop,{x,y-h/2;x+w/2,y;x,y+h/2;x-w/2,y}); bTop.delete();
}
var drawCylinder = function(g, x, y, w, h, bh, color){
var bSide=gdip.solidBrush(0xFFAAAAAA); g.fillRectangle(bSide,x-w/2,y,w,bh); g.fillEllipse(bSide,x-w/2,y+bh-h/2,w,h); bSide.delete();
var bTop=gdip.solidBrush(color); g.fillEllipse(bTop,x-w/2,y-h/2,w,h); bTop.delete();
}
var drawPentagon = function(g, x, y, w, h, bh, color){
var ptsTop=getPolyPoints(x,y,w/2,5,-1.5);
var bSide=gdip.solidBrush(0xFF999999);
for(i=1;#ptsTop;2){ var nx=(i<#ptsTop-1)?i+2:1; if(ptsTop[i+1]>y||ptsTop[nx+1]>y){
g.fillPolygon(bSide,{ptsTop[i],ptsTop[i+1];ptsTop[nx],ptsTop[nx+1];ptsTop[nx],ptsTop[nx+1]+bh;ptsTop[i],ptsTop[i+1]+bh});
}} bSide.delete();
var bTop=gdip.solidBrush(color); g.fillPolygon(bTop,ptsTop); bTop.delete();
}
var drawPlayer = function(g, x, y){
x-=gameState.cameraOffset.x; y-=gameState.cameraOffset.y;
var compress=(gameState.action=="charge")?gameState.power*0.5:0;
var bS=gdip.solidBrush(0x50000000); g.fillEllipse(bS,x-10,y-5,20,10); bS.delete();
var bB=gdip.solidBrush(0xFF333333); var w,h=20+compress/2,40-compress;
g.fillRectangle(bB,x-w/2,y-h-10,w,h); g.fillEllipse(bB,x-12,y-h-25+compress,24,24); bB.delete();
}
var drawTrajectory = function(graphics){
if(gameState.action != "charge") return;
var targetBlock = gameState.blocks[#gameState.blocks];
var dx = targetBlock.x - gameState.playerPos.x;
var dy = targetBlock.y - gameState.playerPos.y;
var len = math.sqrt(dx*dx + dy*dy) || 1;
var dirX, dirY = dx/len, dy/len;
var predictDist = gameState.power * config.powerRatio;
var points = {};
var step = 0.05; var penGuide = gdip.pen(0xAAFFFFFF, 2, 2/*Dash*/);
for(t=0; 1; step){
var tx = gameState.playerPos.x + dirX * predictDist * t;
var ty = gameState.playerPos.y + dirY * predictDist * t;
var height = math.sin(t * math.pi) * config.jumpHeight;
ty -= height;
table.push(points, tx - gameState.cameraOffset.x);
table.push(points, ty - gameState.cameraOffset.y);
}
if(#points > 2) graphics.drawCurve(penGuide, points);
penGuide.delete();
var landX = gameState.playerPos.x + dirX * predictDist - gameState.cameraOffset.x;
var landY = gameState.playerPos.y + dirY * predictDist - gameState.cameraOffset.y;
var bMark = gdip.solidBrush(0xAAFF0000); graphics.fillEllipse(bMark, landX-5, landY-2.5, 10, 5); bMark.delete();
}
winform.plus.onDrawForegroundEnd = function(graphics, rc){
// 1. 绘制背景
graphics.clear(gameState.weather.bgColor);
graphics.smoothingMode = 4;
// 2. 绘制闪电 (云层后)
var ln = gameState.weather.lightning;
if(ln.active){
var penBolt = gdip.pen(0xFFFFFFFF, 3);
for(i=1; #ln.segments){ var seg=ln.segments[i]; graphics.drawLine(penBolt, seg.x1, seg.y1, seg.x2, seg.y2); }
var penGlow = gdip.pen(0x50FFFFFF, 8);
for(i=1; #ln.segments){ var seg=ln.segments[i]; graphics.drawLine(penGlow, seg.x1, seg.y1, seg.x2, seg.y2); }
penBolt.delete(); penGlow.delete();
}
// 3. 绘制云
for(i=1; #gameState.weather.items){
var item = gameState.weather.items[i];
if(item.type=="cloud") drawCloud(graphics, item.x, item.y, item.scale, false);
elseif(item.type=="darkcloud") drawCloud(graphics, item.x, item.y, item.scale, true);
}
// 4. 绘制方块
var drawList = table.clone(gameState.blocks); table.sort(drawList, function(b){ return owner.y < b.y });
for(i=1; #drawList){
var b = drawList[i];
var dx, dy = b.x - gameState.cameraOffset.x, b.y - gameState.cameraOffset.y;
if(b.type=="cylinder") drawCylinder(graphics, dx, dy, config.blockWidth, config.blockHeight, config.bodyHeight, b.color);
elseif(b.type=="pentagon") drawPentagon(graphics, dx, dy, config.blockWidth, config.blockHeight, config.bodyHeight, b.color);
else drawCube(graphics, dx, dy, config.blockWidth, config.blockHeight, config.bodyHeight, b.color);
}
// 5. 绘制辅助线和玩家
drawTrajectory(graphics);
var py = gameState.playerPos.y;
if(gameState.action=="jump") py-=math.sin(gameState.jumpProgress*math.pi)*config.jumpHeight;
drawPlayer(graphics, gameState.playerPos.x, py);
// 6. 绘制雨滴 (最上层)
if(gameState.weather.type == "rainy"){
var penRain = gdip.pen(0x88AAAAFF, 1);
for(i=1; #gameState.weather.items){
var item = gameState.weather.items[i];
if(item.type=="rain") graphics.drawLine(penRain, item.x, item.y, item.x, item.y+item.len);
}
penRain.delete();
}
// 7. 闪电全屏闪光
if(ln.flashAlpha > 0){
var argb = (math.floor(ln.flashAlpha) << 24) | 0xFFFFFF;
var brushFlash = gdip.solidBrush(argb); graphics.fillRectangle(brushFlash, 0, 0, rc.right, rc.bottom); brushFlash.delete();
}
// 8. UI
var font = gdip.font("微软雅黑", 20, 1);
var txtColor = (ln.flashAlpha > 100) ? 0xFF000000 : 0xFFFFFFFF;
var info = "分数: " + gameState.score;
graphics.drawString(info, font, ::RECTF(20,20,400,60), gdip.stringformat(), gdip.solidBrush(txtColor));
if(gameState.isGameOver) graphics.drawString("挂了! 按空格重开", font, ::RECTF(120,200,400,100), gdip.stringformat(), gdip.solidBrush(0xFFFF0000));
font.delete();
}
// ==========================================
// 5. 循环与控制 (集成版)
// ==========================================
winform.setInterval(function(){
if(gameState.isGameOver) return;
// 1. 更新天气
updateWeather();
// 2. 独立更新镜头 (丝滑跟随)
var targetCamX = gameState.playerPos.x - winform.plus.width/2;
var targetCamY = gameState.playerPos.y - winform.plus.height/1.5;
gameState.cameraOffset.x += (targetCamX - gameState.cameraOffset.x) * config.cameraSpeed;
gameState.cameraOffset.y += (targetCamY - gameState.cameraOffset.y) * config.cameraSpeed;
// 3. 玩家动作
if(gameState.action=="charge"){
if(gameState.power<config.maxPower) gameState.power+=0.8;
}
elseif(gameState.action=="jump"){
gameState.jumpProgress+=0.04;
if(gameState.jumpProgress>=1){
gameState.jumpProgress=1;
var dist=gameState.jumpTargetDist;
gameState.playerPos.x=gameState.jumpStartPos.x+gameState.jumpDirection.x*dist;
gameState.playerPos.y=gameState.jumpStartPos.y+gameState.jumpDirection.y*dist;
if(!checkLanding()){ gameState.action="fall"; gameState.isGameOver=true; }
} else {
var dist=gameState.jumpTargetDist*gameState.jumpProgress;
gameState.playerPos.x=gameState.jumpStartPos.x+gameState.jumpDirection.x*dist;
gameState.playerPos.y=gameState.jumpStartPos.y+gameState.jumpDirection.y*dist;
}
}
winform.plus.redraw();
}, 16)
winform.plus.onKeyDown = function(keyCode,lParam,repeat){
if(gameState.isGameOver){ initGame(); winform.plus.redraw(); return; }
if(gameState.action=="idle"){ gameState.action="charge"; gameState.power=0; }
}
winform.plus.onKeyUp = function(keyCode,lParam){
if(gameState.action=="charge"){
gameState.action="jump"; gameState.jumpProgress=0; gameState.jumpStartPos=table.clone(gameState.playerPos);
gameState.jumpTargetDist=gameState.power * config.powerRatio;
var tb=gameState.blocks[#gameState.blocks];
var dx,dy=tb.x-gameState.playerPos.x, tb.y-gameState.playerPos.y;
var len=math.sqrt(dx*dx+dy*dy)||1;
gameState.jumpDirection={x=dx/len; y=dy/len};
}
}
winform.plus.setFocus();
initGame();
winform.show();
return win.loopMessage();
3 个回复 | 最后更新于 3 小时前
登录后方可回帖
wow 不错啊,你用的免费的还是收费的