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

[Lua] Noteblock Player

Started by TristanTroll, 05 September 2012 - 08:50 PM
TristanTroll #1
Posted 05 September 2012 - 10:50 PM
I want a program that when I type say "1" into the terminal, it will send a signal to the white wire through bundled cables. I recently asked for help on a song, but this guy basically told me nothing useful and said go script yourself an entire noteblock player with no additional help or thought that maybe I can't code to save my life. I tried MysticT's noteblock stuff and that didn't work, considering I am actually a multiplayer player, not a weird singleplayer guy who can access his rom/lua files and whatnot. I just need a noteblock player that works on a piano that goes lowest(left) to highest(right). I don't understand most of what this forum says, the tutorials on youtube are just "Hey guys look at what I made on minecraft today" which isn't helpful to people starting computercraft like me at all. And if I seem angry it's probably because I've spent the last week, hours a day looking for help and have received none that is useful…
OmegaVest #2
Posted 05 September 2012 - 11:09 PM
So, wait, you're just looking for a numerical keyboard player? Well, that's actually quite simple if you don't mind a little roundabouts.

For starters, every wire in a bundled cable has a numerical value to it. White is 1, Orange 2, Magenta 4, and so on up the binary ladder. (I think that's the right order). And by combining these numbers, we can get different ones. Like white+orange is 3, magenta and orange is 5, etc. By the way, using 'help colors' should give you the list of colors, and in the correct order. Just, it helps to know binary counting.

So, if you want to play note 1, you can type in '1', and then pass the input to a bundled output, like so.


input = tonumber(read())
rs.setBundledOutput(side, input)

Now it's really just a matter of understanding how to make each wire activate. The simplest way is to make an array that is nothing but the colors.


myColors = {}
myColors[1] = 1
myColors[2] = 2
myColors[3] = 4
myColors[4] = 8
myColors[5] = 16
myColors[6] = 32
myColors[7] = 64
myColors[8] = 128
myColors[9] = 256
myColors[10] = 512
myColors[11] = 1024
myColors[12] = 2048
myColors[13] = 4096
myColors[14] = 8192
myColors[15] = 16384
myColors[16] = 32768

And then apply what we have already learned to the array.


rs.setBundledOutput(side, myColors[input])


And that should get you started, if nothing else presently.
TristanTroll #3
Posted 05 September 2012 - 11:32 PM
I'm not going to type rs.setBundledOutput(side, myColors[input]) For each and every note. What I need is a Noteblock Player I can use in multiplayer and I'm not the owner. Can you make one of those with a test song and a picture of your piano setup?
Cranium #4
Posted 05 September 2012 - 11:39 PM
Nobody wants to write a program for someone who won't code some of it themselves. I know I wouldn't want to do that, because you would never learn how to do it. OmegaVest already did some of the hard work for you.
NIN3 #5
Posted 05 September 2012 - 11:42 PM
Now it's really just a matter of understanding how to make each wire activate. The simplest way is to make an array that is nothing but the colors.


myColors = {}
myColors[1] = 1
myColors[2] = 2
myColors[3] = 4
myColors[4] = 8
myColors[5] = 16
myColors[6] = 32
myColors[7] = 64
myColors[8] = 128
myColors[9] = 256
myColors[10] = 512
myColors[11] = 1024
myColors[12] = 2048
myColors[13] = 4096
myColors[14] = 8192
myColors[15] = 16384
myColors[16] = 32768

And then apply what we have already learned to the array.


rs.setBundledOutput(side, myColors[input])


And that should get you started, if nothing else presently.

Um, what about colors.(color)? Last time I checked, that worked just fine….
Cranium #6
Posted 05 September 2012 - 11:45 PM
Now it's really just a matter of understanding how to make each wire activate. The simplest way is to make an array that is nothing but the colors.


myColors = {}
myColors[1] = 1
myColors[2] = 2
myColors[3] = 4
myColors[4] = 8
myColors[5] = 16
myColors[6] = 32
myColors[7] = 64
myColors[8] = 128
myColors[9] = 256
myColors[10] = 512
myColors[11] = 1024
myColors[12] = 2048
myColors[13] = 4096
myColors[14] = 8192
myColors[15] = 16384
myColors[16] = 32768

And then apply what we have already learned to the array.


rs.setBundledOutput(side, myColors[input])


And that should get you started, if nothing else presently.

Um, what about colors.(color)? Last time I checked, that worked just fine….
Either works interchangeably. Numbers are just easier to work with, in my opinion.
Kingdaro #7
Posted 05 September 2012 - 11:49 PM
Um, what about colors.(color)? Last time I checked, that worked just fine….

As well as colors.

I actually wrote a noteblock player a while ago that would read a list of outputs to induce. I had it play gangnam style but it didn't work out that well because of inaccurate timing.

However this would be much easier to do:

local tCommands = {
  [keys.q] = 'white';
  [keys.w] = 'red';
  [keys.e] = 'blue';
  --continue this with all of your colors, but in the order of how you would want your keys mapped in correspondence to the order of redstone outputs to the noteblocks.
}

while true do
  local _, k = os.pullEvent('key')

  if tCommands[k] then
    rs.setBundledOutput('back', 0) --replacing 'back' with whatever side you want, of course.
    rs.setBundledOutput('back', colors[tCommands[k]])
  end
end
TristanTroll #8
Posted 06 September 2012 - 12:11 AM
Well maybe, just maybe cranium kid I said that I can't code to save my life, just maybe, and this is the ask a pro section and I needed help, so maybe I was just doing what I was supposed to, no reason to be mean to me. I don't understand what anyone here is doing because I see a crap ton of scattered scripts.
Kingdaro #9
Posted 06 September 2012 - 12:22 AM
You should probably look up a tutorial on CC lua first :D/>/>

http://computercraft.info/wiki/index.php?title=Tutorials
TristanTroll #10
Posted 06 September 2012 - 12:40 AM
Nah I'd rather leave this to the Lua pros… besides making this doesn't just help me it helps everyone.
Cranium #11
Posted 06 September 2012 - 01:02 AM
I'm not trying to be mean. I just want to let you learn how to do it instead of demanding that someone do it for you. This is just a generally accepted "rule". See here that it's one of the stickies. We have tutorials in the forums for a reason. I'm sorry if I sound like I'm speaking for the entire community, but as a whole, I think everybody would like you to learn, instead of being spoonfed lines of code. We're not here to generate code FOR you, just to help you with your problems.
Pharap #12
Posted 06 September 2012 - 02:56 AM
Well maybe, just maybe cranium kid I said that I can't code to save my life, just maybe, and this is the ask a pro section and I needed help, so maybe I was just doing what I was supposed to, no reason to be mean to me. I don't understand what anyone here is doing because I see a crap ton of scattered scripts.
Nah I'd rather leave this to the Lua pros… besides making this doesn't just help me it helps everyone.

Lua is an easy language, trust me. (I know Lua, VB, C#, bits of perl and bits of C++, and lua is by far the easiest to get to grips with).
There's not much point trying to use computercraft unless you're willing to learn a bit about how to program. Part of the whole reason the mod was created was so people had a reason to learn how to program (As well as make something current programmers could use in minecraft to help simplify things).
Programming as a concept isn't hard, the hard bit is knowing what processes you have to perform to get your program to do what you want it to. For example you might know that you want to get a noteblock to play when someone presses a button while using the computer, but there are so many different ways you could go about it, it's sometimes hard to clear your head enough to think how you would go about doing it.


Also, it's pretty much an unwritten rule around here that you should never expect to come to the pros section and expect someone to provide you with a full running program, you should always assume they are just going to tell you where you are going wrong or suggest ways of doing things or things you may have missed (like the existence of a function that would help),which is one of the reasons Cranium was annoyed (also the fact that he's put a lot of effort into learning how to program in lua and had to overcome a lot of obstacles. Any programmer worth their salt has been through this struggle and gets annoyed when beginners want to take short cuts or people expect the code monkeys to deliver any program they ask for on a plate).

regardless, here is some code that will output data to a bundled cable at the back of a computer so you can play it like a keyboard(providing noteblocks are attached):

local side = "back" -- variable holding the side to send the data
term.clear() -- clear screen
term.setCursorPos(1, 1) --reset cursor
while true do
local e, k = os.pullEvent("key")
--you can choose the keys you want to set corresponding code to by using the keys constant (keys.keyname)
--k represents the key pressed. Test what key it is by using a key constant.
--here I demonstrate
--the w key sending output to the red wire,
--the r key sending output to the blue wire and
--the e key sending output to the white wire
--these can be changed by changing the key constant, the colour and
--more options can be added by adding more "else if k == keys.keyname then" blocks
--this is not the most efficient method, but if you are a beginner you dont need to worry about efficiency,
--just understanding what is going on

if k == keys.w then
redstone.setBundledOutput(side, colours.red) -- sets output to red
elseif k == keys.r then
redstone.setBundledOutput(side, colours.blue) -- sets output to blue
elseif k == keys.e then
redstone.setBundledOutput(side, colours.white) -- sets output to white
end
sleep()
redstone.setBundledOutput(side, 0) --cuts all output
end
Kingdaro #13
Posted 06 September 2012 - 03:16 AM
@Pharap, a long list of elseifs is a very unprofessional way of writing programs. Also, if the signal is cut off instantly after being sent, the note blocks won't play. They need to have the signal on for a certain amount of time, therefore they should be cut either before sending input, or have a sleep() after sending input.
Pharap #14
Posted 06 September 2012 - 03:38 AM
@Pharap, a long list of elseifs is a very unprofessional way of writing programs. Also, if the signal is cut off instantly after being sent, the note blocks won't play. They need to have the signal on for a certain amount of time, therefore they should be cut either before sending input, or have a sleep() after sending input.
I considered a sleep, but then forgot it at the last minute, that much I will admit to.
No it isn't brilliant programming but firstly, lua doesn't have a switch statement and secondly, it's no good bombarding a beginner with advanced efficient techniques if they aren't going to understand what it does. Showing things clearly is how people learn, not by showing them stuff that they need to understand a load of other junk first to understand.

Also I'd like to point out that quotes are much better than @ symbols, this isn't twitter or Java.
Kingdaro #15
Posted 06 September 2012 - 03:58 AM
No it isn't brilliant programming but firstly, lua doesn't have a switch statement and secondly, it's no good bombarding a beginner with advanced efficient techniques if they aren't going to understand what it does. Showing things clearly is how people learn, not by showing them stuff that they need to understand a load of other junk first to understand.
I read over what I said and I understand why you wrote your program the way you did.

Also I'd like to point out that quotes are much better than @ symbols, this isn't twitter or Java.
I used "@" because I didn't feel like cutting out parts of your huge post, haha.
TristanTroll #16
Posted 06 September 2012 - 04:14 AM
Thanks Pharap, this isn't what I first asked for but I think it's way cooler. Thanks for not being a post farmer and taking time to give useful code for a super beginner like me :D/>/> The instructions were understandable for me.
Pharap #17
Posted 06 September 2012 - 04:15 AM
No it isn't brilliant programming but firstly, lua doesn't have a switch statement and secondly, it's no good bombarding a beginner with advanced efficient techniques if they aren't going to understand what it does. Showing things clearly is how people learn, not by showing them stuff that they need to understand a load of other junk first to understand.
I read over what I said and I understand why you wrote your program the way you did.

Also I'd like to point out that quotes are much better than @ symbols, this isn't twitter or Java.
I used "@" because I didn't feel like cutting out parts of your huge post, haha.
Cutting is fine, it's preferable to the @ thing, because if I'm only watching quotes, I won't know you've replied, or if I am watching both, I might just think your reply was a general one and not aimed at me (luckily my instincts told me otherwise).

I'm glad you understand why I did it though, I feel that a lot of experienced programmers start to forget what it was like when they were first starting out and tend to give people code that is wonderfully efficient but really hard for beginners, hence why I always try to explain code I give to people who are just starting out as well as making it require as least knowledge as possible. That way people learn whether they want to or not lol.

As for any mistakes I made, I put it up to tiredness (it's 04:14 where I am, UTC-0 is a late place to be right now)
Pharap #18
Posted 06 September 2012 - 04:25 AM
Thanks Pharap, this isn't what I first asked for but I think it's way cooler. Thanks for not being a post farmer and taking time to give useful code for a super beginner like me :D/>/> The instructions were understandable for me.

You're welcome. I mostly saw 'noteblock player' and skimmed the rest, since it's a commonly asked for program.
As long as you tune it correctly, it should be fine. I'm not sure how many wire colours there are, but hopefully enough to match the 24 notes that noteblocks can produce, if not, just rig it up so there's a separate bundled cable on each side of the computer.

I'm glad you understood it, I've had an arduous journey in programming to get to where I am now, and since I only started a year ago, I still remember my first few weeks learning to program, so when I hear that someone is still new, I look back and say 'how would I explain this to myself back then' and thus try to make my code as simple as possible. Also I have a 'functionality over all' attitude, which basically means I worry more about if code works than if it's efficient.

Regardless of my ramblings, I'm glad you understand now, hopefully you'll get your noteblock keyboard working and soon move onto bigger and better things :P/>/>
TristanTroll #19
Posted 06 September 2012 - 12:25 PM
My idea is to have a town bell tune from animal crossing with noteblocks that plays every hour if that's possible, so my idea is to type like sleep(3600) with a world anchor from tekkit by it so it always loads, but how do I make a program loop?
Kingdaro #20
Posted 06 September 2012 - 01:36 PM
My idea is to have a town bell tune from animal crossing with noteblocks that plays every hour if that's possible, so my idea is to type like sleep(3600) with a world anchor from tekkit by it so it always loads, but how do I make a program loop?
To sleep every hour and then play the tune every hour, you would make a while loop.

while true do
  playSong() -- replace this with your song playing code.
  sleep(3600)
end

However if you wanted the song to sound at all like a real song, you would have a waiting period in the song that would offset the hour-long cycle. Another way to do this would be to make a while loop using the parallel API to play both the timer and the song at the same time.

local function songTimer()
  sleep(3600)
end

while true do
  parallel.waitForAll(songTimer, playSong)
end

The parallel API waits for both the song to complete, and for the timer to cycle 3600 seconds. Hopefully this makes sense.

Also I have a 'functionality over all' attitude, which basically means I worry more about if code works than if it's efficient.
Aha, you and I are on two completely different spectrums; I can't leave the edit program unless my code is the shortest it can be while being readable XD
KaoS #21
Posted 06 September 2012 - 01:49 PM
Also I have a 'functionality over all' attitude, which basically means I worry more about if code works than if it's efficient.
Aha, you and I are on two completely different spectrums; I can't leave the edit program unless my code is the shortest it can be while being readable XD

Likewise, I am big on functionality but my code must be neat and complete… I also have a thing where it has to be able to cater for any eventuality - no matter how outlandish

guess I'm just a coding perfectionist…. sux2bme :D/>/>
TristanTroll #22
Posted 06 September 2012 - 02:40 PM
So if I made a song named bell it would look like this?

local function bellTimer()
sleep(3600)
end

while true do
parallel.waitForAll(bellTimer, playbell)
end

You are very complicated for me to understand, try to type like Pharap.

EDIT: Spaces before sleep and parallel, they just don't show up when I post.
Kingdaro #23
Posted 06 September 2012 - 02:44 PM
It would look like that, yes. Just make sure you have your playbell function defined beforehand, which actually plays your bell.

And sorry I can't change my typing style to be more beginner friendly, it'd be cool if someone could translate my words into something you could understand more.

Also, in order to have spaces in your code, just wrap it around
tags.
TristanTroll #24
Posted 06 September 2012 - 11:42 PM
How do I make a function beforehand and don't talk gibberish.
OmegaVest #25
Posted 06 September 2012 - 11:53 PM
For a function:


function functionName(params)

  --  Code here

   return value  -- Not always needed, but it is how things like os.pullEvent() give off variables.
end

--Some Code

FunctionName(params)

--End of program

And there may be zero or more parameters, such as a string, integer, character, etc.
TristanTroll #26
Posted 07 September 2012 - 12:32 AM
So would that go on top of this or what?

local function bellTimer()
sleep(3600)
end

while true do
parallel.waitForAll(bellTimer, playbell)
end
Pharap #27
Posted 07 September 2012 - 01:17 AM
So would that go on top of this or what?

local function bellTimer()
sleep(3600)
end

while true do
parallel.waitForAll(bellTimer, playbell)
end

My turn again lol

Ok, so let's say you've got all your noteblocks set up at the back of your computer, hooked up to a bundled cable.
You know you want to play, and how you are going to play it (eg the order of noteblocks).
Then you figure out the code required to play the song, which may look something like this:

local side = "back"
redstone.setBundledOutput(side, colours.blue)
sleep(0.15)
redstone.setBundledOutput(side, colours.green)
sleep(0.1)
redstone.setBundledOutput(side, colours.red)
sleep(0.15)
redstone.setBundledOutput(side, colours.green)
sleep(0.1)
redstone.setBundledOutput(side, colours.blue)
sleep(0.3)
redstone.setBundledOutput(side, colours.red)
sleep(0.2)
Now you want to put this in a function, which would be achieved like so:

local function playsong()
local side = "back"
redstone.setBundledOutput(side, colours.blue)
sleep(0.15)
redstone.setBundledOutput(side, colours.green)
sleep(0.1)
redstone.setBundledOutput(side, colours.red)
sleep(0.15)
redstone.setBundledOutput(side, colours.green)
sleep(0.1)
redstone.setBundledOutput(side, colours.blue)
sleep(0.3)
redstone.setBundledOutput(side, colours.red)
sleep(0.2)
end
Since this function is only performing a song, you don't need to worry about it giving back any data with the 'return' statement, the only bit you need to worry about now is the fact that by putting this block of code in a function, it can be called on as required.
To call this function, simply use the line

playsong()
Anywhere after the function is declared. (Some languages are different, but in lua a function has to be declared before you call it because of the way the code is read/compiled.)
Now for the actual code of the program (assuming you have already declared the playsong function at the top of your program):

while true do
playsong()
sleep(3600)
end
This will play your song and then sleep the console for an hour. Don't forget to account for how long your song plays for.
Eg time how long it takes to play and subtract that amount from the sleep time. So, if it takes 12 seconds, change sleep(3600) to sleep(3588).

That's assuming you want to make it chime on every real world hour. Minecraft time is something rather different, but can also be done with the right arrangement. I could have done this using the parallel API, but that would require explaining the basic ideas of the parallel API. I can do this if you want, since it will save you attempting to time your song, but it would still take a bit more time to explain.
TristanTroll #28
Posted 07 September 2012 - 02:05 AM
Wow Pharap that was awesome, I understood all of that and now I know how to make a function, and how localside works :D/>/>.
And that the function has to be in the program before you call it. Because I thought the other guy was saying I need to make the function in a separate file. Now I can manually transfer some of my animal crossing town tunes to Minecraft :D/>/>
TristanTroll #29
Posted 07 September 2012 - 02:59 AM
Yay I made it. pastebin.com/uEmpPp2t
Kingdaro #30
Posted 07 September 2012 - 03:07 AM
i would tell you an easier way to do that but i'm apparently no help in this thread ;~;
TristanTroll #31
Posted 07 September 2012 - 03:28 AM
Because you don't make any sense :D/>/>
Try to make it easier and I'll see if I can decipher it.
jaytime104 #32
Posted 07 September 2012 - 03:43 AM
nice lil thing u got going here hummm?
Pharap #33
Posted 07 September 2012 - 11:42 PM
Wow Pharap that was awesome, I understood all of that and now I know how to make a function, and how localside works :D/>/>.
And that the function has to be in the program before you call it. Because I thought the other guy was saying I need to make the function in a separate file. Now I can manually transfer some of my animal crossing town tunes to Minecraft :D/>/>

Thank you, I'm glad you understand it all and managed to get your program working.
If you ever need any more help, and other people aren't making sense, I don't mind being asked questions directly. Be sure to pose your question to the whole forum first though, people here do try their best to help.
ElectricOverride #34
Posted 11 September 2012 - 04:19 PM
Well maybe, just maybe cranium kid I said that I can't code to save my life, just maybe, and this is the ask a pro section and I needed help, so maybe I was just doing what I was supposed to, no reason to be mean to me. I don't understand what anyone here is doing because I see a crap ton of scattered scripts.
Nah I'd rather leave this to the Lua pros… besides making this doesn't just help me it helps everyone.

Lua is an easy language, trust me. (I know Lua, VB, C#, bits of perl and bits of C++, and lua is by far the easiest to get to grips with).
There's not much point trying to use computercraft unless you're willing to learn a bit about how to program. Part of the whole reason the mod was created was so people had a reason to learn how to program (As well as make something current programmers could use in minecraft to help simplify things).
Programming as a concept isn't hard, the hard bit is knowing what processes you have to perform to get your program to do what you want it to. For example you might know that you want to get a noteblock to play when someone presses a button while using the computer, but there are so many different ways you could go about it, it's sometimes hard to clear your head enough to think how you would go about doing it.


Also, it's pretty much an unwritten rule around here that you should never expect to come to the pros section and expect someone to provide you with a full running program, you should always assume they are just going to tell you where you are going wrong or suggest ways of doing things or things you may have missed (like the existence of a function that would help),which is one of the reasons Cranium was annoyed (also the fact that he's put a lot of effort into learning how to program in lua and had to overcome a lot of obstacles. Any programmer worth their salt has been through this struggle and gets annoyed when beginners want to take short cuts or people expect the code monkeys to deliver any program they ask for on a plate).

regardless, here is some code that will output data to a bundled cable at the back of a computer so you can play it like a keyboard(providing noteblocks are attached):

local side = "back" -- variable holding the side to send the data
term.clear() -- clear screen
term.setCursorPos(1, 1) --reset cursor
while true do
local e, k = os.pullEvent("key")
--you can choose the keys you want to set corresponding code to by using the keys constant (keys.keyname)
--k represents the key pressed. Test what key it is by using a key constant.
--here I demonstrate
--the w key sending output to the red wire,
--the r key sending output to the blue wire and
--the e key sending output to the white wire
--these can be changed by changing the key constant, the colour and
--more options can be added by adding more "else if k == keys.keyname then" blocks
--this is not the most efficient method, but if you are a beginner you dont need to worry about efficiency,
--just understanding what is going on

if k == keys.w then
redstone.setBundledOutput(side, colours.red) -- sets output to red
elseif k == keys.r then
redstone.setBundledOutput(side, colours.blue) -- sets output to blue
elseif k == keys.e then
redstone.setBundledOutput(side, colours.white) -- sets output to white
end
sleep()
redstone.setBundledOutput(side, 0) --cuts all output
end
I agree I remember when i first started I used to get frustrated if something didn't work, it takes some time to get a grip but once you've broke through that, it starts to get a bit easier the more you practise.
ElectricOverride #35
Posted 25 November 2012 - 02:38 PM
I agree I remember when i first started I used to get frustrated if something didn't work, it takes some time to get a grip but once you've broke through that, it starts to get a bit easier the more you practise.
And here I am now, with my shiny new OS. :D/>/>
Laserman34170 #36
Posted 26 November 2012 - 05:40 AM
The simplest way is to make an array that is nothing but the colors.
 myColors = {}
myColors[1] = 1
myColors[2] = 2
myColors[3] = 4
myColors[4] = 8
myColors[5] = 16
myColors[6] = 32
myColors[7] = 64
myColors[8] = 128
myColors[9] = 256
myColors[10] = 512
myColors[11] = 1024
myColors[12] = 2048
myColors[13] = 4096
myColors[14] = 8192
myColors[15] = 16384
myColors[16] = 32768
And then apply what we have already learned to the array.
 rs.setBundledOutput(side, myColors[input]) 

I would use the colors API if I were you. http://computercraft...hp?title=Colors
It allows you to use a bunch of functions for combining bundled cable outputs and accessing a bunch of variables for the different wires.

white = colors.white
orange = colors.orange
whiteAndOrange = colors.combine(white, orange)
rs.setBundledOutput(whiteAndOrange)