Risk Legacy Mapper History

I’ve created a page where I’ll keep track of the history of changes to the Risk Legacy Mapping Tool. It’s also a good place to give me feedback and stuff. Thanks.

Tagged with: , , , , ,
Posted in D3, Mapping Tool, Risk, SVG

Risk Legacy Mapper – new and in D3!

So, it’s been a while since I posted anything, because I’ve been working on a new version of the Risk Legacy Mapper.

Risk Legacy Mapper

You can find the new mapping tool here.

The most obvious change is that it uses the proper Risk map that I found in the previous post, rather than the somewhat blocky (but stylish?… probably not) map that I used for the previous version of the mapper. Under the hood, the application is built using D3 instead of jQuery SVG.

The new mapper is still very much in the design stage. You can add and name cities, add scars, add armies and name continents, but that’s about it at the moment. I’ll be adding other functionality in the coming weeks, including the ability to save your map as a code, like the old mapper.

There are no spoilers on the map. Everything on it is available from the moment you break the seal on the box. If and when I add later-game functionality, it will be a pro-active choice to turn it on, so there’s no danger of seeing anything you shouldn’t!

If you happen to find the tool, and you have any thoughts on things I could add or change to make it more useful, then please let me know by commenting on this post.

Tagged with: , , , , ,
Posted in D3, Risk, SVG

A Risk Map in SVG

I’ve managed to track down a decent map of a Risk board, created using SVG. You can find the original SVG, generated using Inkscape by Gr0gmint here. For my own nefarious purposes, I have stripped out everything except the country outlines and changed the co-ordinate system slightly. You can see the result below, and you can access the source here.

Tagged with: , , ,
Posted in Risk, SVG

SVG Dice using D3

This is a javascript D3 function I wrote to create SVG dice images.

function append_die(element,number,cx,cy,width,colour,dotcolour) {
	element.append("rect").attr("x", cx-width/2).attr("y", cy-width/2).attr("width", width).attr("height", width).attr("rx", width/6).attr("ry", width/6).attr("fill", colour);
	if (number == 1) {
	element.append("circle").attr("cx", cx).attr("cy", cy).attr("r", width/8).attr("fill", dotcolour);
	}
	if (number == 2) {
	element.append("circle").attr("cx", cx+width/4).attr("cy", cy+width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx-width/4).attr("cy", cy-width/4).attr("r", width/8).attr("fill", dotcolour);
	}
	if (number == 3) {
	element.append("circle").attr("cx", cx).attr("cy", cy).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx+width/4).attr("cy", cy+width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx-width/4).attr("cy", cy-width/4).attr("r", width/8).attr("fill", dotcolour);
	}
	if (number == 4) {
	element.append("circle").attr("cx", cx+width/4).attr("cy", cy+width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx-width/4).attr("cy", cy-width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx+width/4).attr("cy", cy-width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx-width/4).attr("cy", cy+width/4).attr("r", width/8).attr("fill", dotcolour);
	}
	if (number == 5) {
	element.append("circle").attr("cx", cx).attr("cy", cy).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx+width/4).attr("cy", cy+width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx-width/4).attr("cy", cy-width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx+width/4).attr("cy", cy-width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx-width/4).attr("cy", cy+width/4).attr("r", width/8).attr("fill", dotcolour);
	}
	if (number == 6) {
	element.append("circle").attr("cx", cx+width/4).attr("cy", cy+width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx-width/4).attr("cy", cy-width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx+width/4).attr("cy", cy-width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx-width/4).attr("cy", cy+width/4).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx+width/4).attr("cy", cy).attr("r", width/8).attr("fill", dotcolour);
	element.append("circle").attr("cx", cx-width/4).attr("cy", cy).attr("r", width/8).attr("fill", dotcolour);
	}
	
}

To use the function, just include this line in your code.

append_die(element,number,cx,cy,width,colour,dotcolour)

The element parameter is the element you want to make the die a sub-element of. The number is the number on the die. cx and cy are the co-ordinates of the centre of the die. The rest should be obvious.

You will, of course, need to have D3 included on your page for this to work. If you right-click the iframe example below you can take a look at a complete page.

Tagged with: ,
Posted in D3, SVG

A Risk Legacy Mapping Tool

Warning! Work in progress.

** EDIT 11 Sep 2013 **
There is now a new version of the Risk Legacy Mapping Tool which you can find here. There’s a post about it where you can tell me what needs changing.

Here is a link to my Risk Legacy Mapping Tool.

At the moment, it’s in working order, but isn’t complete. It allows you to to do all things you would expect to be able to do to a Risk Legacy board, with no spoilers. Every bit of functionality that is available is present in the Risk Legacy rules at the moment you open the box.

It uses SVG to render all the graphics, so you’re going to need a vaguely modern browser to use the application. That basically means anything other than IE8 or below.

I’m afraid there aren’t any instructions at the moment, but a basic summary goes something like this…

1. Add and remove resources from a territory by clicking the little circles below the territory name.
2. Add, change the size of, and remove cities by clicking above the marker in each territory. You should get a hover effect if you’re in the right place.
3. Add, change and remove scars by clicking below the marker in each territory. You should get a hover effect if you’re in the right place.
4. Name cities by clicking on ClickMeToName when you’ve created a city.
5. Add fortification to city by right-clicking it, and change the fortification number by clicking the little blue number.
6. Place troops in a territory by clicking in the territory. Clicking in the territory a second time will change the troops into a base. Clicking a third time will remove the troops.
7. Change the number of troops by left-clicking the troops/base shape.
8. Change the colour of troops by right-clicking the troops/base shape, or by selecting from the colour picker in the top right before creating the troops.
9. Name a continent by clicking in the white space above the territory count for the continent.
10. Change a continent bonus by clicking in the little white square on the right of the continent label.
11. Toggle stuff using the buttons on the right.
12. NOT FINISHED! In theory, you can save the state of the board by generating a code using the ‘Generate Code’ button. This code can then be re-entered later by using the ‘Read Code’ button. This should work for resources, troops, cities and fortifications. It does not work for continent names, or for the winners statistics section in the bottom left, which I’ll let you work out for yourselves.

If you do find this tool and have a go on it, I’d be really grateful for any feedback in the comments of this post.

Changes to come are:

1. Finishing the functionality to save the layout.
2. Changing some of the right-click stuff to drags so it will work on tablets.
3. Find or create a decent vector map of the Risk board – if you know where one is, please let me know!

Thanks!

Tagged with: , , , , ,
Posted in jQuery SVG, Risk, SVG

SVG Polygon Generator

OK, so the hexagon generator in the previous post seems a little inadequate in hindsight. So here is the code for a more general, regular, convex polygon.

function polygon(x,y,rad,sides) {
	var path = "M ";
	for (a=0;a<sides;a++) {
		if (a>0) {path = path + "L ";}
		path = path + (x+(Math.sin(2*Math.PI*a/sides)*rad)) + " " + (y-(Math.cos(2*Math.PI*a/sides)*rad)) + " ";
	}
	path = path + "z";
	return path;
}

The code will generate a path string for use in SVG. Call it wherever you normally put a path string as shown in the jQuery SVG example below. It always draws the polygon with its first vertex directly above the centre point. If you want it rotated, you’ll need to apply a transform to it.

$('#svg_div').svg();
var svg = $('#svg_div').svg('get');
// call using polygon(x,y,rad,sides) where x and y are centre co-ordinates
// rad is the radius of the vertices, and sides is the number of sides
svg.path(polygon(70,70,60,3),{stroke: "black", "stroke-width":5, fill: "red",});
svg.path(polygon(140,70,60,4),{stroke: "black", "stroke-width":5, fill: "orange",});
svg.path(polygon(210,70,60,5),{stroke: "black", "stroke-width":5, fill: "yellow",});
svg.path(polygon(280,70,60,8),{stroke: "black", "stroke-width":5, fill: "green",});
svg.path(polygon(350,70,60,13),{stroke: "black", "stroke-width":5, fill: "blue",});

As always, if you right-click the iframe image below, you should be able to bring the complete source for the iframe.

** edit ** Note that the function can be used just as easily with D3 or Raphael or whatever other SVG tool you happen to like. Since it generates a standard SVG path string, the call to the polygon() function can be put anywhere that you’d normally put a path string.

In D3 this would probably be in path.attr( “d” , polygon() ).

Tagged with: , ,
Posted in jQuery SVG, SVG

An SVG Hexagon

Do you need a quick way to generate hexagons in SVG? Include this script in your javascript, and use it to generate the path string for a hexagon. You can then use the string with your chosen SVG plugin. I’ve include an example at the bottom using jQuery SVG.

function hexagon(x,y,r) {
	var x1 = x;
	var y1 = y-r;
	var x2 = x+(Math.cos(Math.PI/6)*r);
	var y2 = y-(Math.sin(Math.PI/6)*r);
	var x3 = x+(Math.cos(Math.PI/6)*r);
	var y3 = y+(Math.sin(Math.PI/6)*r);
	var x4 = x;
	var y4 = y+r;
	var x5 = x-(Math.cos(Math.PI/6)*r);
	var y5 = y+(Math.sin(Math.PI/6)*r);
	var x6 = x-(Math.cos(Math.PI/6)*r);
	var y6 = y-(Math.sin(Math.PI/6)*r);
	
	var path = "M"+x1+" "+y1+" L"+x2+" "+y2+" L"+x3+" "+y3+" L"+x4+" "+y4+" L"+x5+" "+y5+" L"+x6+" "+y6+"z";
	return path;
}

The x and y co-ordinates are for the centre of the hexagon. The variable r is the radius at which the points are drawn. Here is the script in use.

<script>
	$('#svg_div').svg();
	var svg = $('#svg_div').svg('get');
	svg.path(hexagon(100,100,60),{stroke: "black", "stroke-width":5, fill: "red",});
	svg.path(hexagon(212,100,60),{stroke: "black", "stroke-width":5, fill: "blue",});
	svg.path(hexagon(156,197,60),{stroke: "black", "stroke-width":5, fill: "yellow",});
</script>

Tagged with: ,
Posted in jQuery SVG, SVG

Comparing SVG Plugins

My last post on SVG was basically an extremely light introduction to the subject. It was basically a way of working out what the best way of embedding SVG in a WordPress post was. Iframes as it turns out. Anyway, in the post, I want to stick with some very simple SVG, but demonstrating the difference between raw SVG, and dynamically created SVG using three different plugins.

Here are our orange circles again.

Each of them has been created using a different method and, if you right-click any of them, you should be able to view the iframe source code to see how they were created. I compare the code below, leaving out all the irrelevant HTML.

Basic SVG
The circle on the left was created by simply including SVG elements in the HTML. No need for any external plugins.

<body style="padding: 0; margin: 0;">
  <svg height="120px" width="120px">
    <circle cx="60" cy="60" r="50" fill="orange" stroke="black" stroke-width="5"></circle>
  </svg>
</body>

jQuery SVG
For jQuery SVG, you need to include the jQuery SVG plugin. For some functionality, you need a custom version of jQuery as well. Check out the jQuery website for more information.

<body style="padding: 0; margin: 0;">
  <div id="svg_div"></div>
</body>
<script>
  $('#svg_div').svg();
  var svg = $('#svg_div').svg('get');
  svg.circle(60,60,50, {fill:"orange", stroke:"black", "stroke-width":5});
  svg.text(60,65,"jQuery SVG", {"text-anchor":"middle", "font-family": "arial", "font-size": "16px"});
</script>

On line 5 I’ve attached an svg element to the empty div I prepared, and line 6 sets up a variable to refer to this canvas. The rest should be reasonably self explanatory. Each new element is created with some mandatory data (co-ordinates and radius and stuff), and all the variably attributes are included after the mandatory stuff. The script produces the html structure below.

<svg version="1.1" width="1243">
  <circle cx="60" cy="60" r="50" fill="orange" stroke="black" stroke-width="5"></circle>
</svg>

If you compare the SVG element to the basic one further up, you’ll see that jQuery has basically created the same structure as the basic version.

D3
The D3 equivalent is shown below. Check out the D3 website for the plugin you need.

<body style="margin: 0; padding 0;">
  <div id="svg_div"></div>
</body>
<script>
  var svg = d3.select("#svg_div").append("svg");
  svg.attr("width", 120)
     .attr("height", 120);
  var circle = svg.append("circle")
     .attr("cx", 60)
     .attr("cy", 60)
     .attr("r", 50)
     .attr("fill", "orange")
     .attr("stroke", "black")
     .attr("stroke-width", 5);
var text = svg.append("text")
     .text("D3")
     .attr("x", 60)
     .attr("y", 65)
     .style("text-anchor", "middle");	
</script>

OK, so there’s a lot more code there. All those attributes could be strung together on one line, but nevertheless, it’s a bit more verbose than jQuery SVG. That’s mainly because it doesn’t provide any shortcuts for creating elements. Still, I think it’s pretty simple to understand what’s going on, and D3 will come into its own when we want to start manipulating data within our webpage. I’m not going to show the HTML it creates, as it’s fundamentally the same as the jQuery SVG structure.

Raphael
Finally, Raphael. Raphael is really strong when it comes it animation, but I’m not sure it’s as capable of manipulating the SVG DOM as the other two plugins are. That said, I’ve not got a lot of experience with it yet so we’ll see how it goes. Get the script at the Raphael website.

<body>
  <div id="svg_div"></div>
</body>
<script>
  var paper = new Raphael("svg_div",120,120);
  var circle = paper.circle(60,60,50)
     .attr("fill", "orange")
     .attr("stroke", "black")
     .attr("stroke-width", 5);
  var text = paper.text(60,60,"Raphael")
     .attr("text-anchor", "middle");
</script>

Raphael falls somewhere between jQuery SVG and D3 in terms of the amount of code required to describe an element. It’s still fairly simple though. One interesting thing to note is the “text-anchor” attribute I’ve used in all these examples. By setting it to “middle” the middle point of the text is anchored to the co-ordinates provided. However, Raphael behaves differently to the other two plugins. Raphael anchors both horizontally and vertically, whereas the other two only anchor horizontally. This is why the text co-ordinates are (60,65) in jQuery SVG and D3, but (60,60) in Raphael (which is the centre of the circle).

That sounds great, but let’s look at the HTML Raphael has created for us.

<svg height="130" version="1.1" width="130" xmlns="http://www.w3.org/2000/svg" style="overflow: hidden; position: absolute; left: 0px; top: 0px;">
  <desc style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Created with Raphaël 2.1.0</desc>
  <defs style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></defs>
  <circle cx="60" cy="60" r="50" fill="#ffa500" stroke="#000000" stroke-width="5" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></circle>
  <text x="60" y="60" text-anchor="middle" font="arial" stroke="none" fill="#000000" font-family="arial" font-size="16px" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); text-anchor: middle; font-style: normal; font-variant: normal; font-weight: normal; font-size: 16px; line-height: normal; font-family: arial;">
    <tspan dy="6" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">Raphael</tspan>
  </text>
</svg>

Yeesh. To be honest, I’m not a fan of plugins generating a lot of code that I didn’t ask for. It’s converted “orange” to hex. It’s created a tspan element so it can offset the text to make the text-anchor work vertically. It puts in all sort of default settings that I would rather weren’t there. It’s hard enough getting CSS right without having a plugin throw in extra information all over the place.

So, while Raphael does seem to have some great features, I’m already less fond of it than the other two options! Time will tell.

Posted in D3, jQuery SVG, Raphael, SVG

Risk Legacy Tools

Many of you have probably played the classic strategy game of Risk. Less have you are likely to have played one of the many variations that Hasbro have released over the years: Risk Legacy.

The cool thing about Risk Legacy is that it’s a campaign game. You and your group of friends begin with a plain map of the world and some simple rules, and by the end of the first game you’ll have written on the board, put some stickers on it, and ripped up some of the cards that came with the game. These changes are permanent, and will affect all your subsequent games. Not only does the map change, but the rules too. There are various secrets to unlock as you reach certain landmarks, so the game is constantly evolving.

Most players really, really don’t want spoilers about what happens later in the game, so please don’t post anything below which might give the game away!

Anyway, right from the start, the combat rules of Risk Legacy are a little different to the original game. While there are many tools available to automate long battles and calculate odds in the orginal game, nobody seems to have done the same for Legacy… so I thought I would.

The first link is to a battle calculator which will automatically run battles for you, based on various input parameters. The rules I used are the ones that apply from the start of the game, so there are no spoilers in there (unless you haven’t even opened the box yet!).

Risk Legacy Fighter

The second link is to an odds calculator. I’m not sure whether players should be allowed to use this during a game, but the statistics are interesting, and show just how much difference a bit of defence can make.

Risk Legacy Odds Calculator

At the moment, the tools are written with just HTML and Javascript. I might update them to use SVG sometime soon. As a group, we are only on game 3, so we haven’t uncovered to much just yet. When we do, if battles are affected, I may create new tools to include new rules… but these tools won’t change, so you’ll know they’re always spoiler-free.

If you make use of the tools, I’d be grateful for any feedback.

Tagged with: , , , , , ,
Posted in Risk

SVG – Basic Choices

So, where to start with SVG? It’s a fantastic tool, which I think is quite underused at the moment. It allows simple implementation of vector graphics in web pages. In fact, it’s possible to build a webpage entirely from SVG. You can make it scale perfectly to any screen size, and it will work on pretty much all modern browsers, including the mobile ones. Internet Explorer 8 and below are the only exceptions – nothing’s perfect! If you can see the orange circle below, then your browser is SVG compatible.

There are a couple of problems with building a 100% SVG webpage. The first is that the way it displays text is not particularly conducive to a website with multi-line prose – so every website really. SVG doesn’t do text wrapping. However, there are ways around this by embedding HTML in the SVG (which is already embedded in HTML!). More on that in a later post.

The other issue is that I’m not sure how well search engines respond to SVG. I’ll be looking into that as I write posts for the blog.

On to the choices. The rest of this post is going to demonstrate a few different approaches to writing in SVG, starting with simply embedding hard-coded SVG straight into HTML. The circle above was created in this way, using the code below. By the way, each of the images is just a simple HTML page in an iframe, so you if you want to see all the source just right-click the image and do what you have to.

<body>
  <svg height="120px" width="120px">
    <circle cx="60" cy="60" r="50" fill="orange" stroke="black" stroke-width="5">
  </svg>
</body>

But what if you want to do something a bit more exciting – user interaction and dynamic manipulation of your SVG elements? Well there are a few options, all of which use Javascript to get things moving. To the left, I’ve embedded two similar looking circles. However, one was rendered by a plugin called jQuery SVG, and the other by Raphael. If you right-click the iframe you should be able to bring up the source for comparison. I don’t have a lot of experience with Raphael yet, but my gut feeling is that it’s trying to do too much for me. It creates a lot of element attributes which I didn’t ask for, while jQuery SVG keeps things very clean. That said, Raphael has some really amazing built in functions, particular in the animation area. A third option is D3, which was built for manipulation and display of data within webpages. I’ll add some more on that in a later post.

Posted in SVG