Log In  

Hi all! I'm learning to use Lua as I make games, so this may have an easy answer. I just haven't figured it out yet:

Cart #thedustbbs1-0 | 2020-03-03 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA


edit:

I placed the actual cart here from a recommendation in the comments. I've placed every shape except for the cube shape somewhere besides the start of the file in the code (grid & photo are in spreadinit() and the rest can be found in the presets tab). The cube & grid show up fine, but everything else seems to be difficult to find for the program.


original post:

I'm currently making a game where there are several 3d objects you can peruse & rotate. I'm using the same function to display the objects as well as 3d grid to help me visualize where I should map everything--

draw_shape(clutter[cs]) --clutter is a table with each object's name in it. which object gets shown is determined by cs, or cardspot, a variable that changes with the player's selection
draw_shape(grid,3) --grid is the name of the grid shape, and it uses a different colour from the default

--So the functions work as they should. When I started the code for this game, the info for each shape (point coordinates & which points to connect) was placed at the beginning of the file. So far so good.

The thing now is that I'm trying to move the shape info to the init() section of a game, so that the coordinates have a chance to reset to their defaults. This should work in theory, and it does work perfectly for draw_shape(grid), which is great! However, for any of the shapes that are pulled up using the clutter[cs] table, I am told that the local 'shape' value cannot be found.

I know the function works without the use of a table, so I would really like to understand why throwing a table into this process seems to wreck everything. Is it just one too many steps to process at a time?

This isn't the first time I've run into this problem, and my solution in the past has just been to write around the problem, usually throwing the table out & explicitly specifying which variables, or by moving the code to the easiest to access spot. I'd like to outgrow the former habit since it seems like a bad approach to coding, especially as things get more complicated. The latter seems possible, but the current placement does work well for non-tabled objects, so I'd like to avoid that as well if possible.

Anyway, that's my situation. Any thoughts & insights are super appreciated!

P#73624 2020-03-03 03:11 ( Edited 2020-03-03 22:29)

I think it would be most helpful to us, in order to help you, if you uploaded the cart in its broken state. Many of us are very good at spotting problems as long as we can see the code.

If you want to debug it, I'd suggest adding these lines before the call to draw_shape(clutter[cs]):

cls()
color(7)
print(clutter)
print(cs)
print(clutter[cs])
stop()

That might tell you which variable is lacking in definition at the time.

Ideally you want to see something like this:

[table]
2
[table]

But if anything is nil, or if cs isn't a valid index, that'll tell you a lot.

P#73625 2020-03-03 04:47 ( Edited 2020-03-03 04:50)

Thanks for the recommendation! I've uploaded the cart for review.

I tried the debugging test, and it was able to pull up:

[table]
1
[table]

...when cs was defined as 1. So things seem to be running properly on that front.

Each of the shapes' info are able to be read as tables as well, so long as they're defined somewhere by the point we hit the test (ie the shapes in spreadinit() won't show up in a titledraw() test, but they will if we move the shape info info to titleinit()).

P#73644 2020-03-03 22:41 ( Edited 2020-03-03 22:46)

It looks like it's because you're defining clutter globally, which happens well before shapes like photo are defined.

The way PICO-8 works is that it builds the final source out of some hidden prefix Lua code, your code, and some hidden suffix code. The prefix code sets up some globals and such, then your code is passed over once, and then the suffix looks to see if you have _init() defined and calls it once if so, and then runs a main loop that calls your _update() or _update60() and your _draw() if they're defined and flips the drawn frame to the front.

Everything written at global scope runs in a linear fashion. If you define something in global that references something else, it better have been defined already or the reference will be a (quiet) nil.

It's handy to define your pure data globally, kind of like having external static files, and then build your data structures that reference it in _init().

Looks like the solution would be to move the clutter init to inside spreadinit(), maybe? Or write a clutterinit() that you call any time you replace a clutter model.

P#73659 2020-03-04 12:20 ( Edited 2020-03-04 12:52)

Actually, a better option might be to have the models have a layer of indirection:

-- your global shapes are now basically shape handles
cube = {ref = {what you currently assign to cube}}
photo = {} -- not set up yet, .ref implicitly nil for now

-- clutter points to these handles, not directly to the shapes
clutter = {cube, photo, ..., etc}

function spreadinit()
  :
  -- only replace the reference, not the global
  photo.ref = {what you currently assign to photo}
  :
end

function draw_shape(h,c)
  local s = h.ref
  for l in all(s[2]) do -- for each line in the shape...
    draw_line(s[1][l[1]], s[1][l[2]], c) -- draw the line
  end
end

Something like that, anyway. Something where you can set up your clutter table statically to point at your shapes, but replace the contents of the shapes it points to without completely changing their global table reference which was copied only once to the clutter table.


PS: Indenting is a good thing. ;)

P#73660 2020-03-04 12:52 ( Edited 2020-03-06 08:33)

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-29 09:20:04 | 0.011s | Q:19