Unity Unity 3.0 unveiled!

0 Comments

Whoa. Unity really is going to be omni-platform!

I can’t wait to have a chance to make a web game that I then port to iPhone, Android, and XBox Live Arcade. This kind of thing can’t really be understated for small developers because the best way to maximize your revenue per game is to release it on as many platforms as possible.

Some highlights from the press release:

…major updates to Unity’s rendering capabilities, its physics features and significant optimizations to its core systems… [I hope this means PhysX and Mono upgrades!! Confirmed! Mono 2.6.x!]

Illuminate Lab’s Beast lighting software provides Unity developers with a complete global illumination solution for photorealistic scene lighting.

[Unity iPhone has] a very fast 2D sprite engine…

Global illumination and occlusion culling might be Pro-only features, but it’s still really exciting.

Set for release this Summer. Bring it on!!

Marketing Love or Hate: anything else is mediocre

0 Comments

Creating passionate users is NOT about finding ways to make everyone like you. It’s about finding ways to use your own passion to inspire passion in others.
via The Creating Passionate Users blog

Applies just as much with games as anything else.

Zynga has some massive MAU and DAU numbers, but I think you have to be pretty “middle ground” to be that main stream. I also think that’s why social games have a lower ARPU than “core” MMOs and the like.

It’s the hardcore players that will pay. You can certainly get some revenue out of the rest with ads, but I think it would be interesting to try to aim squarely at a specific audience and ignore the allure of being able to state that you have a zillion monthly active users. I’d love to know the ARPPU on that “mediocre” audience versus a passionate audience of 500,000.

Monetization, Virtual Goods Value versus price–let your players decide

0 Comments

“$40 for lips couch, selling like hotcakes.”
–Sebastien de Halleux, PlayFish, speaking about Pet Society

Whoa. I would *never* have priced a virtual couch at $40. Not because I think virtual goods are not worth money, but because my personal sense of value tells me that it’s not worth that price. But there are a lot of factors in play on that decision: my sense of what is fun, my desire to “show off” to other players, my personal income, and so on.

The big lesson here is, as someone famous said, “Value is what it’s worth to a customer; price is what you charge for it.”

We simply can’t comprehend what our players might be willing to pay or do based on our own judgment. I think, especially as indie developers who might not have as much business experience, it’s really hard for us to imagine the value of our products and then price accordingly. I see this a lot in downloadable games with prices like $3 or $5 or $9. If players love your game enough to pay even $1 for it, they probably will pay a lot more (price wars not withstanding).

Online games such as MMOs and social games implementing a virtual goods business model have a similar obstacle. When pricing virtual goods, pick a price that you think nobody would ever pay, then double it. Heck, I’d probably have to quadruple it! I would find it hard to image someone paying $10 for a couch in Pet Society. But to hear that it sells like hotcakes for $40 shows that I could be losing a lot of revenue.

So, start with a high price. You can always come down. Nobody complains about a price drop. You can also test price points with analytics to find the sweet spot.

Project Darkstar, RedDwarf The RedDwarf phoenix

0 Comments

I was kind of shocked to hear that Project Darkstar has been shut down, and its staff laid off. My online multiplayer technology strategy was hinging on Darkstar. Major downer!

But I also learned that a couple of the original Darkstar team members, led by Owen Kellett, has forked the code and is trying to keep it alive as RedDwarf. So, that’s a very cool thing. I hope that it does thrive, because Darkstar is a pretty amazing server technology despite the fact that it’s not finished.

I hope all of Darkstar’s users will migrate to the new project and support it. Anyone can contribute code (though there is a sensible review process), so please go make your mark, and save this great server solution from the trash bin of history!

Marketing Planning a “social media” marketing strategy

0 Comments

A company has to sell products or it can’t continue to create more. To sell, you have to be able to reach people so that they know you exist. I’d rather interact in a useful way with a company about its products than endure more traditional “talk at me” marketing. So I think social media (Facebook, Twitter, etc.) is a pretty cool way to achieve that because it’s very consumer friendly. If you don’t like what you hear, you just stop the interactions (unless it’s an email list you can’t get off of–grrr).

Particularly, I like Facebook’s way of doing things, where you can fan something easily and remove yourself just as easily if it gets spammy. I feel like I am in control, not the marketer, and that makes me more open to hear what’s being offered.

Interesting to those of us who make games and market them, I came across a great post about framing just what a “social media” strategy is and some thoughts on how such a beast ideally works. There was a list of questions to consider when planning, but also some good additions in the comments. So, I’ve gathered them here and integrated them (hopefully!) logically.

  • Do you have something to sell in the end that you can deliver or communicate about? This is the starting point.
  • What types of people do we want to talk to?
  • Where do we find them?
  • What are they talking about already?
  • Is it appropriate for us to join that conversation and, if so, when? (Focus on the conversations that matter and that are relevant and impactful to your brand.)
  • When is it not appropriate to join the conversation. What are the criteria?
  • Who do we empower within the organization to serve as our conversationalists?
  • How do we inject usefulness into the conversation without being overly promotional?
  • What value can we provide in terms of knowledge, opinion or content?
  • How can we earn their trust?
  • When we do earn their trust, how can we best ask for their input into our product or service?
  • Under what circumstances can we point the conversation toward considering our product?
  • Can we say or do something that invites someone else to point the conversation toward considering our product?
  • How do we leverage this vehicle of social media to create brand evangelists?
  • How shall we apologize and regroup if we overstep their comfort level or accuse us of violating their trust?
  • What do we do if people “call us out” and react adversely to our social media presence in a given network?
  • If those unfortunate interactions take place, what can we do to offset said negative interaction from ranking well in search results?
  • What are you learning from their adverse reactions to your product or service?
  • Are you OK with social networks not being OK with everything you do?
  • What is our strategy for true brand opposition?
  • Continue traditional marketing and sales. Social media enhances it, it doesn’t replace it.
  • Don’t expect a sudden influx in orders. It takes about 6 months of hard work and time to get the results coming through.

Marketing .breaking conventionS .and generating interesT

0 Comments

Very entertaining video about how drab following formulas can make things.

Now, there is something to be said about conventions. In games, specifically, many conventions are necessary and good: control schemes, for example, should be common between games because it’s less for a new player to learn (and thus less reasons to be frustrated and quit). Visual interface elements are often useful when shared across games (or computer applications, generally), such as X for “close this window” or a musical note icon for audio options.

The types of conventions I’m thinking of, though, are more along the lines of gameplay mechanics (shoot everything that moves for points) or story lines (save the princess) or visual style (photo-realism). These conventions really can make your game less than great if used carelessly.

The solution? Pick one thing, one feature or one facet of your game, and push it so far over the top that it grabs people right away. The key is balance: don’t overdo it. Too much change, and people will be left confused–and quit your game.

Business Papermint indie

0 Comments

This is a fantastic, heartfelt indie tale. Helps keep you grounded in the experience and the product–not the business plan, monetization, or demographics. Those things are important (critical!), but if you lose your vision tending to them, they don’t matter anymore. A unique game is nothing without its soul.

Please allow me to tell you – merely from my humble perspective – the unbelievable but true story about us, Avaloop, the team that created Papermint. It’s a story about friendship and independence, about how to lose a multi-million lottery ticket, about the really unique thing we created and about hope.

When I came back from the countryside to that cinema in Vienna I was welcomed with so much warmth and enthusiasm. It was just wonderful. I knew that nothing could ever blow us off our little indie feet… whatever the future will bring. With or without Mister Big.

Suddenly we felt this spirit of freedom again! The spirit we were lacking while being drunk of that strange hope for money or fame or security… whatever it was… it had tamed us. Papermint had not grown the natural way during the “PowerPoint”-times… it was endangered to be squeezed into a shape that was not its true shape… it was a marketing/PR/get more users/blah blah/demographic needs-shape we had not consciously cared for in our original plan.

But somehow we were able to stop that deformation in our minds and went back to the original plan.

Inspiring stuff! Read more, and check out the game.

Monetization, Virtual Goods, iPhone Tapulous Pirates

0 Comments

Virtual Goods News reports that:

Over the weekend Tapulous head of business development Tim O’ Brien announced that the company was successfully monetizing pirated copies of its iPhone game Tap Tap Revenge 3 by selling the pirates virtual goods as in-app purchases. Tapulous estimates that Tap Tap Revenge 3 has been downloaded 2.5 million times, but that 1 million of those downloads are pirated copies.

Ok, first of all, if you’re pirating a $.99 game, that’s pathetic and you are a loser. Full stop.

But, it’s nice to see that you can upsell pirates with virtual goods. :)

Pirated copies can still communicate with the Tapulous network and their in-game virtual item shops still work. According to O’Brien, this has lead to some pirate users spending far more than the app’s initial cost on virtual items like additional songs and avatar customization pieces.

So, what if–for non-pirates–you offer the app/game for $.99 (or more, if it’s not on iPhone), and then if the potential customer balks and decides not to buy, you could then offer to give them the game for free?

At least then you have a chance to monetize them later in the cycle. Pirates would have nothing to pirate, and chances are you would end up making more money in the long run even if you give away a majority of copies. (I’m assuming, too, that there’s no physical COGs and it’s exclusively digital delivery.) It sounds like a decent idea and a great experiment to try.

(P.S. My time is being consumed with a non-game business venture right now, but I want to try to blog short little ones like this to keep myself in touch with my most beloved game development universe.)

ActionScript, PushButton Engine Angry Explanations #2: Spinning a freaking image with PBE!

2 Comments

Following on from Angry Explanations #1, we will now add some motion to the scene. For kicks and giggles, we’ll cause the image to rotate each frame.

(Note that this information is in reference to PushButton Engine build r625.)

The key takeaway here is that for a component to be tickable, it must implement the ITickedObject interface and then tell the ProcessManager to start and stop calling onTick() every tick.

Oh, there’s one other key takeaway here: how to use PropertyReferences. You get a property of a component by way of the owning entity. You create a PropertyReference instance for each data member that you need to access. In this example, we’re accessing the rotation field on the SpriteRenderer component we added in Angry Explanations #1.

In a bit more detail, the PropertyReference is constructed with a special string: "@Sprite.rotation" (see line 11 in the code below). That means, this is a reference to the component of this entity with the name “Sprite” (recall that we gave it that name when we created the SpriteRenderer component instance), and the field “rotation” of the SpriteRenderer class. It’s quite simple once you realize what it’s doing (but I’m no less angry, mind you!).

I thought that a SpatialComponent might be necessary to alter the sprite’s position, but apparently that component has been removed (since r470, which is the current packaged release). That data seems to now be handled by the renderer component itself.

Add this one line to the end of showLogo() from the previous example:

spriteEntity.addComponent( new SpinController(), "spinner" );

Then add the following new class in a sub-folder (components/controllers/).

package com.yourcompany.yourgame.components.controllers
{
	import com.pblabs.engine.core.ITickedObject;
	import com.pblabs.engine.core.ProcessManager;
	import com.pblabs.engine.entity.EntityComponent;
	import com.pblabs.engine.entity.PropertyReference;

	public class SpinController extends EntityComponent implements ITickedObject
	{
		// Cache the PropertyReference instance here to avoid a bunch of temporary allocations.
		private var _rotProp:PropertyReference = new PropertyReference( "@Sprite.rotation" );

		// Nothing to do in the constructor because this is such a simple example.
		public function SpinController()
		{
			super();
		}

		// When the component is added to the sprite entity, we want to register to
		// get tick updates by the ProcessManager.
		protected override function onAdd():void
		{
			super.onAdd();

			ProcessManager.instance.addTickedObject( this );
		}

		// When the component is removed from the sprite entity, we want to unregister
		// from the ProcessManager so tick updates will stop.
		protected override function onRemove():void
		{
			super.onRemove();

			ProcessManager.instance.removeTickedObject( this );
		}

		// Each tick, we just change the rotation of the sprite renderer a little bit.
		public function onTick(tickRate:Number):void
		{
			// Get the current rotation.
			var rotation:Number = owner.getProperty( _rotProp ) as Number;

			// Add 1 degree to it.
			rotation += 1;

			// Store the new rotation back in the sprite.
			owner.setProperty( _rotProp, rotation );
		}
	}
}

As an addendum, I should point out that the rotation will probably not be smooth. To fix that, you should have the SpinController implement IAnimatedObject instead of ITickedObject. The registration with the ProcessManager is the same, except you call addAnimatedObject() instead of addTickedObject().

The difference is that IAnimatedObject will update when Flash draws a frame instead of when the ProcessManager ticks, and the motion will appear a lot smoother.

And you’ll want to normalize the rotation based on delta time since the last frame. Er, like this:

public function onFrame( elapsed:Number ):void
{
	var rotation:Number = owner.getProperty( _rotProp ) as Number;

	// Rotate 15 degrees per second, nice and slow.
	rotation += 15 * elapsed;

	owner.setProperty( _rotProp, rotation );
}

ActionScript, Flex, PushButton Engine Angry Explanations #1: How to draw a freaking image with PBE!

5 Comments

(Thanks to Ben G. for that humorous title! :D And just to be super clear–I’m not angry at all about PBE. The anger is entirely tongue-in-cheek.)

So, yeah, I got started with PBE at a bad time, I think.

It’s in transition between some major changes, and so all the docs and tutorials to this point are out of sync and kind of very… confusing. Because of that, I really struggled to figure this out, and in fact couldn’t get an image on the screen without professional help (I’ll let you interpret that however you’d like).

This information is relevant for PBE r625 and up.

(This isn’t to say the engine is poorly designed–it’s simply not accurately documented in places because it has been changing so quickly. And to be fair, it’s still in beta. I wouldn’t use the engine if I didn’t think it was great.)

A frustrated noob’s guide to getting a freakin’ image on the dang screen using Flex 3

Here’s the MXML which will reference the code.

<?xml version="1.0" encoding="utf-8"?>
<game:Game
	xmlns:mx="http://www.adobe.com/2006/mxml"
	xmlns:game="com.yourcompany.yourgame.*"
	width="750"
	height="600"
	layout="absolute">

</game:Game>

Now define a resource in a ResourceBundle subclass, which is the image you want to display, and let PBE automagically make it accessible through the resource manager.

package com.yourcompany.yourgame
{
	import com.pblabs.engine.resource.ResourceBundle;

	public class EmbeddedResources extends ResourceBundle
	{
		// The path is magically also the name of the resource.
		[Embed(source="../assets/images/logo.png", mimeType="application/octet-stream")]
		public var logoImage:Class;
	}
}

Put that image into action! It’s a simple notion, but somewhat complicated if you’re new to the engine and its gooey innards.

package com.yourcompany.yourgame
{
	import com.pblabs.engine.PBE;
	import com.pblabs.engine.entity.IEntity;
	import com.pblabs.engine.resource.ImageResource;
	import com.pblabs.engine.resource.ResourceManager;
	import com.pblabs.rendering2D.DisplayObjectScene;
	import com.pblabs.rendering2D.SpriteRenderer;
	import com.pblabs.rendering2D.ui.FlexSceneView;

	import mx.containers.Canvas;
	import mx.core.Application;
	import mx.events.FlexEvent;

	public class Game extends Application
	{
		public var resources:EmbeddedResources;

		// We need access to this in a couple of functions.
		private var _scene:DisplayObjectScene;

		public function Game()
		{
			super();

			// Let the Flex Application initialize fully before we muck with it.
			addEventListener( FlexEvent.APPLICATION_COMPLETE, onStartup );
		}

		// This is called once the Flex app (stage, in particular) is initialized.
		private function onStartup( e:FlexEvent ) : void
		{
			// Load our embedded resources (the image to show).
			resources = new EmbeddedResources();

			// Tell PBE to initialize and pass it our instance so it can get the stage.
			// (Remember, Application is a subclass of Sprite, which PBE needs.)
			PBE.startup( this );

			createPbeScene();

			showLogo();
		}

		private function createPbeScene():void
		{
			// Create a new IEntity for the scene view.
			var sceneEntity:IEntity = PBE.allocateEntity();
			sceneEntity.initialize( "sceneEntity" );

			_scene = new DisplayObjectScene();

			// Since this is Flex, we need the appropriate scene view class.
			var sceneView:FlexSceneView = new FlexSceneView();

			// Set up the view size.
			sceneView.width = 750;
			sceneView.height = 600;

			// FREAKIN' IMPORTANT: add the view as a child to our display list!
			this.addChild( sceneView );

			// Connect the view to the display object scene (a component).
			_scene.sceneView = sceneView;

			// Add the display object scene to the scene entity.
			sceneEntity.addComponent( _scene, "renderer" );
		}

		private function showLogo():void
		{
			// Create a new IEntity instance for the sprite to be displayed.
			var spriteEntity:IEntity = PBE.allocateEntity();
			spriteEntity.initialize( "logoEntity" );

			// Add a sprite rendering component.
			var sprite:SpriteRenderer = new SpriteRenderer();

			// Tell the renderer to draw (and load) this image resource.
			sprite.fileName = "../assets/images/logo.png";

			// Tell the renderer to draw to the display object scene.
			sprite.scene = _scene;

			// Add the component to the sprite entity.
			spriteEntity.addComponent( sprite, "sprite" );
		}
	}
}

So, what the heck just happened? Pfft! Don’t ask me! I’m still a freakin’ noob! :)

I know a couple of things, though. The SceneView is like a “canvas” where all DisplayObjectRenderers are drawn. So you create entities and fill them with components (like a SpriteRenderer) and tell the renderer component about the scene view. Magically, the sprite appears! It’s not too much to understand if you just want to know the API and how to use it.

To really understand it, you’ll need to look under the hood and figure out the connections. A good bit of hidden work is being done to simplify the API, but possibly at the expense of understanding. It’s neither good nor bad. It’s just The Way of PBE (for now).

Feel free to post here to help fill my gaps in comprehension. I haven’t used the engine enough to write a thorough explanation, and I’m not too proud to accept help. :)