draw脚本库
关于脚本库请参考文档:名字空间、脚本库
一、draw脚本库简介
draw脚本库基本功能是按预设的几何图形、渐开线轨迹遍历所有的坐标点。
移动到一个坐标点以后就会自动触发draw.move函数。
通过重写draw.move函数即可以使用draw类库实现很多常用的功能。
例如:绘图,扫描屏幕,在游戏中自动移动鼠标同时抓点搜怪(利用鼠标移动到怪物身上会导致颜色改变的原理)
二、创建draw脚本库
把下面的代码保存为draw.las文件,并且放到Fairy_Ape\import目录下。
也可以将draw.las放到模拟精灵主程序所在目录、或者需要使用draw脚本库的程序所在目录都可以。
-- 创建名字空间draw 添加参数_G以继承_G全局表中的所有对象
namespace("draw",_G )
--[[
************* 画线函数 **********
说明:
可以修改这个函数决定在画线的时候做什么事
参数:
x,y 当前坐标
返回值:
返回true 表示继续,返回false表示停止
**********************************
]]
move = function(x,y)
error("使用draw类库以前必须重写draw.move函数",2);
end;
--[[
************* 画直线 *************
参数:
x1,y1 起始坐标
x2,y2 结束坐标
返回值:
返回true 表示继续,返回false表示停止
**********************************
]]
line = function(x1,y1,x2,y2)
local step = 1;
local x,y = 1,1;
if(math.abs(x2-x1) > math.abs(y2-y1) ) then
if(x2<x1)then step = -1 end; --坐标如果是反过来的
for x=x1,x2,step do
y = (y2 - y1) / (x2 - x1) * (x - x1) + y1
-- 当前y坐标 = ( 高度 / 宽度 ) * (部份宽度) + 顶点
if(not move(x,y) ) then return false end;
end;
else
if(y2<y1)then step = -1 end; --坐标如果是反过来的
for y=y1,y2,step do
x = (x2 - x1) / (y2 - y1) * (y - y1) + x1
-- 当前y坐标 = ( 宽度 / 高度 ) * (部份宽度) + 顶点
if(not move(x,y) ) then return false end;
end;
end;
return true;
end;
--[[
************* 画矩形 **************
参数:
x1,y1 左上角坐标
x2,y2 右下角坐标
**********************************
]]
rect = function(x1,y1,x2,y2)
if not line(x1,y1,x2,y1) then return false end;
if not line(x2,y1,x2,y2) then return false end;
if not line(x2,y2,x1,y2) then return false end;
if not line(x1,y2,x1,y1) then return false end;
return true;
end;
--[[
************* 画正弦曲线 **************
参数:
x,y 宽高,参数可以忽略(默认为屏幕范围)
**********************************
]]
sin = function(x,y)
local w = win.getScreen();
local y = 1;
for x=1,w,1 do
y = 300 - math.sin(x/30) * 100;
if(not move(x,y) ) then return false end;
end;
return true;
end;
--[[
************* 画渐开线 **************
参数:
fx,fy 宽高,参数可以忽略(默认为屏幕范围)
**********************************
]]
involute = function(fx,fy)
if(not ( fx and fy) ) then
fx,fy = win.getScreen();
end;
local x0,n,y0 = fx/2,1,fy/2;
while( n<88 ) do
x = x0+4*( math.cos(n)+n*math.sin(n) );
y = y0+3*( math.sin(n)-n*math.cos(n) );
if(not move(x,y) ) then return false end;
n = n+0.2;
end;
local x1,n,y1 = fx/2,88,fy/2;
while( n>1 ) do
x = x1+4*( math.cos(n)+n*math.sin(n) );
y = y1+3*( math.sin(n)-n*math.cos(n) );
if(not move(x,y) ) then return false end;
n = n-0.2
end;
return true;
end;
--[[
************* 画渐开线2 **************
参数:
x,y 基圆圆心
R 基圆半径
n 渐开线周波数
**********************************
]]
involute2 = function(x,y,R,n)
for a=0,2 * 360 * n,2 do
x = x + R * (math.cos(a * math.pi / 360) + (a * math.pi / 360) * math.sin(a * math.pi / 360));
y = y + R * (math.sin(a * math.pi / 360) - (a * math.pi / 360) * math.cos(a * math.pi / 360));
if(not move(x,y) ) then return false end;
end;
return true;
end;
--[[
************* 画方形仿渐开线 **************
参数:
step 步长
n 起始正方形边长,指定中间忽略不扫描的正方形边长(默认等于20)
x1,y1 扫描范围坐标,参数可省略(默认等于 1 X 1)
x2,y2 扫描范围坐标2,参数可省略(默认等于屏幕大小)
**********************************
]]
rect_inv = function(step,n,x1,y1,x2,y2)
step = step or 1;
step = math.abs(step);
step = 0 - math.abs(step);
n = n or 20;
x1 = x1 or 1;
y1 = y1 or 1;
if(not ( x2 and y2) ) then
x2,y2 = win.getScreen();
end;
local fx,fy = 1,1;
if(x1<x2)then
fx = x1;x1=x2;x2=fx;
end;
if(y1<y2)then
fx = y1;y1=y2;y2=fx;
end;
fx = x1; fy = y1;
x1 = fx/2;y1= fy/2;
print(x1,y1,x2,y2,fx,fy);
local x,y = 1,1;
for x=x1-n/2,x2,step do
y = (y2 - y1) / (x2 - x1) * (x - x1) + y1;
if not rect( x,y,x1+(x1-x),y1+(y1-y) ) then return false end;
end;
return true;
end;
--[[
************* 画方形仿渐开线2 **********
参数:
x,y 坐标
m 扫描范围
n 扫描速度,可省略(默认等于5)
k 扫描密度,可省略(默认等于50)
示例:
rect_inv2(322,384,300);
**********************************
]]
function rect_inv2(x,y,m,n,k)
n = n or 5; --控制扫描速度
k = k or 50; --控制扫描密度
local l = 0; --控制扫描范围
local tx = {};
local ty={};
for i=1,5,1 do
table.insert(tx,x );
table.insert(ty,y )
end;
while( --[[nStop()and]] l<m ) do --让脚本在一定范围内扫描
tx[1] = tx[1]-k; tx[2] = tx[2]+k;
tx[3] = tx[3]+k; tx[4] = tx[4]-k;
ty[1] = ty[1]-k; ty[2] = ty[2]-k;
ty[3] = ty[3]+k; ty[4] = ty[4]+k;
for i=tx[1],tx[2],n do
if(not move(i ,ty[1]) ) then return false end;
end;
for i=ty[2],ty[3],n do
if(not move(tx[2] ,i) ) then return false end;
end;
for i=tx[3],tx[4],0-n do
if(not move(i ,ty[3]) ) then return false end;
mouse.move( i ,ty[3],true ); delay(10);
end;
for i=ty[4],ty[1],0-n do
if(not move(tx[4] ,i) ) then return false end;
end;
l = l+50
end;
end;
--[[
************* 画多边形 **************
参数
x,y 中心所在的屏幕坐标(像素)
r 多边形外接圆半径(像素)
n 多边形的边数
**********************************
]]
function poly(x,y,r,n)
local i;
local theta=math.pi;
local x1=x;
local y1=y-r;
local x2,y2;
for i=1,n,1 do
theta=theta - (2*math.pi/n);
x2=x+r*math.sin(theta);
y2=y+r*math.cos(theta);
if not line(x1,y1,x2,y2) then return false end;
x1=x2;
y1=y2;
end;
end;
--[[
************* 画椭圆 **************
x,y 中心所在的屏幕坐标(像素)
a,b 长轴和短轴的长度(像素)
precision 边缘精细度
**********************************
]]
function ellipse(x,y,a,b,precision)
local i;
local iMax=2*math.pi;
local step=2*math.pi/(precision*math.sqrt(a*b)*4.5);
for i=1,iMax,step do
if(not move(x+a*math.cos(i),y+b*math.sin(i)) ) then return false end;
end;
end;
三、使用draw脚本库
使用 import("draw"); 运行draw.las并导入draw脚本库。
然后需要重写draw.move函数。以确定移动每个坐标点以后执行什么代码。
draw.move返回true表示继续画线,返回false表示停止。
我们可以使用win.doEvents();或者nStop();自动取得返回值,
这两个函数在用户按了全部停止热键(默认为Ctrl+Alt+L)以后都会返回false。
因为draw类库的扫描移动是一个循环过程,
如果在draw.move中没有使用win.doEvents();或者nStop();取得返回值。
那么用户无法中断draw类库的扫描。
import("draw"); --导入draw类库
--根据自已的需要重写move 函数,要找怪或者抓点都可以写在这个函数里面就行了
-- 注意返回true表示继续画线,返回false表示停止
draw.move = function(x,y)
mouse.move(x,y,true);--鼠标移动到当前坐标点
color("#FF0000"):toPos(x,y);--在屏幕上画一个点
return nStop(); --这个比较通用
end;
--画直线
draw.line(23,100,23,300);
--画矩形
draw.rect(23,32,200,100);
-- 画正弦曲线
draw.sin()
-- 画渐开线
draw.involute();
-- 画方形仿渐开线,步进为5,中间忽略的正方形边长为50
draw.rect_inv(5,50);
--这是真正的渐开线,第三个参数指定基圆的半径
draw.involute2(1024/2,768/2,0.1,10);