Lua修复了瓷砖移动问题
我正在使用Lua重新创建Pacman夫人,最近才了解到一系列瓷砖用于碰撞和移动;我正试着重现这一点。这是瓷砖地图:Lua修复了瓷砖移动问题,lua,tile,ti-nspire,Lua,Tile,Ti Nspire,我正在使用Lua重新创建Pacman夫人,最近才了解到一系列瓷砖用于碰撞和移动;我正试着重现这一点。这是瓷砖地图: nodemap = { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1}, {1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1
nodemap = {
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1},
{1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1},
{1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1},
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1},
{1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1},
{1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1},
{1,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1},
{1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1},
{1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1},
{1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1},
{1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1},
{1,1,1,1,0,1,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,1,1,1,0,1,1,1,1},
{1,1,1,1,0,1,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,1,1,1,1},
{1,1,1,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,1,0,1,1,0,1,1,1,1},
{1,1,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,1,1,1},
{1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1},
{1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1},
{1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1},
{1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1},
{1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1},
{1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1},
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{1,1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1,1},
{1,1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1,1},
{1,1,0,1,1,1,1,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,1,1,1,1,0,1,1},
{1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1},
{1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1},
{1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
}
这创建了一个没有错误的迷宫,但我遇到的问题是Pacman在瓷砖之间平稳移动,不会从瓷砖跳到瓷砖,再跳到瓷砖。。。所以我有一个“平稳”移动Pacman的代码:
-- Make Pacmans position consist of a single decimal (because over time a number of 1.899999994 will occur and that's ugly)
mrspacman.x = math.floor(mrspacman.x*10)/10
mrspacman.y = math.floor(mrspacman.y*10)/10
--If an arrowkey was pressed (Think of this as "A new direction was queued")
if (mrspacman.nextDirection) then
-- If Pacman is in the center of a tile, then
if (mrspacman.x == math.floor(mrspacman.x)) and (mrspacman.y == math.floor(mrspacman.y)) then
-- If the tile in front of Pacman is empty, set direction to that
if (nodemap[mrspacman.y-math2.sin(mrspacman.dir)][mrspacman.x+math2.cos(mrspacman.dir)]~=1) then
mrspacman.dz = mrspacman.dir
-- Disable this queue
mrspacman.nextDirection = false
end
end
end
-- If Pacman is NOT in the center of a tile
if (mrspacman.x ~= math.floor(mrspacman.x)) or (mrspacman.y ~= math.floor(mrspacman.y)) then
-- Constantly move forwards
mrspacman.x = mrspacman.x + (math2.cos(mrspacman.dz)*mrspacman.speed)
mrspacman.y = mrspacman.y - (math2.sin(mrspacman.dz)*mrspacman.speed)
else
-- If the tile in front of Pacman is empty, move to that tile
if (nodemap[mrspacman.y-math2.sin(mrspacman.dz)][mrspacman.x+math2.cos(mrspacman.dz)] ~= 1) then
mrspacman.x = mrspacman.x + (math2.cos(mrspacman.dz)*mrspacman.speed)
mrspacman.y = mrspacman.y - (math2.sin(mrspacman.dz)*mrspacman.speed)
end
end
- mrspacman.dz=所面对的角度
- mrspacman.dir=记录的按键
- mrspacman.speed=.1(是允许平滑移动的小数点)
因此,问题相当广泛: 如何解决这个问题? 答案是:通过调试你的程序 这个问题非常模糊,视频中的测试用例非常大,而且没有重点。要了解正在发生的事情,您至少需要详细查看程序的一些步骤。也就是说,问题是如果墙左边的瓷砖是空的,斯帕克曼先生可以穿过墙。这暗示检查墙是否存在的代码可能有一些错误 问题中的代码不完整,因此错误可能来自外部。然而,在过去的一个小时里,我已经建立了一个基本框架来测试问题代码。(答案末尾列出) 在玩弄了代码之后,我现在相信整个pacman不仅没有一个三角函数,而且根本没有浮点数 问题是它们不适合精确计算。一些编译器和计算系统甚至会因为你那样做而诅咒你
在编辑之前,相关代码具有正弦和余弦表达式:
math.floor(math.sin(mrspacman.dir*pi/180))
我现在已经在我的计算机上对它进行了评估,实际上,对于dir
的值,即0、90、180、270
,它的评估结果是0、1、0、-1
。但这是在64位机器上。我不确定TI Nspire是否能产生同样的精度
在测试期间,我遇到了另一个浮点数问题:
mrspacman.x=math.floor(mrspacman.x*10)/10
将在十进制数字中引入错误:对于mrspacman.x
等于4.3
,它将求值为4.2
,导致pacwoman冻结。奇怪的是,当直接在提示符中求值时,它的行为是正确的。不管怎么说,该函数的使用在铺地之前增加了一些偏差:math.floor(mrspacman.x*10+0.5)/10
除此之外,还有一些轴方向的小问题,由于框架转储的所有调试信息,这些问题很快被检测到 就这些。代码是有效的(不过,我将不带更多参数离开这里)。如果代码在您的设备上仍然不起作用,您需要在其他地方查找问题 程序代码 我将变量保留为全局变量,因为它们可能在程序中,而这在单个文件脚本中可能并不重要。但一般来说,最好将任何变量
设置为局部变量,除非有很好的理由
nodemap = {--I've used small field for debugging
{1,1,1,1,1,1,1},
{1,0,0,0,0,0,1},
{1,0,1,0,1,1,1},
{1,0,0,0,1,1,1},
{1,1,1,1,1,1,1},
}
mrspacman={dz=0,dir=false,x=2,y=2,speed=0.1,nextDirection=false}
local dlog=function(...)--debug function
print(string.format(...))
end
math2 = {
cos = function(angle)
vectors = {1,0,-1,0}--this would be better of by being a local variable
return vectors[(angle/90)+1]
end,
sin = function(angle)
vectors = {0,1,0,-1}--this too
return vectors[(angle/90)+1]
end
}
local graphic_lines={}
for _,line in ipairs(nodemap) do
local l=table.concat(line):gsub("0"," ")
table.insert(graphic_lines,l)
end
local time_step=1
function draw()--quick and dirty output to terminal
print(string.format("\nStep %i",time_step))
time_step=time_step+1
local x,y = mrspacman.x,mrspacman.y
local px,py=math.floor(x+0.5),math.floor(y+0.5)
for index,line in ipairs(graphic_lines) do
if index~= py then
print(line)
else
print( line:sub(1,px-1) .. "@" .. line:sub(px+1))
end
end
print(string.format('Real position (x,y): (%f , %f)',x,y))
print(string.format('Current direction: %i',mrspacman.dz))
if mrspacman.nextDirection then
print(string.format("Trying to turn at %i",mrspacman.dir or "error"))
end
end
local inputs={--i've mixed up directions due to my renderer
w=90,
a=180,
s=270,
d=0,
}
local skips={['']=true,[' ']=true}
function input(macro_input)--read wasd from terminal
print('your move')
local key= (macro_input and macro_input()) or io.read();
if skips[key] then return end
local dir = inputs[key];
if not dir then print('wrong key') return end
mrspacman.dir = dir
mrspacman.nextDirection=true
end
function sim_step()
dlog('"Smoothing" (%f,%f) through (%f,%f) to (%f,%f)',mrspacman.x,mrspacman.y,mrspacman.x*10,mrspacman.y*10,math.floor(mrspacman.x*10)/10,math.floor(mrspacman.y*10)/10)
dlog('"Fixing smoothing" (%f,%f) through (%f,%f) to (%f,%f)',mrspacman.x,mrspacman.y,(mrspacman.x+0.05)*10,(mrspacman.y+0.05)*10,math.floor((mrspacman.x+0.05)*10)/10,math.floor((mrspacman.y+0.05)*10)/10)
mrspacman.x = math.floor(mrspacman.x*10+.5)/10--these lines are different
mrspacman.y = math.floor(mrspacman.y*10+.5)/10--
--If an arrowkey was pressed (Think of this as "A new direction was queued")
if (mrspacman.nextDirection) then
dlog("trying to turn")
-- If Pacman is in the center of a tile, then
if (mrspacman.x == math.floor(mrspacman.x)) and (mrspacman.y == math.floor(mrspacman.y)) then
dlog("Pacman is in the center of a tile")
-- If the tile in front of Pacman is empty, set direction to that
dlog("lookup dy: %f dx: %f",-math2.sin(mrspacman.dir),math2.cos(mrspacman.dir))
dlog("lookup y: %f x: %f",mrspacman.y-math2.sin(mrspacman.dir),mrspacman.x+math2.cos(mrspacman.dir))
dlog(nodemap[mrspacman.y-math2.sin(mrspacman.dir)][mrspacman.x+math2.cos(mrspacman.dir)]==1 and "Its a wall" or "")
if (nodemap[mrspacman.y-math2.sin(mrspacman.dir)][mrspacman.x+math2.cos(mrspacman.dir)]~=1) then
dlog("turning")
mrspacman.dz = mrspacman.dir
-- Disable this queue
mrspacman.nextDirection = false
else
dlog"not turning"
end
end
end
-- If Pacman is NOT in the center of a tile
if (mrspacman.x ~= math.floor(mrspacman.x)) or (mrspacman.y ~= math.floor(mrspacman.y)) then
dlog("Pacman is NOT in the center of a tile, moving with no collision check")
-- Constantly move forwards
dlog("deltaX, deltaY : %f, %f",(math2.cos(mrspacman.dz)*mrspacman.speed),-(math2.sin(mrspacman.dz)*mrspacman.speed))
dlog("before (%f, %f)",mrspacman.x,mrspacman.y)
mrspacman.x = mrspacman.x + (math2.cos(mrspacman.dz)*mrspacman.speed)
mrspacman.y = mrspacman.y - (math2.sin(mrspacman.dz)*mrspacman.speed)
dlog("after (%f, %f)",mrspacman.x,mrspacman.y)
else
dlog("moving with collision check")
-- If the tile in front of Pacman is empty, move to that tile
if (nodemap[mrspacman.y-math2.sin(mrspacman.dz)][mrspacman.x+math2.cos(mrspacman.dz)] ~= 1) then
dlog("can move")
mrspacman.x = mrspacman.x + (math2.cos(mrspacman.dz)*mrspacman.speed)
mrspacman.y = mrspacman.y - (math2.sin(mrspacman.dz)*mrspacman.speed)
else
dlog("hit wall")
end
end
end
local gen_macro = function(sequence)--function generating predefined set of keypresses
sequence=sequence or ""
local step=0
return function()
step=step+1
if (step>sequence:len()) then return end--return to manual control
return sequence:sub(step,step)
end
end
local simple_macro= function() return gen_macro("wasd") end--simple sample, "--will do nothing
local horizontal_bend = function()--will bring pacman to bottom left
local _x10=string.rep(" ",10);
local sequence=_x10:rep(2).."s".._x10:rep(2).."a".._x10:rep(2)
return gen_macro(sequence)
end
local angry_monkey=function(length)--gen random sequence of buttons
length=length or 0
local keys={"a","s","d","w"," "}
local seq = {}
for i=1,length do
table.insert(seq,keys[math.random(#keys)])
end
return gen_macro(table.concat(seq))
end
local macro
--macro=simple_macro()
--macro=horizontal_bend()
--macro = angry_monkey(100)
--dlog=function() end --uncomment this to disable debug
while true do
draw()
input(macro)
sim_step()
-- if time_step>10 then return end
end
你使用哪个游戏引擎来创建这个游戏?在学生软件中使用TI Nspire Lua脚本应用程序,我只是编辑了代码和帖子(看一看),这没有什么区别。你知道为什么这种情况还在发生吗?你检查过它现在查找哪些值了吗?您提供的代码肯定不完整,dz
值可能有错误。或者代码中可能会出现一些错误,但执行循环的总体程序可能会自动放弃该错误。请使用更多信息更新答案
nodemap = {--I've used small field for debugging
{1,1,1,1,1,1,1},
{1,0,0,0,0,0,1},
{1,0,1,0,1,1,1},
{1,0,0,0,1,1,1},
{1,1,1,1,1,1,1},
}
mrspacman={dz=0,dir=false,x=2,y=2,speed=0.1,nextDirection=false}
local dlog=function(...)--debug function
print(string.format(...))
end
math2 = {
cos = function(angle)
vectors = {1,0,-1,0}--this would be better of by being a local variable
return vectors[(angle/90)+1]
end,
sin = function(angle)
vectors = {0,1,0,-1}--this too
return vectors[(angle/90)+1]
end
}
local graphic_lines={}
for _,line in ipairs(nodemap) do
local l=table.concat(line):gsub("0"," ")
table.insert(graphic_lines,l)
end
local time_step=1
function draw()--quick and dirty output to terminal
print(string.format("\nStep %i",time_step))
time_step=time_step+1
local x,y = mrspacman.x,mrspacman.y
local px,py=math.floor(x+0.5),math.floor(y+0.5)
for index,line in ipairs(graphic_lines) do
if index~= py then
print(line)
else
print( line:sub(1,px-1) .. "@" .. line:sub(px+1))
end
end
print(string.format('Real position (x,y): (%f , %f)',x,y))
print(string.format('Current direction: %i',mrspacman.dz))
if mrspacman.nextDirection then
print(string.format("Trying to turn at %i",mrspacman.dir or "error"))
end
end
local inputs={--i've mixed up directions due to my renderer
w=90,
a=180,
s=270,
d=0,
}
local skips={['']=true,[' ']=true}
function input(macro_input)--read wasd from terminal
print('your move')
local key= (macro_input and macro_input()) or io.read();
if skips[key] then return end
local dir = inputs[key];
if not dir then print('wrong key') return end
mrspacman.dir = dir
mrspacman.nextDirection=true
end
function sim_step()
dlog('"Smoothing" (%f,%f) through (%f,%f) to (%f,%f)',mrspacman.x,mrspacman.y,mrspacman.x*10,mrspacman.y*10,math.floor(mrspacman.x*10)/10,math.floor(mrspacman.y*10)/10)
dlog('"Fixing smoothing" (%f,%f) through (%f,%f) to (%f,%f)',mrspacman.x,mrspacman.y,(mrspacman.x+0.05)*10,(mrspacman.y+0.05)*10,math.floor((mrspacman.x+0.05)*10)/10,math.floor((mrspacman.y+0.05)*10)/10)
mrspacman.x = math.floor(mrspacman.x*10+.5)/10--these lines are different
mrspacman.y = math.floor(mrspacman.y*10+.5)/10--
--If an arrowkey was pressed (Think of this as "A new direction was queued")
if (mrspacman.nextDirection) then
dlog("trying to turn")
-- If Pacman is in the center of a tile, then
if (mrspacman.x == math.floor(mrspacman.x)) and (mrspacman.y == math.floor(mrspacman.y)) then
dlog("Pacman is in the center of a tile")
-- If the tile in front of Pacman is empty, set direction to that
dlog("lookup dy: %f dx: %f",-math2.sin(mrspacman.dir),math2.cos(mrspacman.dir))
dlog("lookup y: %f x: %f",mrspacman.y-math2.sin(mrspacman.dir),mrspacman.x+math2.cos(mrspacman.dir))
dlog(nodemap[mrspacman.y-math2.sin(mrspacman.dir)][mrspacman.x+math2.cos(mrspacman.dir)]==1 and "Its a wall" or "")
if (nodemap[mrspacman.y-math2.sin(mrspacman.dir)][mrspacman.x+math2.cos(mrspacman.dir)]~=1) then
dlog("turning")
mrspacman.dz = mrspacman.dir
-- Disable this queue
mrspacman.nextDirection = false
else
dlog"not turning"
end
end
end
-- If Pacman is NOT in the center of a tile
if (mrspacman.x ~= math.floor(mrspacman.x)) or (mrspacman.y ~= math.floor(mrspacman.y)) then
dlog("Pacman is NOT in the center of a tile, moving with no collision check")
-- Constantly move forwards
dlog("deltaX, deltaY : %f, %f",(math2.cos(mrspacman.dz)*mrspacman.speed),-(math2.sin(mrspacman.dz)*mrspacman.speed))
dlog("before (%f, %f)",mrspacman.x,mrspacman.y)
mrspacman.x = mrspacman.x + (math2.cos(mrspacman.dz)*mrspacman.speed)
mrspacman.y = mrspacman.y - (math2.sin(mrspacman.dz)*mrspacman.speed)
dlog("after (%f, %f)",mrspacman.x,mrspacman.y)
else
dlog("moving with collision check")
-- If the tile in front of Pacman is empty, move to that tile
if (nodemap[mrspacman.y-math2.sin(mrspacman.dz)][mrspacman.x+math2.cos(mrspacman.dz)] ~= 1) then
dlog("can move")
mrspacman.x = mrspacman.x + (math2.cos(mrspacman.dz)*mrspacman.speed)
mrspacman.y = mrspacman.y - (math2.sin(mrspacman.dz)*mrspacman.speed)
else
dlog("hit wall")
end
end
end
local gen_macro = function(sequence)--function generating predefined set of keypresses
sequence=sequence or ""
local step=0
return function()
step=step+1
if (step>sequence:len()) then return end--return to manual control
return sequence:sub(step,step)
end
end
local simple_macro= function() return gen_macro("wasd") end--simple sample, "--will do nothing
local horizontal_bend = function()--will bring pacman to bottom left
local _x10=string.rep(" ",10);
local sequence=_x10:rep(2).."s".._x10:rep(2).."a".._x10:rep(2)
return gen_macro(sequence)
end
local angry_monkey=function(length)--gen random sequence of buttons
length=length or 0
local keys={"a","s","d","w"," "}
local seq = {}
for i=1,length do
table.insert(seq,keys[math.random(#keys)])
end
return gen_macro(table.concat(seq))
end
local macro
--macro=simple_macro()
--macro=horizontal_bend()
--macro = angry_monkey(100)
--dlog=function() end --uncomment this to disable debug
while true do
draw()
input(macro)
sim_step()
-- if time_step>10 then return end
end