Inference

Telling you how we see the world.

A Sliding Puzzle While You Wait

Posted by Jay on Apr 24th, 2010

One of the issues we have had with Cadmus is that the first time you sign in or if you sign in after a while you would need to wait a bit before we show you your updates. On an average it takes around a minute to process your Twitter stream. We are working on ways to improve that but in the meanwhile we wanted to do something to improve the user experience during that delay.

We decided to add in a game that users could play around with while they waited for the process to complete. Inspired by the pong preloaders on some of the console games and the Highrise Tic-Tac-Toe setup game we set out to build one of our own. I looked at the various options and settled on the Sliding Puzzles since it was moderately difficult to play, relatively simple to build and easy to brand! The result is a fun to play 9-piece sliding puzzle that uses the Cadmus logo as the image.

puzzle

The puzzle was intended only for new users and users that have been inactive for a while but it was so fun to test/play; I decided to make it available for existing users as well. You can check it out @ http://thecadmus.com/?puzzle. You need to be logged in before visiting that URL.

The Details

Lets dive right into some the things that I used to build the puzzle. Firstly the puzzle image which is a single image of the Cadmus logo. I wanted each of the pieces in the puzzle to seem like a piece on a board. Meaning it needed to have a shadow to give a feel that it is sitting on top of the board. I did this by using the CSS3 box-shadow property and the rgba properties to give the effect of a shadow.

div.puzzle div.piece {
	width: 100px;
	height: 100px;
	background: transparent url(puzzle-image.png) no-repeat top left;
	position: absolute;
	cursor: pointer;
	box-shadow: 1px 1px rgba(0, 0, 0, 0.26);
	-moz-box-shadow: 1px 1px rgba(0, 0, 0, 0.26);
	-webkit-box-shadow: 1px 1px rgba(0, 0, 0, 0.26);
}
div.puzzle div.piece-0 {
	background-position: 0 0;
}
div.puzzle div.piece-1 {
	background-position: -100px 0;
}
...

The second part of creating the puzzle was the board itself. As with all the other elements it is important that it fits in with the rest of the application. I went with the look where the board is cut into the canvas because it reminds me of how most sliding puzzles are in reality. They are usually set into the surface so the pieces don’t slide off the board.

Picture 6

The grid within the board are also cutting further into the board to give a really crisp feel to the whole thing. Lets look at the effects used to create the board in a little more detail.

board

  1. A 1 pixel stroke on the outside of the board that is lighter than the background giving the impression that the board is set into the canvas. There is also an inner shadow on the board to further the effect. It is a matter of playing around with these effects to figure out how much the board is cut into the canvas.
  2. The texture and color of the board is different from the texture of the canvas to give you the feel that there is something underneath the canvas. I used a layer of noise and a layer of the Gray Granite texture in Photoshop to create it. My general rule of thumb with textures is that they should be noisy but not too noisy. It means that it should be noisy enough to give you the feel of the texture but not too noisy that you see the Photoshop layer effects instead of the texture itself.
  3. There is also a slight inner glow to further the effect of the shadow the canvas casts on the board.
  4. The grid is three 1 pixel lines; the two outer ones are white and the inner one is black in color. The three lines have 13%, 45% and 43% opacity respectively. The values would differ depending on the background but it is important to remember that it is the third line’s job to highlight the second one. The effect does not work if they don’t play well together.
  5. Finally, there is a slight gradient across the whole board that is darker at the top and lighter at the bottom. Again, further adding to the effect that the board is cut into the canvas.

The final part of creating the puzzle is the JS portion of it. Most of it is really straight forward; I have an array representation of the board, an array of possible moves for each position and an array of CSS left and top values for each position. And so every time a piece is clicked the following function runs.

'onPieceClick': function(e, el, args) {
	var from = this.getPositionForPiece(args.position),
	to = this.getAvailableMove(from);
 
	return (to === null)
		? this
		: this
			.stopMoveAnimation()
			.setCurrentPieceEl(args.el)
			.movePiece(args.position, args.el, from, to)
			.checkStatus();
},

We find the position given the piece number (pieces are numbered 0-8) and find the available moves given the current position. If there is a move then we stop any current animations (the last piece could still be sliding into place), save a reference to the current piece, move the piece and check the status of the board to see if the puzzle has been solved.

To start the game we need to randomize the board. But a number of possible positions for this puzzle are unsolvable. So I wrote up this function that shuffles the pieces along in a similar manner a user would click around the board to shuffle it up.

'shufflePiece': function(i, position, lastPosition) {
	if (i > 0) {
		var from = this.getRandomExcept(
			this.movesList[position],
			this.getExcludeList(lastPosition)
		),
		piece = this.getPieceForPosition(from);
 
		return this.movePiece(
			piece,
			this.getPieceEl(piece),
			from,
			position,
			function() {
				return this.shufflePiece(i - 1, from, position);
			}
		);
	}
 
	return (this.isSolved())
		? this.shufflePiece(this.shuffleCount, 9, null)
		: this.startGame();
},
...
this.shufflePiece(this.shuffleCount, 9, null);
...

I get the available moves for the given empty position in the board and I also exclude the previous empty position since I don’t want the randomizer to pick the previous move. This function calls itself as it shuffles every move. I start it off by passing in the number of times I want it shuffled and the first empty position on the board. Now at the end of all the shuffling I might end up right where I started so I have a simple check that restarts the shuffling if that happens. A better approach would be to calculate the distance of the shuffled state from the solved state and set a lower limit on that.

The entire code for the game is actually quite small and it was relatively simple to implement (not to mention fun to test). We will keep an eye on how this impacts the experience for a new user and see if it actually helps.

By going into the different aspects (CSS, Photoshop and JS) of building this feature, I am hoping it would help others venture out into areas that they have been previously shying away from.

Notes

If you have any questions or would like me to go into further detail; just let me know on Twitter.

Also, check out the 37signals post about the Tic-Tac-Toe game in their Highrise iPhone app.

Share

Please do share this on .

Thanks for all the mentions

Posted by Jay on Apr 11th, 2010

Just wanted to make a quick post about the press Cadmus has gotten recently.

The Tweet House panel at SXSW with @brian_wong, @scobleizer, @markmilian, @domLink (around 13:07)

Opening up opportunity with Twitter at Mix10 by @rsarver and @raffiLink (around 20:39)

A Cinchcast with @louisgrayLink

With @scobleizer at the Palo Alto Apple Store – Link

Thanks guys!

Lists and Topics in Cadmus

Posted by Jay on Mar 24th, 2010

We recently rolled out the Lists feature for everybody. This means that Cadmus will find top conversations and trending topics from your lists. You can use this to stay updated on a certain topic (like social media) without having to follow all the related people on Twitter. You can simply follow a list (Cadmus will sync your lists automatically) and you can keep up with them really easily.

We used this idea to create a page that helped people stay up to date with the SXSWi speakers. We simply used the list created by @sxsw and started finding the top content from that list. And now we extended the idea to other topics. Earlier this week @raffi tweeted about the suggested users API. We used that API to create lists for certain topics and have created public pages where you can see their trending topics and conversations. For example, you can see the top content from the topic of technology here and you can see all the topics we have here.

A quick note on syncing lists; if you find that a list that you have just followed or un-followed is not showing up in Cadmus it might be because we haven’t synced it yet. But if you want to see the changes right away, you can head over to the Services page and click on your Twitter service and then hit the Sync Service button.

Let us know what you think of the Lists and Topics feature on Twitter.

I had previously created the Cadmus “post” button in Photoshop and it was essentially three images for the different states. I wanted to use this style for all our buttons, but doing it with single images is not a good idea. So I set about creating the same style of the buttons with CSS3. And this is what I ended up with.

post-buttons

I want to go into detail on the steps I took to create the button and the effects that make it work.

The Devil is in the Details

The whole idea is to use a combination of subtle effects to create a three dimensional object. Mike Rundle covers some of the ideas used here in his post about subtlety in interfaces. I’m hoping to expand a bit more on that. The idea is that:

  • The button is set into the canvas.
  • The texture of the button is different from the canvas and the surface is slightly raised.
  • And the text of the button is pressed into it.

Lets take a deeper look at the button and the various effects that we use to create this idea. The HTML used for the button is a bit excessive, but it will make sense when we go into detail.

<a class="button"><b class="o"><b class="m"><b>Post</b></b></b></a>

Now onto the styles.

  1. A simple gradient that is lighter at the top to show that the light source is above it and the surface is slightly raised. We use a 1px width background image for this.
  2. a.button b.m {
    	background: transparent url(button.png) repeat-x 0 0;
    }
  3. A lighter border around it to show that light is reflecting off the edges. We use the CSS3 rgba property for this. We need the alpha blending because the reflected light is far more visible at the bottom than the top.
  4. A hard 1px top border to show that light reflects off the top edge more than the other edges.
  5. a.button b.m {
    	border-width: 1px;
    	border-style: solid;
    	border-color: #FFF rgba(255, 255, 255, 0.33) rgba(255, 255, 255, 0.33);
    }
  6. A lighter 1px bottom border to create the effect that the button is sitting right in the canvas.
  7. a.button {
    	border-width: 1px;
    	border-style: solid;
    	border-color: transparent transparent rgba(255, 255, 255, 0.63);
    }
  8. A 1px border around the button to show the shadow of the button on the canvas. Again using the rgba.
  9. a.button b.o {
    	border: 1px solid rgba(0, 0, 0, 0.56);
    }
  10. And finally the shadow on the button text to show that it is pressed into the surface.
  11. a.button b.m b {
    	text-shadow: 0 1px 0 #DDD;
    	color: #262626;
    }

The State of Buttons

I like adding hover states to my buttons and the simplest way is to lighten the background color of the button. For the active or mouse down state of the button the effect we are trying to achieve is that of a raised surface pressed inwards. Hence, the lighting of the button should reflect that. Now there are a couple of different ways to do this.

I like the idea where the surface is pressed in, but the top edge doesn’t move. Instead of having the entire button moving in, just the raised part gets pressed in. We go from a convex shape to a concave shape when it is pressed.

Lets look at it in detail again.

  1. Flip the gradient from before. The darker shade of the gradient is darker than the darkest shade of the previous gradient. This is important because the light hitting the bottom of a convex shape should reflect more than the light hitting the top of a concave shape.
  2. a.button:active b.m {
    	background-position: 0 -160px;
    }
  3. A light top border to emphasize that the top edge doesn’t move when the shape of the surface changes.
  4. The bottom border is lighter as well since the bottom edge doesn’t move either.
  5. The borders of the side are a bit lighter, but not very much since they do move with the surface.
  6. a.button:active b.m {
    	border-color: rgba(255, 255, 255, 0.11) rgba(255, 255, 255, 0.23) rgba(255, 255, 255, 0.27);
    }

Show and Tell

The result is a great looking button with CSS3. Below is a live demo of it tested on Firefox 3.6, Safari 4 and Chrome. On IE8 the rounded corners and active state are missing, and I haven’t tested it on Opera yet. If you do either of them, please ping me on Twitter and let me know.

Below is most of the CSS and here is the image sprite that is used. I use the yui reset CSS on the page so it might be a bit different for you.

a.button {
	text-decoration: none;
	border-color: transparent transparent #ECECEC; /** rgba fallback **/
	border-color: transparent transparent rgba(255, 255, 255, 0.63);
	cursor: pointer;
	outline: none;
}
a.button:hover {
	text-decoration: none;
}
a.button,
a.button b.o,
a.button b.m {
	-moz-border-radius: 4px;
	-webkit-border-radius: 4px;
	border-radius: 4px;
	border-width: 1px;
	border-style: solid;
	display: block;
}
a.button b.o {
	border-color: #5A5A5A; /** rgba fallback **/
	border-color: rgba(0, 0, 0, 0.56);
}
a.button b.m {
	background: transparent url(button.png) repeat-x 0 0;
	border-color: #FFF transparent #C7C7C7; /** rgba fallback **/
	border-color: #FFF rgba(255, 255, 255, 0.33) rgba(255, 255, 255, 0.33);
}
a.button:hover b.m {
	background-position: 0 -80px;
}
a.button:active b.m {
	background-position: 0 -160px;
	border-color: #B7B7B7 transparent #D4D4D4; /** rgba fallback **/
	border-color: rgba(255, 255, 255, 0.11) rgba(255, 255, 255, 0.23) rgba(255, 255, 255, 0.27);
}
a.button b.m b {
	display: block;
	font-weight: bold;
	padding: 4px 8px;
	text-shadow: 0 1px 0 #DDD;
	color: #262626;
	/** Make the text unselectable **/
	-moz-user-select: none;
	-webkit-user-select: none;
}

I use the innermost b tag in some other buttons to add an icon to the background. The b.m tag is required because the alpha blending for the b.o border needs to have its own “layer”. Otherwise the b.o border would be on top of the background image and the shading would change according to it.

I am hoping that by going into the detail you can use these techniques in your designs and as Mike mentions in his post; think about your designs in 3D. It is less about using the specific border effects and more about using them together to achieve an overall look.

Notes

I would love to hear your feedback and comments; just catch me on Twitter.

Also, check out zurb’s super awesome CSS3 buttons. They have a take on CSS3 buttons and the buttons are super awesome!

Share

Please do share this on .

Updates

I have received some really impressive feedback for this post. And I am glad that people have taken my ideas further and have done a great job with it. Here are some of the ones that I found. Please let me know on Twitter if I am missing some.

Thanks to @mliao for reading over this post.

So I’ve been thinking about the idea of how our perceived value of things shapes our lives and habits. It all started when my co-founder and I were out getting lunch. Over the course of working on our startup we have tried several places (mostly cheap ones) for food. And we are always looking for a good deal that fits our taste and choice. But after trying so many different ones we have grown tired of pretty much all of them. So inevitably around lunch time we need to answer the question; what should we get for lunch? And most of the time we just delay the question till we are so hungry that it doesn’t matter what we get anymore. But recently we went to this place that gives you one of those little cards with ten squares that they mark off every time you buy something from them. And when you fill up all the squares you get a free lunch. And now we suddenly have a preference when it comes to getting lunch. This place gets a slight advantage when we need to decide where to go.

This got me thinking and so I was trying to figure out why this is so. Now the initial response would be; well they give you a free lunch for every ten purchases which gives it a slightly higher value. But there is more to it; if we could change the price of the lunches so that buying 10 (and getting 1 free) from them would be equivalent to buying 11 from any other place; this place would still get a slight advantage. And that is the idea of the perceived value. The real value of the two cases might be the same but the perceived value is not.

Marketers have been doing this really well over the years [1]. A strong brand can create a greater perceived value. A star using a certain product can create it. A fashion trend can create it as well; nerdy glasses are suddenly all the rage. As people living in society it is hard for us the clearly distinguish between real and perceived value. Marketers use this to their advantage and work on increasing the perceived value rather than the real value of a product or service.

I found that the increase in perceived value can be traced to two factors that matter to our daily lives. If the usage of a product or service aids in self improvement (real or otherwise), its perceived value increases. The “buy 10 lunches get 1 free” is an example of that. It gives me the feeling that it is a better deal and if I’ve just bought my fifth lunch, I am that much closer to bettering myself. The second factor is how well we are doing when compared to our peers as a result of using that product of service. We can see examples of this all around us. And so, many products are considered status symbols as a result of this.

Now if we apply these ideas together we are really able to increase the perceived value of a product. So imagine if I could not only get a free lunch but also if I could see how well I am doing when compared to my friends. You can really tap into this with the help of social media. Great examples of this are the social gaming space [2]. Where we are able to show our friends what games we play, how well we are doing with respect to each other and our achievements in them. The games also do a great job of giving you the feeling that the real cost of playing the game is almost negligible but the perceived value of doing well at it is really high. They also ensure that the perceived value rises as you continue to play the game. We also see examples of perceived value in social networks where we want to show our peers how many friends/followers/fans we have, how many different books we have read, the number of movies we have watched, etc. The social networks are fine tuned to make it really easy to show this off as well. A great example of this are those Foursqare Twitter updates that keep filling up our stream.

With social media we have found a way to bring our everyday lives online and make it far more accessible to people around us (and the world). Now more than ever it is easier to let others know about the great benefits of using a certain product or the high score on your game. It is easier to participate, easier to voice your opinion, easier to show off your unique tastes and hence from a brand’s perspective easier to increase the perceived value of their product or service.

[1] There is a talk about this by Rory Sutherland – Life lessons from an ad man

[2] Jesse Schell on the Facebook games era – DICE 2010: “Design Outside the Box” Presentation

Anomaly Follow us on Twitter Contact us via Email