This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Joe3000's profile picture

Line 157, Invalid key to 'next'

Started by Joe3000, 06 June 2013 - 10:29 PM
Joe3000 #1
Posted 07 June 2013 - 12:29 AM
I think it's because once the lasers hit the end of the screen they nil out and then it doesn't know how to update, how do i fix :3

l, h = term.getSize()
refreshRate = 0.15
gtID = os.startTimer(refreshRate)
starTime = os.startTimer(0.01)
enemyTime = os.startTimer(.5)
running = true

--Background
function background()
  stars = {
	xpos = math.random(l);
	ypos = math.random(h);
	xvel = 1;
  
	draw = function(self)
	  term.setCursorPos(self.xpos, self.ypos)
	  term.setBackgroundColour(colours.black)
	  term.setTextColour(colours.white)
	  term.write("*")
	end;
  
	update = function(self)
	  self.xpos = self.xpos - self.xvel
	  if self.xpos <= 0 then
		self.xpos = l
	  end
	end;
  }
  return stars
end

--player

player = {
  xpos = 5;
  ypos = math.floor(h/2);

  update = function(self, key)
	if key == keys.up then
	  self.ypos = self.ypos - 1
	elseif key == keys.down then
	  self.ypos = self.ypos + 1
	elseif key == keys.right then
	  table.insert(lAmount, laser())
	end
  
  
	if self.ypos >= h -1 then
	  self.ypos = h - 1
	elseif self.ypos <= 1 then
	  self.ypos = 1
	end
  end;


  draw = function(self)
	term.setTextColour(colours.green)
	term.setCursorPos(self.xpos, self.ypos)
	term.setBackgroundColour(colours.black)
	term.write("\\")
	term.setCursorPos(self.xpos, self.ypos + 1)
	term.setBackgroundColour(colours.black)
	term.write("/")
  end
}


--Enemies
function spawnEnemy()
  enemy = {
	xpos = l;
	ypos = math.random(h);
  
	draw = function(self)
	  term.setCursorPos(self.xpos, self.ypos)
	  term.setBackgroundColour(colours.black)
	  term.setTextColour(colours.red)
	  term.write("<")
	end;
  
	update = function(self)
	  self.xpos = self.xpos - 1
	
	  if self.xpos <= 0 then
		self.xpos = l
	  end
	end;
  
  }
  return enemy
end

--Lasers
function laser()
  shoot = {
	 xpos = player.xpos + 1;
	 ypos = player.ypos;
	
	 update = function(self)
	   self.xpos = self.xpos + 1
	  
	   if self.xpos >= l then
		 table.remove(lAmount)
	   end
	 end;
	
	 draw = function(self)
	   term.setCursorPos(self.xpos, self.ypos)
	   term.setBackgroundColour(colours.black)
	   term.setTextColour(colours.yellow)
	   term.write("-")
	   term.setCursorPos(self.xpos, self.ypos -1)
	   term.write("-")
	 end;
  }
  return shoot
end

sAmount = {}
for i=1,100 do
  table.insert(sAmount, background())
end

eAmount = {}
for i=1,5 do
  table.insert(eAmount, spawnEnemy())
end

lAmount = {}
for i=1,1 do
  table.insert(lAmount, laser())
end

function drawGame()
  term.clear()
  term.setBackgroundColour(colours.black)
  for i,v in pairs(sAmount) do
	v:draw()
  end
  player:draw()
  for i,v in pairs(eAmount) do
	v:draw()
  end
  for i,v in pairs(lAmount) do
	v:draw()
  end
end

function updateGame()
  id, p1 = os.pullEvent()
  if id == "key" and p1 == keys.q then running = false end
  if id == "timer" then
	if p1 == starTime then
	  for i,v in pairs(sAmount) do
		v:update()
	  end
	  for i,v in pairs(lAmount) do
		v:update()
	  end
	  starTime = os.startTimer(0.01)
	elseif p1 == enemyTime then
	  for i,v in pairs(eAmount) do
		v:update()
	  end
	  enemyTime = os.startTimer(.5)
	end
  end
  if id == "key" then
	player:update(p1)
  end
end

function gameLoop()
  while running do
	drawGame()
	updateGame()
  end
end

gameLoop()
shell.run("clear")

–Edit–
I did just realize that this is a slightly older version, so I don't think the error is showning… let me fix it real quick….
Engineer #2
Posted 07 June 2013 - 01:40 AM
Also put it on pastebin, because notany are in the mood to count to 157.. Pastebin has line numbers :P/>
Bomb Bloke #3
Posted 07 June 2013 - 01:52 AM
I know I'm turning into a stuck record about this, but putting functions in a table then duplicating that table is simply a waste of RAM. There's no need to store identical copies of your code. You start out by creating 100 copies of a function to draw asterisks, for example… If you MUST put those functions in tables, treat them as you'd treat a static object!

Anyway. This code:

           self.xpos = self.xpos + 1

           if self.xpos >= l then
                 table.remove(lAmount)
           end

… removes whatever laser is at the end of your "lAmount" table. And it's pretty much sure to do so, too, because you've just incremented self.xpos by 1. I guess you meant to check against a larger number?

Looking at the rest of your code logic, the laser to be removed is nearly guaranteed to not be the laser that the function is actually processing at the time, because it's the newest laser that will always be at the end of that table (due to the way you're using the insert function), and it's the oldest laser that's most likely to actually reach the point where you want it to be deleted (which'll usually be sitting at the start of the table).

With only one laser in the table, that doesn't matter so much, except that you've then just deleted a function that the Lua interpreter was busy running. I'm going to guess that's what's triggering your error.

There may be other issues.

Actually it strikes me that removing entries from the table with "table.remove", even if you rig it to do so in the right order, is probably going to entirely mess up your "for i,v in pairs(lAmount) do" loop. Assuming it's bright enough to end the loop at the correct spot ('cause the table length just changed), it's still probably going to miss iterations every time you remove an entry ('cause it'll move all the other indexes down).

So I guess my answer boils down to "use all the techniques I covered in your last thread to manually track what you're doing in the table and externalise your functions from it".