BGE: Stealth mechanics

With the BGMC 16 underway and as I’m running it and won’t be entering and the theme being stealth I thought I’d put together a quick tutorial on making a stealth game. We’ll start by looking and creating enemies that patrol or look around on guard, then see how we can create line’s of sight for them. From there we’ll explore ways we the player can distract enemies, get them to follow footprints and hide in the shadows. So lets get stuck in…

Set up and background

Most of my tutorials focus on python, and this one is no different. For many of the things detailed below there are ways to accomplish the same thing using logic bricks etc. I’ll give some outlines of how you might do this, but won’t go into much detail on them.

Scripting

For the python side of things we’re going to be using the python controller in module mode. This allows us to break each enemy action into a distinct function. The benefit here is that we can make use of logic states for each of the actions an enemy can perform. So all the python in this tutorial will contained within a single python file called guards.py, which I’ll post in full at the end.

Each enemy will start with an initiation state to set them up for later. This uses an always controller connected to a python module controller. Each enemy will also have a property called ‘mode’, the value of which will control if they are patrolling or guarding:

And here’s the python:

import bge
from math import sin

# enemy state definitions
INIT =              1 << 0
SCAN =              1 << 1
PATROL =            1 << 2
TOPOINTOFINTEREST = 1 << 3
LOOKAROUND =        1 << 4
RETURNTOPOST =      1 << 5
FOLLOWFOOTPRINTS =  1 << 6

def init(cont):
    own = cont.owner
    own['target'] = 'Player'
    
    own['baseRotation'] = own.worldOrientation.to_euler().z
    own['rot'] = 0.0
    
    own['currentPoint'] = 1   
    
    if own['mode'] == 'scan':             
        own.state = SCAN
    elif own['mode'] == 'patrol':        
        own.state = PATROL

There’s not much to explain here. The only note worthy part is how the state definitions are created at the top. By bit shifting 1 ( << left bit shift operator) by the state we want, minus 1, we get a bit mask for the state we’re after. So to get to state 16, for example, we just go 1 << 15. Handy little tip there.

On guard

Lets start with an enemy that stands on-guard scanning the area. First we need to set the second state to use an always sensor set to pulse mode connected to a python module controller running our scan function. Then we need set the ‘mode’ variable to ‘scan’:

scanningGuardLogicLayout

The python side of things here is pretty straightforward:

import bge
from math import sin

def scan(cont):
    own = cont.owner
    own['rot'] += 0.02
    own.worldOrientation = [0.0, 0.0, own['baseRotation'] + sin(own['rot'])]
    if spotPlayer(own):
        bge.logic.endGame()

Once we’ve done the usual process of getting the owner (remember, when working with the python module controller the current controller is passed by default) we then increment the ‘rot’ variable created in our enemy initialization. This controls the rate at which the enemy scans back and forth. Increase this value will speed it up, while decreasing it will slow it down.

The magic all happens in line 7 where we set our enemy’s orientation to the initial orientation of our enemy on the z axis plus the sine of our ‘rot’ value. By using the sin() function we get a a value between -1 and 1 based on what value we plug into the function. This gives the ability to sweep back and forth between -1 and 1 by using our ‘rot’ value without having to keep track of the value of ‘rot’.

Since our enemy’s rotation is in radians, using values between -1 and 1 give use a sweep of 57.295 degrees, which looks about right. If you want more control over the sweep angle then you’ll have to keep track of ‘rot’ yourself, or you could just animate the scanning back and forth instead of using python.

The final function call in our our scan function is spotPlayer(). We’ll come to how this one works later, but for now all you need to know is that it returns true if the player is in the enemy’s visual field and there is a clear line of sight. At this point, if the enemy can see the player we can take some kind of action. Since this is just a simple example we end the game, but at this point you could follow or attack or alert other guards, or whatever your game requires.

Patrolling

Before we can set up our patrolling enemy we need to make sure the level is prepared. First of all, you’re going to need a navigation mesh. Then we need to add patrol points. To do this I used empties placed on the navigation mesh. In order for the python side of things to work they need a very particular naming convention that follows the name of the path they belong to followed by the order the point appears in in the path. In this example it’s ‘SquarePatrol1’ which leads to ‘SquarePatrol2’ and so on.

demonstrating the patrol route layout and naming conventions

This may seem a little convoluted of a set up at first, but it allows use to have a variety of different patrol routes within each map. And the addition of number to the end of each point helps us keep track of where the enemy should be heading to.

Moving onto the enemy logic, in a new state (this time state 3) add an always sensor set to pulse mode, a python module controller and a steering actuator. For the enemy properties, we need the ‘mode’ property set to ‘patrol’ and 2 new properties. The first is called ‘path’ and it takes the value of the name of the patrol points (in this example ‘SquarePatrol’). The second value is ‘pathLength’ and this takes the number of points in the patrol route.

showing the logic set up for patrolling enemies

Ok, now it’s time for our patrol function:

def patrol(cont):
    own = cont.owner  
    pathFinder = cont.actuators['PathFinder']
    if own.getDistanceTo(pathFinder.target) <= 3:
        own['currentPoint'] += 1
        if own['currentPoint'] > own['pathLength']:
            own['currentPoint'] = 1        
        pathFinder.target = own['path'] + str(own['currentPoint'])
    cont.activate(pathFinder)
    if spotPlayer(own):
        bge.logic.endGame()

It may look like there’s a lot going on here, but it is surprisingly simple. Lets break it down. We start by getting the owner and steering actuator. We then check the distance the enemy is to the patrol point they are heading to. If they’re close enough to it we need to move to the next point. We do this by increasing the ‘currentPoint’ variable our initialization function created. Then we make sure we haven’t gone past the end of the patrol route by comparing this value to the ‘pathLength’ variable, if we have we just set ‘currentPoint’ to 1.

Now here’s where the patrol point naming convention comes in. When we move to the next point we take the ‘pathName’ variable (which should be the same as the points you want the enemy to follow) and add the ‘currentPoint’ number (after converting it to a string). So, if our enemy is following the SquarePatrol path and they reach the second point in that path then they need to head to the point called ‘SquarePatrol3’. Get it…?

I can see you!

When designing a sight mechanism I toyed with a number of different set ups. To begin with I thought of using a radar sensor. However, feedback in the forums tend to report these as being slow and then once the radar sensor has picked up on the player you’d still need to cast a ray to make sure that the line of sight is clear. Of course you could still combine a radar sensor with a ray cast sensor to an and controller if you wanted a pure logic brick solution.

Next I tried using a collision sensor as a physical field of view. This kinda works, but once the player is inside the field of view collisions don’t reliably register. I even went as far as writing scripts to test if an object is in a cone or pyramid projected from the enemy. These worked perfectly, but were a tad over-engineered.

Which brings us round to the solution I settled on. First we cast a ray from the player to the enemy to check the line of sight is clear. Then, if there are no obstacles we get the angle between the vector from the enemy to the player and a vector projected along the enemy’s local y axis. We can then compare this angle to the enemy’s view angle, and if it’s less than the view angle we know that player is in the enemy’s field of view.

calculating enemy sight

The advantage of this is that we can do a cheap ray cast first and only do the more expensive calculations to determine if it possible to see the player. Additionally, by using a ray cast we can determine the scenarios in which the enemy can see the player. This will come in handy later when we look at shadow mechanics.

So, here’s spotPlayer():

def spotPlayer(own):
    ob = own.rayCastTo(own['target'], 10)
    if ob:
        coneVec = own.getAxisVect([0,10,0]) 
        vecTo = own.getVectTo(ob)[1] 
        angle = coneVec.angle(vecTo)
        if angle <= 0.5235: # enemy view angle in radians

 in radians
            return True
    return False

I’m not going to over-explain the above python. Take a look at it, all the variables and function names should explain what’s going on. Although it involves some vector math we don’t actually need to worry too much about what’s going on behind the functions. Things worth noting are that the range of the enemy’s vision is determined by the ray cast length (10 in this example). And the angle of the cone is in radians.

Distracting guards

Ok, we’ve got guards moving around, we’ve got them guarding a spot and they can see the player. Now lets start distracting some guards.

At this point things are going to get a bit more confusing. We’ll start by getting the player to create some noise. This function lives within guards.py, but ideally should exist elsewhere since it belongs to the player’s functionality. However, for ease and clarity I’ve bunched it in with the enemy’s logic in the demo file. Logic-wise, the player has a keyboard sensor called ‘MakeNoise’ and this is connected to a python module controller calling the below function:

def makeNoise(cont):
    own = cont.owner
    if own.sensors['MakeNoise'].positive:
        marker = own.scene.addObject('Marker', own)    
        enemies = [ob for ob in own.scene.objects if 'mode' in ob]
        for e in enemies:
            if own.getDistanceTo(e) < 15:
                e['pointOfInterest'] = marker
                if 'prevState' not in e:
                    e['prevState'] = e.state
                e.state = TOPOINTOFINTEREST

First off, we start by creating a point in the game for the enemy to move towards, called marker. Next we gather all the enemies in the scene by using list comprehension. I’m not going to cover that today, but in this example we identify enemies by the property ‘mode’ since all enemies will hold that property.

with our list of enemies we can then loop through it and if an enemy was close enough to hear the sound we can process them. The first step in this is by giving the enemy a property called ‘pointOfInterest’ which we set to our marker, this will be used to guide the enemy later. We also store the enemy’s current state in a property, so that later down the line the enemy can return to what they were doing before we interrupted them. Finally, we set the enemy’s new state. So lets look at that.

Rather than explain the logic setup this time, you can just look at the picture below. Moving towards a noise (state 4):logic set up for moving towards a noise

And the python:

def goToPointOfInterest(cont):
    own = cont.owner        
    pathFinder = cont.actuators['PathFinder']   
    
    if 'oldPos' not in own:
        own['oldPos'] = own.scene.addObject('Marker', own)
        own['oldTarget'] = pathFinder.target
    
    try:    
        pathFinder.target = own['pointOfInterest']
    except SystemError:
        own.state = RETURNTOPOST
        return    
    
    if pathFinder.target:
        if own.getDistanceTo(pathFinder.target) < 3:
            own['pointOfInterest'].endObject()
            own.state = LOOKAROUND
            own['rot'] = 0.0
            own['lookRotation'] = own.worldOrientation.to_euler().z
    else:
        own.state = RETURNTOPOST
        
    cont.activate(pathFinder)
    
    if spotPlayer(own):
        bge.logic.endGame()

Before we can move onto heading towards the noise we need to store a couple of values so that the enemy can return to what they were doing. The first is a marker for their current position before being called away, the second is whatever they were path finding towards before the interruption.

We then try to update the attached steering actuator. Why try? Well, there’s a chance that the noise marker could be removed, and rather than risk the enemy crashing or some other strange bug we can just have the enemy return to what they were doing if something goes wrong. Notice that the try block only encapsulates a small bit of code, and the error we’re looking for is specified. This is because we only want to catch the exceptions that we’re prepared to handle.

But all going well, we’re able to update the steering actuator’s target. The next ‘if’ statement exists for similar reasons. Once we get near the marker, we can then remove it from play and start to look around (see why those try/except and if blocks are needed now?). This functions similarly to our on guard state, so it shouldn’t be too surprising to see that we set an initial rotation and a ‘rot’ variable for holding rotations. So lets look at looking around.

Looking around logic (state 5):

lookingAroundLogicLayoutAnd the python:

def lookAround(cont):
    own = cont.owner    
    own['rot'] += 0.02
    direction = 0
    
    if own['rot'] / 4 >= 1.5707:
        direction = 3.145
    if own['rot'] / 8 >= 1.5707:
        own.state = RETURNTOPOST
    
    own.worldOrientation = [0.0, 0.0, own['lookRotation'] + sin(own['rot']) + direction]    
    
    if spotPlayer(own):
        bge.logic.endGame()

Although it looks different, this is more or less the same as when we had scanning guards. The main different here is we’ve got a variable called direction and we’re keeping track of ‘rot’. When we’ve completed 4 sweeps back and forth (one sweep would be a ‘rot’ value of 1.5707, where sin(1.5707) = 1) we then add pi (well, roughly) to get the enemy to face the other way and scan behind them 4 more times. Once that’s complete they can then return to their post.

Return to your post

Hopefully, this next step is staightforward. Here’s the logic (state 6):

logic layout for returning to previous action

And the python:

def returnToPost(cont):
    own = cont.owner    
    pathFinder = cont.actuators['PathFinder']
    pathFinder.target = own['oldPos']
        
    if own.getDistanceTo(pathFinder.target) < 2:
        if 'oldTarget' in own:
            pathFinder.target = own['oldTarget']
        own['oldPos'].endObject()
        del own['oldPos']
        own.state = own['prevState']
        del own['prevState']
        return
    
    cont.activate(pathFinder)
    
    if spotPlayer(own):
        bge.logic.endGame()

We begin with updating the steering actuator with the position marker we set before the enemy moved from their last position to investigate. Then, once the enemy is back in position we go about restoring it to its previous state and variables to their previous values that were previously saved. We also delete some unneeded properties so that they can be set again should the enemy get called to a point of interest again.

Following footprints

This started out as one of the trickier problems to solve. And I came up with a fairly long-winded solution to it. Then when it came to writing the conclusion to this post I thought about other ways it could be solved, which turned out to be much simpler, so I re-wrote this section. The power of reflection.

Lets start with getting the player to lay down some tracks:

def setPrints(cont):
    own = cont.owner    
    if cont.sensors['FootPrintDelay'].positive:
        fp = own.scene.addObject("FootPrints", own, 125)
        
        if 'lastPrint' in own:
            own['lastPrint']['nextPrint'] = fp
        own['lastPrint'] = fp

The logic set up on the player is pretty simple, a delay sensor called ‘FootPrintDelay’ set to a delay of 10 tics and to repeat connected to a python module controller running the above function. Like the previous player code, this lives in guards.py.

When it’s time to lay another print the player object stores the print added. Then, when we add a new print, we go back to that stored last print and give that last print a reference to the latest added print. The latest print then becomes the last print. What this results in is a linked list, where each footprint points to the next one in the sequence. More on this later.

Before an enemy can start following footprints they need to be able to see them:

def spotFootprints(own):
    for fp in activePrints:
        ob = own.rayCastTo(fp, 10)
        if ob:
            coneVec = own.getAxisVect([0,10,0]) 
            vecTo = own.getVectTo(ob)[1] 
            angle = coneVec.angle(vecTo)
            if angle <= 0.5235:
                own['pointOfInterest'] = fp
                if 'PathFinder' in own.actuators:
                    own['oldTarget'] = own.actuators['PathFinder'].target
                if 'prevState' not in own:
                    own['prevState'] = own.state
                if 'oldPos' not in own:
                    own['oldPos'] = own.scene.addObject('Marker', own)
                own.state = FOLLOWFOOTPRINTS
                return

This is a modified version of spotPlayer(). We start by going through all the footprints in the ‘activePrints’ list, and just like checking to see the player, we cast a ray to them and check if they’re in the field of vision. Then, just like with making noise, once we’ve spotted a footprint we need to save all the old values in case the enemy needs to return to their post. Finally, we exit the function after spotting the first print, there’s no need to check against them all.

Then we just need to add our footprint search function to other guard functions where we might want an enemy to be on the lookout for footprints.

    ...
    if spotPlayer(own):
        bge.logic.endGame()
    spotFootprints(own)
    ...

Once we’ve found a footprint, we need to start following them. So, create our final state ( state 7), which looks exactly like going to a point of interest state or returning to post state, except the python function we’re calling this time is this one:

def followFootprints(cont):
    own = cont.owner    
    pathFinder = cont.actuators['PathFinder']
    try:
        pathFinder.target = own['pointOfInterest']
    except SystemError:
        own.state = RETURNTOPOST
        return
    if own.getDistanceTo(pathFinder.target) < 1:
        own['pointOfInterest'] = pathFinder.target['nextPrint']
    cont.activate(pathFinder)

We update the steering actuator with the footprint that the enemy has spotted. As the enemy moves near this footprint we can get the next footprint in the sequence from the current footprint (remember our linked list), update the steering actuator with that and repeat.

The try/expect block will catch when we move to a footprint that either doesn’t have another footprint attached to it or that footprint has been moved from the game. If that is the case, we can then instruct the enemy to return to their post, look around or complete some other action. The use of a return statement in the exception block allows us to exit early from the function once we’ve established that we can’t follow the rest of the footprints.

Using ‘try’ is faster than asking for permission with an ‘if’ statement, expect when we enter the exception block, then it performs slightly worse than an ‘else’ block. Since we’ll only ever enter the except block once (ie, it’s exceptional) this solution should perform more efficiently than if/else. It also syntactically makes a bit more sense: lets try and follow the footprints, rather than if we can follow the footprints.

try/except is a powerful tool and it’s worth making sure you understand it fully. I’ve recently come across a video tutorial showing some poor usage of it – not specifying errors, not handling them, not explaining why you would use it in that situation. That kind of practice is only going to cause more problems than it solves later down the line.

Hiding in the shadows

I thought we’d end on an easy problem. This requires just a simple tweak of our spotPlayer() function (the addition of a ‘visible’ player property):

def spotPlayer(own):
    ob = own.rayCastTo(own['target'], 10)
    if ob and ob['visible']:
        coneVec = own.getAxisVect([0,10,0]) 
        vecTo = own.getVectTo(ob)[1] 
        angle = coneVec.angle(vecTo)
        if angle <= 0.5235:
            return True
    return False

Then we just need to add a property to the player called visible. We can then update this property accordingly. In the demo file I used a collision sensor looking for materials connected to a property actuator. It doesn’t produce the most reliable of results, but with a bit of thought I’m sure you can come up with a reliable way to update the player’s visibility. Similarly, it wouldn’t be too much of a stretch to do something similar with the footprints so enemies can’t see them when you’re in the shadows (like only calling set footprints when the player is standing on particular materials).

Final words

There are some drawbacks with the sight mechanics that need some consideration. Because we’re casting a ray to the center of the player object it means that so long as the player’s center is obscured the enemy cannot see them, even if parts of the player are clearly within the visual field.

demonstration of a broken line of sight despite the player remaining in the enemy's field of view

There are a couple of ways around this. Smoking_mirror came up with a method that involves casting rays to key bones in the player armature to check if any parts are sticking out. If you wanted even more accurate player detection you could also loop through all the vertices in the player model and cast rays to them. Of course, this would be more process intensive than Smoking_mirror’s method.

Out of all the tutorials I’ve done this is probably the most buggy. One of the main causes behind this is due to trying to use the steering actuator with objects that eventually get removed from the scene. My work around was to use attempt to try and use the object and if it had gone for the enemy to give up and return to post (rather than crash). This leads to them giving up in situations where they probably shouldn’t. The issue is furthered when the enemy has repeated state changes and saves the wrong return-to-post data. Generally, they behave as expected, but if you start putting them through their paces, mixing them up with footprints and noise they quickly get confused. Ultimately, I think the whole enemy structure would have been easier using classes rather than functions and states because of the high amount of shared data between states. But that’s a tutorial for another time.

As always feel free to leave you feedback, comments and suggestions below. Don’t forget to ‘like’, and if you manage to improve/fix some of the bugs let me know!

Resources

Here’s the stealthExample.blend demo

Here’s guards.py in full:

import bge
from math import sin

# enemy state definitions
INIT =              1 << 0
SCAN =              1 << 1
PATROL =            1 << 2
TOPOINTOFINTEREST = 1 << 3
LOOKAROUND =        1 << 4
RETURNTOPOST =      1 << 5
FOLLOWFOOTPRINTS =  1 << 6

def init(cont):
    own = cont.owner
    own['target'] = 'Player'
    
    own['baseRotation'] = own.worldOrientation.to_euler().z
    own['rot'] = 0.0
    
    own['currentPoint'] = 1   
    
    if own['mode'] == 'scan':             
        own.state = SCAN
    elif own['mode'] == 'patrol':        
        own.state = PATROL

def spotPlayer(own):
    ob = own.rayCastTo(own['target'], 10, 'hidden')
    if ob and not ob['hidden']:
        coneVec = own.getAxisVect([0,10,0]) 
        vecTo = own.getVectTo(ob)[1] 
        angle = coneVec.angle(vecTo)
        if angle <= 0.5235:
            return False
    return False

def spotFootprints(own):
    activePrints = [ob for ob in own.scene.objects if ob.name == "FootPrints"]
    for fp in activePrints:
        ob = own.rayCastTo(fp, 10)
        if ob:
            coneVec = own.getAxisVect([0,10,0]) 
            vecTo = own.getVectTo(ob)[1] 
            angle = coneVec.angle(vecTo)
            if angle <= 0.5235:
                own['pointOfInterest'] = fp
                if 'PathFinder' in own.actuators:
                    own['oldTarget'] = own.actuators['PathFinder'].target
                if 'prevState' not in own:
                    own['prevState'] = own.state
                if 'oldPos' not in own:
                    own['oldPos'] = own.scene.addObject('Marker', own)
                own.state = FOLLOWFOOTPRINTS
                return
    
def scan(cont):
    own = cont.owner
    own['rot'] += 0.02
    own.worldOrientation = [0.0, 0.0, own['baseRotation'] + sin(own['rot'])]
    if spotPlayer(own):
        bge.logic.endGame()
    spotFootprints(own)
    
def patrol(cont):
    own = cont.owner  
    pathFinder = cont.actuators['PathFinder']
    if own.getDistanceTo(pathFinder.target) <= 3:
        own['currentPoint'] += 1
        if own['currentPoint'] > own['pathLength']:
            own['currentPoint'] = 1        
        pathFinder.target = own['path'] + str(own['currentPoint'])
    cont.activate(pathFinder)
    
    if spotPlayer(own):
        bge.logic.endGame()
    spotFootprints(own)
    
def goToPointOfInterest(cont):
    own = cont.owner        
    pathFinder = cont.actuators['PathFinder']   
    
    if 'oldPos' not in own:
        own['oldPos'] = own.scene.addObject('Marker', own)
        own['oldTarget'] = pathFinder.target
    
    try:    
        pathFinder.target = own['pointOfInterest']
    except SystemError:
        own.state = RETURNTOPOST        
        return    
    
    if pathFinder.target:
        if own.getDistanceTo(pathFinder.target) < 3:
            own['pointOfInterest'].endObject()
            own.state = LOOKAROUND
            own['rot'] = 0.0
            own['lookRotation'] = own.worldOrientation.to_euler().z
    else:
        own.state = RETURNTOPOST
        
    cont.activate(pathFinder)
    
    if spotPlayer(own):
        bge.logic.endGame()

def lookAround(cont):
    own = cont.owner    
    own['rot'] += 0.02
    direction = 0
    
    if own['rot'] / 4 >= 1.5707:
        direction = 3.145
    if own['rot'] / 8 >= 1.5707:
        own.state = RETURNTOPOST
    
    own.worldOrientation = [0.0, 0.0, own['lookRotation'] + sin(own['rot']) + direction]    
    
    if spotPlayer(own):
        bge.logic.endGame()
    spotFootprints(own)

def returnToPost(cont):
    own = cont.owner    
    pathFinder = cont.actuators['PathFinder']
    pathFinder.target = own['oldPos']
        
    if own.getDistanceTo(pathFinder.target) < 2:
        if 'oldTarget' in own:
            pathFinder.target = own['oldTarget']
        own['oldPos'].endObject()
        del own['oldPos']
        own.state = own['prevState']
        del own['prevState']
        return
    
    cont.activate(pathFinder)
    
    if spotPlayer(own):
        bge.logic.endGame()
    spotPrints(own)

def followFootprints(cont):
    own = cont.owner    
    pathFinder = cont.actuators['PathFinder']
    try:
        pathFinder.target = own['pointOfInterest']
    except SystemError:
        own.state = RETURNTOPOST
        return
    if own.getDistanceTo(pathFinder.target) < 1:
        own['pointOfInterest'] = pathFinder.target['nextPrint']
    cont.activate(pathFinder)
    
    

##### setPrints and makeNoise should be else where
# since technically they belong to the player
# but for clarity's/ease sake they're here
# if you were to move them

def setPrints(cont):
    own = cont.owner
    
    if cont.sensors['FootPrintDelay'].positive:
        fp = own.scene.addObject("FootPrints", own, 125)
        
        if 'lastPrint' in own:
            own['lastPrint']['nextPrint'] = fp
        own['lastPrint'] = fp
            
def makeNoise(cont):
    own = cont.owner
    if own.sensors['MakeNoise'].positive:
        marker = own.scene.addObject('Marker', own)    
        enemies = [ob for ob in own.scene.objects if 'mode' in ob]
        for e in enemies:
            if own.getDistanceTo(e) < 15:
                e['pointOfInterest'] = marker
                if 'prevState' not in e:
                    e['prevState'] = e.state
                e.state = TOPOINTOFINTEREST
Advertisements

~ by Jay on May 29, 2015.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: