size = #sequenceCode
for i=1, size do
if sequence[1]==sequenceCode[i][1] and sequence[2]==sequenceCode[i][2] and sequence[3]==sequenceCode[i][3] and sequence[4]==sequenceCode[i][4] then
sequenceMatch = sequenceCode[i].name break
end
end
Two: create a unique identifier for each sequence that's important for you:
local maxvalue = 9
local sequencelength = 4
function getSequenceID(sequence)
local uniqueID = 0
for i=1, sequencelength do
uniqueID = uniqueID+sequence[i]*maxvalue^(i-1)
end
return uniqueID
end
Edit: You could make a string based unique ID if you wanted, that might be more intuitive for you:
ID = function(table)
--ID for checking equality of tables containing only numerical and string values in integer keys
local idstring = ""
for i, value in ipairs(table)
idstring = idstring..value
end
return idstring
end
if ID(sequence) == ID(dragonpunch) then
Okay, lots of things looking good in my game so far, though I'm running out of time. One question: I want to load several sounds and then play them all at once on a certain trigger - I seem to remember you saying there was a way of doing that, DarkGod?
It's very easy actually, I see mosaic Game class already inherits from engine.interface.GameSound
so all you have to do is call game:playSound("whatever") of which sound you wish to play.
It'll load & cache things so the first time you play a sound it is read form the disk and then it's kept in memory.
The files are to be placed in data/sound/whatever.ogg
The files can also be lua files that look like:
Which will tell the code to load coins.ogg and set the volume to 50
So if you call taht file coins50.lua you can do:
game:playSound("coins50")
or if you want the full volume:
game:playSound("coins")
[tome] joylove: You can't just release an expansion like one would release a Kraken XD
--
[tome] phantomfrettchen: your ability not to tease anyone is simply stunning
darkgod wrote:It's very easy actually, I see mosaic Game class already inherits from engine.interface.GameSound
so all you have to do is call game:playSound("whatever") of which sound you wish to play.
It'll load & cache things so the first time you play a sound it is read form the disk and then it's kept in memory.
What I don't get is the cache thing, as since I understand it doing game:playSound("whatever") will just straight away play that sound.
What I want to do is every, say, second load a bunch of sounds and play them all at once. Would I be able to load all of the files and then initiate a "play all" command?
Also, since the game is turn-based, what's the best way to actually call the notes at regular real-time intervals?
There's probably a better way, but if playSound caches them, you could play them at very low volume whenever you know you're going to need them, just to get them ready. For instance, you could do that at load time (sounds like you're building a keyboard?) But chances are there's a slightly better way to do it that I'm not aware of.
My favorite way to keep track of time is the function os.clock(), which if I'm not mistaken returns the time in seconds since the application has began. It does so with perfectly high precision (I get three places after the decimal, but it potentially varies for different operating systems), so it would be a good way to keep rhythm, although at 30fps, it's gonna be iffy
Mostly I'm piping up because there are limitations to the ID method I offered earlier: it really only works with single digit positive integers. (As an example, consider the comparison of {11, 1} with {1, 11} or {1,1,1}.) If you sequences contain numbers larger than 9, you're better of with the numerical method immediately preceeding that string-based ID, which will work for positive integers of any value (so long as you know a maximum value).
My comparison was only with the numbers 1 to 4, so rather handily it works just great :)
I'm not sure if the os.clock will help me much - how can I get the game to trigger a sound release every second or half-second for instance?
With sound caching, is there a limit to how much I can cache? To be clear I want to make the map behave like the grid in Tonematrix: http://tonematrix.audiotool.com/ So as certain squares get turned on/off they become part of a background sequence of music. There would be 11 notes, with perhaps a few other notes for different map entities.
I don't believe there's an onFrame hook (which surprised me because it's the very first hook I would make). So you hijack a function that runs reliably every frame. mod/class/game.lua (in default ToME) contains _M:display() which runs once each and every frame-- good target for hijacking, even if nobody would ever think to look there to see what's triggering your sound code. You superload that, if you haven't already replaced it, get it to run the old display as well as your own onFrame function.
Your onFrame goes through your list of sounds. If one is due to be played, it plays it. It knows that it's due to be played because soundlist.whenToPlay <= os.clock(). Translation: your sound knows it's supposed to sound off at 1 o'clock, so when it looks at the clock and sees that it's 1:05, and it hasn't yet sounded, it gives a holler. When it plays, it prevents it from playing again next frame by setting whenToPlay = whenToPlay+rhythm until whenToPlay>os.clock(), where rhythm is a constant indicating how frequently to play sounds. Rhythm, of course, can be different for every sound you might want to play. (If you wanted to play a sound every second, rhythm = 1. Every half second, rhythm = 0.5. soundlist.whenToPlay is assuming you've got a ton of sounds you don't want to deal with individually, so you're running through them with a for loop. If you've only got one, you're of course only dealing with WhenToPlay.)
I think it's a little easier to understand when describing it with more English than code, so I hope that's enough to get you started. I don't know how reliably the game will end up syncing the sound-- that stuff can get a little tricky, I understand, but there's not a lot you can do about it unless you want to recode the engine (and/or the OS). You'll just have to try it and see.
Edit: Don't know exactly how the caching works, but DG's probably talking about it getting loaded into RAM from your hard drive, which is important for any kind of rhythmic play. There's probably some overhead for each sound, but in general, you can just look at how big a soundfile is [as a wave file], and figure that if that's loaded, then ToME is using that much more RAM than it would otherwise. If you're aiming for 8GB machines, with sound files that are a second long or shorter, you've got a long ways to go before you have to worry about it.
New question: I have added an option called "Help" on the main game menu, which pulls up a dialogue box with a bunch of helpful text. This all works delightfully except the text is too big for the box and a scrollbar doesn't appear.
Wow, my first attempt at the music generator worked! Well, sort of - it sounds a bit pants. The computer isn't great at keeping rhythm either. Will see what I can do with it...
One issue I have is with the sound continuing to play when the window is unfocused. Is there a command to check if the window is in focus or not?
Edit: Also if I just leave the program in focus but idle it'll eventually just go silent. Once I start moving again the sound comes back on. It's a bit weird...
Also also, can anyone recommend a way of highlighting the squares as they are played? Like a little glow effect or something on the tile. Particles would be too much - it would need some shader lighty thing. But I don't really know how to do that :-/
Still tweaking it, but the game makes music based on how much of the map is filled in. At times it sounds pretty good!
Issues remaining:
- Would like a better way of showing pulsed tiles
- If you don't touch it for a while the music stops. Not a big issue, but strange.
- It behaves a little oddly when window out of focus.
Isn't it fun? You just put together a few legos and next thing you know you have a shrieking flashing computer Giving it a go now.
That's really cool. The sounds are syncing up nicely on my end. The only thing that bothered me was that I think it used my ToME settings as default, which had audio off (or else the default settings for Mosaic were to have audio off), which was only accessible from the main screen-- took me a bit to figure out why it wasn't playing.
Your tile light effect is cool. If you're talking about making them pulse, rather than have the little bouncing thing, consider that you can use that same sound function to draw things to the screen (which is actually, duh, what display() is really for). You can draw your tiles manually using tileshat[1]:toScreen. If they're underneath the character, you can just draw your character's tile on top of that. You might need a way to convert from map coordinates to screen coordinates-- if you want to do something like that, let me know, I'll send you a function I made to do that.
But with two hours left you might not want to get too ambitious Especially with something so cool already.
nate wrote:The only thing that bothered me was that I think it used my ToME settings as default, which had audio off (or else the default settings for Mosaic were to have audio off), which was only accessible from the main screen-- took me a bit to figure out why it wasn't playing.
Yeah, the engine settings seem universal. DarkGod, know of a way I can have a custom sound profile for Mosaic?
Your tile light effect is cool. If you're talking about making them pulse, rather than have the little bouncing thing, consider that you can use that same sound function to draw things to the screen (which is actually, duh, what display() is really for). You can draw your tiles manually using tileshat[1]:toScreen. If they're underneath the character, you can just draw your character's tile on top of that.
Looking at dressing up the game a little more now... But I'm not sure of what you're saying here. By pulse I more mean like glow for a second. But it would be a quick fade in/out to give a pulsing effect. I've heard of shaders being used for things like this, but I've no idea how to approach it.
You could do shaders, which SHOULD give you the ability to do some really cool effects, but I don't know shaders, and shaders aren't necessary.
Consider what happens if you make a picture of a rectangular glow. Include an alpha channel. Now, draw it on top of the tile that you want to glow. When you draw things, you do it with something like txt[1]:toScreenPrecise(x1, y1, x2, y2...R, G, B, A) where RGBA is just what you think. By sending an alpha value, you can control blending with whatever's underneath. If you want it to pulse, you can use os.clock() again to control things like the alpha channel ("local A = 0.5+0.5*math.sin(os.clock)") which will give you a nice smooth pulse with a period of 3.14 seconds. You could instead pulse color (R, G, B, A = 0.5+0.5*math.sin(os.clock), 1, 1, 1 will give you a pulse between white and cyan) or you could pulse the size of the texture by altering the bounds that you send toScreenPrecise (x2 = (0.5+0.5*math.sin(os.clock)) *oldx2, x1 = x1 + 0.5*(x2-oldx2)).
You can see that you can do anything here, and you're really just limited by your creativity. If you're not familiar with trigonometry, it might be intimidating, but you can just think of the math functions as black boxes-- don't need to know what they're doing, just need to know what it ends up looking like.
You can draw these on top of the map just by calling them after the call to UIset:display (or displayMap() I think)-- dig into the functions to find the right entry point for drawing. You can also send a display callback-- check out class/actor.lua for an example of display callbacks, they're used to draw health bars, and you can use them to draw in the right layer (like on top of a tile but underneath any entities on that tile).