【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
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步