Skip to content

Instantly share code, notes, and snippets.



Created Sep 18, 2018
What would you like to do?
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
--- 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
counter = metro.alloc()
counter.time = 0.1
counter.count = -1
counter.callback = count
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
for i = 1,16 do
for j = 1,8 do
g.led(i,j,(map[i][j] == 1) and 5 or 0)
g.event = function(x,y,z)
--- key presses build walls
if z == 1 then
map[x][y] = 1 - map[x][y]

This comment has been minimized.

Copy link

@trentgill trentgill commented Sep 20, 2018

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

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 <next condition>.

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!


This comment has been minimized.

Copy link
Owner Author

@rross101 rross101 commented Oct 13, 2018

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.