ClearlyNot.Me Exceptional self improvement, one fail at a time

XNA Audio Learnings - XACT

May 31

The most painful thing about learning new things is not knowing where to look when the tutorial you’re following runs out. In this post I’ll go over the key things about XACT that I had to look all over for.

XACT is the name of Microsoft’s Cross-Platform Audio Creation Tool for XNA development. Here’s why you need to use it.

How do you play sounds?

If you’re building an application, you may find that using SoundEffects suffices for your needs.

A SoundEffect is a single ContentManager loaded sound reference, this is imported in the same way as images for Textures:

   1: SoundEffect effect = Content.Load<SoundEffect>(“someAudio”);

To play the effect, you have to create an instance of the SoundEffect:

   1: SoundEffectInstance instance = effect.play();

Why not skip XACT all together? If you’re building a game, the single instance limitation is going to become evident quite quickly. What do I mean? Say you’ve got a Tower and every time it fires a bullet you play that effect. Providing the instance has finished playing before the next time it’s requested, there’s no issue. As soon as you start requiring multiple instances of the same effect to be played, you find this is a big issue.

XACT helps out here, you define WaveBanks of sound effects, these are your audio file references, then you create SoundBanks which are like the instances. Each Sound in your SoundBank can have a Cue defined. Each Cue can be called multiple times.

To get this up and running, open XACT 3 (Game Studio 3.1 > Tools). Create a new project and save it in your Content folder along side your audio. Create up your WaveBanks and SoundBanks defining a Cue for each Sound.

In Visual Studio, add the .XGS file that XACT 3 produces and build.

Then initialise in your initialise method, and play a cue after that anywhere you need:

   1: //Initialise engine and sound banks, keep a reference for later.
   2: audioEngine = new AudioEngine(@"content\audio\TowerDefence.Sounds.xgs");
   3: sbGameEvents = new SoundBank(audioEngine, @"content\audio\GameSoundBank.xsb");
   4: wbGameEvents = new WaveBank(audioEngine, @"content\audio\GameEvents.xwb");
   5:  
   6: //Play the sound by it's cue, I've defined the string names as constants in this example
   7: sbGameEvents.PlayCue(SoundConstants.GAME_WON);

How do I change the volume?

To do this, you need to set the category on the Sounds in your SoundBank. Click a Sound and choose a category. Then in your initialise:

   1: //Initialise as before
   2: musicCategory= engine.GetCategory(“Music”);

To set volume:

   1: //0.0f is silence, 1.0f is full volume, 2.0f is LOUD
   2: musicCategory.SetVolume(1.0f);

Using categories in this way, you can give options for different volume profiles. Allowing the user to turn off music but leave sound effects on for example. Just another tool in the toolbox.

I’ll be continuing these XNA related posts as I discover more about it. Look forward to it :)

New Tower Defence game in development

May 31

We're building a Tower Defence game for Windows Phone 7 at the moment.

Why Windows Phone 7?

It’s a new platform with a lot of opportunity, I’m anticipating another iPhone app gold rush and I want to be in on it this time. I’ve built quite a few games with my partner in crime Neil and we’re building this one in XNA. It’s a managed framework running on Windows Compact Framework (Not the same Windows Mobile of days gone by) but the same framework used by games that are built for the Xbox.

Why not iPhone? I own an iPhone, I love it, it’s an awesome game platform. The market is saturated though, I’ve dabbled and not enjoyed it. I’ve developed for Android, Blackberry and Windows Mobile, iPhone development on the other hand just threw me. The available tools are archaic, the language can be painful and you need a Mac to do anything at all.

The platform is fantastic though, they use an MVC model with a great stack based window management system. There’s a lot in the framework, it’s very comprehensive. That said, I just don’t want the pain for as long as I can help it.

Why Tower Defence?

My favourite genre on the iPhone is Tower Defence, it’s a relatively straight forward rules based game model. Previous examples are Fieldrunners, geoDefence, TowerMadness, Blighted Earth and Space Station: Frontier.

It seemed an obvious choice, our weakest point is always graphics, which is a key requirement in gaining early interest. As such I’ve managed to recruit an awesome designer based in Mexico.

What progress have we made?

A lot actually! We already have a playable version built in XNA 3.1 that runs at 60 FPS.

We have 5 tower types, 4 creep types, sound, menu system, variable game speed, proper creep routing and walking.

What’s left?

We’ve got multiple levels still to build, difficulty modes, High Score table, Xbox Live support, Extra map download support. Most importantly, we’re running on stock icons.

We’re waiting on our Mexican compadré to progress with his designs with baited breath. We’ve already seen concept art which is something to behold. We’re expecting very good things.

You should too, I’ll update with the new game site with concept art and progress when we get there.

How to write a Custom Header Control in Android

March 01

I’ve been playing with Google’s Android recently, attempting to convert an existing iPhone app to the Android platform. I must say, I’m much enamoured. I’ve found the leap to Java (from C#) and the Android developer SDKs to be a lot less pain than I thought it might be.

The one main failing with Android development so far seems to be in scarcity of documentation (with samples) and of finding answers to the questions you have. Stackoverflow helps a great deal and the android documentation and google groups help too but often I’ll just hit a brick wall and have to try things out until I get them working.

In the specific app I’m porting, we have a Header control which sits at the top of the application and has the current activity’s title and a back button.

As any good developer would, I wanted to conform to the DRY principle as best I could so I wanted to encapsulate this control for reuse throughout the app.

Here’s the spec:

  • Create a control with a predetermined layout, 1 text area centered, one button to the far left.
  • Expose methods on the control to allow programmatic setting of the Title and Button Visibility
  • Force the button click to be wired up in the consuming activity

So, here’s the layout:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <merge xmlns:android="http://schemas.android.com/apk/res/android">
   3:     <RelativeLayout android:layout_height="wrap_content" android:layout_width="fill_parent" android:background="@drawable/button_background" android:orientation="horizontal">
   4:         <Button android:id="@+id/header_button_left" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_alignParentLeft="true" android:layout_marginLeft="5dip" android:background="@drawable/menu_back_button"></Button>
   5:         <TextView android:id="@+id/header_title" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textStyle="bold" android:layout_centerVertical="true" android:layout_centerHorizontal="true" android:layout_width="wrap_content" android:textSize="15dip" android:text="Title not set"></TextView>
   6:     </RelativeLayout>
   7: </merge>

I use a relative layout here so that I can align the controls to the center and left of the parent and vertically align center too. You can do this with LinearLayouts if you prefer.

We have one Button called header_button_left and a TextView called header_title.

The whole thing is wrapped in a merge viewgroup.

Here’s my code

   1: public class HeaderView extends RelativeLayout
   2: {
   3:     OnHeaderButtonClickedListener onHeaderButtonClickedListener = null;
   4:     
   5:     private TextView titleTextView; 
   6:     private Button leftButton;
   7:     
   8:     public interface OnHeaderButtonClickedListener
   9:     {
  10:         public abstract void onLeftMenuButtonClick();
  11:     }
  12:     
  13:     public HeaderView(Context context, AttributeSet attributeSet)
  14:     {
  15:         super(context, attributeSet);
  16:         
  17:         LayoutInflater.from(context).inflate(R.layout.menuheader, this, true);
  18:         leftButton = (Button)findViewById(R.id.header_button_left);
  19:         rightButton = (Button)findViewById(R.id.header_button_right);
  20:         titleTextView = (TextView)findViewById(R.id.header_title);
  21:         
  22:         leftButton.setOnClickListener(new OnClickListener()
  23:         {            
  24:             public void onClick(View v)
  25:             {
  26:                 if(onHeaderButtonClickedListener != null)
  27:                     onHeaderButtonClickedListener.onLeftMenuButtonClick();
  28:             }
  29:         });
  30:     }
  31:     
  32:     public void SetTitle(String newTitle)
  33:     {
  34:         titleTextView.setText(newTitle);
  35:     }
  36:     
  37:     public void SetLeftButtonVisibility(int visibility)
  38:     {
  39:         leftButton.setVisibility(visibility);
  40:     }
  41:     
  42:     public void SetLeftButtonText(String text)
  43:     {
  44:         leftButton.setText(text);
  45:     }
  46:     
  47:     public void setOnHeaderButtonClickedListener(OnHeaderButtonClickedListener listener)
  48:     {
  49:         onHeaderButtonClickedListener = listener;
  50:     }
  51: }

In the constructor I inflate the layout and set some member variables that will hold the control references in the layout. I assign the textview and button references and then wire up to the normal click event listener of the leftButton and in there check if there are any listeners to my local OnHeaderButtonClickedListener, if there are, I fire my onLeftMenuButtonClick event. You’ll see in my interface declaration for the Listener that I’ve marked the onLeftMenuButtonClick as abstract.

I expose those Setter methods I mentioned including one to set a listener and we’re done here.

Now, where I need to put it into a consuming layout I reference it like so by fully qualified namespace:

   1: <me.clearlynot.HeaderView
   2:       and:id="@+id/main_menuheader"
   3:       and:layout_width="fill_parent"
   4:       and:layout_height="wrap_content">
   5: </me.clearlynot.HeaderView>

Then in my consuming class I can set properties and wire up like so:

   1: HeaderView header = (HeaderView)findViewById(R.id.main_menuheader);
   2: header.SetTitle("Contact Us");
   3: header.SetLeftButtonVisibility(View.Visible);
   4: header.setOnHeaderButtonClickedListener(new OnHeaderButtonClickedListener()
   5: {            
   6:     public void onLeftMenuButtonClick()
   7:     {            
   8:         AlertDialog wootDialog = new AlertDialog.Builder(MyConsumingClassName.this)
   9:        .setTitle("woot! worked and everything!")
  10:        .create();
  11:  
  12:        wootDialog.show();
  13:     }
  14: });

Then you click the menu button, sit back, and revel in the reusable glory and golden glow of a woot dialog.

Being new to Java and Android, I'd appreciate hearing about any coding conventions I'm contravening here. Otherwise, enjoy!

How to fix Windows Live Writer’s blog templates

February 28

So you’ve heard great things about Windows Live Writer, it’s installed and you’ve pointed it at your blog and you got this:

LiveWriterFailLive Writer has auto detected your blog theme and tried to help you out by setting the {posttitle} and {postbody} tags in the first html header it found and the next text related tag.

The interface doesn’t allow you to change this so you’ll have to go hunting, here’s where it could hiding on your machine:

On XP – C:\Documents and Settings\[Your Username]\Windows Live Writer\blogtemplates\

On Windows 7 and probably Vista - C:\Users\[Your Username]\AppData\Roaming\Windows Live Writer\blogtemplates\

You’ll find there are some folders in there with names that look remarkably GUID-like. Just open the index.htm in a browser and you’ll be able to identify which one you’re after.

A few html / css changes later, a restart of Live Writer and you’re ready to start posting!

Thanks to David Risley whose post led me to this solution.

Just another sheep joining the flock

January 14

I thought I'd start the impromptu new years resolution (to express myself more) a little late.

If I were more of a social animal, I might have decided to do that in person, but hey, we are who we are.

As for me, I'm incredibly picky and I have a very particular esthetic when it comes to almost everything, this can be a real pain when it comes to making decisions.

Coding style, house, electronics, car, socks.. They all have to be as close to 'right' as possible.

As such, the decision to start a personal blog was much more than just the decision to write. It was the decision to embark upon the QUEST for the RIGHT blog engine.

The decision kind of comes down to a choice between Wordpress and BlogEngine.NET.

Simple decision here, PHP vs .NET, with my hosting environment under stress already I can't go adding more dependencies (MySQL, PHP etc).

Otherwise it'd have been a harder decision. I like that Wordpress has millions of plugins and themes (maybe even the right one!), awesome that it's also open source but written in a language I don't know.

I like that I know how to crack open the source for BlogEngine.NET (written in C#) and tweak to my hearts content, though the chance is slim I'd need to, dislike that it's not mainstream enough, there are few templates and plugins available.

I'm still on the quest for the right template but here are some sites that look hopeful.

blogengine theme, janko at warp speed, onesoft and themes4blogs.

If anyone finds any other theme sites or awesome plugins, please comment.

Tristan loves developing with a passion, mostly spending time on project ideas that *could* one day see the light of day.