利用aardio制作简单的贪吃蛇游戏

Mr_MAO 1天前 62

//贪吃蛇小游戏
import win.ui;
/*DSG{{*/
var winform = win.form(text="贪吃蛇小游戏 (By: Mr_MAO)";right=600;bottom=640;border="dialog frame";max=false)
winform.add(
btnRestart={cls="button";text="重新开始";left=480;top=5;right=580;bottom=35;z=2};
gameCanvas={cls="plus";left=0;top=40;right=600;bottom=640;bgcolor=0x333333;notify=1;z=1};
lblHint={cls="static";text="按方向键控制,空格暂停";left=160;top=13;right=400;bottom=32;align="center";color=0x808080;transparent=1;z=4};
lblScore={cls="static";text="分数: 0";left=10;top=8;right=182;bottom=33;font=LOGFONT(h=-16;weight=700);transparent=1;z=3}
)
/*}}*/

import win.timer;
winform.tmr = win.timer(winform);

// --- 游戏环境参数 ---
var conf = {
    cellSize = 20; 
    cols = 30;     
    rows = 30;     
    speed = 100;
    colors = {
        food = 0xFFFF4500;  // 橙红
        snake = 0xFF00FF00; // 绿
        head = 0xFFADFF2F;  // 亮绿
        text = 0xFFFFFFFF;  // 白
    }
}

// --- 当前游戏状态 ---
var state = {
    snake = {};  //数组,存储构成snake的多个方块的位置
    food = {x=0; y=0};
    dir = "right";
    nextDir = "right";
    score = 0;
    gameOver = false;
    paused = false;
}

// --- 生成豆子(food)位置 ---
var generateFood = function(){
    while(true){
        var x = math.random(0, conf.cols - 1);
        var y = math.random(0, conf.rows - 1);
        var conflict = false;
        // 检查是否生成在蛇身上
        for(i=1; #state.snake; 1){
            if(state.snake[i].x == x && state.snake[i].y == y){
                conflict = true; 
                break;
            }
        }
        if(!conflict){
            state.food = {x=x; y=y};
            break;
        }
    }
}

// --- 初始化 ---
var initGame = function(){
    state.snake = {{x=5; y=10}; {x=4; y=10}; {x=3; y=10}}; 
    state.dir = "right";
    state.nextDir = "right";
    state.score = 0;
    state.gameOver = false;
    state.paused = false;
    generateFood(); 
    
    winform.lblScore.text = "分数: 0";
    winform.btnRestart.text = "重新开始";

    // 启动定时器
    winform.tmr.enable(conf.speed);
}

// 游戏结束时要做的处理工作
var endGame = function(){
    state.gameOver = true;
    winform.tmr.disable();
    winform.btnRestart.text = "重玩(R)";
    winform.gameCanvas.redraw();
    
    win.msgbox('游戏结束! \r\n(🏆得分: ' ++ state.score ++ ")","提示");
}


// --- 核心游戏循环 ---
var update = function(){
    if(state.gameOver || state.paused) return;

    state.dir = state.nextDir;
    var head = state.snake[1];
    var newHead = {x=head.x; y=head.y};

    select(state.dir) {
        case "up"    newHead.y--;
        case "down"  newHead.y++;
        case "left"  newHead.x--;
        case "right" newHead.x++;
    }

    // 碰撞检测:墙壁
    if(newHead.x < 0 || newHead.x >= conf.cols || newHead.y < 0 || newHead.y >= conf.rows){
        endGame(); return;
    }

    // 碰撞检测:自身
    for(i=1; #state.snake-1; 1){
        if(state.snake[i].x == newHead.x && state.snake[i].y == newHead.y){
            endGame(); return;
        }
    }

    // 往前移动一节
    table.insert(state.snake, newHead, 1);
    
    // 吃食物
    if(newHead.x == state.food.x && newHead.y == state.food.y){
        state.score++;
        winform.lblScore.text = "分数: " + state.score;
        generateFood();
    } else {
        table.remove(state.snake,-1); //删掉最后一节身体
    }
    
    winform.gameCanvas.redraw(); 
}

// 定时器,让画面动起来
winform.tmr.onTimer  = function(){
    update();
}

// --- 键盘事件处理 ---
winform.isDialogMessage = function(hwnd,msg){
    if(msg.message == 0x0100/*_WM_KEYDOWN*/){
        var vk = msg.wParam;
        
        if(vk == 0x20/*_VK_SPACE*/){
            if(state.gameOver) initGame();
            else {
                state.paused = !state.paused;
                winform.gameCanvas.redraw();
            }
            return true; 
        }

        if(!state.paused && !state.gameOver){
            // 防止反向掉头
            if(vk == 0x26/*_VK_UP*/ && state.dir != "down") {state.nextDir = "up";}
            elseif(vk == 0x28/*_VK_DOWN*/ && state.dir != "up") {state.nextDir = "down";}
            elseif(vk == 0x25/*_VK_LEFT*/ && state.dir != "right") {state.nextDir = "left";}
            elseif(vk == 0x27/*_VK_RIGHT*/ && state.dir != "left") {state.nextDir = "right";}
        }
        
    }
}

// --- Plus控件绘图逻辑 ---
winform.gameCanvas.onDrawForegroundEnd = function(graphics,rect){
 
    // 1. 绘制食物
    var brushFood = gdip.solidBrush(conf.colors.food);
    graphics.fillRectangle(brushFood, 
        state.food.x * conf.cellSize + 1, 
        state.food.y * conf.cellSize + 1, 
        conf.cellSize - 2, conf.cellSize - 2
    );
    brushFood.delete();

    // 2. 绘制蛇
    var brushSnakeBody = gdip.solidBrush(conf.colors.snake);
    var brushSnakeHead = gdip.solidBrush(conf.colors.head);
    
    for(i=1; #state.snake; 1){
        var part = state.snake[i];
        var brush = (i==1) ? brushSnakeHead : brushSnakeBody;
        graphics.fillRectangle(brush, 
            part.x * conf.cellSize + 1, 
            part.y * conf.cellSize + 1, 
            conf.cellSize - 2, conf.cellSize - 2
        );
    }
    brushSnakeBody.delete();
    brushSnakeHead.delete();
    
    // 3. 绘制状态文字(暂停 或 结束)
    if(state.gameOver || state.paused){
        var txt = state.gameOver ? "GAME OVER" : "PAUSED";
        var font = gdip.font("Arial", 30); 
        var brushTxt = gdip.solidBrush(conf.colors.text);
        var strFormat = gdip.stringformat();
        strFormat.align = 1; // Center
        strFormat.lineAlign = 1; // Center
        
        //文本绘制在plus控件中心
        var rc = gdip.RECTF(rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top);
        graphics.drawString(txt, font, rc, strFormat, brushTxt);
        
        font.delete();  brushTxt.delete(); strFormat.delete();
    }
}

// --- 按钮事件 ---
winform.btnRestart.oncommand = function(id,event){
    initGame();
}

winform.enableDpiScaling(false);
winform.show();

initGame(); //运行程序后,直接开始游戏

win.loopMessage();


最新回复 (1)
  • nanyi 10小时前
    0 2
    进化出游戏了啊
返回