
//贪吃蛇小游戏
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();