{{ message }}

Instantly share code, notes, and snippets.

# rross101/bounce.lua

Created Sep 18, 2018
Bounce for Norns
 --- bounce by declutter; can't remember who first created this app in Max for the monome --- to-do: --- sound on collision --- multiple balls g = grid.connect() function init() --- set up variables and grid position = {1,1} v = {1,1} map = {} for i = 1,16 do map[i] = {} for j = 1,8 do map[i][j] = 0 end end --- initial state to make it more interesting map[4][1] = 1 map[4][2] = 1 map[4][3] = 1 map[9][6] = 1 map[9][7] = 1 map[9][8] = 1 ---timing counter = metro.alloc() counter.time = 0.1 counter.count = -1 counter.callback = count counter:start() end function count() --- move ball position[1] = position[1] + v[1] position[2] = position[2] + v[2] --- detect edges --- this is ugly; there must be a prettier way if (position[1] == 16) or (position[1] == 1) or (map[position[1]+1][position[2]] == 1) or (map[position[1]-1][position[2]] == 1) then v[1] = (-1)*v[1] end if (position[2] == 8) or (position[2] == 1) or (map[position[1]][position[2]+1] == 1) or (map[position[1]][position[2]-1] == 1) then v[2] = (-1)*v[2] end --- redraw grid g.all(0) for i = 1,16 do for j = 1,8 do g.led(i,j,(map[i][j] == 1) and 5 or 0) end end g.led(position[1],position[2],15) g.refresh() end g.event = function(x,y,z) --- key presses build walls if z == 1 then map[x][y] = 1 - map[x][y] end g.refresh() end

### trentgill commented Sep 20, 2018 • edited

 this looks pretty clean to me, mostly just about readability. your `position` and `v` tables could use key-value pairs, rather than just be integers, eg `v = { x=1, y=1 }`. that way you can refer to them using `v.x` rather than `v[1]`. this clarifies that `v` is table with entries `x` and `y`, rather than a generic array. it's weird having `position` in full, and `v` as short for `velocity`. i'd use the full form for both, or the 1letter form. use the full form if the program is going to grow in complexity. i'd name `map` something else, like `walls` or `obstacles`. map usually refers to a function that applies a function over all elements of a list. put the `move ball` into a function called `move_ball()` then you don't need the documentation. the code documents the intention. inside this function you can use `position.*` and `velocity.*` rather than the array notation. if you're thinking about adding multiple balls you're going to need multiple `position` and `v` tables. one set per ball. so make a table `ball` which contains a `position` and `v` table. then your `move_ball()` function can take a `ball` table as it's argument, meaning it could be applied to different balls just by sending a different argument to the function. regarding the edge detection, there's not a lot you can do structurally - you need to check all these cases - but you can make it a little prettier. first is (again) wrapping it in a function `detect_collision()` which you can send a `ball` table. inside this function (your current `or` chain), you don't need the parentheses around each condition as `or` has higher precedence. you can also split the lines across multiple lines like: ``````if position.x = 16 or position.x = 1 etc... then `````` which should make it clearer that you are checking a series of conditions, any of which will cause the action. in terms of the action, you can simply negate by prefacing it with a `-` symbol. no need to explicitly multiply. final suggestion is that `map` could contain a boolean (true/false) rather than a number. this limits you to 'on/off' state, but it allows you to simplify the map[][] lookup. if it's a bool you would change `== 1` to `== true` which is the default condition, so you can drop it altogether for `or map[*][*] or `. following from here @64: i think it would be more idiomatic to say map[x][y] = not map[x][y] to invert the state. that's all i've got!

### rross101 commented Oct 13, 2018

 @trentgill somehow I missed this comment. This is excellent - will do some looking at it. Thank you.