以前的一个a*练习,搬过来凑个数……
A*算法描述见这篇博文
ruby代码:
#encoding=utf-8 MAP = [ [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 1, 0, 1, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], ] class Point attr_accessor :x attr_accessor :y attr_accessor :g attr_accessor :h attr_accessor :f attr_accessor :parent def initialize(x, y, parent) self.x = x self.y = y self.parent = parent end def to_s "#{super.to_s}, #{[self.x, self.y, self.g, self.h, self.f]}" end end $open = {} $close = {} def find(sx, sy, ex, ey) startP = Point.new(sx, sy, nil) startP.g = 0 pos = startP while (!$open[[ex, ey]]) do dealAround(pos, ex, ey) # 检查周围元素,计算f pos = getMinFPos end pos = $open[[ex, ey]] path = [] while (pos.parent) do path << [pos.x, pos.y] pos = pos.parent end path << [pos.x, pos.y] for y in 0...MAP.size for x in 0...MAP[0].size print (path.include?([x, y])) ? "☆" : (MAP[y][x] == 0 ? "□" : "■") end print "\r\n" end p path end def getMinFPos return nil if $open.size < 1 minG = $open.values[0].g minGPos = $open.values[0] $open.values.each{|pos| if minG > pos.g minG = pos.g minGPos = pos end } return minGPos end def dealAround(pos, endx, endy) # 将pos加入close列表 $close[[pos.x, pos.y]] = pos # 将pos从open列表中移出 $open.delete([pos.x, pos.y]) # 检查周围元素 [[-1, -1], [0, -1], [1, -1], [-1, 0], [1, 0], [-1, 1], [0, 1], [1, 1]].each{|posOffset| # 跳过边界 next if pos.x + posOffset[0] < 0 or pos.y + posOffset[1] < 0 or pos.x + posOffset[0] > MAP[0].size - 1 or pos.y + posOffset[1] > MAP.size - 1 # 跳过不可通行的方块 next if MAP[pos.y + posOffset[1]][pos.x + posOffset[0]] != 0 # 跳过close列表 next if $close[[pos.x + posOffset[0], pos.y + posOffset[1]]] newPos = Point.new(pos.x + posOffset[0], pos.y + posOffset[1], pos) # 计算g if posOffset[0].abs + posOffset[1].abs == 2 # 斜向 newPos.g = pos.g + 14 else newPos.g = pos.g + 10 end # 计算h newPos.h = (endx - newPos.x).abs * 10 + (endy - newPos.y).abs * 10 # 计算f newPos.f = newPos.g + newPos.h # 添加到open列表 if $open[[newPos.x, newPos.y]] # 已存在 thePos = $open[[newPos.x, newPos.y]] tempG = ((thePos.x - pos.x).abs + (thePos.y - pos.y).abs == 2) ? (pos.g + 14) : (pos.g + 10) if tempG < thePos.g # 当前节点使g更小 thePos.g = tempG thePos.f = tempG + thePos.h thePos.parent = pos # 修改父节点为当前节点 end else # 不存在 $open[[newPos.x, newPos.y]] = newPos end } end find(0, 0, 7, 7)
require 'sdl' require "rexml/document" include REXML SDL.init(SDL::INIT_VIDEO) row = 4 col = 4 filename = "citizen-1.png" image = SDL::Surface.load(filename) w, h = image.w, image.h if filename[/^(.*)?\.(png|jpg|bmp)?/i] p $1, $2 end picname = $1 ext = $2 doc = Document.new("<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">") doc << XMLDecl.new(1.0, "utf-8") root_node = doc.add_element("plist") root_node.attributes["version"] = "1.0" root_dict = root_node.add_element("dict") # frames frame_key = root_dict.add_element("key") frame_key.text = "frames" frame_dict = root_dict.add_element("dict") for i in 0...row for j in 0...col key = Element.new("key") key.text = "#{picname}_#{i * col + j}.#{ext}" dict = Element.new("dict") # dict ek = [] ev = [] ek[0] = Element.new("key") ek[0].text = "width" ev[0] = Element.new("integer") ev[0].text = (w / col).to_s ek[1] = Element.new("key") ek[1].text = "height" ev[1] = Element.new("integer") ev[1].text = (h / row).to_s ek[2] = Element.new("key") ek[2].text = "originalWidth" ev[2] = Element.new("integer") ev[2].text = (w / col).to_s ek[3] = Element.new("key") ek[3].text = "originalHeight" ev[3] = Element.new("integer") ev[3].text = (h / row).to_s ek[4] = Element.new("key") ek[4].text = "x" ev[4] = Element.new("integer") ev[4].text = (j * w / row).to_s ek[5] = Element.new("key") ek[5].text = "y" ev[5] = Element.new("integer") ev[5].text = (i * h / col).to_s ek[6] = Element.new("key") ek[6].text = "offsetX" ev[6] = Element.new("real") ev[6].text = "0" ek[7] = Element.new("key") ek[7].text = "offsetY" ev[7] = Element.new("real") ev[7].text = "0" for t in 0...ek.size dict.elements << ek[t] dict.elements << ev[t] end frame_dict.elements << key frame_dict.elements << dict # end dict end end # end frames # metadata metadata_key = root_dict.add_element("key") metadata_key.text = "metadata" metadatat_dict = root_dict.add_element("dict") ek = [] ev = [] ek[0] = Element.new("key") ek[0].text = "format" ev[0] = Element.new("integer") ev[0].text = "2" ek[1] = Element.new("key") ek[1].text = "textureFileName" ev[1] = Element.new("string") ev[1].text = filename ek[2] = Element.new("key") ek[2].text = "realTextureFileName" ev[2] = Element.new("string") ev[2].text = filename ek[3] = Element.new("key") ek[3].text = "size" ev[3] = Element.new("string") ev[3].text = "{#{w},#{h}}" for t in 0...ek.size metadatat_dict.elements << ek[t] metadatat_dict.elements << ev[t] end #end metadata # texture texture_key = root_dict.add_element("key") texture_key.text = "texture" texture_dict = root_dict.add_element("dict") ek = [] ev = [] ek[0] = Element.new("key") ek[0].text = "width" ev[0] = Element.new("integer") ev[0].text = "#{w}" ek[1] = Element.new("key") ek[1].text = "height" ev[1] = Element.new("integer") ev[1].text = "#{h}" for t in 0...ek.size texture_dict.elements << ek[t] texture_dict.elements << ev[t] end # end texture file = File.open("#{picname}.plist", "w") doc.write(file, 4, false, true) file.close p doc.xml_decl()
bug啥的慢慢修。
本身是Array所以直接Marshal.load就好了,期间使用zlib解压一次。读出来后回头可以做个在线查看默认脚本的东西……
require "zlib" def load_data(filename) File.open(filename, "rb") { |f| obj = Marshal.load(f) } end scripts = load_data("./scri.rxdata") File.open("script.txt", "wb") {|f| scripts.each{|spriteObj| spriteObj[3,0] = Zlib::Inflate.inflate(spriteObj[2]) p spriteObj[1] f.puts "#" + spriteObj[1] f.puts spriteObj[3] } }