Gemini3写的《跳一跳》小游戏

Mr_MAO 8天前 217

Gemini-3-pro写的,大家有兴趣可以把下面代码喂给AI进一步完善!



import win.ui;
import gdip;
// 1. 创建主窗口
/*DSG{{*/
var winform = win.form(text="aardio版《跳一跳》小游戏 - (by:Gemini-3-pro)";right=600;bottom=800;border="dialog frame";max=false)
winform.add(
gameCanvas={cls="plus";left=0;top=0;right=600;bottom=798;bgcolor=0xFEEEDD;db=1;dl=1;dr=1;dt=1;notify=1;z=1}
)
/*}}*/

// --- 全局配置 ---
var config = {
    playerScreenX = 300; // 目标位置:屏幕中心X
    groundY = 500;       // 目标位置:屏幕中心Y
    playerRadius = 15;
    blockHeight = 70;
    gravity = 0.8;
    jumpFactor = 3.8;   
    maxPower = 150;
    initialBlockCount = 20; 
}

// --- 游戏状态 ---
var game = {
    score = 0;
    state = "idle"; // idle, charging, jumping, falling, over
    power = 0;      
    player = { x = 0; y = 0; z = 0 }; 
    offsetX = 0; 
    offsetY = 0;
    blocks = {};
    lastTargetIndex = 1;
    showPerfect = 0;
    fallAngle = 0;   // 摔倒旋转角度
    fallFrame = 0;   // 摔倒动画帧计时
    fallDirection = 1; // 1: 向右倒, -1: 向左倒
}

// --- 辅助函数:安全地调亮颜色 ---
function getLighterColor(c){
    var r = (c >> 16) & 0xFF;
    var g = (c >> 8) & 0xFF;
    var b = c & 0xFF;
    r = math.min(255, r + 30);
    g = math.min(255, g + 30);
    b = math.min(255, b + 30);
    return (0xFF << 24) | (r << 16) | (g << 8) | b;
}

// --- 逻辑函数 ---
function initGame(){
    game.score = 0;
    game.state = "idle";
    game.power = 0;
    game.blocks = {};
    game.lastTargetIndex = 1;
    game.showPerfect = 0;
    game.fallAngle = 0;
    game.fallFrame = 0;
    // 1. 创建起点方块
    table.push(game.blocks, {x=0; y=0; w=120; h=100; color=0xFFCCCCCC}); 
    for(i=1; config.initialBlockCount; 1) addNextBlock();
    game.player = { x = 0; y = 0; z = 0 };
    game.offsetX = game.player.x - config.playerScreenX;
    game.offsetY = game.player.y - config.groundY;
}

// --- 生成下一个底座  ---
function addNextBlock(){
    var lastBlock = game.blocks[#game.blocks];
    var direction = math.random(0,1) == 0 ? -1 : 1; 
    var distance = math.random(180, 320); 
    var sizeW = math.random(80, 120);
    var sizeH = sizeW * 0.8;
    
    var newX = lastBlock.x + (distance * (direction == -1 ? -0.8 : 0.8)); 
    var newY = lastBlock.y + (distance * -0.5); 
    
    var colors = { 0xFF67C23A; 0xFFE6A23C; 0xFF409EFF; 0xFFF56C6C; 0xFF52D4E7; 0xFFADB0B8; 0xFF8E44AD; 0xFFFF69B4; 0xFF1ABC9C; 0xFF3CC4D6 };
    table.push(game.blocks, {x=newX; y=newY; w=sizeW; h=sizeH; color=colors[math.random(1, #colors)]});
    if(#game.blocks > 40) table.remove(game.blocks, 1);
}

// 检查落点
function checkLanding(){
    var px, py = game.player.x, game.player.y;
    var landedIndex = 0;
    for(i=#game.blocks; 1; -1){
        var b = game.blocks[i];
        var dx, dy = px - b.x, py - b.y;
        var rx, ry = b.w / 2, b.h / 2;
        if ( (dx*dx)/(rx*rx) + (dy*dy)/(ry*ry) <= 1 ) {
            landedIndex = i; break;
        }
    }
    if(landedIndex > 0){
        // --- 命中成功逻辑 ---
        game.state = "idle"; 
        if(landedIndex > game.lastTargetIndex) {
            var distToCenter = math.sqrt((px - game.blocks[landedIndex].x)**2 + (py - game.blocks[landedIndex].y)**2);
            if(distToCenter < 15){ 
                game.score += 2; game.showPerfect = 10; 
            } else {
                game.score += 1;
            }
            game.lastTargetIndex = landedIndex;
            addNextBlock();
        }
    } else {
 		// --- 未命中,开始摔倒 ---
        game.state = "falling";
        game.fallFrame = 0;
        game.fallAngle = 0;
        // 计算倒地方向(寻找距离当前落点最近的方块中心,以决定相对于它是左偏还是右偏)
        var closestDist = 999999;
        var closestBlockX = px; // 默认
        
        for(i=math.max(1, game.lastTargetIndex-1); #game.blocks; 1){
            var b = game.blocks[i];
            var dist = math.sqrt((px - b.x)**2 + (py - b.y)**2);
            if(dist < closestDist){
                closestDist = dist;
                closestBlockX = b.x;
            }
        }
        game.fallDirection = (px < closestBlockX) ? -1 : 1;
    }
}

// --- 绘图逻辑 ---
winform.gameCanvas.onDrawContent = function(graphics, rc) {
    graphics.smoothingMode = 4;
    // 1. 绘制底座
    for(i=1; #game.blocks; 1){
        var b = game.blocks[i];
        var drawX, drawY = b.x - game.offsetX, b.y - game.offsetY;
        if(drawX < -200 || drawX > rc.width + 200) continue;
        
        var brushSide = gdip.solidBrush(b.color);
        var lightColor = getLighterColor(b.color);  // 防止颜色溢出
        var brushTop = gdip.solidBrush(lightColor); 
        // 画底面
        graphics.fillEllipse(brushSide, drawX-b.w/2, drawY + config.blockHeight - b.h/2, b.w, b.h);
        // 画侧面
        graphics.fillRectangle(brushSide, drawX-b.w/2, drawY, b.w, config.blockHeight);
        // 画顶面
        graphics.fillEllipse(brushTop, drawX-b.w/2, drawY-b.h/2, b.w, b.h);
        // 绘制中心小白点
        var brushPoint = gdip.solidBrush(0x55FFFFFF);
        graphics.fillEllipse(brushPoint, drawX-5, drawY-5, 10, 10);
        brushSide.delete(); brushTop.delete();brushPoint.delete();
    }
    // 2. 绘制角色
    var px = game.player.x - game.offsetX;
    var py = game.player.y - game.offsetY - game.player.z; 
    // 角色形变计算
    var scaleY = 1.0;
    var scaleX = 1.0;
    if(game.state == "charging"){
        var compression = game.power / config.maxPower * 0.4; 
        scaleY = 1.0 - compression;
        scaleX = 1.0 + compression * 0.5;
    }
    // 摔倒旋转
    var state = graphics.save();
    graphics.translate(px, py); // 移动到角色底部中心
    if(game.state == "falling" || game.state == "over"){
        graphics.rotate(game.fallAngle * game.fallDirection);
    }   
    var pW = config.playerRadius * 2 * scaleX;
    var pH = 50 * scaleY;
    var brushPlayer = gdip.solidBrush(0xFF005DFF);
    
    // 绘制角色身体 (坐标以 0,0 为基准)
    var bodyW = config.playerRadius * 2 * scaleX;
    var bodyH = 45 * scaleY; var headR = 22;
    var brushBody = gdip.lineBrush(::RECTF(-bodyW/2, -bodyH, bodyW, bodyH), 0xFF333344, 0xFF4A4A6A, 1);
    graphics.fillEllipse(brushBody, -bodyW/2, -bodyW/3, bodyW, bodyW/2); // 底部圆盘
    graphics.fillRectangle(brushBody, -bodyW/2, -bodyH, bodyW, bodyH);   // 中段
    graphics.fillEllipse(brushBody, -bodyW/2, -bodyH - bodyW/4, bodyW, bodyW/2); // 顶部
    
    var brushHead = gdip.solidBrush(0xFF333344);
    graphics.fillEllipse(brushHead, -headR/2, -bodyH - headR - 2, headR, headR);
    var brushLight = gdip.solidBrush(0x40FFFFFF);
    graphics.fillEllipse(brushLight, -headR/4, -bodyH - headR - 2, headR/3, headR/3);
    
    graphics.restore(state);
    brushBody.delete(); brushHead.delete(); brushLight.delete();
    
    // 蓄力条 (跟随角色)
    if(game.state == "charging"){
        var pen = gdip.pen(0x88000000, 2);
        var barW = 60;
        graphics.drawRectangle(pen, px - barW/2, py - pH - 60, barW, 8);
        var brushPower = gdip.solidBrush(0xAAFF0000);
        graphics.fillRectangle(brushPower, px - barW/2, py - pH - 60, barW * (game.power/config.maxPower), 8);
        pen.delete(); brushPower.delete();
    }
    brushPlayer.delete();
    
    // 3. 绘制文字
    var family = gdip.family("Microsoft YaHei UI");
    var brushText = gdip.solidBrush();
    // ① 分数
    var fontScore = family.createFont(35, 1);
    brushText.color = 0xFF555555;
    graphics.drawString("Score: " + game.score, fontScore, gdip.RECTF(30, 40, 400, 100), gdip.stringformat(), brushText);
    // ② 完美特效
    if(game.showPerfect > 0 && game.state == "idle"){
        var fontP = family.createFont(25, 1);
        var brushP = gdip.solidBrush(0xFFFF9900);
        graphics.drawString("PERFECT!", fontP, gdip.RECTF(px - 60, py - 120, 150, 40), gdip.stringformat(), brushP);
        game.showPerfect--;
        fontP.delete(); brushP.delete();
    }
	// ③ GAME OVE
    if(game.state == "over"){
        var title = "GAME OVER";
        var fontBig = family.createFont(40, 1);
        brushText.color = 0xFFDC143C; 
        var rc_size1 = graphics.measureString(title, fontBig,::RECTF(0,0,,),gdip.stringformat());
        graphics.drawString(title, fontBig, gdip.RECTF((rc.width-rc_size1.width)/2, (rc.height-rc_size1.height)/2 - 50, rc_size1.width, rc_size1.height), gdip.stringformat(), brushText);
        
        var subtitle = "点击屏幕重新开始";
        var fontSmall = family.createFont(25, 1);
        brushText.color = 0xFFA01600;
        var rc_size2 = graphics.measureString(subtitle, fontSmall,::RECTF(0,0,,),gdip.stringformat());
        graphics.drawString(subtitle, fontSmall, gdip.RECTF((rc.width-rc_size2.width)/2, (rc.height-rc_size2.height)/2 + 50, rc_size2.width, rc_size2.height), gdip.stringformat(), brushText);
        fontBig.delete(); fontSmall.delete();
    }
    fontScore.delete(); family.delete(); brushText.delete();
}

// --- 交互 ---
winform.gameCanvas.onMouseDown = function(wParam,lParam){
    if(game.state == "idle") { game.state = "charging"; game.power = 0; }
    elseif(game.state == "over") { initGame(); }
}

winform.gameCanvas.onMouseUp = function(wParam,lParam){
    if(game.state == "charging"){
        game.state = "jumping";
        game.jumpTime = 0;
        game.jumpStartPos = {x=game.player.x; y=game.player.y};
        // 寻找目标方块 
        var nextBlock = game.blocks[game.lastTargetIndex + 1];
        if(!nextBlock) nextBlock = {x=game.player.x+200; y=game.player.y-100};
        var angle = math.atan2(nextBlock.y - game.player.y, nextBlock.x - game.player.x);
        // 蓄力计算速度
        var jumpDistance = game.power * config.jumpFactor;
        var vz = 14; 
        var flightTime = 2 * vz / config.gravity;
        var vHorizontal = jumpDistance / flightTime;
        game.velocity = { x = math.cos(angle) * vHorizontal; y = math.sin(angle) * vHorizontal; z = vz; }
    }
}

// --- 主循环 ---
winform.setInterval( 
    function(){
        // 1. 蓄力逻辑
        if(game.state == "charging") game.power = math.min(game.power + 3, config.maxPower);
        // 2. 跳跃逻辑
        if(game.state == "jumping"){
            game.jumpTime++;
            var t = game.jumpTime;
            game.player.x = game.jumpStartPos.x + game.velocity.x * t;
            game.player.y = game.jumpStartPos.y + game.velocity.y * t;
            game.player.z = game.velocity.z * t - 0.5 * config.gravity * t * t;
            if(game.player.z <= 0){ game.player.z = 0; checkLanding(); }
        }
        // 3. 落地摔倒动效逻辑
        if(game.state == "falling"){
            game.fallFrame++;
            // 角色快速旋转到90度(倒地)
            if(game.fallAngle < 90) game.fallAngle += 10;
            // 掉落动画:Z轴坐标从0减小到负的 blockHeight
            var dropProgress = game.fallFrame / 30;	// 动画持续30帧,所以每帧掉落 1/30 的高度
            if(dropProgress > 1) dropProgress = 1;
            game.player.z = - (dropProgress * config.blockHeight);
            // 摔倒动画持续 30 帧后结束
            if(game.fallFrame > 30) game.state = "over";
        }
        // 4. 摄像机跟随逻辑 
        var targetCamX = game.player.x - config.playerScreenX;
        var targetCamY = game.player.y - config.groundY;
        // 保持镜头跟随
        if(game.state != "over"){
            var lerp = (game.state == "falling") ? 0.05 : 0.1; 
            game.offsetX = game.offsetX + (targetCamX - game.offsetX) * lerp;
            game.offsetY = game.offsetY + (targetCamY - game.offsetY) * lerp;
        }
        winform.gameCanvas.redraw();
    }, 16
)

initGame();
winform.bgcolor = 0xFEEEDD; 
winform.show();
win.loopMessage();
最新回复 (1)
  • mfk 5天前
    0 2

返回