Log In  


Hi everybody!

So, for a jam I'm far too unskilled to have considered, I'm putting together a little game where up to four players can pilot tiny ships and defend a fort. The ships can move about, and (eventually) shoot in the direction of a target that can be rotated around the ship by holding a button. It looks like this in practice:

(Enemies and animations forthcoming.)

Right now, I am attempting to optimize the code, because the player inputs eat a LOT of tokens in their current form. I currently have four different sets of inputs, one for each player, and each also moves a target that is specified as its own object (target1 with .x and .y, target2 with .x and .y, etc.). This is obviously no good, given the immense redundancies.

I think one could probably code a generic input function by making each target a property of its ship, using something like this:

function input(p)
  if btn(0,p.c) then p.x=p.x-1 p.targetx=p.targetx-1         --repositions player and target
   if p.x<0 then p.x=0 end                                   --prevents leaving the screen
   if p.targetx<0 then p.targetx=p.x+radius*cos(p.a/360) end
  end
  if btn(1,p.c) then p.x=p.x+1 p.targetx=p.targetx+1         --repositions player and target
   if p.x>120 then p.x=120 end                               --prevents leaving the screen
   if p.targetx>120 then p.targetx=p.x+radius*cos(p.a/360) end
  end
  if btn(2,p.c) then p.y=p.y-1 p.targety=p.targety-1         --repositions player and target
   if p.y<16 then p.y=16 end                                 --prevents moving into sandbar at top of screen
  end
  if btn(3,p.c) then p.y=p.y+1 p.targety=p.targety+1         --repositions player and target
   if p.y>120 then p.y=120 end                               --prevents leaving the screen
   if p.targety>120+radius then p.targety=p.y+radius*sin(p.a/360) end
  end
  if btn(4,p.c) then end                                     --fires bullet (to be implemented)
  if btn(5,p.c) then p.a+=target_speed                       --rotates target
   p.targetx=p.x+radius*cos(p.a/360)
   p.targety=p.y+radius*sin(p.a/360)
   if p.a>360 then p.a=0                                     --resets target angle if needed
   elseif p.a<0 then p.a=360
   end
  end
end

Basically, as long as we specify the controller (c) associated with each player (p), we can use one function to dictate all player inputs. So, for each player, we have to put together a simple table of attributes.

And here is where my problem occurs: those stupid little targets.

Here's what I have tried to use for the first player's attribute table:

 p1={
   exist=false,
   dead=false,
   idle=true,
   x=50,
   y=50,
   a=180,
   idlesprite=3,
   movesprite=7,
   w=8,
   h=8,
   score=0,
   lives=3,
   c=0,
   targetx=p1.x+radius*cos(p1.a/360),  --PICO-8 doesn't like this line.
   targety=p1.y+radius*sin(p1.a/360),  --Or this one.
   targetsprite=16
   }

It seems PICO-8 doesn't accept putting p1.x, p1.y, and p1.a in those trig functions for p1.targetx and p1.targety. It raises an error, saying that they indicate an attempt to index a nil value. I guess I could just throw in a raw number for them? But I kind of need those variables, I think, since the location of the player's target must depend on the location of the player's ship.

TL;DR: A table isn't working like my noob brain would expect, and I have three questions:

  • Why are p1.x, p1.y, and p1.a nil values, if I already provide values for them in the table?
  • How else might I define targetx and targety, such that they remain properties of p1?
  • If the method I've proposed is stupid, what might you suggest as a workaround?


Nevermind! I managed to make it work by writing out the tables in this form:

p1={}
 p1.x=
 p1.y=
 ...

Anyway, the input optimization thingy worked, so if any of you have need of its code, let me know!

Thanks for reading.



[Please log in to post a comment]