How to Make a Platformer in Gamemaker Studio

GameMaker-Studio-Logo

Making 2D platformers in GameMaker Studio involves more than jumping a character up and down. It needs calculations of horizontal movement, Creation Code for a basic checkpoint system and novice developers often stumble because they underestimate what goes into a 2D platformer. While not overwhelming, 2D platformers are a reasonable step up from basic maze and space shooter projects.

After a month of development, I will show you how to make a 2D platformer foundation straight forward enough to develop, but simple enough so you can add your own ideas for a 2D platformer game.

Part 1: Sprites

Make a new project

Create a sprite by pressing this icon

Capture

Make 10 sprites and name them: spr_wall, spr_player, spr_moving_wall, spr_movingwall2, spr_onewayplatform, spr_enemy, spr_emblem, spr_coin, spr_goal, spr_checkpoint

Double click on the sprites and give them the following properties:(The properties can be edited with these GUI interfaces. You can make the sprites anything you want, but its best to work with basic coloured squares)

spr_wall 32×32
spr_player 32×32, 16×16 origin
spr_moving_wall 64×32, 32×0 origin
spr_moving_wall2 64×64, 32×0 origin
spr_oneway_platform 64×32, 32×0 origin
spr_enemy 32×32, 16×16 origin
spr_emblem 32×32
spr_coin 32×32
spr_goal 32×32
spr_checkpoint 32×32, 2 subimages

Part 2: Scripts

Now make a script by pressing this icon

tut-pic-4

In the script, put in the following code:

///—–CHECKPOINT SYSTEM—–///
//—————————-//
if (global.checkpointR != 0)
{
room_goto(global.checkpointR);
}
else
{
room_restart();
}
//—————————-//

//This system needs Creation Code in order to operate
//Make a room called rm_initialise and only put in Creation Code and room_goto_next
//Global Variables are values that carry their functions across all aspects of a game
//The player will never see this room, but is needed in order to make checkpoints work properly
//In the first line, it checks if a checkpoint is activated (if checkpoints are not off)
//The second line enclosed in a curly bracket will spawn the player in the checkpoints position
//The third line checks if the conditions of the first two lines has not been met
//Then the fourth line will spawn the player at the beginning of the level, but only when the conditions of the first two lines has not been met
//In my example, the enemies have room_restart that makes the player start the room over whenever they touch the enemies and have not jumped on top of them
//Because the Creation Code sets the checkpoint system, room_restart or scr_death will achieve the same thing, make the player spawn on an active checkpoint
//But because it restarts the room, global variables for things such as collectables and coins will not be kept intact
//You should use scr_death if you want certain aspects of progress to remain in memory
//Keep in mind that this system is very basic

checkpoint-illustration

Part 3: Objects

After that, make 12 objects and name them: obj_jumprefine, obj_wall, obj_movingwall, obj_movingwall2, obj_onewayplatform, obj_enemy, obj_enemy2, obj_enemy3, obj_emblem, obj_coin, obj_goal, obj_checkpoint

Object 1/12

In obj_jumprefine, edit these values: Depth -1

Put the following code into these events:

Create Event

///—–ESTABLISH PLAYER VARIABLES—–///
//————————————-//
hsp = 0 //horizontal movement
vsp = 0 //vertical movement
grav = 0.5 //force of gravity that pulls the player down to the ground
key_down = 0 //allows players to go down oneway platforms
hsp_carry = 0 //horizontal movement on moving platforms
vsp_carry = 0 //vertical movement on moving platforms (Legacy code, meaning this project ended up not using vertical platforms due to programming difficulties)
acc = 0.50 //the amount a player’s speed revs up until they hit their max
max_speed = 5 //default speed and can be changed by sprinting. Can be any letter key with (keyboard_check(ord(“”)))
jump_number = 1 //how many times a player can jump in the air

//Checkpoint spawning
if (global.checkpointR == room)
{
x = global.checkpointx;
y = global.checkpointy;
}
//When an activated checkpoint exists in a room
//The player spawns in the checkpoints X and Y position
//When a checkpoint isn’t in existence, the player spawns back at the start of the room
//The player’s spawn is affected by falling out of room borders and touching enemies
//————————————-//

Step Event

///—–CONTROLS KEYBOARD INPUT AND GRAVITY—–///
//———————————————-//
if (keyboard_check(vk_right))
{
if (hsp < max_speed) hsp += acc
}

//When the right arrow key is pressed
//The game checks if horizontal movement is less than the maximum movement
//When less than max_speed, hsp adds acc(o.5) for every frame the arrow key is pressed
//This rises until hsp is equal to max_speed(5 or 7)

if (keyboard_check(vk_left))
{
if(hsp > -max_speed) hsp -= acc
}

//When the left key is pressed
//The game checks if horizontal movement is less than the maximum movement
//When less than max_speed, hsp adds acc(o.5) for every frame the arrow key is pressed
//This rises until hsp is equal to max_speed(5 or 7)

if (keyboard_check(ord(“Z”)))
{
max_speed = 7.5
}
else
{
max_speed = 5
}

//When the Z key is pressed
//max_speed is changed to 7.5, making the player move faster because acc now adds more multiples of 0.5 every frame
//When the Z isn’t pressed
//max_speed is set back to normal

running-illustration

if(!keyboard_check(vk_left)&& !keyboard_check(vk_right) || keyboard_check(vk_left) && keyboard_check(vk_right))
{
hsp = 0 + hsp_carry
hsp_carry = 0
}

//To allow the player to stop moving when letting go of a movement key
//The game checks if movement is not pressed or if it is pressed
//Horizontal movement is set to zero when let go or starts it at zero if being pressed
//Previous movement code is responsible for increasing hsp’s value
//! is NOT, && is AND, || is OR
//The hsp carry bracket allows the player to stand and move with a horizontal moving platform

if(place_meeting(x,y+1,obj_wall))
{
jump_number = 1
}
if (keyboard_check_pressed(vk_up)) && (place_meeting(x,y+1,obj_wall))
{
vsp = -12
jump_number -=1
}
if (keyboard_check_pressed(vk_up)) && (!place_meeting(x,y+1,obj_wall)) && jump_number >=0
{
vsp = -12
jump_number -=1
}
if(keyboard_check_released(vk_up) && vsp < 0)
vsp *= 0.5
else
{
vsp +=grav
}

//The game checks if the player is touching or rather 1 pixel above a wall
//If in contact jump_number is set to 1, allowing the jump again after the vsp has been set on input
//When the jump button is pressed
//The jump(vsp) moves the player upwards and subtracts 1 jump_number count
//When jump_number is greater than or equal to 0
//The player can make an additional jump
//This jump can happen on ground or the air and resets after landing
//When the jump key is pressed and released
//It checks if vsp is less than 0
//vsp then equals and multiply by 0.5 until the key is let go
//After these functions have been met or don’t meet conditions
//vsp will equal gravity, that pulls the player down to earth for every frame where a condition hasn’t been met
//———————————————-//

///—–COLLISION AND MOVEMENT CHECKS—–///
//Turn off Solid in your wall object because this paragraph gives superior control over collisions with the player//
//—————————————-//
if(place_meeting(x+hsp,y,obj_wall,))
{
while(!place_meeting(x+sign(hsp),y,obj_wall,))
{
x+=sign(hsp)
}
hsp = 0
}
x += hsp

//When the player’s position meets the wall horizontally
//sign returns 1 or -1 values and checks if left or right meets the wall
//Then if 1 pixel in a space is free, the player keeps moving left or right
//Once the player touches the wall, they stop moving and don’t past through the wall horizontally
//They will then carry on with their current X position

if(place_meeting(x,y+(vsp),obj_wall,))
{
while(!place_meeting(x,y+sign(vsp),obj_wall,))
{
y+=sign(vsp)
}
vsp = 0
}
y += vsp

//When the player’s position meets the wall vertically
//sign returns 1 or -1 values and checks if up or down meets the wall
//Then if 1 pixel in a space is free, the player keeps moving up or down
//Once the player touches the wall, they stop moving and don’t past through the wall vertically
//They will then carry on with their Y position
//—————————————-//

 

///—–GOING DOWN ONE WAY PLATFORMS WHEN STANDING ON THEM—–///
//—————————————–//
key_down = keyboard_check(vk_down)
//When the down key is pressed on a one way platform, the player will fall through it
//The player can also pass through Horizontal and Vertical moving platforms
//—————————————–//

onwayplatform-illustration

Other, Outside Room

///—–FALLING OUTSIDE GAME BORDERS—–///
//—————————————//
room_restart() //When the player goes outside the game borders, the room restarts
//—————————————//

Object 2/12

In obj_wall, edit these values: Children:obj_movingwall, obj_movingwall2, obj_onewayplatform

tut-pic-6

Object 3/12

In obj_movingwall, put the following code into these events:

Create Event

///—–ESTABLISH MOVEMENT PROPERTIES—///
//————————————–//
dir = -1
movespeed = 3
hsp = 0
sprite_index = -1;
//dir is the direction the platform moves in
//movespeed is how fast the platform moves
//hsp is horizontal speed
//Sprite_index allows the player to go through the bottom and sides of the platform
//————————————–//

Step Event

///—–PLAYER COLLISION WITH THE MOVING PLATFORM—–///
//obj_movingwall is a parent of obj_wall, meaning it shares many of obj_wall’s coding properties//
//—————————————————-//
mask_index = spr_moving_wall
hsp = dir * movespeed

//mask_index is the objects collision box
//Horizontal movement is set by direction and movement speed

if (place_meeting(x+hsp,y,obj_wall))
{
while(!place_meeting(x+sign(hsp),y,obj_wall))
{
x += sign(hsp);
}
hsp = 0;
dir *= -1;
}
x += hsp;
if (instance_exists(obj_jumprefine))
{
if (round(obj_jumprefine.y + (obj_jumprefine.sprite_height/2)) > y) || (obj_jumprefine.key_down) mask_index = -1;
else
{
mask_index = spr_moving_wall;
if place_meeting(x,y-1,obj_jumprefine)
{
obj_jumprefine.hsp_carry = hsp;
}
}
}

//When the platform touches a wall
//And they are currently not touching one
//The X position is rounded by sign hsp
//Then the hsp is set to 0
//And the direction is flipped in the other direction
//The platform carry’s on with its X position
//This creates a loop where the platform goes left and right so long as it bounces off a wall
//When a player exists on the platform
//Their Y position is calculated to be above the horizontal platform
//When above the platform, the mask below the platform is off, allowing the player to jump up, down or sideways onto the platform’s centre position
//This is why the platform sprite’s X centre origin is placed in the top middle of the platform (You can change it in the Sprite properties)
//When this condition isn’t met the mask_index is on, allowing the platform to collide with the wall
//When the player is standing on the platform
//Their hsp will equal the platform’s own hsp, allowing them to move with the platform
//—————————————————-//

Draw Event

///—–SHOW SPRITE ON SCREEN—–///
//——————————–//
draw_sprite(spr_moving_wall,0,x,y);
//The objects sprite is shown on screen
//——————————–//

Object 4/12

In obj_movingwall2, put the following code into these events:

Create Event

///—–ESTABLISH MOVEMENT PROPERTIES—–///
//————————————–//
dir = 1
movespeed = 1
vsp = 0
sprite_index = -1
//dir is the direction the platform goes in (up and down)
//movespeed is how fast the platform goes
//vsp is vertical movement
//sprite_index sets the sprite subimage

Step Event

///—–MOVEMENT AND COLLISION OPERATIONS—–///
//Legacy code that does not work properly
//——————————————–//
vsp = dir * movespeed
mask_index = spr_moving_wall2
if (place_meeting(x,y+vsp,obj_wall))
{
while(!place_meeting(x,y+sign(vsp),obj_wall))
{
y += sign(vsp);
}
vsp = 0;
dir *= -1;
}
y += vsp;
if (instance_exists(obj_jumprefine))if (round(obj_jumprefine.y + (obj_jumprefine.sprite_height/2)) > y) || (obj_jumprefine.key_down) mask_index = -1;
else
{
{
mask_index = spr_moving_wall2
if place_meeting(x,y-1,obj_jumprefine)
{
obj_jumprefine.vsp_carry = vsp;
}
}
}
//——————————————–//

Draw Event

///—–SHOW SPRITE ON SCREEN—–///
//——————————–//
draw_sprite(spr_moving_wall2,0,x,y);
//The objects sprite is shown on screen
//——————————–//

Object 5/12

In obj_onewayplatform, put the following code into these events:

Create Event

///—–ESTABLISH ONE WAY PLATFORM VARIABLES—–///
//———————————————–//
sprite_index = -1
//sprite_index is responsible for affecting the collision box
//By default, -1 turns off the collision box
//the Draw Event, separate from this code script allows players to see the object sprite
//The Step Event affects if the player can stand on top of the platform by turning the sprite_index on and off

Step Event

///—–PLAYER COLLISION WITH ONEWAY PLATFORM—–///
//————————————————//
//Check for player existing in the game to prevent death script conflict and crashes
if(instance_exists(obj_jumprefine))
{
if (round (obj_jumprefine.y + (obj_jumprefine.sprite_height/2)) > y) || (obj_jumprefine.key_down) mask_index = -1
else mask_index = spr_oneway_platform
}
//When the player exists in the game
//The sprite’s foot is checked
// when its greater than the position of the one way platform
//round turns numbers into integers to ensure whole numbers are caculated
//mask_index is turned on, letting the player stand on top of the platform’s origin

Draw Event

///—–SHOW ONEWAY PLATFORM SPRITES ON SCREEN—–///
//————————————————-//
draw_sprite(spr_oneway_platform,0,x,y)
//Shows Oneway platfrom’s sprite
//————————————————-//

Object 6/12

In obj_enemy, put the following code into these events:

Create Event

///—–ESTABLISH ENEMY VARIABLES—–///
//————————————//
state = e_state.idle//allows the enemy to move once the player is close enough
dir = -1;//the direction the enemy moves
movespeed = 2;//the speed the enemy moves at
grav = 0.5;//the force of gravity dragging the enemy down to the ground
hsp = 0;// horizontal movement
vsp = 0;//vertical movement
//————————————//

Step Event

///—–ENEMY LOGIC AND COLLISION—–///
//————————————//
switch (state)
{
case e_state.idle:
{
hsp = 0;
vsp = (min(7,vsp+0.5));
if (distance_to_object(obj_jumprefine) < 384) state = e_state.chase;
}
break;
case e_state.chase:
{
dir = sign(obj_jumprefine.x – x);
hsp = dir * 2;
vsp = (min(7,vsp+0.5));
if (distance_to_object(obj_jumprefine) > 416) state = e_state.idle;
}
break;
}
if (place_meeting(round(x+hsp),round(y),obj_wall))
{
while(!place_meeting(round(x+sign(hsp)),round(y),obj_wall)) x += sign(hsp);
hsp = 0;
}
x += hsp;
if (place_meeting(round(x),round(y+vsp),obj_wall))
{
while(!place_meeting(round(x),round(y+sign(vsp)),obj_wall)) y += sign(vsp);
vsp = 0;
}
y += vsp;

//The enemy has their state set to idle
//State machines are isolated forms of code that can be called upon at any time
//They are a useful advanced rescource for making A.I, complex mechanics and menus
//In idle, the enemy is still and is affected by gravity
//When the player comes into a close distance to the enemy, the state changes to chase
//The previous state is replaced with the new activated state
//The enemy moves to the player’s X posistion at a speed of 2
//The enemy is still affected by gravity
//Once the player has enough distance away from the enemy
//The enemy’s state goes back to idle and the chase state is lost until activated again
//The rest is collision code with the wall that rounds caulations to whole numbers
//————————————//

enemy-a-i-illustration

///—–PLAYER ABILITY TO JUMP ON AND DEFEAT ENEMIES—–///
//——————————————————-//
if(place_meeting(x,y,obj_jumprefine))
{
if(obj_jumprefine.y < y – 20)
{
with(obj_jumprefine) vsp = -vsp
instance_destroy()
}
else
{
room_restart()
}
}

//When the player is touching an enemy
//The player has their Y posistion checked to see if its a set number less than the enemies own Y posistion
//When less than the enemies Y posistion, the player will bounce upwards off the enemy and kill it
//The player’s bounce is equal to how much vsp was caculated during the check
//If falling from a great height, the player will have a great bounce upwards and vice versa
//If that check isn’t met, the player is beaten by the enemy and the room restarts
//In my example, the enemies have room_restart that makes the player start the room over whenever they touch the enemies and have not jumped on top of them
//Because the Creation Code sets the checkpoint system, room_restart or scr_death will achive the same thing, make the player spawn on an active checkpoint
//But because it restarts the room, global variables for things such as collectibles and coins will not be kept intact
//You should use scr_death if you want ceartin aspects of progress to remain in memory
//——————————————————-//

enemy-stomp-illustration

Outside Room

///—–FALLING OUTSIDE GAME BORDERS—–///
//——————————-//
instance_destroy()//When outside the room’s borders, the enemy is destroyed
//——————————-//

Object 7/12

In obj_enemy2, edit these values: Children: obj_enemy3

Put the following code into these events:

Create Event

///—–ESTABLISH ENEMY VARIABLES—–///
//————————————//
dir = -1//the direction the enemy moves
movespeed = 2//the speed the enemy moves at
grav = 0.5//the force of gravity dragging the enemy down to the ground
hsp = 0// horizontal movement
vsp = 0//vertical movement
fearofheights = 0//allows obj_enemy3, a child of obj_enemy2 to move without falling off the ground
//————————————//

Step Event

///—–ENEMY LOGIC AND COLLISION—–///
//————————————//
hsp = dir * movespeed;
vsp += grav;

//hsp is caculated by direction and movement speed
//vsp is gravity, the force that pulls objects down to the ground

if (place_meeting(x+hsp,y,obj_wall))
{
while(!place_meeting(x+sign(hsp),y,obj_wall))
{
x += sign(hsp);
}
hsp = 0;
dir *= -1;
}
x += hsp;

//When touching walls
//The enemy goes in the opposite direction
//They retain their X posistion

if (place_meeting(x,y+vsp,obj_wall))
{
while(!place_meeting(x,y+sign(vsp),obj_wall))
{
y += sign(vsp);
}
vsp = 0;
if (fearofheights) && !position_meeting(x+(sprite_width/2)*dir, y+(sprite_height/2)+8, obj_wall)
{
dir *= -1;
}
}
y += vsp;

//When moving across walls and near an edge
//The enemy’s sprite is checked to see if it’s 8 pixels away from changing its Y position
//If the enemy is 8 pixels away from going off a edge, the enemy will have its direction changed before they fall off
//They retain their Y position
//This code only affects obj_enemy3 that inherits obj_enemy2’s properties
//————————————//

///—–PLAYER ABILITY TO JUMP ON AND DEFEAT ENEMIES—–///
//——————————————————-//
if (place_meeting(x,y,obj_jumprefine))
{
if (obj_jumprefine.y < y-20)
{
with (obj_jumprefine) vsp = -vsp;
instance_destroy();
}
else
{
room_restart();
}
}

//When the player is touching an enemy
//The player has their Y posistion checked to see if its a set number less than the enemies own Y posistion
//When less than the enemies Y posistion, the player will bounce upwards off the enemy and kill it
//The player’s bounce is equal to how much vsp was caculated during the check
//If falling from a great height, the player will have a great bounce upwards and vice versa
//If that check isn’t met, the player is beaten by the enemy and the room restarts
//In my game, the enemies have room_restart that makes the player start the room over whenever they touch the enemies and have not jumped on top of them
//Because the Creation Code sets the checkpoint system, room_restart or scr_death will achieve the same thing, make the player spawn on an active checkpoint
//But because it restarts the room, global variables for things such as collectables and coins will not be kept intact
//You should use scr_death if you want ceartin aspects of progress to remain in memory
//——————————————————-//

Object 8/12

In obj_enemy3, put the following code into these events:

Create Event

tut-pic-5Drag and Drop in Control tab

///—–ABILITY TO NOT FALL OFF EDGES WHEN MOVING LEFT AND RIGHT—–///
//————————————————————————//
fearofheights = 1//Allows the enemy to not fall off edges
//Affects only obj_enemy3
//————————————————————————//

Object 9/12

In obj_emblem, put the following code into these events:

Collision Event with obj_jumprefine

///—–PLAYER INTERACTION WITH EMBLEM—–///
//—————————————//
instance_destroy()
//When the player touches the emblem, the emblem vanishes
//It does nothing and is there to see the basic idea of collectables in action and how they affect player behaviour
//—————————————//

Object 10/12

In obj_coin, put the following code into these events:

Collision Event with obj_jumprefine

///—–PLAYER INTERACTION WITH COIN—–///
//—————————————//
instance_destroy()
//When the player touches the coin, the coin vanishes
//It does nothing and is there to see the basic idea of collectibles in action and how they affect player behaviour
//—————————————//

Object 11/12

In obj_goal, put the following code into these events:

Collision Event with obj_jumprefine

///—–PLAYER INTERACTION WITH GOAL—–///
//—————————————//
room_goto_next()
//When touching the goal, the player is sent to the next room
//This order can be arranged simply by having rooms ordered top to bottom in the room folder
//e.g rm_initialize, rm_level1, rm_level2, rm_testing
//—————————————//

Object 12/12

In obj_checkpoint, put the following code into these events:

Create Event

///—–ESTABLISH VISUAL ELEMENTS—–///
//————————————//
image_index = 0
image_speed = 0
//image_index sets the sprite subimage drawn on the screen
//image_speed sets how quickly the sprite shows its animation frames
//In this suitation, the checkpoint will rapidly flash without its speed set to 0
//————————————//

Step Event

///—–CHECKPOINT REACTION TO PLAYER—–///
//—————————————-//
if (place_meeting(x,y,obj_jumprefine))
{
global.checkpoint = id;
global.checkpointx = x;
global.checkpointy = y;
global.checkpointR = room;
}
if (global.checkpointR == room)
{
if (global.checkpoint == id) image_index = 1; else image_index = 0;
}
//When the player touches a checkpoint
//The checkpoint sets its global variables
//== room checks for the existence of a activated checkpoint inside a room to reduce repetition
//When in existence, the specific checkpoint is identified
//the checkpoints subimage is switched so the player sees that it is working
//When not in existence or a new existence is found, the subimage for the previous existence goes back to normal
//—————————————-//

Part 4: Rooms

Finally, make 3 rooms and name them the following: rm_initialise, rm_level1, rm_level2

Room 1/3

In rm_initialise, enter Creation Code in the Settings tab and put in the following:

///—–ESTABLISHING GLOBAL SYSTEM VARIABLES—–///
//———————————————–//
global.checkpoint = noone;
global.checkpointR = 0;
global.checkpointx = 0;
global.checkpointy = 0;
room_goto_next();
//global variables are values that are always accessible to every aspect of a game, instead of normal values that only affect the object their made in
//checkpoint is the ID of a currently active checkpoint. It’s set to noone so when a checkpoint is activated, GML does not get confused over the existence of multiple checkpoints
//checkpointR is what room the player is currently in
//checkpointX is the left and right position of the checkpoint
//checkpointY is the up and down position of the checkpoint
//When a checkpoint is activated, these global variables change to match its location values
//After this system is set, the game goes straight to the first interactable room
//———————————————–//

Room 2/3

In rm_level1, go into the Views tab

Tick “Enable the use of Views”

Have View 0 selected

Tick “Visible when room starts”

Set W to 650, H to 600 in “View in room”

Set W to 1024, H to 768 in “Port on screen”

Set Hbor and Vbor to 999 and select obj_jumprefine in “Object following”

In the Settings tab, set “Speed” to 60. The size and length of the room can be changed with “Width” and “Height”

In the Objects tab, select obj_wall in “Object to add with left mouse” and place it in the room. Add and create the objects you want in the room to your heart’s content

Room 3/3

Repeat for rm_level2

Upon finishing this example your game should have pixel perfect wall collisions, movement with weight that creates a feeling of greater control, a double jump for the ground and air that resets on landing, the ability to defeat enemies by jumping on top of them and die and respawn when touching them, checkpoints that start players at their position when activated, horizontally moving platforms that carry the player with them, the ability to freely run and walk by pressing down a run key, specific platforms the player can pass through downwards and jump back onto and collectable coins and emblems for leading players like breadcrumbs and expanding into bonus content.

My example isn’t perfect however. The way horizontal control is made means that a sliding effect can happen with a very specific use of the run button and move controls. Vertical platforms have also proven in the end to be out of my abilities. If you are seeking vertical platform solutions, you will likely have to use other resources such as ZGB’s Moving Platforms.

I hope my example has helped you in your projects. Do not hesitate to point out what is wrong with my example and I hope this foundation will allow you to make the product the video game industry deserves.

Advertisements

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