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

Mr_MAO 18天前 272

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 scaleX, scaleY = winform.getScale();
    graphics.scale(scaleX, scaleY);
	
    // 2. 绘制食物
    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();

    // 3. 绘制蛇
    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();
    
    // 4. 绘制状态文字
    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)/scaleX, (rect.bottom-rect.top)/scaleY);
        graphics.drawString(txt, font, rc, strFormat, brushTxt);
        
        font.delete();  brushTxt.delete(); strFormat.delete();
    }
}

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

winform.show();
initGame(); //运行程序后,直接开始游戏
win.loopMessage();


最新回复 (7)
  • nanyi 17天前
    0 2
    进化出游戏了啊
  • 光庆 15天前
    0 3
    厉害厉害,学到了
  • netfox 14天前
    0 4
    光庆 厉害厉害,学到了
    严重怀疑大佬,在恶意顶贴
  • 光庆 13天前
    0 5

    添加了个蛇头的图片,处理了一下身体,代码如下:

    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控件绘图逻辑 ---
    var ag = {
    	down = 0;
    	left = 90;
    	up = 180;
    	right = 270;
    }
    winform.gameCanvas.onDrawForegroundEnd = function(graphics,rect){
        
        // 1. 适应显示器分辨率
        var scaleX, scaleY = winform.getScale();
        graphics.scale(scaleX, scaleY);
        
        // 2. 绘制食物
        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();
    
        // 3. 绘制蛇
        var brushSnakeBody = gdip.solidBrush(conf.colors.snake);
        var brushSnakeHead = gdip.solidBrush(0x88D9FF00);
        
        for(i=1; #state.snake; 1){
            var part = state.snake[i];
            var w = conf.cellSize * 0.5 * (2-i/#state.snake);
            var rect = ::RECT(part.x * conf.cellSize + (conf.cellSize-w)/2,
            			part.y * conf.cellSize + (conf.cellSize-w)/2, 
            			part.x * conf.cellSize + (conf.cellSize-w)/2+w,
            			part.y * conf.cellSize + (conf.cellSize-w)/2+w);
            if i==1 {
                graphics.rotateRect(rect,ag[[state.nextDir]]:0);
            	graphics.drawImageStretch(gdip.bitmap("C:\Users\Administrator\Desktop\head.png"),rect.inflate(5,5));
            	graphics.resetTransform();
            } else {
             	graphics.fillEllipse(brushSnakeBody,rect); 
             	graphics.fillEllipse(brushSnakeHead,rect.inflate(-2,-2).offset(-1,-1)); 
            }
        }
        brushSnakeBody.delete();
        brushSnakeHead.delete();
        
        // 4. 绘制状态文字
        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)/scaleX, (rect.bottom-rect.top)/scaleY);
            graphics.drawString(txt, font, rc, strFormat, brushTxt);
            
            font.delete();  brushTxt.delete(); strFormat.delete();
        }
    }
    
    // --- 按钮事件 ---
    winform.btnRestart.oncommand = function(id,event){
        initGame();
    }
    
    winform.show();
    initGame(); //运行程序后,直接开始游戏
    win.loopMessage();


    上传的附件:
  • Mr_MAO 13天前
    0 6
    抛砖引玉了,@光庆,厉害厉害!👍👍👍
  • 近我者赤 13天前
    0 7

    加个网格看得清楚

    // 2. 添加网格
        var penGrid = gdip.pen(0x0cc0c0cF, 1);
        graphics.smoothingMode = 2;
    	for(i=0;600;20){
    		if i!=0 graphics.drawLine(penGrid, 0, i, 600, i)	
    	}
    	
    	for(i=0;600;20){
    		if i!=0 graphics.drawLine(penGrid, i, 0, i,600)	
    	}
        penGrid.delete();

  • 光庆 13天前
    0 8

    加了网格和汉堡

    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控件绘图逻辑 ---
    var ag = {
    	down = 0;
    	left = 90;
    	up = 180;
    	right = 270;
    }
    winform.gameCanvas.onDrawForegroundEnd = function(graphics,rect){
        
        // 1. 适应显示器分辨率
        var scaleX, scaleY = winform.getScale();
        graphics.scale(scaleX, scaleY);
        
    	// 2. 添加网格
        var penGrid = gdip.pen(0x09c0c0cF, 1);
        graphics.smoothingMode = 0;
        for(i=0;600;20){
            if i!=0 graphics.drawLine(penGrid, 0, i, 600, i)    
        }
        
        for(i=0;600;20){
            if i!=0 graphics.drawLine(penGrid, i, 0, i,600)    
        }
        penGrid.delete();  
        graphics.smoothingMode = 2;  
        
        // 3. 绘制食物
        graphics.drawImageStretch(..gdip.bitmap("C:\Users\Administrator\Desktop\hanbao.png"),::RECT(
            state.food.x * conf.cellSize -3, 
            state.food.y * conf.cellSize -3, 
            state.food.x * conf.cellSize + conf.cellSize +3,
            state.food.y * conf.cellSize + conf.cellSize +3 
        ));
    
        // 4. 绘制蛇
        var brushSnakeBody = gdip.solidBrush(conf.colors.snake);
        var brushSnakeBody1 = gdip.solidBrush(0x88D9FF00);
        
        for(i=1; #state.snake; 1){
            var part = state.snake[i];
            var w = conf.cellSize * 0.5 * (2-i/#state.snake);
            var rect = ::RECT(part.x * conf.cellSize + (conf.cellSize-w)/2,
            			part.y * conf.cellSize + (conf.cellSize-w)/2, 
            			part.x * conf.cellSize + (conf.cellSize-w)/2+w,
            			part.y * conf.cellSize + (conf.cellSize-w)/2+w);
            if i==1 {
                graphics.rotateRect(rect,ag[[state.nextDir]]:0);
            	graphics.drawImageStretch(gdip.bitmap("C:\Users\Administrator\Desktop\head.png"),rect.inflate(5,5));
            	graphics.resetTransform();
            } else {
             	graphics.fillEllipse(brushSnakeBody,rect); 
             	graphics.fillEllipse(brushSnakeBody1,rect.inflate(-2,-2).offset(-1,-1)); 
            }
        }
        brushSnakeBody.delete();
        brushSnakeBody1.delete();
        
        // 5. 绘制状态文字
        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)/scaleX, (rect.bottom-rect.top)/scaleY);
            graphics.drawString(txt, font, rc, strFormat, brushTxt);
            
            font.delete();  brushTxt.delete(); strFormat.delete();
        }
    }
    
    // --- 按钮事件 ---
    winform.btnRestart.oncommand = function(id,event){
        initGame();
    }
    
    winform.show();
    initGame(); //运行程序后,直接开始游戏
    win.loopMessage();


    上传的附件:
返回