Monthly Archives: November 2015

Attack of Giant Jumping Man Revealed

Pleased to say we’ve just recently released the first trailer of gameplay footage from ‘Attack of Giant Jumping Man’, the debut Joystick Junkyard title. The trailer is taken from actual gameplay footage of the alpha version which contains the first five levels of the game.

The trailer was all thrown together pretty quickly and we weren’t going to make it public – then we thought ‘ What the hell… why not?’ So far it’s had a pretty good response too!

Anyway – please check it out and any liking/sharing and all that other nonsense is much appreciated!


Attack of Giant Jumping Man

Updating Legacy MonoGame Projects to iOS9 / Unified API

Just the moment you long for. Apple releases a new iOS update and that breaks something in your development platform of choice (Xamarin/MonoGame in my case) and all your apps no longer work. Great. Like I didn’t have enough to do.

And as with everything Apple nowadays – any kind of update seems to break everything else thereby creating a domino effect of pain and tedium as you wait for gigabytes of data to download over a shitty rural broadband connection. Oh, the joy!

So, without further ado here’s how to update your legacy MonoGame projects to iOS9 and the Unified API. Hopefully this will make life a little easier for someone.

If you have a crappy broadband connection buy a copy of ‘War And Peace’ or something suitable to keep you occupied.

If you’re running an OS earlier than Yosemite update to El Capitan. You’re going to have to unfortunately. You’ll need XCode 7 and that only runs on Yosemite or later. Apple aren’t big on backwards-compatibility these days.

Update to XCode 7.

Update everything Xamarin-related to the latest version. I’m currently running Xamarin Studio 5.10 which at the time of writing is on the alpha update channel. I was getting some issues with creating archives using the current ‘stable’ release.

Update any additional components you are using to the latest version – for example I was using the Xamarin Google AdMob component. Make sure to add the ‘unified’ version.

Open the solution you are updating and try to build it – you may get the following error:

/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/iOS/Xamarin.iOS.Common.targets: Error: Error executing task DetectSdkLocations: Unknown TargetFrameworkIdentifier: .NETFramework

Remove the references to monotouch and OpenTK from your project and instead add references to OpenTK-1.0.dll and Xamarin.iOS.dll (these are visible under the ‘all’ tab when you go to edit references).

Try and build the project again. You will probably get a shedload of errors to do with it not being able to find the MonoTouch namespace. Just get rid of all references to MonoTouch, ie replace ‘using MonoTouch.Foundation;’ with ‘using Foundation;’ or ‘using MonoTouch.UIKit;’ with ‘using UIKit;’ etc.

Depending on how many of the native classes you referenced you may have some additional work to do here, probably involving changing ‘float’ references to ‘nfloat’. Hopefully you’re not referencing too many of these as the whole point of MonoGame is that we avoid the native classes if possible (I just had to change some of my ad-serving code).

Hopefully your code should now compile and the only remaining errors (if any) are due to an outdated MonoGame, for example:

Error CS0012: The type `MonoTouch.UIKit.UIImage’ is defined in an assembly that is not referenced. Consider adding a reference to assembly `monotouch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065′ (CS0012)

Download and build the latest version of MonoGame from the Develop branch on GitHub. At the time of writing there are issues with the latest ‘stable’ build of MonoGame (3.4) with iOS9 so you will need the version from the Develop branch. Change all the MonoGame references in your project to the latest versions.

Hopefully you should now get an error free compile, however you may get something like the following:

Error MT0073: The minimum deployment target for iOS is 5.1.1 (current deployment target is 4.2). Please select a newer deployment target in your project’s Info.plist. (MT0073)

To resolve this simply change the deployment target of your iOS project to 5.2 (note: this setting is now in the info.plist file).

Try and compile again. Most likely you will now get the following errors:

Error MT0016: The option ‘–nomanifest’ has been deprecated. (MT0016)

Error MT0016: The option ‘–nosign’ has been deprecated. (MT0016)

To resolve this your .csproj file needs to be changed so that it’s building using the ‘unified’ settings. Bit of voodoo required here as you will have to quit Xamarin and edit the .csproj file for your iOS project using your text editor of choice. Follow the instructions in step one of the ‘Steps To Update Manually’ section here. In short:

Change the project flavor in your csproj files from ‘6BC8ED88-2882-458C-8E55-DFD12B67127B’ to ‘FEACFBD2-3405-455C-9665-78FE426C6842’. Edit the csproj file in a text editor and replace the first item in the <ProjectTypeGuids> element.

Change the Import element that contains ‘Xamarin.MonoTouch.CSharp.targets’ to ‘Xamarin.iOS.CSharp.targets’.

You should now, finally, be able to compile and run your project on a connected iOS device. If, on launch, you get the following error:

System.EntryPointNotFoundException: alcMacOSXMixerOutputRate
at at (wrapper managed-to-native) Microsoft.Xna.Framework.Audio.OpenALSoundController:alcMacOSXMixerOutputRate (double)
at at Microsoft.Xna.Framework.Audio.OpenALSoundController.OpenSoundController () in <filename unknown>:line 0
at at Microsoft.Xna.Framework.Audio.OpenALSoundController..ctor () in <filename unknown>:line 0
at at Microsoft.Xna.Framework.Audio.OpenALSoundController.get_GetInstance () in <filename unknown>:line 0
at at Microsoft.Xna.Framework.iOSGamePlatform..ctor (Microsoft.Xna.Framework.Game game) in <filename unknown>:line 0
at at Microsoft.Xna.Framework.GamePlatform.Create (Microsoft.Xna.Framework.Game game) in <filename unknown>:line 0
at at Microsoft.Xna.Framework.Game..ctor () in <filename unknown>:line 0

You are not running the latest MonoGame build from the Develop branch as described earlier. Unfortunately MonoGame 3.4 and earlier exhibit this problem with iOS9. Update all the MonoGame references in your project to the latest version from the Develop branch on GitHub.

If you’ve made it this far without losing the will to live your app should be running on iOS9. I’m afraid to say your problems aren’t over though. Once you have built your updated app and try and upload to iTunesConnect using the Application Loader you will more than likely run into the following errors:

ERROR ITMS-90086: “Missing 64-bit support. Beginning on February 1, 2015 new iOS apps submitted to the App Store must include 64-bit support and be built with the iOS 8 SDK. Beginning June 1, 2015 app updates will also need to follow the same requirements. To enable 64-bit in your project, we recommend using the default Xcode build setting of “Standard architectures” to build a single binary with both 32-bit and 64-bit code.”

To fix this under Project Options->Build->iOS Build->Supported Architectures select ‘ARMv7+ARMv7s+ARM64’

ERROR ITMS-90474: “Invalid Bundle. iPad Multitasking support requires these orientations: ‘UIInterfaceOrientationPortrait,UIInterfaceOrientationPortraitUpsideDown,UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationLandscapeRight’. Found ‘UIInterfaceOrientationPortrait’ in bundle ‘com.bitbull.flappingbird’.”
ERROR ITMS-90475: “Invalid Bundle. iPad Multitasking support requires launch story board in bundle ‘com.bitbull.flappingbird’.”

To fix this add a setting’UIRequiresFullScreen’ to your project’s info.plist file and set it to ‘YES’.

Hopefully you should now be good to go and if you got this far without topping yourself – well done! It’s not exactly the most straightforward process in the world!

Playing MP3 Background Music In MonoGame Windows

The process of porting ‘Attack Of Giant Jumping Man‘ to Windows Desktop has been generally painless. One of the things that has given me the most issues though has been getting MP3 background music to play correctly. For some reason the WindowsGL version of MonoGame doesn’t support MP3 files as XNA Song objects to play via MediaPlayer.Play().The solution, as usual with these kind of issues, is to go native. Unfortunately just doing something as simple as playing an MP3 file on Windows is much more convoluted than would seem necessary if you want to avoid including additional dependencies (DirectX, Windows Media Player etc) into your project.

So, here’s some code that will play MP3 files without the need for additional dependencies by hooking into the winmm.dll. Import your MP3 resources using the MonoGame pipeline tool and just set to ‘copy’ with no pre-processing. Code could probably do with tidying up a bit but it works!

#region Using Statements
using System;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Input;
#endregion

namespace com.bitbull.meat.platform.windows
{
    public class WinmmMp3MediaType
    {
        [DllImport("winmm.dll")]
        private static extern long mciSendString(string lpstrCommand, StringBuilder lpstrReturnString, int uReturnLength, int hwndCallback);
        private string filename;
        private string command;
// Expects a name like 'yourfile' WITHOUT an extension (just for consistency with Content.Load)
// Expects files to be stored at root of Content directory with no pre-processing 
        internal WinmmMp3MediaType(string name)
        {
            filename = "Content/" + name + ".mp3";
        }

        internal override void Play(int loopcount, float volume)
        {
            StringBuilder retvalue = new StringBuilder();
// You need to stop and close and currently playing files otherwise it doesn't work properly
            command = "stop Mp3File";
            mciSendString(command, null, 0, 0);
            command = "close Mp3File";
            mciSendString(command, null, 0, 0);
            command = "open " + "\"" + filename + "\"" + " type MPEGVideo alias Mp3File";
            mciSendString(command, retvalue, 0, 0);
// I've commented out the code for setting the volume as it's specific to the way I do things but basically this command expects an integer between 0 (min volume) and 1000 (max volume) 
            // float master_volume = MEAT.Platform.MediaInterface.MusicVolume / 100.0f;
            // mciSendString(string.Concat("setaudio Mp3File left volume to ", (int)volume*master_volume*1000), null, 0, 0);
            // mciSendString(string.Concat("setaudio Mp3File right volume to ", (int)volume*master_volume * 1000), null, 0, 0);
            command = "play Mp3File";
            if ( loopcount<=0 )
            {
                command += " REPEAT";
            }
            mciSendString(command, retvalue, 0, 0);
        }

        internal override void Stop()
        {
            command = "stop Mp3File";
            mciSendString(command, null, 0, 0);
            command = "close Mp3File";
            mciSendString(command, null, 0, 0);
        }
    }
}

Going Full Screen In MonoGame Windows

One of the things that caused me some issues when porting ‘Attack Of Giant Jumping Man‘ to Windows was getting the game to run full screen at the correct resolution.

Unfortunately the MonoGame calls that should return the dimensions of the primary display don’t seem to work correctly on all hardware. My system was OK (a Mac Pro running Windows 8 via VMWare Fusion) but on @PVBroadz Surface Pro 3 MonoGame would, for some reason, insist the primary display was only 720 pixels wide.

My solution to this was to use native calls to return the width and height of the primary display, the following in my Game.Initialize() method seems to work just fine when placed after baseInitialize()…

GraphicsDeviceManager.PreferredBackBufferWidth = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width;
GraphicsDeviceManager.PreferredBackBufferHeight = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height;
GraphicsDeviceManager.IsFullScreen = true;
GraphicsDeviceManager.ApplyChanges();

…don’t forget to add a reference to the System.Windows.Forms dll!