ID:43124
 
Keywords: design

If you're new, or semi-new, to programming, trying to add on to a complex project can be very confusing. There's a lot going on, and if you just want to make it so that every time a player takes a step his health goes up a little, there should be a simple way to do that, right? There should just be a "code" that you can put somewhere in the project to make that happen. So, you find someone who'll show you a code to do that, or you try to write you own, but it doesn't work. Dream Maker (DM) is giving you all sorts of errors because you've put your code in the wrong place, or maybe you just have the wrong code. So you go and ask the person for a different code, one that will work in your project. You're not being lazy, despite what the people on the forums are saying. You're trying to get a code that will work in your project - you tried writing one, but DM won't let you use it.

If you've ever been in a position like this, then this article may help. The code you were given was probably an example, a half finished and untested attempt, or simply something that's not compatible with your project. In order to use it, you're going to have to learn how it works, how to rewrite it for your own project, and (most importantly) where to put it.

So let's say that you've learned all about variables, and you've made a variable to store your player's health. You named it "hp" and you set it to 100 to start with. Now, you just want to make the hp go up by 1 point every time the player walks, so you do something like this:

hp = hp + 1


Where should we put it? We could try just making a new code file and putting it in there just like that... holy smokes, 6 errors! What does DM mean "instruction not allowed here"? Well, I guess we need to put it somewhere else. We want the player's hp to go up, so let's put it under /mob.

mob
var/hp
hp = hp + 1


What does DM mean by "invalid variable"? Hp was valid just a moment ago, right? And what's a "constant expression"? Well, let's try putting it in New() so we can be sure that it happens. It works for everything else, right?

mob
var/hp
New()
.=..()
hp = hp + 1


Okay, DM is happy with that, now let's try running the program... why isn't anything happening? Our hp is at 101, but it's not going up when we walk. I guess the code was wrong, and we need a new code.




That's one way to try and make a program. Get a code, put it somewhere; if the code doesn't work, get another. That may work for the first couple weeks you're learning to program, but that's really not how it's done. Let's take a look at another approach. Let's say you want to make your player's hp go up whenever he moves, so how do we do this? Well, start with the action. When will the player's hp go up? When he moves. So, let's find the proc that gets called when the player moves; perhaps we ask on the forums, or perhaps we go straight to the reference: atom/movable/Move(). This is where the action starts, this is where our program starts to do something, and we can tell it to do what we want. So, let's try putting our code in there:

mob
Move()
.=..()
hp = hp + 1


Look at that, it works! That's a very simple example, and you've probably already figured out how to do it long before reading this article, but it's the simplest example of putting code where it belongs. Once you understand what code goes where, and how to program working from an event, you'll be on your way to programming great games.




The most important thing to understand about that messy code file you've got on your hard drive is that there are two types of code: code that does something, and code that says what something is. Let's start with the simple kind of code first, the code that says what something is. It starts by saying the name of whatever the object is, like "monster". It then defines a bunch of variables and other nifty stuff, the things that make a monster a monster. It could look something like this:

mob/monster/frost_giant
icon = 'monsters.dmi'
icon_state = "ice guy"
var
hp = 200
team = "ice"


That code doesn't do anything. It doesn't make the monster attack, it doesn't make the monster move around, it doesn't even make a monster! We have to place monsters on the map ourselves, or create them at runtime. All that does is define a type of monster. Now let's take a look at code that does something:

proc/spam_protect(what as text)
what = html_encode(what)
if(length(what) > 300)
what = copytext(what, 1, 301)
return what


The above proc (short for "procedure") takes some bit of text and makes sure that there's no html in it, and that it's less than 300 letters long. A proc like this could be used to help protect our game from some simple spam attacks. We can "call" (use) this proc any time we want, and it will do that list of things inside it.

So those are the two types of code. What can make programming confusing, though, is that the two types look like they're mixed together all the time. Look at the next example, where we define an object (code that says what something is), and then we give it verbs (code that does something):

obj/item
var
value = 20
icon = 'items.dmi'
verb/get()
set src in oview(1)
usr.contents.Add(src)
verb/drop()
loc = usr.loc


Here the two types of code appear in the same basic place, but they're not mixed. The code that does something can't be placed outside the verbs, because that's the area where we're still defining what our object is. In fact, the verbs are part of the object definition: we're defining how our object behaves.




Now that we know about the two types of code, let's talk about events. Everything that happens in your game is a proc or a verb that's being "called". What we mean by "calling" a proc is that we tell a proc to run and do its thing. This is important: Procs don't just run by themselves. You can't just put a proc under /mob/monster and expect it to happen. Think about if we put this into a game:

mob/monster
var/strength = 10
proc/attack_player(mob/player/target)
target.hit(strength)


Our monster is just going to sit there and do nothing. So, we start thinking, we want it to happen when the player is 1 step away from the monster. So we try and put this in:

mob/monster
var/strength = 10
proc/attack_player(mob/player/target)
if(get_dist(target,src) <= 1)
target.hit(strength)


There! That should do it, right? We told the computer to attack when the player is within 1 tile distance, right? Well, that's not how procs work. In order for that to work, the proc would have to be constantly running, constantly checking to see if the player was 1 tile away, and procs don't just constantly run like that. They only run when we call them (like where we called "target.hit()"). So if our procs don't run by themselves, and we can't define a proc to make things run (we have to call it somewhere), where do we call our procs? That's where events come in.

Events are procs (or verbs) defined by the Dream Maker language which happen at special times. One of those events is world/New(), an event which happens whenever Dream Seeker (or Dream Daemon) loads a world. So, if you have something special that needs to happen when the world first starts up, you call it during the world/New() event. Imagine that you load old high scores every time the world starts up, and that you have a proc for doing that. To make that proc work, you could call it during world/New(), and it might look something like this:

proc/load_high_scores()
var/high_scores = file2text('high_scores.txt')
// Do fun stuff with scores, etc.

world
New()
.=..()
load_high_scores()


There! That's putting code in the right place! Now we know exactly when our code will run, and more importantly, why it runs at that time! Not all events run just once, though; the really important events happen over and over again. One of those events is the mob/Move() proc. Wait, didn't I just say it was a proc? Yes, but an event is only a proc that gets called at special times. mob/Move() is special because it get's called whenever the client (your player) presses one of those arrow keys. So, you can put calls to all your other procs in Move() (You should only put the ones in there that you want to happen when the mob moves, though). Remember our attacking example above? If we want the monster to attack the player when the player is 1 tile away, then we can call the proc whenever the player moves. The complete system might look something like this:

mob/monster
var/strength = 10
proc/alert(mob/player/target)
// this proc should be called whenever there's a player moving around in the area
if(get_dist(target,src) <= 1)
attack(target)
// when alerted, if the thing that alerted us is within range, attack it.
proc/attack(mob/target)
target.hit(rand(1,strength))

mob/player
Move()
.=..() // do the default stuff. If we don't do this, our player can't move.
for(var/mob/monster/M in view())
M.alert(src)
// whenever the player moves, alert all monsters in view.


It may look like a lot of code, but it's code that works, and it's code that works in a way that you can follow. Whenever something happens, it starts with an event. That event then calls other procs and gets the ball rolling. That ball will continue to roll for as long as you tell it to, but it doesn't start on its own. Your procs won't just call themselves, and they won't just start working or always be working for some magical reason... and that's a good thing! If it were mysterious and hard to understand to all except the master programmers, the rest of us would never be able to program. The great thing about programming is that our projects will only ever do what we want them to. Once we know how to tell a program what to do (where to place our code) then we can build anything. Just remember these important things:

  • There are two types of code: code that defines something, and code that does something.
  • Everything that happens in a program starts with an event.





Before we go, let's take a look at another very important event. You've seen all sorts of games where the monsters all start moving around the moment the game starts, so certainly I'm lying about this whole "event" thing, right? I mean, they don't sit around and wait for an event to tell them what to do, they move around and attack things the moment they're made! Well, that's the secret to it, they've got custom code defined in the New() event. Every object has a New() proc, and a lot of programmers call walk_rand() in that event so their enemies will begin moving around right away. But what about attacking? They're not just walking around, they're attacking, too! And they're doing it without waiting for an event! Well, the event that's making them attack is the Move() proc. During New() a call is made to walk_rand() which makes the enemy take random steps. Each time they want to take a step the Move() proc is called, and the programmer has placed some attacking code inside of Move(). It could look something like this:

mob/monster
var/strength = 10
New()
.=..()
walk_rand(src, 10)
Move()
.=..()
for(var/mob/player/target in range(1,src))
attack(target)
proc/attack(mob/target)
var/damage = rand(1,strength)
target.hit(damage, src)

mob
var/health = 100
proc/hit(damage, attacker)
health = health - damage


Now, what if we want to make it so that every time a player gets attacked they have a chance of counter attacking? Well, we're going to use the hit proc... but how do we know the proc is even going to be called? Let's trace it back: hit() is called whenever a monster attacks; attack() is called whenever a monster moves in range of a player; Move() is called because the monster is walking randomly; and walk_rand() is called during New(), which is the event that started it all.

Here are some other events to get your projects going. You can look them up in the reference to read about when exactly they get called.
  • datum/New()
  • client/Center()
  • atom/Enter()
  • atom/Exit()
  • atom/Entered()
  • atom/Exited()
  • atom/movable/Move()
  • atom/movable/Bump()
  • Any Verb
This instructional was awesome, good post IainPeregrine. It was good reading.
Thanks !
Nice, exactly what was needed. I read most of it and found a slight typo under the spam protect code example. :D
Mecha Destroyer JD wrote:
Nice, exactly what was needed. I read most of it and found a slight typo under the spam protect code example. :D

Thanks. I fixed it, if it's indeed the one you're talking about: be "[used to] help"

Good to know this article is helpful.
The icon and icon_state in the frost giant code should not be under the var block.
Garthor wrote:
The icon and icon_state in the frost giant code should not be under the var block.

Fixed. Thanks.
really good job! You guys think long term coding causes brain damage? i been coding 4 years now and i study everything i can find and i sometimes wonder that.
Wholeinthesky wrote:
really good job! You guys think long term coding causes brain damage? i been coding 4 years now and i study everything i can find and i sometimes wonder that.

Lol. If that really happens, it would suck.
cool thnx
Wholeinthesky wrote:
really good job! You guys think long term coding causes brain damage? i been coding 4 years now and i study everything i can find and i sometimes wonder that.

Are you sure you've been doing this for 4 years speaking like that? If anything it's good for your brain, when you code you're constantly challenging yourself, your brain gets used to solving complicated problems. This might be the reason why most real programmers seem smart.

And humans only use around 10% of their brains (thats embarrassing) it's no where near overloading or anything.
O.o it only says error error
How did you learn to code?
Carrz soulja wrote:
How did you learn to code?

I didn't start by reading the DM guide, but up until I did read it I didn't really understand what I was doing. I didn't read it all at once, but I read it chapter by chapter, trying the code examples they gave and then seeing if I could expand and modify them. What was even more important than the guide, however, was the reference. Whenever I was bored I'd just look through the reference until I saw some proc or variable I didn't know about, and then I'd try and use it. Over several years I learned about everything in the reference by building little projects.

That's really the key to it, though: You have to start with nothing, build little projects, and then work up from there. If someone starts with a source, they'll only learn how to modify the source, they'll never learn how to build a new system from the ground up.
IainPeregrine wrote:
Carrz soulja wrote:
How did you learn to code?

I didn't start by reading the DM guide, but up until I did read it I didn't really understand what I was doing. I didn't read it all at once, but I read it chapter by chapter, trying the code examples they gave and then seeing if I could expand and modify them. What was even more important than the guide, however, was the reference. Whenever I was bored I'd just look through the reference until I saw some proc or variable I didn't know about, and then I'd try and use it. Over several years I learned about everything in the reference by building little projects.

That's really the key to it, though: You have to start with nothing, build little projects, and then work up from there. If someone starts with a source, they'll only learn how to modify the source, they'll never learn how to build a new system from the ground up.

Can I have a link to how to code?
Carrz soulja wrote:
Can I have a link to how to code?

In the upper right hand corner of this page is a box with all the links you should need. If you have any problems, you can ask for help on the Developer Forums. The link to those forums is also in the top navigation bar under the menu labeled "Developers".

I would suggest starting with the link that says Start Here.
does any1 know the code to add teams to a pokemon game on dreammaker
Can you plz be my coder im good at iconning i just need a coder and a mapper can u plz be my coder plzzzzzzzzzzzz

Very nice tutorial.
I would recommend adding in some other key words, to make it easier to find. :)

Great work and thanks for the help!