以前的一个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]
}
}