# 例程1:贪吃蛇游戏源码
gui = GUI("fine")
gui.HideConsoleWindow()
time = TIME()
math = MATH()
GAME_WIDTH = 640
GAME_HEIGHT = 480
# 初始化方向
global direction = "right" # 初始运动方向向右
global Snake
# 自定义类
class SNAKE(object) # object 不能省略,object表示是基类,可以继承
{
snake = []
food = []
def draw(self,gui) # draw方法是刷新界面,参数1是类对象本身,参数2是窗口ID
{
packageList = [] # 先创建一个空的指令包
# 首先刷新游戏背景
drawlist = ["CanvasPutImage","background",0,0] # 重画背景指令
packageList.append(drawlist) # 把指令打包
# 刷新食物
listfood = self.food # 获取食物属性。listfood[0],listfood[1]是食物位置,listfood[2]是食物图片昵称
drawlist = ["PutImage",listfood[2],listfood[0],listfood[1],32,32]
packageList.append(drawlist)
# 刷新蛇
listsnake = self.snake # 获取设身体属性
for i in listsnake
{
# i[0]~i[1]是蛇的部件的位置,i[2]是蛇的部位昵称,i[3]是蛇的运动方向
drawlist = ["PutImage",i[2],i[0],i[1],16,16] # 循环获取蛇身的每一段位置
packageList.append(drawlist) # 打包
}
gui.DrawPackage(packageList) # 一次性发出多个绘画指令
}
}
# 移动蛇
def move_snake(Snake) # 参数是个全局变量,是蛇对象
{
delt_x = 0
delt_y = 0
snake_list = Snake.snake # 取出蛇身体是个双重列表:[[x0,y0,"Head","方向"],[x1,y1,"Body","方向"],……]
Snake_Head = snake_list[0] # 蛇头列表
head_x = Snake_Head[0] # 蛇头x位置
head_y = Snake_Head[1] # 蛇头y位置
if direction == "right"
{
delt_x = 16 # 一次移动8个像素
}
elif direction == "left"
{
delt_x = - 16
}
elif direction == "up"
{
delt_y = - 16
}
elif direction == "down"
{
delt_y = 16
}
# 边界检测
head_x = head_x + delt_x #
head_y = head_y + delt_y #
if head_x < 0 or head_x >= GAME_WIDTH or head_y < 0 or head_y >= GAME_HEIGHT
{
return False
}
# 将当前蛇头一节用蛇身节替换
Snake_Head.replace(2,"Body") # Snake_Head的第二项是皮肤,给蛇头换皮肤
snake_list.replace(0,Snake_Head) # 组合换装后的蛇,蛇头已经被蛇身替换
head = [head_x,head_y,"Head",direction] # 构造新的蛇头
snake_list.insert(0,head) # 给蛇增加一个蛇头(不论是否吃到食物,先增加一个节蛇身)
# 获取当前食物位置
food_list = Snake.food
food_x = food_list[0]
food_y = food_list[1]
# 判断是否吃到食物
if (head_x > food_x-20 and head_x < food_x+20) and (head_y > food_y-20 and head_y < food_y+20 )
{
# 如果吃到食物,蛇身维持新的状态,同时,重新随机放置食物
food_x = math.rand(32,GAME_WIDTH-32)-8
food_y = math.rand(32,GAME_HEIGHT-32)-8
food_list = [food_x,food_y,"Food"] # 参数1~2是位置,参数3食物
}
else # 没有吃到食物,恢复蛇身体,并前进一步
{
x = snake_list.pop() # 先抛弃掉最后一节
length = len(snake_list) # 计算当前蛇身长度
temp_list = snake_list[length-2] # 取出蛇身倒数第二节 temp_list = [xn-2,yn-2,"Body","方向"]
temp_list.replace(2,"Tail1") # 将倒数第二节的图形换掉 temp_list = [xn-2,yn-2,"Tail1","方向"]
temp_list = snake_list[length-1] # 取出蛇身倒数第二节 temp_list = [xn-1,yn-1,"Body","方向"]
temp_list.replace(2,"Tail0") # 将倒数第二节的图形换掉 temp_list = [xn-1,yn-1,"Tail0","方向"]
# 这样做始终保持尾部是小图形
}
# 由于类属性发生了变化,生成新的贪吃蛇类对象
Snake = SNAKE(snake_list,food_list) # 根据更新后的数据,生成新的贪吃蛇的类对象
return True
}
# 定义初始化函数
def init()
{
# 初始化,食物随机位置
food_x = math.rand(32,GAME_WIDTH-32)-4 # 食物坐标
food_y = math.rand(32,GAME_HEIGHT-32)-4 # 食物坐标
food_list = [food_x,food_y,"Food"] # 食物列表:参数1~2是位置,参数3食物图片名称
# 初始化蛇体,只有三节
snake_list0 = [3*16,5*16,"Head" ,"right"] # 参数1~2是位置,参数3是体态,惨数4是方向
snake_list1 = [2*16,5*16,"Tail1","right"]
snake_list2 = [1*16,5*16,"Tail0","right"]
snake_list = [snake_list0,snake_list1,snake_list2] # snake_list是双重列表,是蛇身体,包含三节。
# 生成初始化类对象
Snake = SNAKE(snake_list,food_list) # 生成贪吃蛇的类对象
}
# 创建游戏窗口
title = "贪吃蛇游戏" # 窗口标题
size = [10,3,82.3,38] # 窗口尺寸
# 四个方向控制按钮
button_up = ["上", "button", 13, 32, 10, 1]
button_down = ["下", "button", 28, 32, 10, 1]
button_left = ["左", "button", 43, 32, 10, 1]
button_right = ["右", "button", 58, 32, 10, 1]
list = [title,size,button_up,button_down,button_left,button_right] # 打包窗口元素
gui.Fine(list) # 创建Fine窗口,并返回资源ID
# 加载游戏资源
loadList = [] # 创建一个空的列表,用于打包绘图指令
drawlist = ["LoadImage","D:\\fine\\fin\\snake\\background.bmp","background"] # 加载背景图片
loadList.append(drawlist) # 添加到指令包
drawlist = ["LoadImage","D:\\fine\\fin\\snake\\food.bmp","Food"] # 加载食物图片
loadList.append(drawlist)
drawlist = ["LoadImage","D:\\fine\\fin\\snake\\snakeBody.bmp","Body"] # 加载身体图片
loadList.append(drawlist)
drawlist = ["LoadImage","D:\\fine\\fin\\snake\\snakeHead.bmp","Head"] # 加载头图片
loadList.append(drawlist)
drawlist = ["LoadImage","D:\\fine\\fin\\snake\\snakeTail1.bmp","Tail1"] # 加载尾部大图片
loadList.append(drawlist)
drawlist = ["LoadImage","D:\\fine\\fin\\snake\\snakeTail0.bmp","Tail0"] # 加载尾部小图片
loadList.append(drawlist)
gui.DrawPackage(loadList) # 一次性加载所有资源
buttonenable = 0 # 按钮enable
speed = 30 # 初始速度
init() # 初始化SNAKE
count = 0
while gui.FineClosed() != -1 # 检查窗口关闭消息
{
PowerDown(3)
if gui.FineReady() == 0 # 有按键按下
{
x = gui.FineRead()
button_action = x[0]
if button_action == "button-0" # 上
{
direction = "up"
}
elif button_action == "button-1" # 下
{
direction = "down"
}
elif button_action == "button-2" # 左
{
direction = "left"
}
elif button_action == "button-3" # 右
{
direction = "right"
}
buttonenable = 0 # 禁止按键,避免多次按键
}
count = count + 1 # 节能设置
if(count < speed) {continue}
count = 0
if not move_snake(Snake) # 按既定方向移动一位,如果越界game over,没有越界继续
{
box = GUI("box")
box.MessageBox("游戏结束!是否继续?","确定|取消")
while box.MessageBoxClosed() != -1 {PowerDown(3)}
select = box.MessageBoxRead()
if select != 0
{
gui.CloseFine() # 关闭窗口,退出程序
}
else # 如果按了确定键
{
init() # 初始化
count = 0
continue # 跳转到while循环起点
}
}
if len(Snake.snake) > 14 # 如果蛇身体长大到超过10节,认为可以通关了。
{
box = GUI("box")
box.MessageBox("恭喜你顺利通关!再来一局?","确定|取消")
while box.MessageBoxClosed() != -1 {PowerDown(3)}
x = box.MessageBoxRead()
if x == 0 # 如果选择继续玩,则逐渐提高速度
{
speed = speed - 2 # 速度逐渐变快
if speed < 26
{
speed = 26 # 限制最快速度
}
init() # 初始化
count = 0
continue # 重启游戏
}
else # 如果选择取消、或直接关闭MessageBox窗口,则退出程序
{
gui.CloseFine() # 关闭窗口,退出程序
}
}
Snake.draw(gui) # 自定义类方法,绘图
}