So long, and thanks for all the fish

This post is very difficult to write.

When I started Building Browsergames back up again, I had big plans – a new design, a cleaner interface, more guest writers. Unfortunately, things didn’t go quite as I planned – and that’s why I’m writing this today.

Building Browsergames is shutting down. Forcing myself to find more writers and games to review and tutorials has had a detrimental effect on quality of the content here – and when you’re teaching someone, you need to know what you’re teaching very well.

By continually trying to post tutorials and reviews under a time constraint, I’ve done a disservice both to myself, and to the browsergame community. Corners would get cut because the tutorial needed to be up in time, and questions would go unanswered.

I also have my own projects to consider. Faction Wars, while currently in the alpha stages, is doing very well – and there are a number of other projects that are getting close to that stage themselves. Writing something for Building Browsergames once or twice a week has proven to be too much of a distraction for me to be able to get as much done as I’d like to on my own projects.

What does this mean for you, the reader? Well, it means a few things:

  • Fewer Updates

    I won’t be writing much anymore. And while I’d like to publish guest posts from other developers and enthusiasts, no one actually seems interested – and anyone who does quickly changes their mind. With that in mind, it’s fairly safe to assume that Building Browsergames will not be updating very often in the near future.

  • The tutorials stay

    I’m proud of what was built using the tutorials – and it even spawned an open-source project based on the code. While the code might not be the best I’ve written, I’m glad that it’s helped visitors who wanted to learn to make their own games to get started.

Essentially, Building Browsergames takes up too much of my time for me to be able to afford to keep it running at the level that I have without making some sort of income from it – and I don’t want to just plaster the site with ads and let the networks go to town. I don’t really want to do that to any of you – so for now, Building Browsergames has to go on a hiatus.

Thanks again to everyone who personally got in touch with me – there’s a good community here, and with a little bit of nurturing I think it can go on to achieve great things.

Monday, March 29th, 2010 code Comments

BBGameZone Contest Winner: Wicked Dead

I managed to get in touch with Hypemaster
from the Browser-Based Game Zone forums to ask him a few questions about his entry in
the BBGZ 2010 PBBG competition. His entry,
Wicked Dead, was the winner of the contest with a 68 point lead over the
next entry. Here’s what he had to say:

Tell us a little about Wicked Dead.

Well, the game starts where life ends.

You are dead – and instead of going to heaven or hell, you’ve gone to a place called Wicked Dead. You are Wicked Dead! Here, you get a chance for a new life. You need to enter the gates and complete
objectives and battles. For every level you complete, a new one will open – but if you fail a level,
you’re bumped back 2 levels. The goal of the game is to complete level 100 – then you are given a new life!

In the levels you will need to do wicked stuff. If you die you die very painfully, but get reborn
and can improve your stats. Yeah, you read that right – you can only improve your stats by dying! So
deciding whether to complete a level or die is sometimes a hard decision.

Energy is your life-force – you need energy to enter a gate and complete the objective. No energy means no fun. You regain energy over time though, so don’t worry. You also have a stat called ‘pain’ – when you die, your pain goes up. If you have a pain rate higher than 90 you will be unable to access a gate because you are so scared and have so much pain that you can’t do anything (so don’t die too much!). Pain goes away over time.

One thing to remember while playing Wicked Dead: not everything is what it seems! There are many tricks in place, and you will also meet other people in the gates.

What gave you the initial idea for Wicked Dead?

I was playing a game with some friends and we were losing badly. I was
dying all the time and I thought, why don’t they make a game where death is
rewarding? And then I started with an idea to make a game which rewards
dying. My first idea was that you needed to try losing, the one who dies first
wins. When I read about the competition I started working on that idea and
then Wicked Dead was born. I changed it a bit, you get better when dying
and you sometimes need to win and sometimes need to lose. Also, luck
is something you will need. And lastly, I like to fool with people so thats also integrated into the game.

What language did you write Wicked Dead in? What are you hosting it on?

I used PHP, along with XHTML and MySQL for the database. I have a lot of experience with them,
so it was a logical choice. I’m using the same shared hosting provider I use for all of my sites.

What was something that went well during the contest? What was something
that didn’t?

Well the first 2 weeks went well, there is really nothing that went bad in
terms of programming. Only thing that took some time was balancing out the
stats and items. But thats something I always invest a lot of time in.

The thing that went bad was time! During the last two weeks of the contest, I almost
didn’t get time to work on the game! I even forgot to upload my last changes
before the competition ended. But it was no big deal – the basic idea was in place,
and the update only added pvp and more levels.

Do you have any plans for Wicked Dead, going into the future?

At the moment I dont have much time to work on it, but I’m working on it.
In the future more levels will be added and also a Minion minigame with
aura stones. There are only a few and people will fight for it with their
minions. Upgrading their base and creating minions or towers. The next gate
levels will get more complex, more paths to follow, more choices and more
tricks to fool people. I’m planning to make 100 levels, but at the moment there are only 18 ready to go – so there’s still a lot to do. I’m not planning to advertise it yet in
the near future, maybe somewhere in the summer. I first want more levels
ready. The problem is that I can’t make them as fast as people can play
them. And after all, I’m making it for fun.

Have you played Wicked Dead yet? What did you think of it? Let us know in the comments!

Tags: , ,

Monday, March 15th, 2010 site-news Comments

FactionWars is looking for alpha testers!

One of the games that I’ve been collaborating with someone on has finally hit the closed alpha stage – and now, we’re looking for alpha testers.

Here’s what we need alpha testers to do:

  • Play the game.
  • Diligently report any and all bugs/unexpected behavior using the built-in feedback form.

Interested? You can apply to join the closed alpha program by submitting your information at http://bbrowsergames.wufoo.com/forms/faction-wars-closed-alpha/.

Monday, March 8th, 2010 site-news Comments

BBGameZone Contest Participant: Tennis Masters

This write-up comes from dbest
from the BBGameZone forums – he entered the contest with a game
called “Tennis Masters”:

Tennis Masters is planned to be an online tennis management game. The
game puts the players in charge of managing their own academy of
tennis players and making them stars. The idea of the game originated
in August 09 and active development kick started in October 09. The
game is currently being developed by a team of two, using PHP as the
coding language.

What went right?

We decided to enter BBGameZone’s Competition 2010 to complete a
Browser Based Game in a month. The competition deadline was an
incentive for us to complete the game. Before the competition
deadline, we had a rough base code that was ready. We attempted to
leverage the existing code base to complete the game quickly. During
the one month period, we put in a lot of effort in the Match Engine.
The Match Engine of the game is the core of the game and would be
responsible for simulating the matches. Since we realized that the
game would be judged based on usability, we decided to work on the
Help Manuals, so that the user would not be left clueless when
visiting the site.

What went wrong?

As evident, since we did not complete the game in time, there was
plenty that went wrong. As both of us happen to be new dads, we had to
balance the time we spent on the game with the new responsibilities in
our lives. There were times when communication was lacking between the
two of us. As we were nearing the deadline of the competition, we
realized that we would not be able to complete the game and decided to
take it a bit easy.

In conclusion, although we did not complete our game in time, we
really cherished being part of the game making competition. We plan to
start our beta season in April and would be happy to see you join and
help us build a better tennis management game. The demo website is at
http://demo.tennismasters.org and our game development forum is
located at http://dt-games.net/gamesetmatch

Tags: , ,

Monday, March 1st, 2010 contests Comments

Thursday Press Release: PHudBase, a real-time php game engine + client

This week’s release comes from PHudBase, which is an engine for building games using a client/server model in PHP.

A screenshot of PhudBase

PHudBase, a project built by John DeLancey for his upcoming PBBG, has
been released as open-source for the PBBG
community to try out, rip up, and improve upon.

PHudBase (or just PB) is a game engine written in PHP that’s broken up
into two parts — the server (game engine itself) and
a client that connects using HTML 5 WebSockets. The engine also
supports Telnet and Flash connections, but that’s not what it’s
really about.

The server runs on your webserver using the PHP CLI (command line
interface) module. It sets up a server that is meant to
run forever, listening for new connections, processing game actions,
and talking to and hearing from your users.

The client is — really — just an example of what WebSockets and HTML
5 are going to do for us (Google Chrome is the only
browser that currently supports WebSockets). It connects to the
server as you’d expect, with just a few lines of javascript
and no plugins at all.

The codebase — hosted at Google Code — contains a very, very basic
game that you can build on top of or completely discard.
You can use anything you want to store your data, and MySQL is
certainly a great choice. It also supports caching via APC or
memcached (or anything else) with “hooks” that you can replace with
the appropriate store/get/delete function calls (it currently stores
every
object in the game in an array in the Game object, itself).

The project’s homepage is http://www.phudbase.com, where there’s a
demo for you to try out and links to the Google Code and
Google Groups pages for you to download and discuss the project.

Do you have a press release that you’d like us to publish? Get in touch by e-mailing buildingbrowsergames@gmail.com, leaving a comment below, or following us on Twitter.

Tags: ,

Thursday, February 25th, 2010 site-news Comments

BBGameZone Contest Results

The BBGameZone Competition 2010 is now over – here are the games that managed to finish something in the month-long time frame:

Due to unforeseen circumstances, all of the other entrants were forced to drop out (including yours truly). Better luck next time!

If you were interested in participating in the contest, there’s a new contest on to build a small game within 24 hours (spread over up to two weeks) – can view view the thread on bbgamezone if you’re interested.

If you were one of the participants in the contest (whether you finished or not), get in touch! I’d like to talk to some of the other participants about their thoughts on the contest and their entries.

Tags: , ,

Monday, February 22nd, 2010 site-news Comments

Getting Started With MongoDB (Python)

Now that I’ve extolled the virtues of using a NoSQL database, it’s time to put my money where my mouth is and show you how to use one.

To start things off, we’re going to build a super-simple site using the excellent Bottle Python framework, which is built for building simple sites like this.

This tutorial assumes that you already have a mongoDB instance up and running somewhere; if you haven’t done that already, take a look at the quickstart on mongodb.org.

First, download and install Bottle (it’s pretty easy). Once that’s done, we can start working on building our mini project.

Today we’re going to build a small ‘army manager’ site; users will be able to add, edit, and delete members of their army, and everything we need to track for the user will be stored in our mongodb database.

To start off, we’ll just make the index page return a template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import bottle, random
from bottle import route, jinja2_view as view, debug, run
 
DATABASE_HOST = 'localhost'
DATABASE_NAME = 'army'
DATABASE_PORT = 27017
 
import pymongo
from pymongo import Connection
connection = Connection(DATABASE_HOST, DATABASE_PORT)
db = connection[DATABASE_NAME]
users = db.users
 
SOLDIER_NAMES = ["Moe", "Curly", "Janne", "Peter", "Paul", "Kyle", "Chris", "Jude", "Larry", "Gus"]
 
@route('/')
@view('templates/index.html')
def index():
    current_user = get_current_user()
    return {
        'user': current_user,
    }
def get_current_user():
    ip = request.environ['REMOTE_ADDR']
    current_user = users.find_one({'ip': ip})
    if not current_user:
        users.insert({
            'ip': ip,
            'army': [],
        })
        current_user = users.find_one({'ip': ip})
    return current_user    
 
if __name__ == '__main__':
    debug(True)
    run(host='localhost', port=8000, reloader=True)

You may have noticed that instead of using the default template renderer, I used the Jinja renderer instead – which templating engine you use is up to you, but I prefer Jinja.

There’s a lot going on here – and if you’re new to Python, this code probably looks pretty scary. However, it’s pretty simple once you get the hang of it – here’s what we’re doing:

  • First, we’re importing all of the libraries we need, and setting up some of our configuration. This could be split out into another file easily enough – but for the sake of this tutorial, we’re going to keep everything self-contained for now. The libraries and helpers we’ve imported are random, bottle.route, bottle.run, bottle.request, bottle.jinja2_view as view, bottle.response, bottle.debug, bottle.redirect, pymongo, and pymongo.Connection

    Most of these come from the Bottle library, and are designed to help us get our app off the ground faster – we imported random to be able to choose names for our soldiers, and pymongo to help us work with our MongoDB database.

  • The next thing we did was create our index view – by saying that Bottle should route the url ‘/’ to our ‘index’ function. As you can see, all our index function does is retrieve the current user, and return it so that we can render it with our template – which we specified using our view() decorator.

  • The next thing we do is define a function to retrieve the current user, based on their IP address – this is our first dive into working with MongoDB. First, we retrieve the IP address of the computer that’s requesting the page, so that we can track the visitor’s information. Once we have that, we query our users database, to see if a user exists with our IP – if there is no user with the IP address we’re testing for, we create a new user with an empty army, and then return that one.

  • Finally, we have a little bit of utility code to let us test our Bottle app. This piece of code allows us to run our app by navigating to it in the terminal, and then just running “python app.py” – assuming your MongoDB instance is up and running and your dependencies are okay, you should be able to check out your app by navigating to http://localhost:8000/.

If you navigate to your app right now though, you might notice that there’s a problem – we don’t have an index template! We’ll fix that by creating a template for our app, under templates/index.html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
       "http://www.w3.org/TR/html4/strict.dtd">
 
    <html lang="en">
    <head>
    	<title>Python MongoDB Tutorial</title>
    </head>
    <body>
        Your Army: {{ user.army }}
        <form action='/add-soldier/' method='post'>
            <input type="submit" value="Add Soldier" />
        </form>
        <form action='/remove-soldier/' method='post'>
            <input type="submit" value="Remove Soldier" />
        </form>
        <form action='/rename-army/' method='post'>
            <input type="submit" value="Rename All Soldiers" />
        </form>
    </body>
    </html>

As you can see, we’re not shattering any barriers with this template – but it lets us test our app, so it will do for now. Navigate again to http://localhost:8000/, and you should see something like this:

Your Army: [], Add Soldier button, Remove Soldier button, Rename All Soldiers button

With our template all set up, it’s time to write our views – starting with the view that lets us add soldiers:

@route('/add-soldier/', method='POST')
def add_soldier():
    current_user = get_current_user()
    army = current_user.get('army', [])
    army.append(random.choice(SOLDIER_NAMES))
    users.update(
        {'ip': current_user['ip']},
        {'$set': {
            'army': army,
        }}
    )
    redirect('/')

For the most part, this view’s pretty simple – we want it to be at the url ‘/add-soldier/’, and only responding when users POST to it (by clicking on the ‘add soldier’ button in our template). When a user clicks on the button and POSTs to this view, we retrieve their current army (making sure to default to [] if it doesn’t exist – this is important!), add a new soldier to it (by appending a random name from our SOLDIER_NAMES variable), and then update the user’s information in our MongoDB database. Finally, we redirect back to the frontpage so that the user can see their new army.

It’s important to keep in mind that when you’re using a schema-less database like MongoDB, you may not actually have the properties you’re expecting to, especially if you haven’t set them. With that in mind, always be sure to write your code in such a way that it will still work if a an object doesn’t have the property that you were expecting it to.

If you visit your testing page at http://localhost:8000/ now and click the ‘Add Soldier’ button, you should notice that your army has increased – there’s a new name there!

Index page with a new army member

Now that we can add soldiers to our army, we need to be able to remove them as well. Let’s write a quick view to do that:

@route('/remove-soldier/', method='POST')
def remove_soldier():
    current_user = get_current_user()
    army = current_user.get('army', [])
    if len(army) > 0:   # make sure we don't pop from an empty list
        army.pop()
    users.update(
        {'ip': current_user['ip']},
        {'$set': {
            'army': army,
        }}
    )
    redirect('/')

This view is just about the same as our add_soldier view from earlier, except that we’re removing soldiers instead of adding them before we write the user’s army into our database. We make sure they actually have soldiers in their ‘army’ array, and then we remove one if they do before writing their army back to the database, and redirecting back to the front page.

Index page, with an empty army

With that view written, there’s only one more to write – this one will live at ‘/rename-army/’, and update the names of all the soldiers in the user’s army:

@route('/rename-army/', method='POST')
def rename_army():
    current_user = get_current_user()
    army = current_user.get('army', [])
    army = [random.choice(SOLDIER_NAMES) for i in army]
    users.update(
        {'ip': current_user['ip']},
        {'$set': {
            'army': army,
        }}
    )
    redirect('/')

As you can see, there isn’t much changed in this view either – we retrieve the user and their army, update the value of their ‘army’ array, write it to the database, and then redirect them. We use a list comprehension to update the name of every one of our army members, and that’s all that’s special here.

With that, we’re done! If you visit http://localhost:8000/, you should be able to add soldiers, remove soldiers, and rename soldiers – with all the data being stored in your MongoDB database.

If you’re stuck, or can’t seem to get it going, you can download the code for this tutorial at http://buildingbrowsergames.com/blog/wp-content/downloads/mongodb-python-1.zip.

Extra Homework

  • Our views involved writing a lot of boilerplate code, which can probably be refactored. Write a custom User object that handles storage and retrieval, along with making it easier to interact with the user’s army.

  • Modify the ‘army’ array to store custom Soldier objects, which have a name and an attack value – when a user adds a soldier to their army, randomize both values (some of the work for this has been done for you – see the download above).

Tags: ,

Monday, February 8th, 2010 tutorial Comments

Thursday Press Release: Fanta Trade

Hey, game creators – Building Browsergames is starting a new initiative called “Press Release Thursdays” – if you’ve got a new game that’s just getting out there, send us your press release and we’ll publish it!

To start things off, I have a release from Fanta-Trade, a stock market simulation game:

Fanta Trade is a browsergame where users are given 100,000 (fanta) euros to invest when they sign up – in stocks, commodities, currencies, warrants – almost everything you can imagine. One of the nice things about Fanta Trade is that stock names and prices are real – so you can become a successful stock trader (or lose it all) without taking any risks in real life. You can also find some elements typical to most browsergames within Fanta Trade: teams, rankings, and a forum in which the best players can be found providing their own take on the market.

Fanta-Trade is a good game for anyone who has an interest in learning how the world of finance works – or for anyone who wants to face a different kind of competition than “send your soldiers to the enemy’s village”.

Fanta-Trade’s sophisticated simulation engine works well, and has succeeded in transforming something as complicated as investing in the stock market into something easy and enjoyable for all – especially those who don’t know how the market works. And if you get stuck, the vibrant community is always providing tips for the game – all users can open their own financial blog and start writing their own market analyses, so you can even start dispensing your own advice if you so choose.

Fanta-Trade was created in Italy, so most of the players are Italian – but it has also been translated into English. You can check it out at http://fanta-trade.eu.

Do you have a press release that you’d like us to publish? Get in touch by e-mailing buildingbrowsergames@gmail.com, leaving a comment below, or following us on Twitter.

Tags: ,

Thursday, February 4th, 2010 code Comments

You should try a NoSQL database today.

One of the hottest new web technologies being discussed right now on the web is NoSQL Databases – with the two I hear about most being CouchDB and MongoDB.

NoSQL databases provide a different approach than traditional relational databases by being ’schema-less’ – allowing you to quickly and easily add arbitrary data to whatever you need to. This is a feature that’s extremely well-suited to browsergames – if you need a certain item to have a specific attribute that no other item has, it’s easy: you just add it, and move on. In a traditional SQL-based database setup, you’d need to add a column and make sure it was null or defaulted for all of your other items – which would be a major hassle if you had a large number of items.

Both the CouchDB and MongoDB sites have quickstart guides – if you haven’t tried one of the two out already, I highly encourage you to do so.

If you still need some convincing, here are a few areas in a game where a NoSQL database like Couch or Mongo will be better-suited than a traditional database like MySQL or PostgreSQL:

  • Items

    So you have a potion, and potions usually heal people. But for this one super-rare potion, you want to heal the player and teleport them to a secret location. How?

    In a traditional SQL-based system, you’d add a column to your items table to track what the potion did, and then add the extra code and handlers so that when a potion of the one super-rare type was used, the player was both healed and teleported. This works, but it’s a bit of a pain – you need to create/track a new item type, along with writing the code to handle it.

    In a schema-less situation (when you’re using something like Couch or Mongo), all you have to do is add an attribute ‘teleports_player_to’ to your item – and then in your code, check if the item has a ‘teleports_player_to’ attribute. If it does, teleport the player there after running your item handling code. All done!

  • Quests

    Quests are one area where schema-less storage really shines. You want to keep track of quests a player is on – but each quest is different! One quest involves killing a certain number of enemies, while another requires you to talk to two different NPC’s, while yet another needs you to move Important Package A to Secret Location B. How do you track all of that data?

    In a relational database, you do it by keeping track of what ‘type’ each quest is, along with a small amount of arbitrary information related to that quest. For a “kill 10 ogres” quest, you need to track that it’s a killing quest, you need 10 things killed, and those ‘things’ are, in this case, ogres. For a “delivery” quest, you need to track which item the player has to have, and which location they need to take it to.

    In situations like this, using a relational database to track information for your quests starts to break down very rapidly. What if you wanted to have a quest that required a player to kill 10 ogres, and then deliver a package to the town mayor? How would you do that?

    With a schema-less database, this is easy. All you have to do is check which attributes you quest has, and write your code to work around them – so if you wanted to have a quest where users had to kill 28 goblins, talk to the goblin herder and the shepherd, and then deliver the goblin herder’s letter of surrender to the shepherd, you could – all you’d have to do is check the quest attributes.

What other situations can you come up with when a NoSQL database might be superior to using a relational database to track data in your game, or when a relational database is a better option? Let us know in the comments!

Tags: ,

Monday, February 1st, 2010 site-news Comments

Adding a Reward System to your Game

I was recently contacted by Sunchaser from the BBGameZone forums about membership within the PBBG network for his topsite, top-pbbg.com. As you can see, his membership was accepted – and I also managed to get him to write a quick tutorial about how to integrate his site into your PBBG – so that you can drive traffic to your game by providing incentives for your players, using a reward system. Here’s the tutorial in full:

It’s possible to find on the internet a large number of sites that shows a list of browser-based games (these are normally called Topsites, or Toplists). A game owner can register their game into these sites – and by inserting a voting link in their game, their players can cast their vote for the game. With enough votes, your game can be pushed into the top positions on the topsite – increasing visibility, and driving more traffic to your game.

Some of these sites allow you, the game owner, to configure a reward system for your game, so that you can give your players an incentive to vote for your game.

Once you have configured the reward URL, an example of a voting link would be http://exampletoplist.com/in.php?u=789&key=12345667.

The parameter ‘u’ will contain the ID of the player that is voting, and the key is a random number. After the topsite has verified the vote, it will call back your configured link (for example, http://yourgame.com/reward.php?u=789&key=12345667&listname=top_pbbg). The reward script should check for a corresponding couple (userid + key), and then give the player the reward.

This tutorial will walk you through setting up a system that:

  • Sends a player vote to a toplist, recording the vote
  • Processes a callback from the toplist

Sending a player vote to a toplist

In order to trace the votes and prevent cheating, the votes sent to the toplist will need to be recorded within a database table. The first thing we’ll do is create a database table where we store different toplist sites, along with a table for recording user votes:

CREATE TABLE IF NOT EXISTS `cfg_ranking_sites` (
  `id` int(11) NOT NULL AUTO_INCREMENT, --primary key
  `username` varchar(25) NOT NULL,      --the username you registered with in the toplist
  `name` varchar(50) NOT NULL,          --the toplist name
  `url` varchar(255) NOT NULL,          --the toplist url (voting links of the toplist)
  `refererurl` varchar(255) NOT NULL,   --the toplist root url
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM;
 
CREATE TABLE IF NOT EXISTS `voting_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `list_id` int(11) NOT NULL,
  `vkey` varchar(25) NOT NULL,
  `status` varchar(25) NOT NULL,
  `ip` varchar(15) NOT NULL,
  `urlcalled` varchar(255) NOT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM;

Next, we’ll add any topsites we wanted to track into our cf_ranking_sites table (in this case, top-pbbg.com):

INSERT INTO `cfg_ranking_sites` (`id`, `username`, `name`, `voting_link`, `refererurl`) VALUES
(1, 'vlad', 'top_pbbg', 'http://www.top-pbbg.com/index.php?a=in&u=vlad&k=KEY', 'http://www.top-pbbg.com');

Next, we create a file called vote.php, which loads the topsite urls, generates a random key for users, tracks the vote, and sends the vote to the topsite. Here’s the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/****************************************************************************
File:   vote.php
Desc:   traces a vote creating a random key, and sends the vote.
****************************************************************************/
$listname = mysql_real_escape_string( $_REQUEST['listname'] );
 
// load data of rating site
$data = mysql_query( 
	"select id, voting_link 
  from cfg_ranking_sites
  where name = '{$listname}' " );
 
list( $list_id, $voting_link) = mysql_fetch_row( $data );
 
// generate a rnd string
$k =  substr( md5 ( time() . rand(1, 10000000) ), 1, 25);
 
// get the user id from session
// (substitute your method for finding the user id)
$user = User::get_char_info();
$u = $user['user_id'];
 
// place the generated random key and trace the vote
$urlcalled = str_replace( "KEY", $k, $voting_link );
 
mysql_query( "insert into 
	voting_log
  ( user_id, vkey, list_id, ip, status, urlcalled ) 
  values
  ( '{$u}', '{$k}', $list_id, '".$_SERVER['REMOTE_ADDR']."', 'new', '{$urlcalled}' ) ");
 
// send the vote
header ( "location: $urlcalled" );
exit;

Next, put your voting link inside a page that’s visible to your players, so that they can start clicking on it. Make sure the link points to your vote.php file:

    <a href='vote.php?listname=top_pbbg'>Vote for us at Top PBBG!</a>

Now, your players should be able to vote, and you should be able to record their votes in the table voting_log.

Processing a callback from the toplist

Let’s assume you have configured your reward URL on top-pbbg.com to be the following reward URL:

    <a href='http://yourgame.com/reward.php?listname=top_pbbg'>Vote for us at Top PBBG!</a>

To process the toplist callback and give rewards to your player(s), first create a file called reward.php and insert the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Set content type
header('Content-type: text/xml');
// Check input, if keys are not present return error.
// This check and the fields needs to be changed for each toplist
if (
	!isset($_GET['key']) or 
	!isset($_GET['success']) or
	!isset($_GET['listname']) or
	) {
	echo '<response rewarded="0" message="Invalid input." />';
	die();
}
 
// Get data
$key = mysql_real_escape_string($_GET['key']);
$success = mysql_real_escape_string($_GET['success']);
$referer = $_SERVER['HTTP_REFERER'];
 
$sql = "select v.id, v.user_id, r.name
from voting_log v, cfg_ranking_sites r
where vkey = '{$key}' and v.list_id = r.id
and   refererurl = '{$referer}'
and   status = 'new'";
$data = mysql_query( $sql );
 
if ( mysql_num_rows( $data ) == 0 )
{
// insert your debug message, return error
// mydebug( true, "match not found. ip: " . $_SERVER['REMOTE_ADDR'] . " key: " . $key . " referer: " . $referer);
echo '<response rewarded="0" message="match not found." />';
exit;
}
 
list( $id, $user_id, $list_name ) = mysql_fetch_row( $data );
 
// give rewards to user, only if the vote was unique ($success==1)
if ( $success == 1 )
{
	$r = rand( 1,2 );
	if ( $r == 1 ) 
	{
		;
		//example: give reward and send information to user
		//mysql_query( "update user set char_adamantium = char_adamantium + 2 where user_id = " . $user_id );
		//User::send_news( 'char', $user_id, "You got 2 adamantium for your vote at " . $list_name );
	}
 
	else
	{
		;
		//example: give reward and send information to user
		//mysql_query( "update user set char_mythril = char_mythril + 2 where user_id = " . $user_id );
		//User::send_news( 'char', $user_id, "You got 2 mythril for your vote at " . $list_name );
	}
	mysql_query( "update voting_log set status = 'rewardgiven' where id = " . $id );
	echo '<response rewarded="1" message="Reward given." />';
}
else
{
	mysql_query( "update voting_log set status = 'rewardnotgiven' where id = " . $id );
	echo '<response rewarded="0" message="Reward not given (not unique vote)." />';
}
exit;

Now, by changing the code within the if statements above, you should be able to give rewards to your players for voting for your game on different topsites.

Note

The script reward.php has been written to process rewards for one toplist – if you want it to process results from multiple toplists, you will want to have it handle the listname parameter, using that to decide which piece of code to run for which topsite.

And that’s all there is to setting up your game with a rewards URL! If you’re interested in doing this for your game, sign up at top-pbbg.com and get started – and then post a link to your game in the comments when you’re finished.

Tags: ,

Monday, January 25th, 2010 tutorial Comments

About

Building Browsergames is a blog about browsergames(also known as PBBG's). It's geared towards the beginner to intermediate developer who has an interest in building their own browsergame.

Sponsors

Got Something to Say?

Send an e-mail to luke@buildingbrowsergames.com, or get in touch through Twitter at http://twitter.com/bbrowsergames