Share this blog!


A simple battleship game

This is a simpler version of the popular game battleship, where the positions of the battleships must be determined before the lifelines expire.

Game primitives

Lives :
7
Ships :
4 x 1
4 x 1
3 x 1
2 x 1
2 x 1


The code gist for the above is as follows, which is hopefully quite self explanatory.

Internship diaries #2


By the start of the second four-week period, the static web simulation of the Data Mapper tool was achieved by using JS Plumb but when the it required long codes to get the functionality work. Therefore, my mentor discussed with the other team members on an appropriate library to work on in a long term basis and came up to a conclusion on using d3. D3 is a simple yet powerful JavaScript library that provides many useful functionalities in handling document objects.

I was going through a tutorial on creating a bar chart using d3 and met with a a series of similar bugs. Looking into the matter by debugging, I found out that the cause of the bugs were version mismatches. I was using the latest version(v4) in my implementation while the tutorials I was going through were based on a previous version(v3). In order to recover from the bugs, I had to look into the details of version updates, and to my surprise there were quite a long list of structural changes in the version update.

The Data Mapper implementation using d3 started and in the mean time, I was researching on other similar JS libraries such as Jquery, Jquery-UI, AngularJS, NodeJS, BackboneJS and worked on sample projects through tutorials. I hadn’t even heard of some of them before. Additionally, I had to go through HTML SVG components as a majority of D3’s drawings were based on SVG.



The use cases of the JS based Data Mapper were:

  1. File loading
  2. XML parsing
  3. Displaying tree structure
  4. Implementing draggable containers
  5. Implementing draggable nodes 
  6. Detecting node drops.  

Implementation of file loading and XML parsing were reused from the earlier implementation using jsPlumb. Tree structure display was achieved by using a recursive method on which the node dragging functionality was implemented using D3’s drag functionality. The node drops were detected by using a method that calculates the areas of the leaf nodes of the opposite container.

Enabling dragging on containers was the trickiest objective which gave me an opportunity to learn about D3’s mouse events. During line dragging, the positions were calculated using mouse pointer position and the transform:translate attributes of the containers. I was practically living inside StackOverflow. After going through so much trouble, the container dragging functionality was finally solved. And it was time for a new task...


The above topic kept me busy for an exhausting dozen of hours when I wan trying to implement a simple dragging functionality. Basically the components I had were two SVG groups, one called input and the other, output and some lines connecting them. The mapping functionality had been achieved earlier in this post, and the new requirement was to make each container draggable.

The problem:


At first I tried to use d3.event.x and d3.event.y to update the x attribute of the component. As in:

var drag = d3.drag().on("drag", function() {
                   var x = d3.event.x;
                   var y = d3.event.y;
                   d3.select(this).attr("transform", "translate(" + x + "," + y + ")");
                   });


In the that approach, the lines were appended to whichever the container the drag was started from, therefore there was the possibility of lines belonging to both the containers. The observations were that the drag was not smooth and the target ends of the lines that were belonging to the dragged container were not updated (obviously!)

When I was looking into the details of making the drag smooth, I came up with multiple event handlers that could be used.


d3.event vs d3.mouse


d3.event and d3.mouse are two important events defined by d3. The main difference between these two is that d3.event is browser-dependent while d3.mouse is not.

mbostock in StackOverflow responded to this question saying that:

Instead of using d3.event, which is the browser's native event, use d3.mouse to get the coordinates relative to some container.

d3.event.pageX and d3.event.pageY


pageX and pageY belong to d3.event and therefore are native to browser’s implementation.

Further more, Lars says in this that:

pageX and pageY are the event's native properties, which are browser-dependent (as you've discovered). These properties depend on the implementation of the rendering engine. In theory, they're specified in a W3C standard, but in practice the implementations don't necessarily conform to that standard.

d3.event.dx and d3.event.dy


Ultimately, my solution for a smooth drag was using d3.event.dx and d3.event.dy which return the delta values of the mouse movement.

In the words of Naga on this post:

d3.event.dx returns the x delta that the mouse has moved w.r.t to the x-coordinate from where the drag event started.


The final solution:


Finally my container dragging functionality gave out smooth results as:

var drag = d3.drag().on("drag", function() {
  this.x = this.x || 0;
  this.y = this.y || 0;
  this.x += d3.event.dx;
  this.y += d3.event.dy;
  d3.select(this).attr("transform", "translate(" + this.x + "," + this.y + ")");
  });


The working full code relevant for this functionality can be found stuffed up in my Github commit.
Next PostNewer Posts Previous PostOlder Posts Home