| 赞 | 3 |
| VIP | |
| 好人卡 | |
| 积分 | 10 |
| 经验 | |
| 最后登录 | 2026-7-17 |
| 在线时间 | 1391 小时 |
寒
- 梦石
- 0
- 星屑
- 1049
- 在线时间
- 1391 小时
- 注册时间
- 2010-8-9
- 回帖
- 3301
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有账号?注册会员
×
本帖最后由 寒冷魔王 于 2015-8-21 13:30 编辑
经过一个多月的书写、测试,SMRC V5终于可以发布。
SMRC是处理SRPG地图移动范围生成的代码,是SRPG地图的核心代码。使用纯Ruby构建。
V5版本是V4的进化版本。经过重构,性能、功能和质量全面提升。
高性能、精简
经过V4的性能提升后,V4相对V3提升了100倍,而V5又在此基础上提升3-4倍。同时,V5遵循着最小代码的准则,其核心代码只有几十行。
功能升级、使用方便
V5的Map类传入一个一维数组,而不是以往的只能通过直接构造;
Route类传入移动力消耗地图,因此V5的具有很大的灵活性,使用者可以方便的修改以达到使用目的。
V5原生支持阻碍(移动力-1)和ZOC(只能放置不能通过),如下的测试代码中显示了这一点。
稳定、能够满足基本需要
自第一版于2014年10月构建以来,SMRC经历了许多次变革,性能和质量不断提升。无数次的测试,SMRC质量有着可靠的保证。
SMRC在V4版本就已经能够满足基本需要。500*500的地图,空地图(最坏情况),移动力100时,在RMVA下的运行结果V4需要0.25s,而V5仅需0.08s。
而同时附加的两种新形态,使得SMRC能够普遍地满足大多数人的需要。SMRC的时代即将来临。
兼容RGSS1-3
由于是Ruby书写的代码,故其具有很强的兼容性。
目前已在XP、VX、VA下测试通过。测试如图【RGSS1-3三版速度比较(移动力100)】。
由于Ruby1.8与1.9的区别,所以部分Ruby方法无法调用,但本代码本身是兼容的。
定制自由
本代码不仅仅适用于默认的4方向,还可以通过定制轻松实现6方向、8方向。
可以自由变更所想要的形状,只需变更79-82行judgeSet即可。默认形状见3L,变更形状见9L。
P.S.关于具体的原理如果大家有兴趣日后本人会写出来。
下面贴代码:
[fold=SMRC主体 (基本代码)][pre lang="ruby"]#==============================================================================
# SMRC.rb
# Author : Chill
# Version : 5.1.7.0 BETA
# Date(V5) : 2015-06-20 to 2015-07-30
# Description: SRPG on Map of Ruby by Chill.
#==============================================================================
#=================================================
# Basic Method
#=================================================
module SRPG
#----------------------------------------------------------------------------
# Class Map
#----------------------------------------------------------------------------
class Map
# Reader
attr_reader :x, :y
# Initialize
def initialize(x, y, data = nil)
@x, @y = x, y
# There is Setting Reference.
@data = data.is_a?(Array) ? data : Array.new(x*y,data)
end
# Data Method
# Unsafe
def get(x, y)
@data[y*@x+x]
end
def set(x, y, inc)
@data[y*@x+x] = inc
end
# Check
def out?(x, y)
x>=@x || y>=@y || x<0 || y<0
end
end
#----------------------------------------------------------------------------
# Class Route
#----------------------------------------------------------------------------
class Route
# Const Variable
MaxMoves = 500
# Data Struct
Route_Way = Struct.new(:x, :y, :way)
Route_Data = Struct.new(:x, :y, :move)
# Reader
attr_reader :movmap, :waymap
# Initialize
def initialize(map, x, y)
# Set Reference of Map, To Clone this Map, Using 'clone' Method.
@map = map
# Set Position to save time, Each Actor with a single Instance.
putError("Error: Position(#{x},#{y}) was Out.") if (@map.out?(x,y))
@position = [x, y]
# Set Route Map.
@movmap = Map.new(map.x,map.y,MaxMoves + 1)
@waymap = Map.new(map.x,map.y)
end
# Search
def search(moves)
# Record Moves
@moves = (moves < MaxMoves) ? moves : MaxMoves
putError("We Don't Have a Right Value of Moves.") if (@moves < 0)
# Create Arrays
@record = Array.new
# Set Data
x, y = *@position
setData(x,y,x,y,0,0)
# Start Search
@record.each do |route|
x, y = route.x, route.y
move = route.move + @map.get(x,y) # Current Point
next if (move > @moves)
# judgeSet
judgeSet(x, y-1, x, y, move, 1) # Up
judgeSet(x, y+1, x, y, move, 2) # Down
judgeSet(x-1, y, x, y, move, 3) # Left
judgeSet(x+1, y, x, y, move, 4) # Right
end
end
private
# Private Method
def judgeSet(x, y, rx, ry, move, dir)
return if (@map.out?(x,y) || move >= @movmap.get(x,y) || @map.get(x,y).zero?)
setData(x,y,rx,ry,move,dir)
end
def setData(x, y, rx, ry, move, way)
@movmap.set(x,y,move)
@waymap.set(x,y,Route_Way.new(rx,ry,way))
@record.push(Route_Data.new(x,y,move))
end
end
end
[/pre][/fold]
[fold=功能代码][pre lang="ruby"]#=================================================
# Function Method
#=================================================
class SRPG::Map
include Enumerable
# Const Variable
MaxShowSize = 20
# Data Method
# Safe
def [](x, y)
judgeOut(x,y) ? nil : get(x,y)
end
def []=(x, y, inc)
judgeError(x,y); set(x,y,inc)
end
# Create & Copy
def clone
SRPG::Map.new(@x,@y,@data.clone)
end
def new
SRPG::Map.new(@x,@y,@data.collect{|a|yield(a)})
end
# Enumerable Basic
def each
@data.each { |a| yield(a) }; self
end
def each_index
@y.times { |y| @x.times { |x| yield(x,y) } }; self
end
private
# Judge Method
def judgeOut(x, y)
out?(x,y)
end
def judgeError(x, y)
putError("Error: Point in Map (#{x},#{y}) is Out.") if judgeOut(x,y)
end
end
class SRPG::Route
# Data Method
def getPath(x, y)
return if @waymap[x,y].nil?
way = @waymap.get(x,y)
x, y, w = way.x, way.y, way.way
ways = Array.new
until w.zero?
ways.push(w)
way = @waymap.get(x,y)
x, y, w = way.x, way.y, way.way
end
return ways.reverse
end
def getPoints
return @points if defined?(@points)
@points = Array.new
@movmap.each_index do |x,y|
e = @movmap.get(x,y)
@points.push([x,y]) if e >= 0 && e <= MaxMoves
end
return @points
end
def points_each
if defined?(@points)
@points.each { |p| yield(*p) }
return self
end
@movmap.each_index do |x,y|
e = @movmap.get(x,y)
yield(x,y) if e <= MaxMoves && e >= 0
end
return self
end
end
# Using in TEST
module SRPG
class Map
# Print
def printt
mX, mY = [@x,MaxShowSize].min, [@y,MaxShowSize].min
mY.times { |y| mX.times { |x| yield(x,y) }; print("\n") }
end
def prints
printt { |x,y| print(self.get(x,y),' ') }
end
end
class Route::Route_Way
def to_s
"[#{x}, #{y}],#{way}"
end
end
def self.prints(map) # Using in prints for passmap, movmap & waymap
map.printt do |x,y|
tmp = map.get(x,y)
if (tmp.nil?) # waymap
print('[X, X],- ')
else
print(((tmp == Route::MaxMoves + 1) ? 'x' : tmp),' ')
end
end
end
end[/pre][/fold]
[fold=测试代码][pre lang="ruby"]#=================================================
# Testing Code
#=================================================
module Chill
# Method
def max(a,b); return (a>b) ? a : b; end
def min(a,b); return (a<b) ? a : b; end
def putError(msg); puts(msg); exit; end
# Self Method
def self.test
t = Time.new
yield
Time.new - t
end
end
module SRPG
#---------------------------------
# Set
# Set Data for Test.
#---------------------------------
# Only Using in the Convert.
M = Route::MaxMoves + 1
MapData = [
[ 1, true ], # 0: Bland
[ 1, true ], # 1: Self
[ 1, false ], # 2: Party
[ 0, false ], # 3: Enemy
[ 0, false ], # 4: Barrier
[ 2, true ], # 5: Hinder
[ M, true ], # 6: ZOC
[ 0, false ] # 7: Other
]
#---------------------------------
# Test 1
# Test class Map & class Route.
#---------------------------------
puts("\nTest 1:")
# Pass One Dimensional Array.
# Set Data.
data = [
[0,0,0],
[0,5,0],
[0,0,1],
].flatten
map = Map.new(3,3,data)
puts('realmap:')
map.prints
# Convert Map to Pass Map.
map = map.new { |e| MapData[e][0] }
# Or:
# data.collect! { |e| MapData[e][0] }
# map = Map.new(3,3,data)
route = Route.new(map,2,2)
route.search(3)
# Print the Pass Map
puts('passmap:')
prints(map)
# Print the Move Map
puts('movmap:')
prints(route.movmap)
# Print the Way Map
puts('waymap:')
prints(route.waymap)
#---------------------------------
# Test 2
# Test Correct Move.
#---------------------------------
puts("\nTest 2:")
data = [
[0,0,5],
[4,0,5],
[4,1,0],
].flatten.collect { |e| MapData[e][0] }
map = Map.new(3,3,data)
route = Route.new(map,1,2)
route.search(6)
path = route.getPath(0,0)
# Print
puts('passmap:')
prints(map)
puts('movmap:')
prints(route.movmap)
puts('waymap:')
prints(route.waymap)
print(path,"\n")
#---------------------------------
# Test 3
# Test Correct Move 2.
#---------------------------------
puts("\nTest 3:")
data = [
[0,0,0],
[0,4,5],
[0,0,1],
].flatten.collect { |e| MapData[e][0] }
map = Map.new(3,3,data)
route = Route.new(map,2,2)
route.search(5)
# Print
puts('passmap:')
prints(map)
puts('movmap:')
prints(route.movmap)
puts('waymap:')
prints(route.waymap)
#---------------------------------
# Test 4
# Test Correct Move 3. ZOC.
#---------------------------------
puts("\nTest 4:")
data = [
[0,6,0,0],
[6,3,6,0],
[0,6,1,0],
].flatten.collect { |e| MapData[e][0] }
map = Map.new(4,3,data)
route = Route.new(map,2,2)
route.search(6)
# Print
puts('passmap:')
prints(map)
puts('movmap:')
prints(route.movmap)
puts('waymap:')
prints(route.waymap)
#---------------------------------
# Test 5
# Test Speed.
#---------------------------------
puts("\nTest 5:")
x, y = 500, 500
route = Route.new(Map.new(x,y,1),*[250,250])
puts Chill.test { route.search(100) }
puts route.getPoints.size
end
[/pre][/fold]
[fold=运行结果:]
[/fold]
【2015.08.03补充】
[fold=RGSS1-3三版速度比较(移动力100)]
[/fold]
历史版本:
V4: https://rpg.blue/thread-378114-1-1.html
V3: https://rpg.blue/thread-375993-1-1.html
V2: https://rpg.blue/thread-374090-1-1.html
{:2_255:} 顺便庆祝GCC 5.1的发布
【2015.7.30补充】
关于在XP和VX的控制台问题,刚刚在VX测试的时候将它顺便解决了,如下:
[pre lang="ruby"]Win32API.new('kernel32', 'AllocConsole', 'v', 'v').call
$stdout = open('CONOUT$', 'w')
$stdin = open('CONIN$')
def print(*args)
$stdout.print(*args)
$stdout.flush
return
end
def puts(*args)
$stdout.puts(*args)
$stdout.flush
return
end
def p(*args)
puts args.map{|x| x.inspect}
return args
end
def gets(*args)
$stdin.gets(*args)
end
def printf(*args)
$stdout.printf(*args)
$stdout.flush
return
end
[/pre]
|
|