• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

tgraupmann

Members
  • Content count

    561
  • Joined

  • Last visited

Community Reputation

112 Neutral

About tgraupmann

  • Rank
    Advanced Member
  1. Here's a tip.   Some years ago, Torque3D made the mistake of ditching OpenGL for DirectX. This resulted in future stupicide because with a cross-platform engine it prevented porting to Linux, Mac, Android, and iOS. They made some attempts to correct their mistake, but it was too late. There's been a KS attempt, but interest failed.   You might as well take the route of Unity and make it easy on yourself.
  2. Gravi is an intense puzzle-platformer that'll test your tolerance for pain. Fling yourself through terrorizing traps and manipulate gravity to swing towards victory. Death is guaranteed. Please check out our Create Contest Entry and vote for us - http://forums.ouya.tv/discussion/557/gravi-ouya-create-contest-submission#latest [video]http://www.youtube.com/watch?v=qQwjR-aL7TI[/video] APK download is available. Play now!
  3. Unity

    [html]<img height="150" src="http://tagenigma.com/a/ecosystemgenerator/2011-08-28%2C%20Ecosystem%20Generator%20Android%20014.png"/>[/html] Here you can see how to publish to Android and get the Ecosystem Generator working on your phone: [media]http://www.youtube.com/watch?v=PuV6OkCzm6E[/media]
  4. Unity

    Just letting you know that Unity 3.4 just shipped! [url="http://unity3d.com/unity/whats-new/unity-3.4"]http://unity3d.com/unity/whats-new/unity-3.4[/url] And the Video Painting Series is compatible with 3.4.
  5. Unity 3.4 is right around the corner, and the Paint Video Series is a great way to learn how to use the free version of Unity. You'll learn how to create art for unity. You'll learn how to use the IDE. And then you'll learn how to write script and tie it all together. [url]http://www.youtube.com/watch?v=JiYYp34l-Bw[/url] The video series contains an hour of video footage showing you by example. Go and download the free copy of Unity 3.3 or better. [url]http://unity3d.com/unity/download/[/url] And then head over to the Unity Asset Store and drop $5 for you and all your programming buddies. [url]http://u3d.as/1Dw[/url]
  6. I created a treeview control for Unity that works in the game view, scene view, custom panels and inspectors. You can add items at design time. And you can animate the hover states. It's completely skinable. Feature Video 1: [media]http://www.youtube.com/watch?v=wtcb5U8krdQ[/media] Feature Video 2: [media]http://www.youtube.com/watch?v=p1Jipt_HvH0[/media] Asset Store Link: [url="http://u3d.as/1Uw"]http://u3d.as/1Uw[/url]
  7. Unity

    I've added support to import your own foliage items. Youtube: [media]http://www.youtube.com/watch?v=NPyG6QzDt08[/media] Vimeo: [media]http://vimeo.com/26701662[/media] [img]http://tagenigma.com/unity/Ecosystem%20Generator/shot3_thumb.jpg[/img]
  8. My friend Kenny and I put together a package for Unity to auto generate foliage easily on a mesh from within Unity. [media]http://www.youtube.com/watch?v=eeH59UEgef0[/media] The Modo Vimeo user group came out, so I recorded a video of making a mesh in Modo, importing that to Unity, and then throwing some foliage on to that. [media]http://vimeo.com/25795617[/media] Here's some renders of the example scene in the PRO version of Unity. The unity pro version supports camera effects. The Ecosysem Generator works in the free version of Unity without the cool camera effects. We plan on adding many more types of foliage. An undocumented feature is that you can paint foliage on a mask. I'm trying to work that into an editor script so that it works without having to "play" the scene. The Unity extension is available in the Unity asset store. [url="http://u3d.as/1Y1"]http://u3d.as/1Y1[/url] [img]http://tagenigma.com/unity/Ecosystem%20Generator/shot1.jpg[/img] [img]http://tagenigma.com/unity/Ecosystem%20Generator/shot2.jpg[/img]
  9. I have a tax question that applies for game programmers. If a Washington, USA resident works as an independent contractor for a company not based in the USA, why is the federal government entitled to tax the individual? I'm sure independent contractors are plentiful. Let's say you are a USA resident, and you work for a USA company then you get taxed. That's how it works. But what if you are a USA resident, you move to a foreign country, you work for a foreign country. Should you be taxed by the foreign country or the USA? And my original question, you are a USA resident, you live in the USA, you work for a foreign country. Should you pay federal taxes? And by work, I mean providing a service. And that service is writing software. Ideas, Thoughts!? Thanks, ~Tim
  10. I added the fade in and fade out... and the popping is gone. I used a 0.15 second fade that seems to do the trick. When the fade starts, I switch to the next channel to play the next sample. using Emotiv; using SlimDX; using SlimDX.XAudio2; using SlimDX.Multimedia; using System; using System.Collections.Generic; using System.IO; using System.Threading; using System.Reflection; using System.Runtime.InteropServices; namespace EEG_Example_1 { class EEG_Logger { EmoEngine engine; // Access to the EDK is viaa the EmoEngine int userID = -1; // userID is used to uniquely identify a user's headset /// <summary> /// A dictionary of EEG data by channel /// </summary> Dictionary<EdkDll.EE_DataChannel_t, List<double>> m_eData = new Dictionary<EdkDll.EE_DataChannel_t, List<double>>(); /// <summary> /// The sound thread /// </summary> Thread m_soundThread = null; /// <summary> /// Constructor /// </summary> EEG_Logger() { // create the engine engine = EmoEngine.Instance; engine.UserAdded += new EmoEngine.UserAddedEventHandler(engine_UserAdded_Event); // connect to Emoengine. engine.Connect(); //engine.RemoteConnect("127.0.0.1", 1726); } void engine_UserAdded_Event(object sender, EmoEngineEventArgs e) { Console.WriteLine("User Added Event has occured"); // record the user userID = (int)e.userId; // enable data aquisition for this user. engine.DataAcquisitionEnable((uint)userID, true); // ask for up to 1 second of buffered data engine.EE_DataSetBufferSizeInSec(1); } static void Main(string[] args) { Console.WriteLine("EEG Data Reader Example"); //epoc EEG_Logger p = new EEG_Logger(); //epoc p.Run(); } void Run() { //start the sound thread ThreadStart soundThreadStart = new ThreadStart(WorkerSound); m_soundThread = new Thread(soundThreadStart); m_soundThread.Start(); while (true) { // Handle any waiting events engine.ProcessEvents(); // If the user has not yet connected, do not proceed if ((int)userID == -1) { Console.Error.WriteLine("User is not connected"); return; } Dictionary<EdkDll.EE_DataChannel_t, double[]> data = engine.GetData((uint)userID); if (data == null) { continue; } int bufferSize = data[EdkDll.EE_DataChannel_t.TIMESTAMP].Length; //fill with new data from raw eeg channels for (EdkDll.EE_DataChannel_t channel = EdkDll.EE_DataChannel_t.AF3; channel <= EdkDll.EE_DataChannel_t.AF4; ++channel) { List<double> rawData; if (!m_eData.ContainsKey(channel)) { m_eData.Add(channel, new List<double>()); } rawData = m_eData[channel]; for (int i = 0; i < bufferSize; i++) { double sample = data[channel][i]; rawData.Add(sample); } } Thread.Sleep(0); } } struct SoundItem { public AudioBuffer m_audioBuffer; public DataStream m_dataStream; public SourceVoice m_sourceVoice; public byte[] m_waveData; } // worker for the sound thread public void WorkerSound() { //random Random rand = new Random(); //simdx double SAMPLE_SECONDS = 0.5; //slimdx - create a device XAudio2 device = new XAudio2(); MasteringVoice masteringVoice = new MasteringVoice(device); //slimdx - create a sound format WaveFormat format = new WaveFormat(); format.AverageBytesPerSecond = 88200; format.BlockAlignment = 2; format.Channels = 1; format.SamplesPerSecond = 44100; format.BitsPerSample = 16; format.FormatTag = WaveFormatTag.Pcm; long cbWaveSize = (long)(SAMPLE_SECONDS * format.SamplesPerSecond * format.BitsPerSample / 8); //slimdx double FADE_SECONDS = 0.15; //slimdx long fadeSize = (long)(FADE_SECONDS * format.SamplesPerSecond * format.BitsPerSample / 8); //slimdx - fill with data - 88 piano keys List<double> freqtable = new List<double>() { 4186.01, 3951.07, 3729.31, 3520, 3322.44, 3135.96, 2959.96, 2793.83, 2637.02, 2489.02, 2349.32, 2217.46, 2093, 1975.53, 1864.66, 1760, 1661.22, 1567.98, 1479.98, 1396.91, 1318.51, 1244.51, 1174.66, 1108.73, 1046.5, 987.77, 932.33, 880, 830.61, 783.99, 739.99, 698.46, 659.26, 622.25, 587.33, 554.37, 523.25, 493.88, 466.16, 440, 415.31, 392, 369.99, 349.23, 329.63, 311.13, 293.67, 277.18, 261.63, 246.94, 233.08, 220, 207.65, 196, 185, 174.61, 164.81, 155.56, 146.83, 138.59, 130.81, 123.47, 116.54, 110, 103.83, 98, 92.5, 87.31, 82.41, 77.78, 73.42, 69.3, 65.41, 61.74, 58.27, 55, 51.91, 49, 46.25, 43.65, 41.2, 38.89, 36.71, 34.65, 32.7, 30.87, 29.14, 27.5 }; freqtable.Reverse(); //slimdx - make a sound buffer SoundItem[] sounds = new SoundItem[2]; sounds[0].m_audioBuffer = new AudioBuffer(); sounds[1].m_audioBuffer = new AudioBuffer(); //slimdb - set the buffer flags sounds[0].m_audioBuffer.Flags = BufferFlags.EndOfStream; sounds[1].m_audioBuffer.Flags = BufferFlags.EndOfStream; //slimdx - play the sound buffer sounds[0].m_sourceVoice = new SourceVoice(device, format); sounds[1].m_sourceVoice = new SourceVoice(device, format); //time to next buffer DateTime bufferTimer = DateTime.MinValue; //slimdx - cycle buffers int dsIndex = 0; int dsCount = 2; //simdx - Create the sample data into memory sounds[0].m_waveData = new byte[cbWaveSize]; sounds[1].m_waveData = new byte[cbWaveSize]; using (sounds[0].m_dataStream = new DataStream(sounds[0].m_waveData, true, true)) { using (sounds[1].m_dataStream = new DataStream(sounds[1].m_waveData, true, true)) { while (true) { if (sounds[dsIndex].m_sourceVoice.State.BuffersQueued > 0) { Thread.Sleep(0); continue; } //slimdx - fill with more data when the sounds stops if (bufferTimer < DateTime.Now) { bufferTimer = DateTime.Now + TimeSpan.FromSeconds(SAMPLE_SECONDS - FADE_SECONDS); //slimdx - stop sounds[dsIndex].m_sourceVoice.Stop(); //slimdx -- get buffer byte[] waveData = sounds[dsIndex].m_waveData; //slimdx - clear old data for (long i = 0; i < waveData.Length; ++i) { waveData[i] = 0; } // examine the last N seconds of data //GenerateTone(64, fadeSize, freqtable[41], device, waveData, format); //test GenerateTone(64, fadeSize, freqtable[rand.Next()%freqtable.Count], device, waveData, format); //test //slimdx - start sounds[dsIndex].m_dataStream.Position = 0; sounds[dsIndex].m_audioBuffer.AudioData = sounds[dsIndex].m_dataStream; sounds[dsIndex].m_audioBuffer.AudioBytes = (int)sounds[dsIndex].m_dataStream.Length; sounds[dsIndex].m_sourceVoice.SubmitSourceBuffer(sounds[dsIndex].m_audioBuffer); sounds[dsIndex].m_sourceVoice.Start(); dsIndex = (dsIndex + 1) % dsCount; } Thread.Sleep(0); } } } //slimdx - cleanup the voice sounds[0].m_audioBuffer.Dispose(); sounds[1].m_audioBuffer.Dispose(); sounds[0].m_sourceVoice.Dispose(); sounds[1].m_sourceVoice.Dispose(); //slimdx - dispose the device masteringVoice.Dispose(); device.Dispose(); } // generate some random tones static void GenerateTone(double volume, double fadeSize, double frequency, XAudio2 device, byte[] waveData, WaveFormat format) { double sampleSize = (format.SamplesPerSecond * format.Channels); double t = (Math.PI) / sampleSize; for (long i = 0; (i+1) < waveData.Length; i += 2) { double newVolume; double fade = fadeSize; if (i < fade) { // fade in newVolume = volume * Math.Min(1, i / fade); } else if (i > (waveData.Length - fade)) { // fade out newVolume = volume * Math.Min(1, (waveData.Length - i) / fade); } else { newVolume = volume; } double theta = (double)(i * t * frequency); float amplitude = (int)(Math.Sin((float)theta) * newVolume); // read existing tone - two bytes to float float oldAmplitude = (float)((waveData[i] << 8) | ((int)(waveData[i + 1]))); amplitude = (amplitude + oldAmplitude) * 0.5f; // convert new tone - float to two bytes int data = (int)amplitude; waveData[i] = (byte)(data >> 8); waveData[i + 1] = (byte)data; } } } } [Edited by - tgraupmann on September 19, 2010 9:03:34 AM]
  11. Same result with DataStream. It keeps sputtering between switching buffers. // worker for the sound thread public void WorkerSound() { //random Random rand = new Random(); //simdx double SAMPLE_SECONDS = 0.1; //slimdx - create a device XAudio2 device = new XAudio2(); MasteringVoice masteringVoice = new MasteringVoice(device); //slimdx - create a sound format WaveFormat format = new WaveFormat(); format.AverageBytesPerSecond = 88200; format.BlockAlignment = 2; format.Channels = 1; format.SamplesPerSecond = 44100; format.BitsPerSample = 16; format.FormatTag = WaveFormatTag.Pcm; long cbWaveSize = (long)(SAMPLE_SECONDS * format.SamplesPerSecond * format.BitsPerSample / 8); //slimdx - fill with data - 88 piano keys List<double> freqtable = new List<double>() { 4186.01, 3951.07, 3729.31, 3520, 3322.44, 3135.96, 2959.96, 2793.83, 2637.02, 2489.02, 2349.32, 2217.46, 2093, 1975.53, 1864.66, 1760, 1661.22, 1567.98, 1479.98, 1396.91, 1318.51, 1244.51, 1174.66, 1108.73, 1046.5, 987.77, 932.33, 880, 830.61, 783.99, 739.99, 698.46, 659.26, 622.25, 587.33, 554.37, 523.25, 493.88, 466.16, 440, 415.31, 392, 369.99, 349.23, 329.63, 311.13, 293.67, 277.18, 261.63, 246.94, 233.08, 220, 207.65, 196, 185, 174.61, 164.81, 155.56, 146.83, 138.59, 130.81, 123.47, 116.54, 110, 103.83, 98, 92.5, 87.31, 82.41, 77.78, 73.42, 69.3, 65.41, 61.74, 58.27, 55, 51.91, 49, 46.25, 43.65, 41.2, 38.89, 36.71, 34.65, 32.7, 30.87, 29.14, 27.5 }; freqtable.Reverse(); //slimdx - make a sound buffer AudioBuffer buffer = new AudioBuffer(); buffer.Flags = BufferFlags.EndOfStream; //slimdx - play the sound buffer SourceVoice sourceVoice = new SourceVoice(device, format); //time to next buffer DateTime bufferTimer = DateTime.MinValue; //time to next log DateTime logTimer = DateTime.MinValue; //slimdx - cycle buffers int dsIndex = 0; int dsCount = 2; byte[][] waveDatas = new byte[dsCount][]; //simdx - Create the sample data into memory waveDatas[0] = new byte[cbWaveSize]; waveDatas[1] = new byte[cbWaveSize]; using (DataStream ds0 = new DataStream(waveDatas[0], true, true)) { using (DataStream ds1 = new DataStream(waveDatas[1], true, true)) { DataStream[] streams = new DataStream[dsCount]; streams[0] = ds0; streams[1] = ds1; while (true) { if (sourceVoice.State.BuffersQueued > 0) { Thread.Sleep(0); continue; } //slimdx - fill with more data when the sounds stops if (bufferTimer < DateTime.Now) { bufferTimer = DateTime.Now + TimeSpan.FromSeconds(SAMPLE_SECONDS); //slimdx - stop sourceVoice.Stop(); //slimdx -- get buffer byte[] waveData = waveDatas[dsIndex]; //slimdx - clear old data for (long i = 0; i < waveData.Length; ++i) { waveData[i] = 0; } // examine the last N seconds of data GenerateTone(freqtable[41], 8, device, waveData, format); //test //GenerateTone(freqtable[rand.Next()%freqtable.Length], 8, device, waveData, format); //test //slimdx - start streams[dsIndex].Position = 0; buffer.AudioData = streams[dsIndex]; buffer.AudioBytes = (int)streams[dsIndex].Length; sourceVoice.SubmitSourceBuffer(buffer); sourceVoice.Start(); dsIndex = (dsIndex + 1) % dsCount; } Thread.Sleep(0); } } } //slimdx - cleanup the voice buffer.Dispose(); sourceVoice.Dispose(); //slimdx - dispose the device masteringVoice.Dispose(); device.Dispose(); }
  12. I'm going to try a SlimDX.DataStream. [example] I had a suspicion it was copying the buffer. Since modifying the buffer while playing did nothing.
  13. I'm providing wave data via a memory stream. And then I pass the memory stream to SlimDX. I want to start and stop the SourceVoice every 50 to 500ms. But when I do I hear popping. Is there a way to start and stop without the popping? //slimdx - fill with more data when the sounds stops if (bufferTimer < DateTime.Now) { bufferTimer = DateTime.Now + TimeSpan.FromSeconds(SAMPLE_SECONDS); //slimdx - stop sourceVoice.Stop(); //slimdx - clear old data for (long i = 0; i < waveData.Length; ++i) { waveData[i] = 0; } // examine the last N seconds of data GenerateTone(freqtable[41], 8, device, waveData, format); //test //slimdx - start ms.Position = 0; buffer.AudioData = ms; buffer.AudioBytes = (int)ms.Length; sourceVoice.SubmitSourceBuffer(buffer); sourceVoice.Start(); } When I generate a tone of 100ms or 2 seconds, when the SourceVoice starts I hear a pop. My issue is within WorkerSound(). [Full source] [Edited by - tgraupmann on September 20, 2010 1:28:53 AM]
  14. [SlimDX] is a pretty neat wrapper around XAUDIO2. DirectX SDK now bundles XAudio2 with C++ examples. I first wrote a tone generator in C++. And with SlimDX it was very easy to port the example over to C#. I spent my weekend on messing with the PCM format, bits, and research. Hopefully you can benefit. [Example] extended. Also I think I heard a bug in Audacity which I used as a reference to listen to tones. I think they blend and multiple with 0.75 instead of 0.5. [This post] talking about the pcm channel bits was helpful too.
  15. What are the 4 elements this year?