MMORPG Principals and basics
Author: | Lew
|
Submitted: | 21st January, 2004
|
Views: | 6511
| Rated: |
|
|
Update: Added shooting for newbies.
An MMORPG is a Massively Multiplayer Online Role Playing Game-In other words, a large game playing with other people online. Good examples of the genre are Graal, Runescape, Second Life etc. I'm going to take you through the basic programming principals in MMF for making one of these fantastic games.
Server, no server?
One of the main aspects of a game of this nature is whether to have a maintained, permanent server or allow users to host their own servers. Here are the pros and cons:
Dedicated:
Pros:
99% Guaranteed uptime
Puts you in complete control of what goes on
Easier for people new to the concept
Less coding
Cons:
Costs more
Your sole responsibility to keep it up and running
Higher possibility of being hacked
User-based:
Pros:
Allows for 'custom' games and maps
Costs less
You don't have to maintain this, it's up to the user
Less chance of being hacked as servers can be taken down with no real problem
Cons:
Much more coding ala lobby system
Chance of no servers to play on
If someone with a slow connection hosts, it's a problem
Personally, I'd go with a mixture of the two. Have a dedicated server, possibly with a monthly fee to support it, which has bigger maps and more options, then have a user hosted option free, with smaller maps and less options.
Setting up the game
Ok, now you've decided on how you are going to connect the players together, it's time to actually do it. Code for online games is actually a lot simpler than it seems, as long as you remember the golden rule:
You've got to code for everyone in the same application!
One of the most common misconceptions to newbies about online coding is that sending is all you need to do; But don't forget that all the players are using the same application, so you have to code for both.
First off, you'll need to connect to the server, and sign on to a 'channel'. The channel is basically like a sub-server. It helps you distinguish between levels, or have multiple servers on the same connection. For example, you could connect to one computer, which has 2 level maps. The first map's channel is pipe_eating_monsters and the second is monster_eating_pipes. People in pipe_eating_monsters will not be able to see or hear people in monster_eating_pipes.
Ok. Upon signing on, the player will be given an ID. The ID number is important because it helps distinguish between players-for example if two players have the same name. Use the set name action to set the username.
In order to track each player, you will need to assign each players object with it's ID number-so when you sign on, set alterable value A to the ID. Now it's time to see the other players.
There is a few actions regarding players in the channel: User is here, User joined and User left.
User is here basically states that a user is in the channel whenever it is called until it has stated all of them; for example, if there are 14 players in a channel, it will execute the action 14 times. You want to create an object in this action. You then want to set it's alterable value to his/her ID using the 'get ID' under the 'user joined/left' menu,
User joined executes when a user joins a channel. You can use this to create new player objects every time a player joins after you have joined. Do the same as above.
User left is executed every time a user leaves a channel. This time, use the 'pick objects with an alterable value' condition and set the alterable value it picks to the get user ID under joined/left. Destroy this object.
It's alive, I tell you, alive!
Now that we've created our 14 players on the screen, we notice that they're all in the same place and not moving. That's because we aren't picking up any data. Moo's dead reckoning sorts this out for us.
Dead reckoning is basically a formula that tries to work out where you are going to move. If you are moving in a straight line at a constant speed, it won't bother sending more data until you move out of this line. This saves a lot of packet data and therefore reduces latency. If you are moving around like a loony with a frog up his arse, then it will still try and predict where you are going to move, but it will send more data.
When you connect, you want to set Output tracking to your object. You do this by having a sequence of events in order, that basically says:
+Connected
=Set object to (player object)
=Set output tracking on track 1*
*tracks are different sets of data. You could send x and y on track 1, and speed on track 2.
This data is sent to all users on the channel. Fiddle with the options to optimize data; For example, if your game's players all have one speed, then you only want to send x and y, whereas if your players have speed 'stats' you want to send speed for the dead reckoning algorithm to work best.
You then want to see other players moving. On the user is here or user joined commands, where we set the other users alterable values, use the same sort of thing, but instead of output tracking, use input tracking. The first variable is the users ID; set it the get user id, and the second is track. If you are sending on track 1, use 1.
Now what?
Now, we have a fully working movement engine that uses other players over the internet-it's beginning to form! Now all we need is a game to go with it. You might want to add a chat box: Pretty simple, have a key to get focus of an edit box (t for example) and when the user presses enter and the edit box isn't empty, send it on subchannel 0. When you recieve a message on subchannel 0, use something similar to:
Edit box: Set edit box to 'Str$(Edit Box) + Newline$ + < + Get name + > + Get message'.
If I was called Bob, and I sent a message saying we am de best! other players and I would see the current contents of the box, and a new line that says '<Bob> we am de best!'.
Now you need to add a level. Just add obstacles, the ground etc. A good thing about online games is that you don't have to code collisions etc for every user, as it only sends x and y positions and so doesn't move indipendantly. You only see what they see, so to speak.
There's nothing to do!
A prominent feature in most MMORPG's is a sub-game type known as a quest. Generally, quests are simple things, like bring a certain NPC a certain object, slay a certain monster and bring back his diamond tooth, etc. They keep the player entertained and usually reward him/her for their efforts. A good feature would be to include multi-player quests, quests that can only be achieved if one or more players do it at the same time-such as open a door that has 2 switches.
Quests don't have to be linear. The game known as Second Life is completely customizable through an inbuilt scripting language. A similar thing can be achieved-look at Tigerworks' script example. You can have a simple interface such as:
`My quest
questname = When come back, bring pie!
getobject = 1337 (You could have an object reference guide with numbers, or even names.)
bringto = NPC_banker or if you feel like a challenge, player_random or player_Bob
reward = Red Chair or £100
You could then set the quest on other people, by looping through and sending data that is sent as Do you want to do the quest, When come back bring pie? You will get a Red Chair in return. Just get the magic staff and bring it to the banker in the village.
If you have played the recent game, flanville, you will know that everyone can buy a house and furnish it as they like. Such a feature is achieved by user accounts and server side IMI's. This is an advantage of having a dedicated server; it can be achieved on user servers, but it's not as reliable.
Registration
Registration is actually very very simple. If you know how to use an INI, you can do it. I'm not going to explain how to use an ini, however the basics of a server side are:
Items and strings. If the user's name is Bob, and his selected password is TheBuilder, set the Group to Bob, and the item to assigned. If assigned is 0, set assigned to 1 and set the item to password and the string to TheBuilder. If assigned is 1, tell the user the name is already taken. There. One login system-just encrypt passwords so it can't be hacked!
The same thing can be used if the player wants house number 47; if they click buy and have enough gold, deduct the gold, set the group to Bob, the item to house, the value to 47. Then set the group to house, the item to 47 and the string to Bob. This allows people viewing Bob's profile to read that his house is number 47, and people outside bob's house to read that it belongs to him.
Subchannels are damn handy
When adding in features such as fighting, subchannels are very handy. Imagine a channel as a collection of wires. Each wire is called a subchannel. If you send chat over wire 1, then anyone recieving on wire 1 will pick up the chat-but if the other person is only recieving on 2, he won't. If you have a battle system, this means you can chat and send fight commands at the same time- so if you type a message to a user saying D13 j00 L4M3r!!!!111 and press sword, and the user has a longsword, it sends D13 j00 L4M3r!!!!111 on wire one and a string on wire two saying something like longswordswing. Then on the other end, if you recieve longswordswing on wire 2, play the user that sent it's long sword swing animation and trigger appropriate actions, and anything on wire 1 gets added to chat.
Bullets for newbies
There is a very simple way to fire bullets in online games-described briefly above, it's just parsing data. The only problem with this method is that if it is lagging a lot it can be inaccurate. However-
When the user presses the fire button, the keyboard sends a message to the computer saying 'shift' or 'space' or whatever, which the computer then processes and the software on the computer intercepts and performs and action. It's much the same in a game.
When you press the fire button (let's just say it's shift) then the computer does all this for us-but we have to do it manually for other players. The easiest way is to have a custom shooting engine-just have a bouncing ball object and set direction to the players direction. You send a message on an unused subchannel (lets say it's 5) along the lines of "shoot". If "shoot" is recieved on 5, create a bullet and set the bullet's alterable value to that of the sender. Make sure there is a pick all objects with a value(Get User) then position the bullet at that player and set it's direction to the direction of that player. If you have multiple guns, such as a machine gun, you have two options-send it at small intervals for each bullet, or have it send something like "machine" on 5, then when it's recieved, always shoot until "machinestop" is recieved, which is sent when the user lets go of shift. Try and keep string lengths down to reduce the amount of data sent-it may not seem like a lot, but if you have 100 people all shooting and sending the word 'shoot', thats 500 letters being sent, as well as co-ordinates, direction etc which can soon clog up slow connections.
Ideas
The string system used above can be used for so many things. Here is some inspiration:
Challenging users to 'private' battles
Determining whos bullets/magic spells/raging demons are whos
Sending private messages
Having 'say' and 'shout' commands-for example, have areas on the map where it sends on subchannel 1 and other areas where it sends on 2, then only check in the appropriate areas.
Sending files, sounds etc.
Conclusion
This article hasn't been heavy on coding-that wasn't the point. The point was to inspire more people to use the amazing MOO extensions, and show that with some logical thinking, it isn't hard at all. This isn't perfect, and is pretty vague, but it outlines the major points. Hopefully we should see some more online games in the near future!
|
|
Lew
Registered 06/01/2002
Points 1014
|