Friday, 24 April 2015

DIY guitar kits in Saltdean

My usual hardware store shopping list probably looks something like this:

  • Jayes cleaning fluid? Check.
  • Bin bag? Check
  • Pan scourers? Check
  • Multi-part DIY guitar kit? Check.

Ok, maybe that last one doesn't always make the list.
But that might change, after a recent discovery!

After helping a friend with his cooker hood, I called in at a little hardware store, on the main high street in Saltdean. Steve had already recommended calling in, just because of the bizarre combinations of things sold in there. So while I was in the area, I took the opportunity to see what he was on about.


And there they were - in the middle of a hardware store, among the tins of paint and rubber gloves and packets of wood screws, was a selection of DIY guitar kits!


Each kit comes complete with all the hardware for each particular guitar. So with the flying-V guitar, you get a Gibson-style fixed bridge and two humbuckers, with the Telecaster you get a maple-necked fretboard and two classic single-coiled pick-ups. The Warlock style guitar even comes with a Floyd-Rose style floating bridge, and locking nut!

Prices range from £140 to £160 - which when compared to a new instrument, isn't too bad at all. In some ways, these are even better than the cheaper-end guitars on the market, as each has a solid wood (mahogany) body (though the Les Paul copy has a striped maple veneer on top). That's far better quality than my first Squire Strat from over twenty years ago, which - even back then - had a plywood body!

Most of the range, other than the Telecaster, have rosewood fingerboards. I quite fancied trying a maple fingerboard again (my very first guitar had a shiny maple fingerboard, and every other guitar I've owned since then has been rosewood) but I really don't like the Telecaster shape (nor the slightly twangy sound from the rather basic electronics).

So what's the downside? Well, you've got to put it together yourself. You've got to put in the time and effort to get a decent finish. Some of the guitars on display were absolutely stunning - lacquered and sanded back and polished and lacquered and sanded back and polished about five or six times. And it showed. A couple looked like they'd been thrown together, just to complete the display!

So to get a really nice finish, you need to be prepared to put in a bit of work.
But other than that, these kits look like a really nice, relatively easy introduction to making and setting up your own guitar.

They're obviously coming out of China, but with modern CNC routing tools, there's no difference in build quality between these and the Fenders coming out of Korea, Mexico or even the US. Maybe the purists would balk at the idea of using anything but the most exclusive, expensive hardwoods, but for the price, these are pretty decent instruments.

The action on the few guitars I tried there was nice and low, without being "buzzy". The necks are nice and slim (my first Squire had a neck like half-a-drainpipe, it was so fat and round!) and easy to play on. The guitars were pretty much in tune, straight from lifting them off the shelf, despite just hanging in a hardware store for weeks at a time, so the machine heads and other hardware seems to be of decent quality.

 I haven't heard them through an amp, so have no idea what the electrics are like.
But the feel of the constructed demo models was pretty good.
Now I just need to rack up my brownie points, so I don't create World War Three when I come home with a new Flying V or Warlock in pieces in the next few weeks......

[edit: the website hasn't been updated for a while, but the kits are available online at http://diyguitarstore.co.uk ]

Tuesday, 14 April 2015

Using a 74HC164 shift register as an LED driver

Earlier in the week, Jason emailed to ask exactly what the problems were with using a shift register to drive eight LEDs. He's used numerous '595 shift registers in his POV globe successfully, and never had a problem with multiple LEDs lighting up and causing the display to dim.

Perhaps the clue was in the original question all along - what's the problem with driving LEDs? Well, the main problem seems to be sourcing current instead of sinking it.

Admittedly, Jason was using some inline resistors on his LEDs which may have limited the current slightly on each LED, but the main problem we'd had with our 595s was that we we driving - i.e. providing positive voltage to - the LEDs through each pin of the shift register.

Different manufacturers of different shift registers give different technical specifications; but one thing that most are clear on - you can almost always sink a lot more current that you can source it (the NXP shift registers we have here also have internal clamp diodes, allowing you to sink a higher voltage than the supply voltage - but that's a whole other issue).

Now we're trying to create a circuit board on a relatively small space, and don't really want the components to be all that obtrusive (since the panel, once soldered up, is supposed to be the wall of a sci-fi interior). If we really have to, we can put inline resistors on each LED, but for testing, we left them off.

Instead of sourcing current, we joined all the anodes (long legs) of the LEDs to our 3.3v power supply. The cathodes (short legs that normally go to ground) are connected to the output pins of a couple of shift registers.

We've gone for 74HC164 shift registers, over the 595s, because these don't require a latch line; this means that the outputs change immediately as the data is shifted in, but it also means one less connector on every PCB section. Using exactly the same firmware as before, we simply cascaded the "last" output (i/o7) to the "data in" pin on the next shift register in the chain and wired up the clock and data lines to our PIC 16F1825.






Rather fortuitously, everything worked first time. Even better than that, everything worked, without current limiting resistors on the LEDs - and they all appeared to be a uniform brightness!


This was very encouraging - we've managed to lose on of the required connecting wires (no need to latch) and we've got uniform brightness, even when multiple LEDs are lit up. The only downside so far is that there's a very noticeable flicker each time the data is sent, as the shift register outputs update with every clock cycle:


Although not too obvious in the video, because of the camera frame rate, every now and again you can see a visible flicker as the LED patterns update. This is more noticeable in real life.


Fixing this flicker shouldn't be too difficult to resolve. At least, the flickering during updating can be eliminated - or at least, replaced with one, single flicker: since the LEDs are all sharing a common power supply, one solution might be to put this power rail through an NPN transistor (something like a 2N2222 perhaps?)

Just before pushing more data to refresh the display, we could turn off the transistor (starving the LEDs of their supply voltage so they go out) then push all the data into the cascaded LEDs (there may easily be twenty or thirty or more in a chain) then bring the transistor back up, illuminating all the required LEDs at the same time.

It will mean one single (possibly longer) flicker when the lights change, but - given that there could be a relatively large number of shift registers all cascading off each other - this is preferable to seeing the data flicker on each data/clock cycle on every wall section. It also means that the transistor becomes like a "latch" - but the latch line does not need to be cascaded along the entire chain of shift registers.

It's food for thought. We're hoping to get a few PCBs etched this week, so we'll be able to try out a couple of different designs, using both the LED driver and these shift registers, and compare the performance of both.


Friday, 10 April 2015

Testing TLC5916 LED driver with a PIC 16F1825 microcontroller

Combining the benefits of the MAX7219 (namely, constant current, non-dimming LEDs) with the ability to cascade ICs in a "chain" (like the 74HC595 shift register) has opened up some interesting possibilities for interactive, light-up sci-fi terrain.


Using them is really as simple as treating them as cascading shift registers. The only other thing to take care of is the current limiting resistor (from pin 14 to ground). We're using a 1.5K resistor with a 3.3V power supply and the LEDs are nice and vibrant, without being eye-burningly bright.

Here's some sample code which just displays a recognisable pattern on our cascading chips, to demonstrate that they work as expected:

Define CONFIG1 = 0x0804
Define CONFIG2 = 0x1dff
Define CLOCK_FREQUENCY = 32
AllDigital

declarations:
     Symbol tx = PORTC.7
     Symbol rx = PORTC.6
     Symbol data_out = PORTC.3
     Symbol clock_out = PORTC.5
     Symbol led_out = PORTA.2
     Symbol latch_out = PORTC.4
     
     ConfigPin tx = Output
     ConfigPin rx = Input
     ConfigPin clock_out = Output
     ConfigPin data_out = Output
     ConfigPin latch_out = Output
     ConfigPin led_out = Output
     
     Dim wall_pieces As Byte
     Dim g As Byte
     Dim h As Byte
     Dim i As Byte
     Dim j As Byte
     Dim k As Byte
     Dim data(128) As Byte
     
initialise_chip:
     OSCCON = 11110000b 'oscillator = 32mhz
     WaitMs 10
     APFCON0 = 01000000b 'APFCON

     wall_pieces = 2
     
initialise:

     Low data_out
     Low clock_out
     Low led_out
     Low latch_out
     
     data(1) = 11100111b
     data(2) = 00011000b
     data(3) = 10100101b
     data(4) = 01011010b
     data(5) = 00001111b
     data(6) = 11110000b
     
     g = 1
     WaitMs 500
               
loop:
     
     Gosub send_data
     High led_out
     WaitMs 500
     Low led_out
     WaitMs 500
     
Goto loop
End

send_data:
     
     Low latch_out
     
     'send as many bytes as we have wall pieces
     For i = 1 To wall_pieces
          k = data(g)
          
          'we can only send 7 bits
          For j = 0 To 7
               h = k And 00000001b
               If h = 0 Then
                    'send a zero bit
                    Low data_out
               Else
                    'send a one bit
                    High data_out
               Endif
               
               'the led driver can run at 30Mhz, our PIC is running at 32Mhz
               'in truth, it shouldn't be a problem, but just in case, let's
               'add a tiny delay on the clock line.
               High clock_out
               WaitUs 1
               Low clock_out
               
               k = ShiftRight(k, 1)
          Next j

          'now give it a sec just to let everything settle
          WaitMs 1

          g = g + 1
          If g > 6 Then g = 1
                    
     Next i

     'now latch everything with a falling edge
     High latch_out
     WaitUs 10
     Low latch_out
     
                    
Return



It's important to note that the LED driver chip sinks rather than sources current, so you need to connect your LEDs with a common anode (all the long legs connected to the power rail) and as each output on the driver chip is activated, the appropriate pin is pulled to ground, causing the LED to light up.



After proving that the chips work in the way we expected them to, it was back to our favourite PCB editor, ExpressPCB, to design a double-sided board with up to eight LEDs on it.

In our original design, we spaced fewer LEDs around, so that combinations of different colours could be used. In practice, it's probably quite likely - given the small distances between the LEDs - that the player would rather have one area of the game board one colour (rather than a combination of lots of different colours).

So our PCB layout (above) places eight LEDs in relatively close proximity to each other. The ones in the top corners, for example, might both be red, with the lower row of six being a combination of, say, blue, green and, perhaps, yellow. This would mean the player might switch on only the blue LEDs, to make that particular section of the board glow blue, or only green, or perhaps flash red (as some kind of Star-Trek-alike red alert). It's unlikely to be useful to be able to light up more than two colours at any one time, which is why we've placed them relatively close together, instead of spreading them across the entire surface of each wall section.

With the PCB designed, and the circuit tested and proved to be working, all that remains is to etch a couple of double-sided boards and try the idea out! Luckily the weekend will soon be upon us, to give us chance to pop down to the Nerd Unit and laser-etch a few boards...

Wednesday, 8 April 2015

Interactive sci-fi terrain

The long Easter weekend gave us plenty of time not just to mull over a few wacky ideas, but also afforded a few hours to actually put them into practice.

One of the things we looked at was creating some laser cut sci-fi terrain for our larger, 35mm grids.

This meant simply drawing up some vector shapes in Inkscrape and preparing them for laser cutting. It started out pretty simple - some double-length walls, about 68mm long, some inter-connecting pillars (for joining the wall sections either in a straight line, at 90 degrees, or combinations thereof) and spacing them all out onscreen so that, when clipped together, the fit perfectly in our 35mm grid system.

Instead of the relatively chunky 3mm, we designed these to be cut from 2mm MDF. The wall sections are pretty small and fiddly anyway, and we didn't want to make them more difficult to handle, by making them from extra-chunky stock.


Then something went a bit weird. Without even breaking out our favoured ExpressPCB, pads and circuits just appeared on the drawing....

What if, instead of being cut from 2mm MDF, the whole thing was cut from 2mm copper-clad PCB board? That would mean we could put some surface-mount LEDs on them.

And what if we could control individual LEDs? A simple shift register should suffice, allowing multiple walls to be daisy-chained together, all individually controllable from a single source. What if each panel had a few different coloured LEDs placed on them, so that, at the touch of a button, you could - for example - make an entire board area turn red to indicate "red alert"? Or door panels with red and green LEDs to indicate whether the door was locked or open?

Suddenly there was a world of possibility with this "interactive sci-fi wall panel" idea. In fact, since our board game is dependent on some hardware to act as a bridge between a smart device (phone/tablet/PC) and uses serial messages to pass data around, we could re-use the same technology and simply build a stand-alone app, to allow the user to switch lights on and off around their playing surface....

There was nothing for it: we had to crack open the Ferric Chloride!


One thing we hadn't considered (until it came to actually trying out a single wall panel) was that using 74HC595 shift registers meant that every panel needed a five-way connector (power, ground, clock, data, latch lines).


This was a rather chunky connector, and wouldn't work at all well with lots of tiny little, fiddly interlocking pieces. We needed a way of getting that pin-count down.

The Roman Black website has some great ideas for doing just this kind of thing. His site gives a great, detailed explanation about how you can use capacitors and resistors to create an RC circuit, to delay triggering the data/latch pins from a single clock source.


In theory this all sounds great. There's no reason why we couldn't mount a few discrete passive components on each board, and dress them up to look like sci-fi panels on the walls. In practice, things weren't quite so straight-forward.


Here we've connected two shift registers, one cascading into the other (yes, there are three on the breadboard but only two are actually connected together). While the PIC correctly activates the appropriate output pins on the first shift register, the cascade effect fails to send the data on to the second (and, if there were more than two, any subsequent) registers in the chain.

So a single-wire approach is achievable - but only at the cost of losing the cascade ability (and without being able to cascade data from one wall section to another, it'll be really difficult getting any except the first panel to light up!) Maybe we could tie the latch and clock pins together, and reduce our connection count to four pins, instead of five?


By tying the clock and latch pins together (it even suggests you can do this, in the datasheet), we need to provide on extra clock-pulse at the end of sending our data (since the latch is always one clock pulse behind the data). This worked fairly well, but we then discovered the downside of the shift-register approach:

Each shift register is able to source only about 16mA-20mA across all its outputs; roughly the same as the total output of a single PIC i/o pin. That's no problem if we're only lighting one LED at a time. But if we want to light up multiple LEDs, each one gets progressively dimmer, as more are lit at the same time. This could prove to be a real problem, as we've no idea which lights (or combination of lights) the user is likely to want to illuminate at any one time.

What we really need is some kind of constant current, multi-channel, LED driver....
Sometimes you need to invest a bit of time to discover what isn't going to work, in order to work out what is the best way to proceed with some projects.

This weekend we've done just that. We know that not only is a single-wire shift-register unsuitable for, let's be honest, a bit of a crazy whim idea. But investing a bit of time into trying alternatives demonstrated that shift registers aren't exactly the best idea for what we want anyway.

So we've a few TLC5916 LED drivers on order from Farnell.
Etching some PCBs should be straight-forward enough - though quite how we'll cut them into those strange shapes remains to be seen.....

Friday, 3 April 2015

Video showing Unity5 collider problem

Here's a short video demonstrating the problem we're having with our Unity5 box colliders.


The game works by selecting a square containing a character (presenting a playing piece on a tabletop miniatures game). If the square contains a character, that playing piece is said to be "in hand". To demonstrate which square the playing piece is in, we place a new game object (a cube for visibility) on the tile that contains the playing piece

A destination square is selected by clicking on another tile. In Unity, I'm working out which tile has been clicked, and placing a cube on it, to ensure that it's not my tile-selection routines that are screwy. From now on, all calculations, rotations, translations and raycasting are done between these two objects (called sourceObject - the one in the starting square, and targetObject - the one in the target/destination square).

The first time a target square is selected, Unity correctly identifies that the ray from the start point to the destination, on the other side of a wall, passes through the box collider on the wall object. The view flips to the "scene" mode, where you can see the two rays being drawn from source to destination.

The second square selected is also on the "wrong" side of at least two walls. Unity again correctly detects that the ray passes through a box collider and will not allow the character to move into the new target square.

The strange stuff happens when we select a point closer to the wall than the character is. When the third target point is selected, you can see that the rays clearly pass through the wall, but the box collider is not detected, and our character happily walks through a solid wall!

Not just a wall with a collider - but the very wall with the very same collider that it detected earlier, when the target square was further away....

Now to make sure it's not a bug introduced when we move our character around, we repeated the test, this time moving the character before attempting any box collider checks:


Here you can see the character is moved to a new square, and target squares are selected behind the walls. The first time we select a target square, the box collider on the wall is detected and our character cannot move to the destination point.

The second destination point is also "behind" two walls, and Unity correctly detects the box colliders on the door and wall, and the character cannot move.

So what gets really frustrating is that the third point - on the "wrong side" of the very wall that it earlier detected the box collider on - does not trigger the box collider, and Unity animates our character walking through a solid wall.

We can't come up with a reasonable explanation as to why this is happening, other than noting that the problem mainly occurs when the box collider hits the "second half" of the ray. In other words, if our character is further away (in terms of straight-line distance) from the wall with the box collider on it, than the target square is, the raycast does not detect the box collider.

If we choose a target square that is sufficiently far away from the wall (box collider) so that the character is closer to the collider than the target point is (on the other side of the collider) then Unity correctly detects the presence of the box collider and reports a break in our line-of-sight.

It's all rather worrying: if we can't rely on the Unity game engine to handle things like line-of-sight and raycasting, we may as well write the entire LOS routines ourselves, from first-principles and GCSE level trigonometry/mathematics - and we've already done that once in Flash. Unity was supposed to free us up from all that, and make things simpler, not more complicated!!


More Unity Raycasting woes

This Raycasting malarky was supposed to make things simple.
And if it behaved the way we understand it to, things like line of sight (for placing pieces, showing and hiding pieces, and for shooting at enemies) would be a doddle. But it's not.

It's really confusing.
And there's not much clue as to why sometimes our line-of-sight works, and sometimes doesn't.

To create a line of sight, we select a source square (the place you're travelling from) and a destination square (where you want to move to). We create two temporary objects (I created cubes just so they would appear on screen, but they can be empty gameobjects) and place them in the centre of the source and destination squares.



We turn the squares to face each other, so that their rotation represents the direction of travel. When we cast a ray from the source point, in the direction of the target, using

var ray:Ray=new Ray(v1.transform.position, (v2.transform.position- v1.transform.position) );
a = Physics.RaycastAll(ray, dist);
return(a);

The full function is here:

function objectsBetweenSquaresOffset(boardID_start:int, squareNo_start:int, boardID_end:int, squareNo_end:int, xOffset:float):RaycastHit[]{

     // this function takes the centre point between squares and
     // then offsets to the left/right (and to the opposite side on the target)
     // returning anything along the path between the two points
     
     var pt1:point2D=getPointFromBoard(boardID_start, squareNo_start);
     var pt2:point2D=getPointFromBoard(boardID_end, squareNo_end);
     var a:RaycastHit[]=null;

     sourceObject.transform.position.x=pt1.x*2;
     sourceObject.transform.position.z=pt1.z*2;     
     sourceObject.transform.position.y=1.4;
          
     targetObject.transform.position.x=pt2.x*2;
     targetObject.transform.position.z=pt2.z*2;
     targetObject.transform.position.y=1.4;
     
     sourceObject.transform.LookAt(targetObject.transform.position);
     targetObject.transform.LookAt(sourceObject.transform.position);

     // parent the objects to the current character (so when we increase the x values
     // it's relative to the way the character is facing, not just global increase)
     var v1:GameObject=new GameObject();
     var v2:GameObject=new GameObject();
     
     v1.transform.position=sourceObject.transform.position;
     v1.transform.rotation=sourceObject.transform.rotation;
     v1.transform.parent=sourceObject.transform;
     
     v2.transform.position=targetObject.transform.position;
     v2.transform.rotation=targetObject.transform.rotation;
     v2.transform.parent=targetObject.transform;
     
     // now offset the objects either left or right, just a bit
     v1.transform.localPosition.x+=xOffset;
     v2.transform.localPosition.x-=xOffset;

     v1.transform.parent=null;
     v2.transform.parent=null;

     // create a ray from the source object to the target object
     var dist:float = ((pt1.x-pt2.x)*(pt1.x-pt2.x)) + ((pt1.z-pt2.z)*(pt1.z-pt2.z));
     dist=Mathf.Sqrt(dist);
     var c:Color=Color.red;
     if(xOffset<0){c=Color.green;}
     trace("distance to destination: "+dist);
     
     // we tried this and it made no difference
     //var direction:Vector3 = ( v2.transform.position - v1.transform.position ).normalized;
     //var ray:Ray=new Ray(v1.transform.position, direction );
     
     var ray:Ray=new Ray(v1.transform.position, (v2.transform.position- v1.transform.position) );     
     Debug.DrawRay(v1.transform.position, (v2.transform.position- v1.transform.position), c, 30);
     a = Physics.RaycastAll(ray, dist);
     Destroy(v1);
     Destroy(v2);     
     return(a);
}


It's called like this:
The idea is that we assume we're always going to perform a valid move. Then we pass in the boardid and square number of the playing piece (current square) and the boardid and square number of the target square into the function above.


var validMove:boolean=true;

// first check that there's a line of sight between the two squares
// (you're not trying to walk through a wall or a door or something)

var hits1:RaycastHit[]=objectsBetweenSquaresOffset(pieceInHand.curr_boardid, pieceInHand.curr_squareno, boardID, squareNo, 0.8f);
var hits2:RaycastHit[]=objectsBetweenSquaresOffset(pieceInHand.curr_boardid, pieceInHand.curr_squareno, boardID, squareNo, -0.8f);

if(hits1){trace("hits1 returned "+hits1.Length+" collisions");}else{trace("no hits1");}
if(hits2){trace("hits2 returned "+hits2.Length+" collisions");}else{trace("no hits2");}

// first check out hits along the left-hand side
if(hits1){
     for (var i:int=0; i<hits1.Length; i++) {
          var hit1 : RaycastHit = hits1[i];
          if(hit1.collider.gameObject.transform.root.transform==activeCharacter.transform){
               // ignore this, you've just collided with yourself!
               trace("ignore collision with self");
          }else{
               var s1:String=hit1.collider.gameObject.tag;
               // if you hit anything along the way, the way is blocked
               trace("i) path blocked by "+s1+" "+hit1.collider.gameObject.transform.root.name);
               validMove=false;
          }
     }
}

// now hits along the right-hand side
if(hits2){
     for (var j:int=0; j<hits2.Length; j++) {
          var hit2 : RaycastHit = hits2[j];     
          if(hit2.collider.gameObject.transform.root.transform==activeCharacter.transform){
               // ignore this, you've just collided with yourself!
          }else{
               var s2:String=hit2.collider.gameObject.tag;
               // if you hit anything along the way, the way is blocked
               trace("ii) path blocked by "+s2+" "+hit2.collider.gameObject.transform.root.name);
               validMove=false;
          }
     }
}


The collision function converts the current boardid and square number into a pair of points (and does the same for the target square). This function is included below for completeness, but it's accuracy is not in question: the points returned are used to draw the ray on the screen, so we can see that they are correct.

We then place our sourceObject cube and our targetObject cube in the appropriate places on the map. Again, these can be seen as in the correct places, in the screenshot, so there is little question of this being incorrect. We turn the two cubes to look at each other.

We then create a blank object and place this as a child of the sourceObject (and create a blank child for the targetObject too). Then, we shift these blank objects a little to one side (depending of the value of the xOffset parameter passed into the function) by changing their local x co-ordinate (if we changed their global x co-ordinate, the line would not necessarily begin to the side of the cube: local co-ordinates take into consideration the rotation of the cubes when shifting the starting points).

Using a simple Pythagoras equation we work out the distance between the two cubes, and then create a ray between them. We then use Physics.RaycastAll to return a list of all objects collided with along the length of the ray.

The strange thing is, if the point of collision is less than half-way along the ray, the ray successfully detects an obstacle. But if, for example, we place our character two squares away from a wall, and select the target square just one square away from the wall, on the opposite side, something peculiar happens:


Where the obstacle intersects the ray at any point more than half-way along, the box collider is not detected. In the example above, the ray is drawn passing through the door (which has a number of box colliders on it, but we get the same result with a wall section with just one collider) but this time, RaycastAll does not return the obstacle.

The problem is surely not with the box collider on the obstacle, since it is sometimes correctly identified. It only seems be by how much the ray passes through the obstacle that determines whether or not the box collider is detected.

The problem is, we're not sure whether we're not understanding how box colliders work, whether there's a bug in the code that we're just not seeing, whether or not the box collider is set up correctly, or whether there's a bug with Unity and using box collidors on objects that are instantiated in code (online sources suggest that Unity has a bug which can be squashed by disabling then re-enabling an object after instantiating, but even with this in place, we're getting the same results).

A read head-scratcher this one........

Thursday, 2 April 2015

Unity line of sight is not the same as "clear to proceed"

Another minor stumbling block this evening, following on from our Unity box collider problems. This time it's not the syntax or Unity programming language that's the problem, but our approach to solving a particular problem.

The issue is this:

Currently we're drawing a single line-of-sight from centre-to-centre of each square. If there are any obstacles between the two selected points, we say that there is no line of sight. That's fine - most of the time....


Here, our hero is blocked from walking diagonally, because it will cause him to walk through the edge of the wall. The routines are correctly reporting that there is an obscured line of sight to the target square.

But what if there was an object (or an enemy character) in the square? If we place the main camera on the character's head, in 3D space, we can see the board "through their eyes". And we can clearly see (at least partially) the squares on the diagonals.


We're pretty sure that if one of those green squares contained an enemy character, we'd at least expect to see part of it. So our single line-of-sight routine is going to fail us - at present, it'll simply report a wall in the way of the target square, and as a result we'll end up not putting the partially visible enemy character in the target square.

What we really need to do is measure the line of sight from two points on "either side" of the character, to two points "either side" of the centre of the target square. If either one of these lines is obscured, we don't want to allow our character to walk to the target (since at least part of the path is obscured). However, if either of the two lines is clear, then this means that the character can at least see part of the target square - and so, has an uninterrupted line-of-sight to the target.


In the diagram above, we created two rays, offset slightly from the centre of the originating square, to points either side of the centre of the target square. The green ray passes through the wall (and our routine correctly identifies that the wall is in the way.

However, because the red ray reaches its destination unhindered, we can report a line-of-sight between our character and the target square. If any enemy character were in this square, it should be displayed and placed on the board.