April 24, 2019, 03:43:01 pm

The Gang Garrison 2 Forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

Chat with us online! (or @irc.esper.net/#gg2)
Come Mumble with us!

Pages: [1] 2

Author Topic: [Programming Guide] Introduction to Modding | Section 1: Game Maker  (Read 9723 times)

Orpheon

  • Moderator
  • *****
  • Karma: 15
  • Offline Offline
  • Posts: 6445
  • Developer

I. Game Maker

In this section, I will show some basics about the workings of the GM engine, and also some general programming concepts (variables, global variables, events, while/for, etc...). If you already familiar with it or can already decently program, you can skip directly to part II. I won't be touching modding either, so if you are anxious to learn tips on that skip on.
Part II doesn't exist and probably never will, sorry.

If you have any questions about gml/your mod, there is a general modding help thread >>>HERE<<<.
Questions specifically about the guide, as well as criticisms of any kind, can be posted in this thread.
Contributions to the guide too are welcome, but try to make them of good quality.


Ia. Resource types

Setting up a small game maker demo

Opening game maker, shutting off the tutorial and news, you should have a blank screen in front of you, with a folder list on the left. If you want to start a new project, you first need to create a Room. Rooms work sort of like maps, all gameplay should happen inside one. You can leave default settings for now, then close the new Room window and create an Object. Objects are where most of the action is, they are by far the most important thing in GM. Once you create one, you should see a window with two blank columns and a tabbed menu on the right.


Objects

Inside the object, you can create a series of attributes and actions that make them do what they should do. Remember though that the object itself is just a template. It just describes what information and what behavior it is supposed to have. If you actually want to use the object, you need to create an instance of the object. Think of an object like a plan, or a blueprint, and an instance as the actual thing. You can make infinite instances of the same object, and they can all exist at the same time at different places. You only ever have one object of each type.
(click to show/hide)
(click to show/hide)
I might out of habit mix up the names, and call something object when it's supposed to be an instance. People do this often out of convenience, but please don't forget that they are not the same thing, and that objects don't actually exist ingame.

GM lets you define the behavior of an object through so-called Events. Basically, whenever something happens to an instance of your object, you can define a set of actions that gets executed. You can add events in the left column through the "Add Event" button right underneath it. You can then select an event and add actions in the the right column (more on that later).
There are many different kinds of events in game maker, here is a rundown of the most important ones:
  • Create event - This gets called whenever an instance gets created or spawns. This is useful to initialize all your variables, and also to simply set things up for later (like alarms or networking connections).
  • Step event - This is the most important event in the game. It just gets called once every frame. This is where you code behavior that should happen all the time, like pathfinding, handling input, physics, checking whether the instance is dead, etc...
  • Draw event - In simple games, you don't need this. By default if you tell your object to use a sprite (more on that later), it will just draw that. Sometimes you want to do custom drawing things, like lines, overlay (ubers), transparency (think spy cloaking), animations, etc... For those things, you can write code that draws them inside this event, and they will get called each time an instance gets drawn. Also a very useful event.
  • Collision event with <insert any other object> - Somewhat obvious, this gets called every time an instance collides with an instance of that other object. The code can be as simple as removing hp and destroying the instance for bullets, to complex collision handling for character-wallmask collisions.
  • Begin Step and End Step events - Occasionally you want more control about the order of execution game maker does. It makes sense to do certain things first (handle input) and others later (physics) and still others last (networking). For this you have these two events. They are identical to the step event, with the difference that they occur before and after the step event (respectively), which gives some more control. These are more advanced events, also not needed for simple games. GG2 uses them quite a lot though.
  • Key pressed/Key released/Mouse events - They get executed if the user presses/releases/clicks a certain key. Useful for anything that needs input, although it's also possible to query input with code inside a step event (which is what gg2 does for characters).
  • User events - These are custom events that don't ever get executed by default, but that you can call from any other object. For example, if you want each instance to write it's data into a file for saving, you can make a custom user event 1 that saves its own data. Then you can just loop over all instances (easy to do, more on that later) and tell them to execute their event 1. It's a clean way to do it, and it's used in GG2 for many things, including networking and explosions.
  • Destroy event - This event gets called when an instance gets destroyed. Rarely used, because it is sometimes unreliable (strange things happen during room change with create and destroy events), but occasionally necessary. Remember to destroy all your lists and general ds_xxx stuff here.

Once you created an event and selected it, you can drag actions from the right-most menu into the right column, and they will get executed there. As you can see in the menu, you can make entire games with just those predefined actions. I do not recommend it though, drag'n'drop becomes tedious after a certain amount of actions, and much less easy to edit. So instead of starting to build your game with that, go to the control tab and drag the action that looks like a blank page called Execute Code. This should open up a code editing window, where you can start describing behavior with code. I'll describe GML (Game Maker Language, the programming language you will use) in the next section.


Sprites

Sprites are the next thing that are probably useful for your game, if you're not making a text-based game. They are basically small images that get drawn wherever a certain instance is.
Often, people don't use just one sprite, instead they use a spritesheet, which is a sequence of sprites which gets drawn one after the other, giving animations.
In GG2 for example, several sprites get drawn very quickly in succession, which gives the illusion of walking. If the scout possesses the intel, different sprites are displayed instead.
When you create a sprite, you also need to load an image from your hard drive. When you do so, don't forget to check the box "Remove background" or the green/white square around your sprite will also appear ingame.
Once you have a sprite and have given it a descriptive and short name (ALWAYS NAME YOUR STUFF WELL. IT REALLY IS THAT IMPORTANT.), you can in the object menu at the topleft add it as sprite. If you haven't made a draw event and the "Visible" check is on, then the sprite will be drawn at the instance's location. You can also draw it manually inside the draw event with the commands draw_sprite() or draw_sprite_ext() (more later, or check the yoyogames docs/GM help on the F1 key).


Ib. Basic GML

GML is an interpreted scripting language made specifically for game maker, with syntax based mostly on C. It is also in my opinion an endless source of annoyance and problems. If you have never programmed before and wish to start with gml, no problem, it is relatively noob-friendly... at first. But please, go look at some other language (my recommendation would be python, but java, C#, even C++ or C) soon afterwards, to have an idea how programming /should/ work. I don't want to turn this into a GML-rant, so I'll try avoiding to press the subject, but yeah. I really don't like it.

That out of the way, lets look at how it works exactly. Programming with imperative languages like GML (don't worry about the terms right now, if you don't understand them that's fine, you might understand them more later) consists of making a list of things for the computer to do.
Before we go in the exact syntactic details, set up a barebones game you can try out stuff on. You can read about programming forever, but if you want to actually be able to do it you'll probably need to practice, like every other skill in life. First create a Room, create an object, put that object in the room once (you can do that in the room editor), add a create event in the object and add an Execute Code action (the blank page under the Control tab).


Basic Concepts


Variables and Arithmetic


Programming is based on maths at it's core. Addition, subtraction, multiplication, and all the other operations you can do with numbers are usually supported. You can/have to also store values inside so-called variables. Variables are a combination of letters and numbers that serve as a name, and you can store any kind of number value inside ("number value" is called "real" in game maker, short for "real numbers". Will be important later).
Now, some actual code:
To store stuff in variables, use one "=" sign:
Code: [Select]
// This is a comment, anything starting with two slashes is ignored by the computer
// Useful for putting in explanations, tips, warnings, jokes and documentation
// You rarely have too many comments
a = 16; // Creates a variable "a" and stores 16 in it.
b = a+4;
a = b/2; // We can overwrite variables
show_message(a); // Will make a display on the screen showing the value of a.
Copy-paste it into your editor, and before you run it, take a look. What do you think will appear?


Conditionals

Of course this is cool, and you can already let it do a good amount of maths homework for you, but making games with this is somewhat limited.
Another ingredient that is necessary are so-called conditionals.
The basic form of conditionals works like this:
Code: [Select]
if (something is true)
{
   then do stuff
}
else // It isn't true
{
   do something else
}
Everything within the { } will get executed if and only if what's inside the condition (ie. the ()) is true.
The "else" part is optional, you don't have to include it, but it's often a good idea. If you do, then in case the condition is not true, the if block will be skipped and the else block executed.
Not including it just makes the code skip the if block if the condition isn't true.
You can also make in-between statements, like this:
Code: [Select]
if (something is true)
{
   then do stuff
}
else if (something else is true)
{
   then do stuff
}
else if (third possibility)
{
   then do stuff
}
...
else
{
   then do stuff
}

The conditions themselves work like this:
Code: [Select]
if (a == b) // if a and b are equal (Note, see below)
if (a != b) // if a and b are not equal
if (a > b) // if a is larger than b
if (a >= b) // if a is larger or equal to b
if (a < b) // if a is smaller to b
if (a <= b) // I shouldn't have to explain this
(Note to "==", GML allows you to use one "=" to compare. This is a very retarded thing you should not get used to, it will make everyone hate you and will make you fail in every single other programming language.
Please get used to using two "==".)

The possibilities you know have are already decently large, especially if you start getting input from the user.
Code: [Select]
show_message("Quadratic calculator: Gets the solution(s) of any equation ax+bx+c=0.");
a = get_integer("Please enter a"); // Integer == whole number. You can't get a real number without more complex code apparently (yay GM)
b = get_integer("Please enter b");
c = get_integer("Please enter c");

d = b*b-4*a*c; // Quadratic formula, see http://www.sosmath.com/algebra/quadraticeq/quadraformula/quadraformula.html if you don't know it
if d > 0 // Brackets for conditions are optional, some people use them, some don't
{
   show_message("Solution 1:"); // The " " allow me to show text, more on this later too
   show_message((-b + sqrt(d))/(2*a)); // Maths. sqrt() == square root
   show_message("Solution 2:");
   show_message((-b - sqrt(d))/(2*a));
}
else if d == 0
{
   show_message("Only solution:");
   show_message(-b/(2*a));
}
else// d is under 0, ie. negative
{
   show_message("There is no (real) solution");
}


Coding style

Syntax-wise, GML is very lax. You are allowed to do a large number of things, from completely ignoring both ( ) and { }, to using "then", to doing a lot of different things GML borrowed from different languages.
You might have noticed that I also always add ";", this is out of habit. You don't have to do this, just try to be consistent. If you're editing a script with a certain style, try to copy the style if it isn't totally retarded.
Java-style brackets for example is a style I don't like, but it's valid, so some people here occasionally use it:
Code: [Select]
if (condition) {
   do stuff
} else {
   do stuff
}
Pick whatever works for you and work with that.

I recommend the style I usually use, even though even I don't always stick to it (I tend to forget ( ) around conditions for example).
In general, you want a clear style that's consistent and most importantly, easy to read. Machines don't need help reading code, humans do. Try to format it as human-friendly as possible, for example not like this:
Code: [Select]
if a = 0 a = 1but like this:
Code: [Select]
if (a == 0)
{
   a = 1;
}

The same also goes for variable naming. Choosing the right name for a variable is often difficult, but having short self-explaining variable names will go a long way towards making your program readable. In general, avoid using one-letter variables or numbered variables like
Code: [Select]
// Variable names to avoid
tmp
tmp1
tmp2
omnomnomnom (This variable exists in the gg2 source code)
hjnkmklshjdhgvdfsh (or any variation of this)
reallyLongUnnecessaryVariableNameThatTakesAgesToWrite
Some few examples of good variable names (in my opinion):
Code: [Select]
player_name
shotDMG
jumpHeight
num_bots
The main rules to remember are "self-explanatory, simple, hard to confuse with another variable and short to write".

There exist certain naming conventions within the programming world to denote special cases of variables. For example any variable written in all-caps with underscores LIKE_THIS is usually a constant (a fixed parameter whose value is known at compile time, like for example the version number). Another important example are the variables i, j, k and l. They are very often used as anonymous counters for loops (see next section) in that order, and are probably some of the most common variable names ever.
You may also notice that some variables are written lowercase_connected_by_underscores while others use camelCaseToSeparateWords. Other programming languages have one or the other as a standard, and a mixture happens in GM as a result. Pick one or just stay consistent with whatever standard is used in the script you're editing.


Loops

One thing is still missing, and those are loops.
Code: [Select]
while (something is true)
{
   do something
}
Code inside the while block will repeat forever as long as the condition stays true.
There is a variation that's similar that no-one ever uses for some reason
Code: [Select]
do
{
   stuff
} while (something is true)
The only difference is that code gets executed first and the condition checked second, but again, this is practically never used.

With loops, you can do more or less everything already.
Code: [Select]
x = random(10); // Gets a random number between 0 and 10
hasGuessed = false;
while (not hasGuessed) // Negation is this easy. You can also do "!hasGuessed", it's the same thing.
{
   a = get_integer("Guess a number between 0 and 10");
   if a == x
   {
      hasGuessed = true;
   }
   else
   {
      show_message("Wrong!");
   }
}
show_message("Correct!");

A kind of loop that often shows up is the following:
Code: [Select]
i = 0;
while i < 10
{
   show_message(i);
   i = i + 1;
}
In fact, this comes up so often that people use shortcuts.
For one,
Code: [Select]
i = i + 1; can be replaced by
Code: [Select]
i += 1;This is the same code, but you'll never see the first one. Don't get confused by +=, -=, *=, etc...
And second, there's even a custom loop to replace the above loop.
Instead of
Code: [Select]
i = 0;
while i < 10
{
   show_message(i);
   i += 1;
}
people use
Code: [Select]
for (i = 0; i<10; i+=1)
{
   show_message(i);
}
This is used for all kinds of looping through all numbers between something and something, for example looping through all players, through different positions, creating many things, etc...
Code: [Select]
for (i=0; i<10; i+=1)
{
   instance_create(Gib, death_x, death_y); // Creates a gib at the death spot
}
Code: [Select]
for (i=0; i<global.num_bots; i+=1)
{
   instance_create(BotPlayer, 0, 0); // Creates a bot
}
Code: [Select]
// Note: This code doesn't actually exist, it's just a creation to demonstrate this idea. I'm not 100% sure whether socket_error reacts like this.
for (i=0; i<ds_list_size(global.players); i+=1)
{
   player = ds_list_find_value(global.players, i);// This selects the i'th player from the global.players list
   if socket_error(player.socket) != 0
   {
      // Player has a connection error
      disconnect_player(player);
   }
}
You will see this kind of thing a lot, especially when we move on to arrays and lists.
Since looping through all instances of an object is rather common in game maker, GML provides a special third kind of loop to do it, the with:
Code: [Select]
// Kill everyone
with (Character)
{
   hp = 0; // Sets hitpoints to 0, ie. kills the character
}
Code: [Select]
var distance, nearestPlayer; // See section on variable scope for an explanation about this, just ignore for now
distance = 100000; // Very large number
nearestPlayer = -1;
with Character
{
   if point_distance(IntelligenceBlue.x, IntelligenceBlue.y, x, y) < distance
   {
      nearestPlayer = id; // id == the current character. It's a built-in variable, see section on those
      distance = point_distance(IntelligenceBlue.x, IntelligenceBlue.y, x, y);
   }
}
// nearestPlayer now holds the character that's nearest to the blue intel

If you want to break out of a loop before having gone through all, you can use the break keyword.
Code: [Select]
// Kicking
// Name of player that should get kicked is stored in "player_name"
with Player
{
   if name == player_name
   {
      socket_destroy_abortive(socket); // Kick player, see section on networking
      break; // No need to loop over all the remaining players, we've already kicked the one we were searching
   }
}

This wraps up all the statement keywords I want to showcase here, for a more complete list see the docs.


Ic. More Advanced GML

Functions/Scripts

Sometimes, you want to reuse the same code in an object that you've already done in another. Copy pasting is a very bad idea, if you later on find a bug (= a mistake) in it, you have to go around all your copies and change it, a time-consuming process. Ideally you'd have a piece of code that you can just call from different places each time you need it. This exists in most programming languages under the names of function or subroutine. In game maker you have instead Scripts.
Now, if you've been making things in game maker, by now you've already used a number of them.
What is common between all these commands?
Code: [Select]
show_message(15);
draw_sprite(sprite_index, image_index, x, y);
a = sqrt(4);
b = get_integer("Give me a number");
c = keyboard_pressed(vkey_space);
d = point_distance(x1, y1, x2, y2);
They all have a name, brackets, and inside the brackets a sequence of values separated by commas. They are also all highlighted as red. These are built-in functions, functions that exist in game maker by default that are here to make your life easier. Some return values, others don't, but they all do something useful with the values you give them without you having to worry about how they work.
That's the idea behind functions.

Now, you can make your own. Just create a script, give it a meaningful name, and open it. Anything you code in here now can later be called in the exact same way you call default functions.
Lets say we want a function that calculates the area of a circle when given the radius. For that, we create a scripts, maybe named "circle_area" or "area_of_circle".
Inside any object you can then type, say,
Code: [Select]
show_message(circle_area(15));and you should get the area of the circle printed out.
Opening the script (we still have to actually make it), you might wonder how we can access the 15. This is called an "argument", it's information passed on from the user to the function. Arguments in gm are stored in built-in variables named argument0, argument1, argument2, ..., argument15. If the user gave two variables,
Code: [Select]
circle_area(15, 21);then inside our script argument0 would have the value 15 and argument1 the value 21.
Then we also want to return a value, namely the answer. We do this with the return keyword.
Code: (circle_area) [Select]
area = pi * pow(argument0, 2);// pow(a, b) does a^b. In this case, it squares argument0, which is the radius
return area;
Once it hits a return statement, the code immediately stops and jumps back to the place where it was called. Putting code afterwards is useless, it will never be executed.


Variable Scope

Variables aren't (by default) visible everywhere.
How far a variable is known/visible is called that variable's scope. Game maker supports 3 different kinds of scope, we've only used one of them until now.
If you do not declare a variable, that is, just use it, then the variable has so-called Instance scope. That means it's visible from whereever inside that instance, or from any scripts called from an instance.
So say you create a variable in an object's create event
Code: [Select]
maxHp = 100;
hp = maxHp;
you can then access those variables from the entire object including all events in it, and also including all scripts you call from the object. Every instance of that object then has their own set of variables, and they can't share them directly.
You can access the variables of another instance like this:
Code: [Select]
char = instance_nearest(Character);
show_message(char.hp);
Note the ".". It's important.
You can also chain this.
Code: [Select]
show_message(player.object.currentWeapon.ammo);If you don't care about what instance you're taking the value from, lets say it's a value that doesn't change, then you can even use the object name (which will be highlighted yellow):
Code: [Select]
show_message(Scout.maxHp);Be careful though, bugs can appear through this kind of thing. Especially if you start to assign
Code: [Select]
Scout.maxHp = 50;which I do not know why it is legal, but it is. This will take an instance of Scout and change the maxHp variable, but only 1. Avoid this, it breaks stuff and it creates mistakes that are hard to spot.

When you use the "with" keyword, your scope changes to the scope of the instance you're with'ing:
Code: [Select]
with Character
{
   show_message(hp); // Legal
}
show_message(hp); // Will error
If you want to access the scope of the object outside the with loop, you can use other:
Code: [Select]
secret_variable = 5;
with Character
{
   show_message(secret_variable); // Will error
   show_message(other.secret_variable); // The right way to do it
}

Sometimes you don't want a variable to exist forever in an object, for reasons of clutter. Or you simply want a variable to be independent of objects.
In that case you can declare it beforehand using "var":
Code: [Select]
var secret_variable;
with Character
{
   show_message(secret_variable); // Legal
}
The variable will continue to exist for the rest of your current script, and then disappear. It also stays visible even if you go into another scope, with "with".

And then sometimes you can certain variables to be visible from anywhere, at any time, and always exist. These are called global variables, and great dangers come from abusing them, so use with caution.
However, there are some good uses for them.
Code: [Select]
global.playerName = get_string("Enter your name.");There are other ways to make variables global, but the sanest way is just to prefix them with "global." all the time.


Built-in Variables

As I've already mentioned, game maker defines a lot of things before you. Here is a list of the most important built-in variables of every instance:
  • x and y - These represent the current position of the instance in the world. Paramount importance.
  • hspeed and vspeed - These represent the horizontal and vertical speed. Changing them affects direction and speed as well.
  • direction and speed - These represent the same quantity as hspeed and vspeed, but in another form. Direction is in degrees. Changing them changes the above as well.
  • sprite_index - The current sprite of this instance
  • alpha - The transparency of the sprite, from 0 to 1
  • a lot of other variables no-one uses
  • instance_destroy - Don't even think about it. :P
The amount of functions game maker presents too is pretty damn large, too large for me to compile a list here. Besides, lists already exist in quite a few places, like the wiki, the game maker help on F1 (you should really look at it), or even google.


Strings

I somewhat overflew the topic of what types of data actually exist and can be stored in variables/printed. Actually, it's pretty simple, game maker knows two datatypes: real (you should know these, these are simply numbers) and strings (any combination of characters between " "). You can convert between them using the functions real(x) and string(x). This is useful for example for having more than two values in one show_message:
Code: [Select]
sol1 = a + b;
sol2 = a * b;
// Show both solutions
show_message("Solutions: "+string(sol1)+"; "+string(sol2)+";"); // This is how you combine strings

Here are a few very useful functions that handle strings:
  • string_copy(string, index, count) - Returns a new string which contains the contents of string starting from the index and for count letters
  • string_length(string) - Returns the length of the string
  • string_pos(string, substring) - Returns the position of substring in string, assuming it exists. If it doesn't, it returns -1.
  • string_replace_all(string, substring, newstring) - Replaces all substrings in string with newstring

Code: [Select]
string_copy("Hello", 2, 1) --> "e"
a = "Player: Hey"
string_copy(a, 9, 3) --> "Hey"

A useful thing to know: If the length you give to string_copy() is longer than the length of the string, string_copy() just takes the whole string.
Code: [Select]
a = "1234useful information";
a = string_copy(a, 4, string_length(a));
// a will be "useful information"
Since string_length(a) is guaranteed to be longer than any substring, it'll copy the whole remainder and then just continue. You may see this quite often.

Code: [Select]
a = "Player: Hey"
string_copy(a, string_pos(a, ":")+2, string_length(a))// This is a hard one, it prints out "Hey"
Code: [Select]
player_name = "Superb#player";// Small detail: GML interprets "#" as a newline.
// We don't like newlines in names
if string_pos(player_name, "#") >= 0// If # is present anywhere in player_name
{
    string_replace_all(player_name, "#", " ");// Replaces all # with spaces, which are harmless
}
There are many other functions, and a lot more possibilities to use them. Trying to cover them all is a tutorial for itself, if you really have trouble with string handling, ask in the help thread on your concrete problem.


Arrays and Lists

Being able to store a value into a variable is nice, but sometimes you need to store more than one value. You could have a sequence of positions, a list of all players in the game, the map rotation, etc...
Using the variables "player1, player2, player3, ..." until a number you hope is high enough that no-one will go over it is a very bad idea.
Instead, in most languages you use arrays.

Disclaimer: I'm covering arrays because of completeness, and also because you can't say you can program if you don't understand arrays, but let's be honest here, GML arrays suck. The only time where I've used them and I still feel it was a valid use was when making bubble-spammers. Most of the time you should be using lists.

(click to show/hide)
Arrays work like this: You get one variable that points to the first value. Then, if you want to access the others, you use "[n]" for some number n.
Counting always starts with 0, and all values have to be the same type (no mixing of strings and objects, for example).

In GML, you don't actually have to declare an array or even it's length.
Code: [Select]
a = 0;// a is a real here
a[0] = 0; // This line does the same as the above
a[1] = 5;
a[2] = 10;
// Now we have 3 values stored in a
for (i=3; i<10; i+=1)
{
    a[i] = i*5;
}
// Now we have 10 values, all stored in the same variable
// Using a for loop, reading it is rather simple
for (i=0; i<10; i+=1)
{
    show_message(a[i]);
}
The last construction appears everywhere. It's the main reason for loops exist.
Note that you have to keep track of how large the array gets, game maker doesn't do that for you.
This:
Code: [Select]
a[0] = 10;
show_message(a[2]);
will error, because a[2] is not defined.

That's all I want to say about arrays, now on to serious stuff: lists.

Lists work similarly to arrays, only you don't have to use the same type, can get the length of the list easily and also can search for an object with one function.
You first have to create them though, and destroy them manually as well.
Adding elements to the list can be done quite easily with ds_list_add(list, element), and accessing an element is done with ds_list_find_value(list, position). You can also find the index of an element in a list with ds_list_find_index(list, element), which either returns the position of the element or -1 if it isn't in the list.
Code: [Select]
a = ds_list_create(); // Creating empty list
ds_list_add(a, 15);// Adding 15 to the list
ds_list_add(a, 16);
ds_list_find_value(a, 0); // Returns 15
ds_list_find_value(a, 1); // Returns 16
Code: [Select]
var bot;
global.bots = ds_list_create();
for (i=0; i<global.num_bots; i+=1)
{
    bot = instance_create(0, 0, Bot);
    ds_list_add(global.bots, bot);// You can add instances to lists too
}
Code: [Select]
// Finds a player with a certain name and returns the instance
// argument0 = player name
// (Btw, always mark what the arguments are supposed to be when making scripts)

var player;
for (i=0; i<ds_list_size(global.players); i+=1)
{
    player = ds_list_find_value(global.players, i);
    if player.name == argument0
    {
         // This automatically jumps out of the script, no need for a break;
         return player;
    }
}
// No player was found
return -1;

NEVER, EVER FORGET TO DESTROY YOUR LISTS!
Please remember to do ds_list_destroy(list); on all your lists when you don't intend to use them anymore. It frees up the memory used by the list, and forgetting to do so causes a memory leak. Too many memory leaks (and GM already makes enough of them on it's own as it is) will lag your game considerably.


Objects revisited (Inheritance)

This is not technically a GML issue, but it belongs to general programming knowledge in my opinion.
You probably have already realised how useful objects are when it comes to making one template and then many instances, but it can go even further than that.

Often you have several different objects that are similar but not identical, or even just share a single feature.
An excellent example are classes in gg2. They all differ by some properties, but 90% of the code including gravity, collision, drawing, input handling etc... is very similar or identical between them.
It would be very tiresome to code the same code 20 times (red and blue teams), and copy-pasting it would still be a huge problem if you want to change something.
Instead, what is done is to make one "baseline" object, called the parent. Then you can create as many subclasses as you want, called children, which then inherit all code and events from the parent, and only code in the children the actual changes (you only override those events you want different).
You can layer this as often as you want, those children can then have their own, when it is useful to do so.
Here is a manual page of game maker on the subject, although every decent programming language after C knows inheritance, and you can find an explanation of the workings in any python, java, c++, c#, etc... guide.

This is probably an extremely confusing explanation, but I can't really give code examples in gml since game maker mostly does this on the gui level.
If you happen to possess gg2, I recommend taking a look at the objects Objects/IngameObjects/Character, Objects/Characters/*, and the subfolders "red" and "blue" in Objects/Characters/. That is an example of inheritance. Another example in gg2 is the way collisions work; There's an object "Obstacle" that does nothing but collide with things, and the wallmask then inherits from it.
I don't want to stray too far in gg2-land here though, this part is supposed to be somewhat independent, but until I find a good way of showing inheritance this will sort of have to do.


Conclusion of Part 1

That concludes at the moment part I of this guide. Questions and contributions are welcome, and criticisms too, as long as they're constructive, are accepted.
Note that this is only a crash-course, and that I am skipping over many details and distinctions in this guide. There are other resources, most importantly the gml manual (just press F1 in the editor), the Help thread, and of course google. In the end, practice pays off.

Have fun programming.
« Last Edit: November 05, 2015, 08:58:46 pm by Orpheon »
Logged

Orpheon

  • Moderator
  • *****
  • Karma: 15
  • Offline Offline
  • Posts: 6445
  • Developer
Re: Introduction to Modding | Section 1: Game Maker
« Reply #1 on: August 08, 2013, 01:00:46 am »

Reserve.
Logged

Orpheon

  • Moderator
  • *****
  • Karma: 15
  • Offline Offline
  • Posts: 6445
  • Developer
Re: Introduction to Modding | Section 1: Game Maker
« Reply #2 on: August 08, 2013, 01:03:00 am »

Reserve.


I can't really think of any more to fit into Ic, so if anyone has any ideas/questions that are general programming or gml-specific concepts you find should be mentioned, please post them.
Logged

bullets (obviously)

  • Seasoned Member
  • *****
  • Karma: 40
  • Offline Offline
  • Posts: 1980
Re: Introduction to Modding | Section 1: Game Maker
« Reply #3 on: August 08, 2013, 01:45:43 am »

Holy shit this is great, will read first thing in the morning
Logged

Orpheon

  • Moderator
  • *****
  • Karma: 15
  • Offline Offline
  • Posts: 6445
  • Developer
Re: [Programming Guide] Introduction to Modding | Section 1: Game Maker
« Reply #4 on: September 16, 2013, 11:43:33 am »

Requesting move to Mods.
« Last Edit: September 16, 2013, 11:43:45 am by Orpheon »
Logged

iLegend

  • 2013 Haxxy Award Winner
  • *****
  • Karma: 0
  • Offline Offline
  • Posts: 873
  • Force is always the answer.
    • Mah Resume
Re: [Programming Guide] Introduction to Modding | Section 1: Game Maker
« Reply #5 on: September 16, 2013, 04:10:39 pm »

Wait this is amazing wow get this out we could use more devs
Logged
<SecretMan> do i put BotAim.gml in plugins folder?
i hear los angeles is pretty good for casual sex with minors

Haxton Sale

  • The only true
  • Haxxy Organizer
  • *
  • Karma: 18
  • Offline Offline
  • Posts: 3541
  • HAXTON SAAAAAAAAAAALE!
Re: [Programming Guide] Introduction to Modding | Section 1: Game Maker
« Reply #6 on: September 16, 2013, 07:15:32 pm »

Moved and stickied.
Logged
THIS POST GOT SIGNED BY

FUCKINGSHITMEXICAN

  • Junior Member
  • **
  • Karma: 0
  • Offline Offline
  • Posts: 173
  • usted quieren fajitas?
Re: [Programming Guide] Introduction to Modding | Section 1: Game Maker
« Reply #7 on: December 27, 2013, 04:40:00 pm »

any updates?
Logged
edit:francis are you on the forums get a profile pic
http://pastebin.com/hCiaRAPx

(GL) AnInnocentBystander :  hes been at it for like an hour

Venomous

  • Heroic Member
  • ****
  • Karma: 1
  • Offline Offline
  • Posts: 656
  • Monoculus Whisperer
Re: [Programming Guide] Introduction to Modding | Section 1: Game Maker
« Reply #8 on: January 02, 2014, 04:23:25 pm »

By any chance, would it be possible for you to give out some spritesheets of all re-texturable things (Flags, HUDs, characters, bullets, projectiles, etc) for us to modify? Because I suck at code but Ive got a really good idea for a spritemod and I dont know how to make it.
Logged

KnotSoup

  • Lucky Member
  • *******
  • Karma: -8
  • Offline Offline
  • Posts: 1171
  • i haven't been here since god knows when
    • oh fuck me
Re: [Programming Guide] Introduction to Modding | Section 1: Game Maker
« Reply #9 on: January 02, 2014, 05:29:51 pm »

By any chance, would it be possible for you to give out some spritesheets of all re-texturable things (Flags, HUDs, characters, bullets, projectiles, etc) for us to modify? Because I suck at code but Ive got a really good idea for a spritemod and I dont know how to make it.
Try this for sprites and things
Logged

Lol u got rekt u bitsh, imma fuk ur momma iyn heyr possey lyk a pakin buss bitsh! i duntl pakin kair bitsh sok mai pootispowpow dicksh bitsh! imma quickscooupee yer bluuddy assh ya moda fuka! wat u gonna say nao bstch FUCK YOU!

Venomous

  • Heroic Member
  • ****
  • Karma: 1
  • Offline Offline
  • Posts: 656
  • Monoculus Whisperer
Re: [Programming Guide] Introduction to Modding | Section 1: Game Maker
« Reply #10 on: January 03, 2014, 04:09:33 pm »

By any chance, would it be possible for you to give out some spritesheets of all re-texturable things (Flags, HUDs, characters, bullets, projectiles, etc) for us to modify? Because I suck at code but Ive got a really good idea for a spritemod and I dont know how to make it.
Try this for sprites and things
Some of the sprite's pictures cant been seen or are error 404'd, and the mediafire download for it was deleted.
Logged

Phantom Brave

  • All Hail Classicwell
  • Moderator
  • *****
  • Karma: 69
  • Offline Offline
  • Posts: 12730
  • Another one --
Re: [Programming Guide] Introduction to Modding | Section 1: Game Maker
« Reply #11 on: January 03, 2014, 04:29:36 pm »

Spritemods don't need to do any coding. If you have a copy of Game Maker 8.0 Pro, you just open up the game's source code, open up the sprites folders, find the sprite you want to replace, and edit it with Game Maker's build in sprite editor. If you want to use a sprite loader mod, they usually have their own way of doing things.
Logged

http://steamcommunity.com/id/wareya/
ladies and gentlemen i would like to announce that the fact of the matter is up that the fact of the matter is a fact and it matters

Orpheon

  • Moderator
  • *****
  • Karma: 15
  • Offline Offline
  • Posts: 6445
  • Developer
Re: [Programming Guide] Introduction to Modding | Section 1: Game Maker
« Reply #12 on: April 11, 2014, 12:08:31 pm »

By any chance, would it be possible for you to give out some spritesheets of all re-texturable things (Flags, HUDs, characters, bullets, projectiles, etc) for us to modify? Because I suck at code but Ive got a really good idea for a spritemod and I dont know how to make it.
Getting the sprites isn't a problem; here.

After you've done your spritemod, you can either make a thread and upload them, and request someone to put them into a game, or get game maker and just replace the sprites there with yours.
You don't need any coding knowledge, at all.
Logged

notarctic

  • just arctic, what gives?
  • ******
  • Karma: 8
  • Offline Offline
  • Posts: 4956
  • 👎👀 bad aim ba̷̶ ԁ aIm 👎 thats❌ some bad 👎👎aim
    • arcticland
Re: [Programming Guide] Introduction to Modding | Section 1: Game Maker
« Reply #13 on: April 11, 2014, 05:37:56 pm »

Well, if you intend to include a hud modification (to some extent(as in modification that goes beyond modifying the hud sprites)) you do need some coding knowledge
Logged
[1:37:51 PM] Derpduck: arctic u need to quote ppl that make shit posts in case they edit them
[4:20:15 PM] Rubeus Hashgrid: i cant discover anything fuck you imageshack

Orpheon

  • Moderator
  • *****
  • Karma: 15
  • Offline Offline
  • Posts: 6445
  • Developer
Re: [Programming Guide] Introduction to Modding | Section 1: Game Maker
« Reply #14 on: November 09, 2015, 05:38:44 am »

Well, if you intend to include a hud modification (to some extent(as in modification that goes beyond modifying the hud sprites)) you do need some coding knowledge
...I guess.

In that case, go to Objects/Overlays and find the HUD you want to modify, and then start poking around in the draw scripts mostly.
Those can be quite intimidating, as there are many built-in variable names or conventions that look obscure when you don't know them; the "Drawing sprites and backgrounds" page of the in-editor docs (press F1) might be useful.
Logged
Pages: [1] 2
 

Page created in 0.049 seconds with 36 queries.