EDIT: my this was a huge post
... just read it from beginning to end, and slowly
take your time to digest it. I tried to be as clear as possible.
Double == is just programming syntax for "is equal to". In most programming languages, you have to use this when coding comparisons. A single = usually means an assignment, and if used as an assignment will just cause you agony.
Game Maker allows single = signs for comparisons, but right now I'm branching out into other programming languages, so it helps to keep as many practices consistent through them
otherwise I get confused and start screwing up when I switch between.
Okay, when you see me go:
if (variable)
This is a GML convention that I take advantage of. Basically, when you write an if-statement, the results are gonna be
true or
false, and the code block after is executed when it's
true, right? Well, when you just write a single variable like that, it will be
true if the value is
greater than 0, and false otherwise.
So I'll explain this:
if (pushing){
pushing -= 1;
x += push_x;
y += push_y;
depth = -bbox_bottom;
if (pushing == 0){
push_x = 0;
push_y = 0;
}
}
So basically, as long as pushing is > 0, the following code is executed. Remember how we used
movex and
movey to move the character? They represent the relative x- and y position that that player should move to. Well, in the
//Push Horz code, you'll see that I set
push_x to the character's
movex when you successfully push a block. The same happens for y.
Pushing is set to 8. So for 8 steps (because
pushing -= 1 every step, right?), the block moves at your walk speed in the direction you pushed it. Since the walk speed is 2, this means that after 8 increments, it will always have moved 16 pixels, the size of the grid! This is why the block moves smoothly, but remains fixed to the grid every time it stops.
Now, for the more complicated part:
//Push Horz
if (movex != 0){
pushh = instance_place(x + movex, y, o_rock);
if (pushh){
with (pushh){
if (!pushing){
if (!place_meeting(x + movex, y, o_collision)){
push_x = movex;
pushing = 8;
}
}
}
}
}
I'll just explain
// Push Horz, because the same logic applies to
// Push Vert, except for the y-values instead of x.
if (movex != 0)This is my way of saying, "is the player moving horizontally?". Because movex represents the relative x-position to move to, if movex==0, that means that the player has not pressed a key and should not move, so why bother executing the push code?
pushh = instance_place(x + movex, y, o_rock);instance_place is a collision check function. Basically, it checks the specified position for the type of object specified. But the useful think about this function is that, instead of returning
true or
false, it actually returns the instance-ID of the object it collides with! So what I do is I set the return value of the function to
pushh, so now I can reference that particular o_rock instance I've run into. I use this to push the rock, but a few more things have to be checked...
if (pushh){Remember how I said values >0 will be
true in an if-statement? I'm using that trick now! When I use instance_place to reference the o_rock collision, it is supposed to return the instance-ID (usually a value from 100000+), but what if there is no instance there? In that case, the function returns
noone (which is equal to -4, actually). In such a case, this if-block won't be executed, because we aren't pushing anything.
with (pushh){If we ARE in-fact pushing something, I can use a with-statement to control the instance
pushh, which references the o_rock that I am pushing and
only it. If you aren't familiar with the with-statement, the GM manual explains it pretty well
just look it up, it'll all come clear.
if (!pushing){Now, remember how we set
pushing to 8 when we push it, and it counts back down to 0? Well, this line makes sure that we aren't
already pushing this block. If we are, then pushing will be >0, and the following block won't be executed. The
! before pushing is just the coder's way to say "if NOT pushing". So it basically gives the opposite (true->false and false->true) of what "if (pushing)" would give us.
if (!place_meeting(x + movex, y, o_collision)){Notice the
! again, so this is a NOT check. This basically says, "if there is NOT an instance of o_collision at position (x + movex, y)". Also, realize that this code is
within the
with statement, so it's actually the o_rock that is executing this code! Get it? It means that the player isn't checking for o_collision, it's the o_rock that is, because this is the push code, we want to know if o_rock is able to move.
push_x = movex;
pushing = 8;Finally, the first sets o_rock's push_x variable to the same value as our move variable. So if we were moving RIGHT when we pushed it, the block will get pushed to the right. If we were moving LEFT when we pushed it, the block will get pushed LEFT. And, as you know,
pushing is set to 8 so that it moves 8 times (in increments of 2), ending up on the next grid cell.
Now, this one is quite simple:
//When player has stopped walking
if keyboard_check_released(vk_up)
{
if (sprite_index == s_me_wup)
sprite_index = s_me_up;
}
This is the exact same as yours, but except for this line:
if (sprite_index == s_me_wup)Remember how before, when you were holding multiple keys and released one of them, the character would "blip", and face the wrong direction for a quick second? That's because in the release-key event for that key, this code was telling them to do that! What I did, was made it so they only changed into the standing sprite
IF their current walking sprite was in the same direction! So if you're walking RIGHT and then release RIGHT, it will stop. But if you're walking RIGHT and release DOWN, nothing will happen!
One more thing... how did you become so good with GML? Does reading the whole help section in Game Maker help?
The GM help file. The GM Help file. The GM Help file.
I didn't have internet for the first 2 years when I was using Game Maker 4, and just read and read that help file. It's really useful, especially with the search functions available for you!
What I recommend is just going to the language basics section, and reading through everything. You won't digest it all at once, but some things will immediately
jump out at you, and you'll know that you'll be able to use them in your code from that point on. If you need to know something specific, like saaay, changing the screen resolution... just type "resolution" into the search field, and see what pops up! Then read.
Like, go through that stuff I just explained to you there, and try some of it out on your own. I probably have 1000 GMK files sitting around that are
purely files created to test out functions, try out new things, etc. I've basically been working with GM so long that I've hammered that whole help file into my head, and now I can recall most of GM's built-in functions on the fly, even with all their parameters.
It'll take awhile to learn, but like you say, downloading examples and looking at them is just fine. Just try to put into practice everything you learn, so it doesn't sink into the back of your brain, and eventually you'll memorize it like I have, and that's one less thing you have to worry about as you learn the rest of it!
Best of luck, and like I say, you're free to PM, email, or IM me anytime even if you have the simplest question. I generally respond quickly, and enjoy helping out
Best of luck!