【Ruby】用ruby在3D软件Sketchup中开发贪吃蛇小游戏

sketchup是非常简单易用的三维建模软件,可以利用ruby 做二次开发,

今天在su中做了一款小游戏 贪吃蛇,说一下步骤

 

 

展示

 

 

主要思路:

 

我制作的的玩法是这样的


 

关于入口文件


 

复制代码
# ----------------------------- #
#  email:bc8web@126.com        #
# ------------------------------#
# 入口文件
require 'json' 
require_relative 'help.rb'  # 帮助文件
module NaiveSnake
    $game = nil  # 用于保存蛇类实例变量
    class Index
        @@dig = nil
        @@setDig = nil
        @@lydig = nil
        def initialize
            cmd = UI::Command.new("NaiveSnake") {
                # 主窗口
                @@dig = UI::WebDialog.new "NaiveSnake", false, "", 229, 172, 5, 90, false 
                @@dig.set_file __dir__+'/index.html'
                # 设置窗口
                @@setDig = UI::WebDialog.new "NaiveSnake_set", false, "", 262, 315, 235, 90, false 
                @@setDig.set_file __dir__+'/set.html'
                # 排行窗口
                @@lydig = UI::WebDialog.new "NaiveSnake_琅琊榜", false, "", 290, 320, 5, 260, false
                @@lydig.set_url 'http://00a00.com/snake/'
                
                @@dig.show if not @@dig.visible?
                @@dig.add_action_callback 'start' do
                    # 检测是否有模型
                    if Sketchup.active_model.active_entities.length > 0
                        is = UI.messagebox("检测到有模型存在,是否清空?\r\n(注:清空才可进入游戏)",MB_YESNO)
                        if is == 6
                            Sketchup.active_model.active_entities.clear!
                            load __dir__+'/Base.rb'
                            
                            require_relative 'Camera.rb'         
                            require_relative 'Map.rb'            
                            load __dir__+'/Food.rb'             
                            load __dir__+'/Snake.rb'             
                            load __dir__+'/SnakeTool.rb'      

                            Camera.new        # 初始化相机  
                            Map.new.show      # 显示场景
                            Food.new.show     # 显示食物
                            $game = Snake.new # 蛇实例
                            $game.start       # 开始游戏

                            Sketchup.active_model.select_tool SnakeTool.new # 选择工具
                            @@dig.close if @@dig.visible? # 关闭窗口
                            @@setDig.close if @@dig.visible? # 关闭窗口
                            @@lydig.close if @@dig.visible? # 关闭窗口
                        else
                            next
                        end
                    end
                end
                # ready
                @@dig.add_action_callback 'ready' do
                    # 生成随机名字
                    len = 8
                    chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
                    newpass = ""
                    1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
                    config 'nickname', newpass
                end

                # 设置按钮
                @@dig.add_action_callback 'set' do
                    @@setDig.show
                end

                # 琅琊榜
                @@dig.add_action_callback 'langYa' do
                    @@lydig.show
                end
                
                # 确认按钮
                @@setDig.add_action_callback('ok'){|dig, json|
                    hash = JSON.parse json
                    hash.each{|k, v| config k, v }
                    dig.close
                }
                # 默认按钮
                @@setDig.add_action_callback('rec'){|dig, json|
                    json = configRec()
                    @@setDig.execute_script "fill(#{json})"
                }
                # 页面刷新
                @@setDig.add_action_callback('init'){|dig, json|
                    json = configAll()
                    @@setDig.execute_script "data = #{json}"
                }

                
            }
            # 工具栏
            cmd.small_icon = cmd.large_icon = __dir__+"/assets/icon.png"
            cmd.menu_text = "NaiveSnake"

            toolbar = UI::Toolbar.new "NaiveSnake"
            toolbar = toolbar.add_item cmd
            toolbar.show

            # 菜单
            menu = UI.menu('Plugins').add_submenu('NaiveSnake(贪吃蛇)')
            menu.add_item
        end
    end
end
NaiveSnake::Index.new
复制代码

初始化基类

复制代码
# ----------------------------- #
#  email:bc8web@126.com        #
# ------------------------------#
# 基类
module NaiveSnake
    class Base
        @@model = Sketchup.active_model   # 模型
        @@view  = @@model.active_view     #
        @@ent   = @@model.active_entities # 实体
        @@mat   = @@model.materials       # 材质
        
        @@mapWidth     = config('mapWidth').to_i    # 地图宽
        @@mapHeight    = config('mapHeight').to_i   # 地图高
        @@snakeHeight  = config('snakeHeight').to_i # 蛇高度
        @@snakeWidth   = config('snakeWidth').to_i     # 蛇宽度
        @@snakeNums    = config('snakeNums').to_i      # 蛇身数
        @@level        = config('级别')             # 级别
        @@direction    = UP     # 初始方向
        @@currentSnake = []     # 当前蛇body
        @@snakeArr     = []     # 出生蛇body
        @@foot         = []     # 储存食物
        @@blackList    = []     # 食物黑名单
        @@time_id      = nil    # 定时器
        @@score        = 0      # 分数
    end
end
复制代码

 

初始化相机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# ----------------------------- #
#  email:bc8web@126.com        #
# ------------------------------#
# 相机类
module NaiveSnake
    class Camera < Base
        def initialize
            start
        end
        def start
            eye = [0, 0,1300]; target = [0,0,0]; up = [0,1,0]
            start_camera = Sketchup::Camera.new eye, target, up
            @@view.camera = start_camera
        end
    end
end

 初始化场景

复制代码
# ----------------------------- #
#  email:bc8web@126.com        #
# ------------------------------#
# 场景类
module NaiveSnake
    class Map < Base
        def show
            grassland # 草地
        end
        def grassland
            filename = __dir__+'/assets/grassland.skm'
            material = @@mat.load(filename)

            pt1 = Geom::Point3d.new -@@mapWidth/2, -@@mapHeight/2, 0
            pt2 = Geom::Point3d.new @@mapWidth/2, -@@mapHeight/2, 0
            pt3 = Geom::Point3d.new @@mapWidth/2, @@mapHeight/2, 0
            pt4 = Geom::Point3d.new -@@mapWidth/2, @@mapHeight/2, 0
            grp = @@ent.add_group
            grp.entities.add_face pt1, pt2, pt3, pt4
            grp.material = material
        end
    end
end
复制代码

 

初始化蛇类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# ----------------------------- #
#  email:bc8web@126.com        #
# ------------------------------#
# 蛇类
module NaiveSnake
    class Snake < Base
        def initialize
            @@snakeArr = initSnake @@snakeNums
            @up = 38; @down = 40; @left = 37; @right = 39
            @direction = @@direction
            @x = rand(-@@mapWidth..@@mapWidth)/2/10*10
            @y = rand(-@@mapHeight..@@mapHeight)/2/10*10
        end
        def start
            createSnake # 绘制蛇
            speed = 0.5
            case @@level
                when '普通'; speed = 0.4
                when '勇士'; speed = 0.1
                when '地狱'; speed = 0.03
                when '噩梦'; speed = 0.006
            end
            time = 1
            @@time_id = UI.start_timer(speed, true) do
                move(@direction)
                time += 1
            end
        end
        def set(direction)
            @direction = direction
        end
        # 绘制蛇
        def createSnake
            @@currentSnake.clear # 清空蛇当前状态
            @@snakeArr.each do |box|
                xBaseValue = @@snakeWidth/2
                yBaseValue = @@snakeWidth/2
                point1 = Geom::Point3d.new(box[0]-xBaseValue, box[1]-yBaseValue, 0)
                point2 = Geom::Point3d.new(box[0]+xBaseValue, box[1]-yBaseValue, 0)
                point3 = Geom::Point3d.new(box[0]+xBaseValue, box[1]+yBaseValue, 0)
                point4 = Geom::Point3d.new(box[0]-xBaseValue, box[1]+yBaseValue, 0)
                boxGroup = @@ent.add_group
                face = boxGroup.entities.add_face point1, point2, point3, point4
                face.reverse!.pushpull @@snakeHeight
                @@currentSnake.push boxGroup # 重新设置蛇身体
            end
        end
        # 移动
        def move(direction)
            tmpArray = [] # 临时容器
            head = @@snakeArr.last # 蛇头
            # 判断蛇头是否碰到黑名单
            @@blackList.each{|list|
                if head == list # Game Over
                    gameOver
                    return
                end
            }
            #判断蛇头是否碰到边缘
            if head[0].abs >= @@mapWidth/2 || head[1].abs >= @@mapHeight/2
                gameOver
                return
            end
            # 判断蛇头是否碰到食物
            if head == @@foot
                # 加分
                @@score += 10
                # 将食物列入黑名单
                @@blackList.push @@foot
                # 蛇头随机移动
                @x = rand(-(@@mapWidth-50)..@@mapWidth-50)/2/10*10
                @y = rand(-@@mapHeight..@@mapHeight)/2/10*10
                @@snakeArr.push [@x+@@snakeWidth/2, @y+@@snakeHeight/2]
                # 再次显示食物
                Food.new.show
            end
            # 移动数组前一位
            lastValue = @@snakeArr.last.clone;
            for i in 0...@@snakeArr.size-1
                tmpArray[i] = @@snakeArr[i+1]
            end
            tmpArray.push(lastValue)
            case direction
                when @up;    tmpArray.last[1] += @@snakeWidth
                when @down;  tmpArray.last[1] -= @@snakeWidth
                when @right; tmpArray.last[0] += @@snakeWidth
                when @left;  tmpArray.last[0] -= @@snakeWidth
            end
            @@snakeArr = tmpArray # 重新设置蛇body
 
            deleteSnake # 删除
            createSnake # 再次绘制
        end
 
        def deleteSnake
            @@currentSnake.each do |ent|
                ent.entities.each{|ent| @@ent.erase_entities ent}
            end # 删除原来
        end
        def gameOver
            UI.stop_timer @@time_id
            UI.messagebox "游戏结束!\r\n得分:"+@@score.to_s
            updateScore # 更新分数
        end
        def updateScore
            hash = {
                :nickname => config('nickname'),
                :score    => @@score,
                :level    => config('级别'),
                :tk       => 'qwertyuioplkjhgfdsazxcvbnm',      
            }
            request = Sketchup::Http::Request.new("http://00a00.com/snake/save.php", Sketchup::Http::POST)
            request.body= httpBuild(hash)
            request.start do |request, response|
                p '琅琊榜更新成功' if response
            end
        end
        def httpBuild(hash)
            str = ''
            hash.each{|k, v|
                str+= k.to_s+'='+v.to_s+'&'
            }
            str.chop!
        end
        def initSnake(n)
            array = []
            n.times{|i|
                array.push [@@snakeWidth/2+@@snakeWidth*i, @@snakeWidth/2]
                next if i == 0
            }
            array
        end
    end
end

 

初始化食物类

复制代码
# ----------------------------- #
#  email:bc8web@126.com        #
# ------------------------------#
# 食物类
module NaiveSnake
    class Food < Base
        def initialize
            @x = rand(-@@mapWidth..@@mapWidth)/2/10*10
            @y = rand(-@@mapHeight..@@mapHeight)/2/10*10
        end
        def show
            filename = __dir__+'/assets/food.skm'
            material = @@mat.load(filename)

            point = []
            unless isFull?
                point[0] = [@x, @y, 0]
                point[1] = [@x+@@snakeWidth, @y, 0]
                point[2] = [@x+@@snakeWidth, @y+@@snakeWidth, 0]
                point[3] = [@x, @y+@@snakeWidth, 0]

                group = @@ent.add_group

                @@foot = [@x+@@snakeWidth/2, @y+@@snakeHeight/2]
                face = group.entities.add_face point
                face.material = material
                face.reverse!.pushpull @@snakeHeight
                @foot = face
            else
                @x = rand(-@@mapWidth..@@mapWidth)
                @y = rand(-@@mapHeight..@@mapHeight)
            end
        end
        def isFull?
            return @@snakeArr.include? [@x, @y] 
        end
    end
end
复制代码
posted @   白超华  阅读(1674)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示