To start, I feel like I am in no way qualified to actually write a tutorial; tutorials are written by at least a journeyman if not a master of their craft. I'm not even sure I would consider myself an apprentice. But, there aren't really any other tutorials out there and I feel the time I've spent porting America's Most Haunted has given me more experience with UltraDMD than most people. So here goes.
So you've decided to use UltraDMD (UDMD) to give your table some spice and pizzazz. I'm assuming you've already got all your graphical assets ready and you're just wanting to know how to get them to UDMD, this is more a scripting tutorial. But one thing that might be important is for you to know what your FPS is for any animations you're using. This is important for knowing what you're pause time needs to be because as of the time of this writing, UDMD doesn't know when an animation ends, so you need to pause a scene for the length of the animation. I'll write more on this later.
Make sure you keep this link handy as it's a reference to everything UDMD can do.
https://ultradmd.wor...ocumentation-2/
Also, feel free to look at the script for the Test table that's in the same location you downloaded UDMD from, that's how I learned.
Let's begin with what you need to set up in your script to get UDMD working (this is not a tutorial on installing UDMD and getting it running). You need to initialize UltraDMD when the table loads. As you might already be doing, but in case this is one of the first tables you've worked on (kudos for you for trying to make a UDMD table as one of your first), a general good practice to coding is to not code what you're trying to do where you're trying to do it. You might think to yourself "When this bumper gets hit, I want to turn run this lighting animation, add points to the score, run this UDMD animation, play this table sound effect, and play this game sound." Instead of coding all of that into the bumper_hit routine, it might be better to code a separate light animation routine, a point adding routine, a UDMD animation routine, and a game sound routine. Then in the bumper_hit routine, you just call those routines. In the long run, it'll save you from repetitious coding. In that same respect, it's best to simply call a routine to initialize the UDMD; most commonly it's called LoadUltraDMD(). Of course you can call it whatever you want, but you can call this routine either in the Table_init routine (which is run when the table initializes), or just anywhere outside of any routine. You also need to create a variable; most commonly just set a
Dim UltraDMD
Of course, you can call it whatever you want, but this is what you'll be calling whenever you want UDMD to do something, UltraDMD.something.
The contents of the LoadUltraDMD() routine (or whatever you chose to call it) require at a minimum:
Sub LoadUltraDMD
Set UltraDMD = CreateObject("UltraDMD.DMDObject")
UltraDMD.Init
Dim fso
Dim curDir
Set fso = CreateObject("Scripting.FileSystemObject")
curDir = fso.GetAbsolutePathName(".")
UltraDMD.SetProjectFolder curDir & "\test1.UltraDMD" 'Change what's in quotes to wherever it is you have all your art assets that are going to run on the DMD
End Sub
That's it. Of course, there's lots of other stuff you should add because you're a very good programmer and you're always thinking of the end user and how their system might be different from yours. So you can add a bunch of checks that will pop up messages. This is copied from the UDMD site itself:
Sub LoadUltraDMD
Set UltraDMD = CreateObject("UltraDMD.DMDObject")
If UltraDMD is Nothing Then
MsgBox "No UltraDMD found. This table MAY run without it."
Exit Sub
End If
UltraDMD.Init
If Not UltraDMD.GetMajorVersion = 1 Then
MsgBox "Incompatible Version of UltraDMD found."
Exit Sub
End If
If UltraDMD.GetMinorVersion < 1 Then
MsgBox "Incompatible Version of UltraDMD found. Please update to version 1.1 or newer."
Exit Sub
End If
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim curDir
curDir = fso.GetAbsolutePathName(".")
UltraDMD.SetProjectFolder curDir & "\test.UltraDMD"
End Sub
Those additional version check makes sure the user has the most recent version.
Now that you've got UDMD running at the start of your table, we can start scripting scenes. As the UltraDMD documentation states, you really only need two things to get a decent table running:
UltraDMD.DisplayScene00
UltraDMD.DisplayScoreboard
Your first inclination might be to call those directly in the routines that you want them happen; you might think of doing something like this:
Sub Bumper1_Hit() BumperHits = BumperHits + 1 UltraDMD.DisplayScene00 "BumperHit.gif", BumperHits, 15, "", -1, 14, 2000, 14 PlaySound "bumper_hit" End Sub
but you're a well seasons veteran of a programmer, you know it's better to actually make a separate routine that calls .DisplayScene00 and call that routine in the _Hit routine... and no, I'm NOT telling you this because I made the mistake of having to redo a bunch of code because I came this realization too late, not at all. Not only is it a good idea to do that in first place, but there's lots of other things you should consider other than just simply playing an animation. What if an animation is already playing, should you interrupt it, queue this one up so it plays immediately after, or just ignore it? What if the animation that's currently playing is the same one; should you modify it, restart it, queue it up, or ignore it? There's lots of things you need to think about what you're going to do in your table, and a huge benefit of breaking out the UDMD call into it's own routine means if you decide to do something different later, or something breaks, you don't have to go through all of your code and make sweeping changes every place you called UDMD; just change the routine and now every call is fixed. Besides, you've read the UDMD documentation (you have haven't you), but maybe you're still not 100% clear on all the variables you can pass into the DisplayScene method. Let me break it down a bit, and I'll give you an example of I personally did in my AMH table.
Most of this is fairly well explained in the Programming Reference, but let me try to go into more detail. The DisplayScene00 method takes 8 arguments:
Background: This can be
A gif (my personal favorite due to the small size and universal usage)
A static image (one good use might be to display text that looks fancy). Let's say you want to tell the player "Nice Shot!!", but you think the standard text looks dull; you can create an image that's as cool as you want it to be.
A video (I believe this is dependent on what codecs the user has installed which is why I shy away from it)
An animation image list (so if you don't want to make a gif yourself, you can just include the individual frames of the gif and have UDMD make one for you essentially; personally I think it's better to make the gif yourself as it saves on space).
You can pass in a variable if it's a string, or use cStr(VariableName).
You can also concatenate variables and strings which is useful if you have some sort progressive video. E.G. an advancing mode animation. You could name your gifs "Catapult1.gif", "Catapult2.gif", "Catapult3.gif". Then in your code you could call:
UltraDMD.DisplayScene00 "Catapult" & CatapultStage & ".gif", ...
Where CatapultStage is a number that keeps track of how far the player has advanced the catapult. Meaning you'll pass in "Catapult1.gif" the first time the player makes the shot, CatapultStage will get incremented, and the next time the shot is made it will pass in "Catapult2.gif". It saves you from having to do a bunch of If statements, or a Select Case.
Top Text: Optional (well, you've gotta put something here, but that could be "").
Everything in UDMD is currently fixed width text. This is helpful to know for spacing reasons since an I takes up the same amount of width as an O.
If you don't want any text, make this argument "" (as well as the Bottom Text). This is fairly common if your table is highly animation driven as most information can be conveyed with the animation/graphic. But, it's useful for displaying changing information. E.G. How many bumper hits the player has. Instead of making an animated graphic containing every single possible number, you make one animation and display some simple text on top of it (like in Medieval Madness, they didn't make 99 animations of knights hitting each other, they made one and simply displayed a number over it).
If you want text to show only on the bottom, then make this argument " " (notice the space); if you don't, whatever is passed into the Bottom Text argument will take up the whole screen.
If you include only this argument, and have the Bottom Text argument as "", then only one line of large text will show.
If you include a Bottom Text Argument, this line is smaller than the bottom, so put your information accordingly at the top and/or bottom.
If there is no Bottom Text Argument, you can fit about 15 characters on the screen; you might be able to squeeze 16 on, but any more and things start getting pushed off the screen.
If there is a Bottom Text Argument, you can fit about 21 characters on the screen. This information is helpful if you need the text be, say, in a corner. You could pass in something like: " " & BumperHits. That shows the value of BumperHits on the right side, or corner if you have Bottom Text (of course, bumper hits should always be two digits, no more, no less, otherwise it would throw the spacing off; although you could get creative with a Len() function and dynamically put in the number of spaces).
Top Text Brightness: a value between 0 and 15
You might see some examples passing in -1. That works, but that's just to make sure there's no brightness at all.
A dark value creates a shadow; meaning if you put text in the top, give ia Top Text value of 0 but have a bright background, you'll see the text, it'll just be black. As stated above, if you don't want anything to show in the top line, pass in " " in the previous argument
Bottom Text: Much like the Top Text with a key difference
If Top Text is anything other than "", the bottom text is larger than the top text.
If you don't want any text, make this argument "" (as well as the Top Text).
If you have "" as the Top Text, it's the same as passing in something in Top Text and making this one ""; it will just be one line of large text taking up the screen, and you can fit the same ~15 characters on the screen
If you want to show only top text, make this " ".
If you have Top Text too, you can fit about 17~18 characters on the screen (since it's larger than the top text)
Animation in: The only documentation I've found on this is on the Test table. This is a number between 0 and 11, or 14. It would appear that number 0 ~ 3 are currently broken. They are as follows:
0: Fade In - apparently broken
1: Fade Out - apparently broken
2: Zoom In - apparently broken
3: Zoom Out - apparently broken
4: Scroll Off Left
5: Scroll Off Right
6: Scroll On Left
7: Scroll On Right
8: Scroll Off Up
9: Scroll Off Down
10: Scroll On Up
11: Scroll On Down
14: No animation
This is the animation of how the scene starts when its turn comes up (meaning either immediately if the DMD isn't doing anything else, or when its turn comes up in the queue). In the test table, you'll see that UltraPeepi set some variables equal to these numbers. Personally I find it easier to just pass in the number. If you need a reminder, just make a commented section somewhere, but I don't see the need to pass in a constant variable as opposed to just the number, other than making it a little more human readable, but then I would just make the variable something "ScrollOnLeft".
These can have odd effects if you use a "Off" animation here. It'll work, but your animation/scene will just animate off the DMD and you'll never see it again. But that could be useful if you wanted to have, say, an image of a car appear on the screen then drive away... although I think it would be better to have drive on the screen then drive off.
I believe you're going to use 14 the most frequently since you'll probably design your animations to do whatever effects you want. But as I mentioned, if you just took a still picture of a car, did a 7 for the animate in then a 5 for the animate out and had no pause time, then the car would drive across the DMD and it required no work for you at all other than grabbing a still picture of a car.
Pause Time: roughly in milliseconds.
This is how long the animation/picture/scene will be displayed on the DMD. This is key and this is what I tripped up on most when I was first learning UDMD. UDMD currently, if ever, has no way of detecting when an animation ends, so you can't just tell it to play an animation then display the score board. You have to tell it to play an animation for this amount of time. Naturally, this is where knowing the FPS can help; you either need to know the length, in seconds, the animation runs which might be difficult for gifs, or you can just know the number of Frames and the FPS.
If you know the time in seconds, then Pause Time = seconds * 1000 since this is in milliseconds
If you know the # of frames and FPS, then Pause Time = # of Frames * 1000/FPS
Animate Out: See animate in, except this is run at the end of pause time.
Next up, I'll give some code examples and what I've learned to do.










are all trademarks of VPFORUMS.