aardio经典魔幻动画:小孩骑马疾驰

lcj21 14小时前 33

哈哈哈,看我写的aardio游戏:小孩骑马疾驰


import win.ui;
/*DSG{{*/
var winform = win.form(text="小孩骑马疾驰 2D 动画 - aardio GDI+ 自绘";right=794;bottom=437;bgcolor=0xFFFFFF;border="dialog frame";max=false)
winform.add(
canvas={cls="canvas";left=0;top=0;right=795;bottom=438;anchors={left=1;top=1;right=1;bottom=1};z=1}
)
/*}}*/

// ---------------- 动画状态变量 ----------------
var gallopPhase = 0;       // 奔跑周期相位 (弧度)
var bgPos = 0;             // 背景水平滚动距离 (逻辑像素)
var gallopFreq = 7.5;      // 奔跑动作频率 (弧度/秒)
var runSpeed = 420;        // 场景滚动速度 (像素/秒)

// ---------------- GDI+ 逐帧绘制回调 ----------------
winform.canvas.onDrawForeground = function(graphics, rc, foregroundRect, foregroundColor, color, font){
    var dpiX, dpiY = winform.dpiScale(1, 1);
    graphics.scale(dpiX, dpiY);

    var width = rc.width / dpiX;
    var height = rc.height / dpiY;

    // --- 1. 天空与原野背景 ---
    var skyBrush = gdip.solidBrush(0xFF80D8FF); // 晴空蓝
    graphics.fillRect(skyBrush, 0, 0, width, 280);
    skyBrush.delete();

    var groundBrush = gdip.solidBrush(0xFF558B2F); // 深草绿草地
    graphics.fillRect(groundBrush, 0, 280, width, height - 280);
    groundBrush.delete();

    // --- 2. 远景白云 (慢速视差) ---
    var cloudBrush = gdip.solidBrush(0xFFFFFFFF);
    var cloudOffset = (bgPos * 0.15) % (width + 250);
    for(i = 0; 2; 1){
        var cx = (i * 420 - cloudOffset) + 80;
        if(cx < -120) cx += width + 250;
        graphics.fillEllipse(cloudBrush, cx, 50, 90, 36);
        graphics.fillEllipse(cloudBrush, cx + 30, 35, 75, 48);
        graphics.fillEllipse(cloudBrush, cx + 65, 50, 80, 36);
    }
    cloudBrush.delete();

    // --- 3. 远山连绵 (中速视差) ---
    var mountainBrush = gdip.solidBrush(0xFF7CB342);
    var mountStep = 320;
    var mountOffset = (bgPos * 0.35) % mountStep;
    for(x = -mountStep; width + mountStep; mountStep){
        var mx = x - mountOffset;
        graphics.fillPolygon(mountainBrush, [
            [mx, 280],
            [mx + 160, 160],
            [mx + 320, 280]
        ]);
    }
    mountainBrush.delete();

    // --- 4. 跑道栅栏 (快速视差,紧贴前进视角) ---
    var fenceWoodBrush = gdip.solidBrush(0xFFD7CCC8);
    var fenceStep = 110;
    var fenceOffset = (bgPos * 0.9) % fenceStep;
    // 栅栏横木
    graphics.fillRect(fenceWoodBrush, 0, 275, width, 6);
    graphics.fillRect(fenceWoodBrush, 0, 292, width, 6);
    // 栅栏立柱
    for(x = -fenceStep; width + fenceStep; fenceStep){
        var fx = x - fenceOffset;
        graphics.fillRect(fenceWoodBrush, fx, 265, 10, 42);
    }
    fenceWoodBrush.delete();

    // ---------------- 运动学姿态计算 ----------------
    // 马身腾跃与上下颠簸
    var bodyBounce = -math.abs(math.sin(gallopPhase)) * 18;
    var horseTilt = math.cos(gallopPhase) * 0.08; // 腾空时微仰,落地时微俯

    var originX = 400; // 马体中心 X
    var originY = 270 + bodyBounce; // 马体中心 Y

    // 马体色值定义(栗色马匹,远近层明暗区分)
    var colorBodyFar = 0xFF6D3C1F;
    var colorBodyNear = 0xFF8B4513;
    var colorHoof = 0xFF212121;
    var colorMane = 0xFF3E2723;

    // --- 马腿绘制通用骨骼函数 ---
    var drawHorseLeg = function(jointX, jointY, isFrontLeg, isNearLayer, phaseShift){
        var p = gallopPhase + phaseShift;
        var upperAngle, lowerAngle, hoofAngle;

        if(isFrontLeg){
            // 前腿屈伸向前趴地
            upperAngle = 0.55 * math.sin(p) + 0.45;
            lowerAngle = -0.75 * math.sin(p - 0.4) - 0.6;
            hoofAngle = 0.3 * math.sin(p);
        } else {
            // 后腿蹬地与收缩
            upperAngle = 0.65 * math.sin(p + math.pi) - 0.2;
            lowerAngle = 0.85 * math.sin(p + math.pi + 0.5) + 0.4;
            hoofAngle = -0.4 * math.sin(p);
        }

        var len1 = 44, len2 = 42;
        var kneeX = jointX + math.sin(upperAngle) * len1;
        var kneeY = jointY + math.cos(upperAngle) * len1;

        var ankleX = kneeX + math.sin(upperAngle + lowerAngle) * len2;
        var ankleY = kneeY + math.cos(upperAngle + lowerAngle) * len2;

        var hoofX = ankleX + math.sin(upperAngle + lowerAngle + hoofAngle) * 12;
        var hoofY = ankleY + math.cos(upperAngle + lowerAngle + hoofAngle) * 12;

        var legPen = gdip.pen(isNearLayer ? colorBodyNear : colorBodyFar, isNearLayer ? 13 : 11);
        graphics.drawLine(legPen, jointX, jointY, kneeX, kneeY);
        graphics.drawLine(legPen, kneeX, kneeY, ankleX, ankleY);
        legPen.delete();

        // 马蹄
        var hoofBrush = gdip.solidBrush(colorHoof);
        graphics.fillCircle(hoofBrush, hoofX, hoofY, 6);
        hoofBrush.delete();
    };

    var hipJointX = originX - 60;
    var hipJointY = originY - 5;
    var shoulderJointX = originX + 55;
    var shoulderJointY = originY - 10;

    // --- 5. 远侧腿部 (后景层,先画) ---
    drawHorseLeg(hipJointX, hipJointY, false, false, 0.4);
    drawHorseLeg(shoulderJointX, shoulderJointY, true, false, 0.4);

    // --- 6. 马体与飞扬尾巴 ---
    // 飞扬摆动的马尾
    var tailWave = math.sin(gallopPhase * 1.5) * 16;
    var tailPoints = [
        [originX - 75, originY - 20],
        [originX - 120, originY - 35 + tailWave],
        [originX - 165, originY - 10 + tailWave * 1.2],
        [originX - 125, originY + 5],
        [originX - 75, originY - 5]
    ];
    var tailBrush = gdip.solidBrush(colorMane);
    graphics.fillClosedCurve2(tailBrush, 0.4, tailPoints);
    tailBrush.delete();

    // 强壮马腹躯干
    var horseBodyBrush = gdip.solidBrush(colorBodyNear);
    graphics.fillEllipse(horseBodyBrush, originX - 75, originY - 35, 150, 68);

    // 马颈部与头部 (仰角随颠簸微调)
    var neckBaseX = originX + 45;
    var neckBaseY = originY - 15;
    var headBaseX = originX + 95;
    var headBaseY = originY - 80 + (horseTilt * 25);

    var neckPen = gdip.pen(colorBodyNear, 36);
    graphics.drawLine(neckPen, neckBaseX, neckBaseY, headBaseX - 5, headBaseY + 15);
    neckPen.delete();

    // 飘动马鬃
    var maneWave = math.cos(gallopPhase * 2) * 8;
    var maneBrush = gdip.solidBrush(colorMane);
    graphics.fillPolygon(maneBrush, [
        [neckBaseX - 15, neckBaseY - 10],
        [neckBaseX - 30 + maneWave, neckBaseY - 35],
        [headBaseX - 35 + maneWave, headBaseY + 5],
        [headBaseX - 12, headBaseY + 15]
    ]);

    // 马头轮廓与口鼻
    graphics.fillEllipse(horseBodyBrush, headBaseX - 18, headBaseY - 20, 42, 38);
    var muzzleBrush = gdip.solidBrush(0xFF70360F);
    graphics.fillEllipse(muzzleBrush, headBaseX + 8, headBaseY - 14, 32, 26);
    muzzleBrush.delete();

    // 马耳朵与眼睛
    graphics.fillPolygon(horseBodyBrush, [
        [headBaseX - 6, headBaseY - 18],
        [headBaseX - 2, headBaseY - 34],
        [headBaseX + 6, headBaseY - 18]
    ]);
    var horseEye = gdip.solidBrush(0xFF000000);
    graphics.fillCircle(horseEye, headBaseX + 5, headBaseY - 8, 3.5);
    horseEye.delete();

    // 马鞍与汗垫
    var saddleClothBrush = gdip.solidBrush(0xFFE63946); // 红色鞍垫
    graphics.fillRect(saddleClothBrush, originX - 30, originY - 36, 60, 16);
    saddleClothBrush.delete();

    var saddleBrush = gdip.solidBrush(0xFF3E2723); // 深皮鞍座
    graphics.fillEllipse(saddleBrush, originX - 22, originY - 42, 44, 15);
    saddleBrush.delete();

    // --- 7. 小孩骑手 (身体各部自然骑乘随动) ---
    var riderBounce = bodyBounce + math.sin(gallopPhase - 0.5) * 4;
    var riderX = originX - 2;
    var riderY = originY - 55;

    // 小孩双腿跨在马身 (近侧腿)
    var pantsPen = gdip.pen(0xFF1976D2, 10); // 牛仔蓝长裤
    graphics.drawLine(pantsPen, riderX - 5, riderY + 18, riderX + 4, riderY + 45);
    pantsPen.delete();
    var shoeBrush = gdip.solidBrush(0xFF37474F);
    graphics.fillCircle(shoeBrush, riderX + 5, riderY + 48, 5);
    shoeBrush.delete();

    // 躯干 (前倾防后倾)
    var coatBrush = gdip.solidBrush(0xFFFFB703); // 明黄上衣
    graphics.fillEllipse(coatBrush, riderX - 14, riderY - 22, 28, 42);
    coatBrush.delete();

    // 头部与红润脸蛋
    var skinBrush = gdip.solidBrush(0xFFFFDFC4);
    var kidHeadX = riderX + 3;
    var kidHeadY = riderY - 36;
    graphics.fillCircle(skinBrush, kidHeadX, kidHeadY, 15);
    skinBrush.delete();

    // 小孩五官笑脸
    var kidEye = gdip.solidBrush(0xFF263238);
    graphics.fillCircle(kidEye, kidHeadX + 5, kidHeadY - 2, 2);
    kidEye.delete();
    var smilePen = gdip.pen(0xFFD32F2F, 1.8);
    graphics.drawArc(smilePen, kidHeadX + 2, kidHeadY - 1, 8, 8, 20, 140);
    smilePen.delete();

    // 红色棒球帽 (帽檐向前挡风)
    var capBrush = gdip.solidBrush(0xFFE63946);
    graphics.fillPie(capBrush, kidHeadX - 16, kidHeadY - 16, 32, 26, 170, 200);
    graphics.fillRect(capBrush, kidHeadX + 4, kidHeadY - 10, 18, 4); // 帽檐突出
    capBrush.delete();

    // 手臂前伸牵引缰绳
    var armPen = gdip.pen(0xFFFFB703, 7);
    var handX = originX + 40;
    var handY = originY - 45;
    graphics.drawLine(armPen, riderX + 2, riderY - 6, handX, handY);
    armPen.delete();

    // 缰绳 (从手拉至马嘴水勒)
    var reinPen = gdip.pen(0xFF4E342E, 2);
    var bitX = headBaseX + 16;
    var bitY = headBaseY - 2;
    graphics.drawLine(reinPen, bitX, bitY, handX, handY);
    reinPen.delete();

    // --- 8. 近侧腿部 (前景层,遮挡大部分马体轮廓) ---
    drawHorseLeg(hipJointX, hipJointY, false, true, 0);
    drawHorseLeg(shoulderJointX, shoulderJointY, true, true, 0);

    // 释放常驻笔刷
    horseBodyBrush.delete();
    maneBrush.delete();

    // 还原画板变换矩阵
    graphics.resetTransform();
};

// ---------------- 动画定时器更新逻辑 ----------------
winform.canvas.onAnimation = function(prevState, beginning, change, timestamp, duration, deltaMs){
    var deltaSeconds = deltaMs / 1000;
    gallopPhase = (gallopPhase + gallopFreq * deltaSeconds) % (math.pi * 2);
    bgPos += runSpeed * deltaSeconds;

    return true; // 循环刷新
};

// 启动平滑动画(约 16ms/帧,60 FPS)
winform.canvas.startAnimation(16);

winform.onEraseBkgnd = lambda() 0;

winform.show();
win.loopMessage();


最新回复 (2)
  • nanyi 14小时前
    0 2楼
    ai还是好用啊
  • mfk 6小时前
    0 3楼

返回