Pages

Saturday, August 25, 2012

11: 3-Hit Barrage

This time we actually give Tanner access to his full three hit combo, and let him swing to the left finally.

Explaining this part is going to be a little difficult, as my approach was much different than most other moments. See, the next two steps are fairly simple in theory, but I ran into problems every step of the way.

The easier issue to deal with is Tanner's inability to strike anything to his left. After duplicating and flipping Tanner's combo graphic to face the left, all you really have to do is add a bunch of OR statements to any if statement involving the attack graphic.

The more difficult issue is letting him perform swing 2 and 3. Just like with the directional issue, I had to add a bunch of OR statements for the 9th and 19th frame. The next step is a little more complicated, sorta.

Every time the player presses Z to reactivate the attack, the frame is reset to 0. We need an exception. There's a few we could use, but I just ended up with this:

Step Event:
if ((sprite_index == spr_tswingr) || (sprite_index == spr_tswingl))
{
     image_index += 1
}
else
{
     image_index = 0
}

And... that's about it. Every single part of this post was a mess of trial and error. I added some code, tested to see if it worked, and if it didn't, I fixed the typo or adjusted the logic. For the most part, you should definitely check out the .gml file and read the code.

A couple of pieces of advice I learned from this however:

   Be very careful with your parenthesis, especially when it comes to ANDs and ORs.

   Be careful mixing "!=" (NOT) with ANDs and ORs. The logic becomes fairly difficult to follow, and usually your code won't work.

Here's the .gml file:
     https://www.dropbox.com/s/4n0ewv0lyvfj9ni/11%203-Hit%20Barrage.gm81
Here's the .exe file:
     https://www.dropbox.com/s/ly8i6mo3vxjpi1l/11%203-Hit%20Barrage.exe

Friday, August 24, 2012

10b: Taking Swipes Return

One thing I neglected to mention in the last post was the bugs that crept up on me. When i originally worked on the last blog post, I actually wrote it all out before even trying it. Not the smartest thing to do, no, but since what I was doing would work in theory (and wasn't too complicated), I figured it was worth a shot. Fortunately it worked, but not without a lot of bugs. What you ended up seeing me typing was a fully working version, but I actually had several problems along the way. I figure I should go over them now, since debugging is a very important skill to learn.

The biggest problem early on is the alarm event. Originally the code read like this:

End Step:

if (sprite_index == spr_tswingr)
{
     if (image_index == 4)
     {
          image_speed = 0
          lightable = 1
          alarm[0] = 8
     }
}

This originally caused me trouble. Why? Because in the current code, the alarm is reset to 8 every frame as long as Tanner is on his 4th slashing frame, leaving him stuck there. That's why I finally touched it up to:

End Step:

if (sprite_index == spr_tswingr)
{
     if (image_index == 4)
     {
          image_speed = 0
          lightable = 1
          if (alarm < 0)
          {
               alarm[0] = 8
          }
     }
}

With this if statement added, the alarm won't constantly reset itself. Unfortunately, this also means that we have to make sure the alarm is turned off before it reaches this bit of code.

Next off is a small detail, but one I forgot early on.


Step Event:
if (keyboard_check_pressed(z) && lightable == 1)
{
     runable = 0
     jumpable = 0
     lightable = 0
     sprite_index = spr_tswingr
     image_index = 0
     image_speed = (1/2)
}

Early on when repeating the attack animation, I noticed that he wouldn't actually change frames because I never bothered to type in image_index = 0.

That's about it for now. I just thought I'd address the issue, since the last post I ignored all the bugs I ran into.


Thursday, August 23, 2012

10: Taking Swipes

I'm back!

Now that we've given our hero the ability to move about, it's time to move onto the real fun stuff, swinging his sword. Don't laugh please...

No laughing permitted. You can however, chuckle or snicker.

From this point on, I honestly don't know what I'm doing. I've read enough guides on how to make a platformer I could do so without too much hassle. From this point forward, all bets are off, and I'll be trying whatever I can think of. This again stresses what this blog is really supposed to be about: expressing the mindset of a programmer, particularly from a beginner.

As before with movement, the first thing to do is add the sprites into Game Maker. It can be especially troublesome since the sword's width means you have to really extend the sprite's boundaries, which can make adjusting the sprite rather frustrating.


Unlike running and jumping, we need to add the animation first. Now that we have the graphics loaded, we should be able to make our hero slash by typing something like:

Step Event:
if keyboard_check_pressed(z)
{
     sprite_index = spr_tswingr
}

Or not. This code will do absolutely nothing. The problem here is that no matter what, our character's sprite changes based on his movement. Everything we've done so far has been done assuming that running and jumping is the only thing our character can do. From this point forward we have to use variables to set up what your character can and cannot do, and what actions he is performing.

The way I originally did this was through a universal variable called state. Depending on what number it was set to would define what action the character was in the middle of. For example: 1 would mean the player could move, 2 would mean the player was performing a light attack, 3 would mean the player was performing a strong attack, 4 would mean the player was taking damage and so on. The problem with this method was that it was either too general or each state had to be made so specific it became tedious.

Instead we're going to use a series of variables to determine what the player is allowed to do. This means we can controls things a lot closer, and change things on the fly as well. Instead of me rambling on about this though, let's actually try it out.

First let's add the variables:

Create Event:
runable = 1
jumpable = 1
lightable = 1             //able to perform light attack
gravable = 1             //if 0, deactivates gravity for player (for aerial attacks perhaps)

Next, we have to add these new conditions to our original code. We could add new if statements around everything, but it'll look really messy and could be trouble. Fortunately, there's a much easier solution, AND. By adding and/&& inbetween conditional statements, both have to be true in order to work.


From this point on, we can turn the player's controls on or off whenever we want. For instance, now when we add in our sword slash:

Step Event:
if (keyboard_check_pressed(z) && lightable == 1)
{
     runable = 0
     jumpable = 0
     lightable = 0
     sprite_index = spr_tswingr
     image_index = 0
     image_speed = (1/2)
}

...it negates our player's ability to move, jump, or activate the attack swing once more.

Can't... move...

Unfortunately this just causes the poor character to be stuck in his idle animation, since he cannot move and the End Step still changes his sprite despite the restrictions. Perhaps we should fix this.


Now our hero finally can slash that stupid sword of his, and he will continually slash it until his arm falls off. He's stuck in a loop because we haven't actually added anything to stop him from swinging, and perhaps more importantly, let him move once more. This is where things can get a bit dicey, so I'll try and lay it out as plainly as possible.

Again, no laughing, but perhaps a chortle.
It's a very badly flowing flow chart, but this is laying out exactly how I want the character to perform his 3-hit combo. Try playing any 2 games with simple 3-hit combos and you'll find they all have different rules and nuances. To the player, these minor elements aren't really thought about in any kind of intense detail, but to programmers like you and me spreading everything out not only allows us better control over how our game is played, but makes translating ideas to code much easier.

For now, I just want to work with the very first sword swing animation. Let's go to our End Step, shall we?

End Step:
if (sprite_index == spr_tswingr)
{
     if (image_index == 4)
     {
          image_speed = 0
          lightable = 1
          if (alarm < 0)
          {
               alarm[0] = 8
          }
     }
}

Now Tanner stops swinging at the last frame of his sword swing. You may have noticed I used two if statements instead of just &&. I did this solely because I will be adding more conditional statements later, and it just seemed easier to bunch them altogether underneath one if statement, but that is for later. For now, we should actually write some code for that alarm, or else Tanner is now stuck awkwardly holding his blade to the side. Add an event for Alarm 0 and add:

Alarm 0:
if (sprite_index == spr_tswingr) && (image_index ==4)
{
     alarm[0] = -1
     runable = 1
     jumpable = 1
     movable = 1
     lightable = 1
}

As you can see, the if statements are starting to get much more specific, but that isn't necessarily a bad thing. The ifs are actually unnecessary, but it's good to be careful now instead of having to fix everything later.

As a final touch, now that we are using an alarm, we should turn it off whenever we start a new attack to prevent it from stopping the character mid-swing, so let's add one final bit:

Step Event:
if (keyboard_check_pressed(z)) && (lightable == 1)
{
     runable = 0
     jumpable = 0
     lightable = 0
     alarm[0] = -1
     sprite_index = spr_tswingr
     image_index = 0
     image_speed = (1/2)
}

As a little thing to note, alarms are a very useful feature of Game Maker. You can simulate your own fairly easily, but they actually gave them some nice functionality. They always stop at 0, and setting them to any negative number turns them off immediately. The only annoying part to me is that in order to use them you have to actually create an alarm Event for them to function, instead of just working automatically and allowing you to use a simple if statement.

Next, we add more to the combo, and try to get Tanner to swing to the left.

Here's the .gml file:
     https://www.dropbox.com/s/pyyn63er0e14spd/10%20Taking%20Swipes.gm81
Here's the .exe:
     https://www.dropbox.com/s/g9elezj611gblnk/10%20Taking%20Swipes.exe

Tuesday, July 10, 2012

Apologies

Unfortunately, I won't have regular access to Internet soon. Fortunately, I will still have my laptop with me, ensuring my continued work on blog posts. I do apologize for the lack of posting. We have finally reached the point where the blog and my personal work on the project are almost the same. Coupled with me having to rewrite a lot of code due to some mistakes and it has taken longer than I thought to update. Thank you for your patience, and your time.

Tuesday, July 3, 2012

9: Bug Busting

I'm sure the one or two of you fans are excited to get to the inevitable next part, attacks. Unfortunately, at this point, my chief bug tester and I found a few bugs, one of which stuck poor Tanner in the floor. Bugs are inevitable in anything you code, and plenty will exist in your final product. Being an indie game maker, people will typically look over your mistakes, but taking the time to fix bugs adds a excellent polished feel to a game.

I understand that we've just started the game, and it is only natural wanting to get farther, but bugs are always easier to remove the earlier you find them because there is less code to slog through. So what are these bugs I'm talking about? Aside from one particular bug I purposely left in, most of them are not in the code I've been providing, but I would still like to go over them to show what kinds of mistakes can happen.

The worst bug we found was Tanner getting stuck in the floor. When falling at just the right speed and height, Tanner would end up buried into the ground, and wouldn't be able to jump out of it. I'm still not entirely sure how exactly this glitch happened, but after I noticed and fixed up a few smaller mistakes in my code it went away. The biggest mistake was this embarrassing piece:

// Gravity check
if place_meeting(x,y+vspeed,obj_floor)
{
     vspeed = 0
     move_contact_solid(270,vspeed)
etc


It's always a good idea to use a variable for something right after you reset it (note: sarcasm). Again, I'm not the proudest of this blunder, but I would rather a bug come about because I mistyped something than my code just not working overall.

The next bug is something a lot less obvious to find, but a lot easier to fix. In this case, when just mashing the jump button to see if I could find a bug, I noticed that Tanner would do a sort of triple-jump. Basically, when I tapped jump just before touching the ground, he would jump in air, but jump as high as a normal jump. What was happening? Well, first thing to note is that the original code was arranged so:

gravity code
jumping code


If you think logically, you might be able to piece it together. Tanner isn't actually triple-jumping. He is moved to the ground with move_contact_solid(), then immediately jumping within the same frame. In other words, he moves downward, then upward in the code, but only moves upward onscreen. The fix is simple:

jumping code
gravity code


Changing the order removes the possibility of this happening. Now the player can only jump when he can visually see Tanner touching the ground.

The last bug is is mainly asthetic, but it looks terrible. This bug is actually present in the code I've provided. It only became noticeable when we added the animations. Whenever Tanner touches the ground, his graphic glitches slightly. Now it is time to put debug mode to the test. Try testing the game in Game Maker (this doesn't work with just the exe), but this time in debug mode. One of my favorite features of debug mode is the "Set Speed" command.

I typically set it to 5 or 10 when I want to see what is happening frame by frame. Do this, and then jump. When Tanner lands, he goes into the standing animation like you would expect, but for a single frame, he switches to the falling graphic. It has nothing to do with our animation code. If you use the debug functions to watch the variable inair, you'll notice it turns to 1 for a single frame after Tanner lands. The fix for this is small, but how do we figure it out? Just try and think through everything logically.

We know that when Tanner lands, move_contact_solid() places him onto the floor. It also sets the inair variable to 0. Apparently at this point, the code sets inair back to 1, and then to 0 again. It only changes in the gravity event, so it has something to do with that.


if place_meeting(x,y+vspeed,obj_floor)
{
     move_contact_solid(270,vspeed)
     vspeed = 0
     doublejump = 1
     inair = 0
}
     else
     {
          vspeed += 2
          inair = 1
     }


The only way inair returns to 1 is if the place_meeting() check fails. This is where I figured it out, so I'll lay it out completely.

Tanner touches the ground, and the gravity check does it's work. Afterwards, vspeed is set to 0, and Tanner is placed just above the floor. When the check is made again, it tests if Tanner would collide with the ground by checking his current position, and adding vspeed, which is zero. Since he isn't actually touching the floor, this means for that single frame, the game assumes Tanner is in the air and moves him 2 pixels downward. After that, the code works fine because Tanner is actually inside the floor at this point.

How do we fix it? It seems really minor, but it works.

if place_meeting(x,y+vspeed+1,obj_floor)


If we simply add 1, the game will check just underneath Tanner's feet even if vspeed is 0. Now the glitchy effect no longer happens.

Next time, we finally let our hero swing his sword around. The horrors await!

Also, I'm not posting the gm81 or exe file this time. I added two characters to the code.

Friday, June 29, 2012

Drawing is Easy... for Artists

Hey guys, no update today. I just thought that today I'd make a quick post about spriting.

If you're reading this blog trying to learn something, then I'm guessing you are not the best at programming. If fate has smiled upon you, you probably are not very good at programming, but are an excellent artist. If so, good for you. However, if you are like me, you probably cannot draw to save your life. Being a good artist is a talent gained through time and practice. If you don't want to take that time and effort, there are alternatives. Not nearly as good alternatives, but still there.

One way is to use a sprite template. As mentioned before, I used one by Chumbucket, and it actually contains a ton of animations that you can use. I honestly don't know of any others, but editing pre-existing sprites is a possibility as long as your game is freeware.

For me though, it wasn't enough. While I have not shown them yet, the attack animations are actually edits of the template's graphics, for better or for worse, but I like to have at least a slight personal touch in what I use. Here are some pretty good pixel art tutorials I have read and learned a few tricks from. Again, these will not make you great artists, but they teach skills worth learning.

A tutorial by Derek Yu. A personal favorite artist.
     http://www.derekyu.com/?page_id=218
A tutorial by The Mechanical Maniacs.
     http://themechanicalmaniacs.com/guides/spriteguide.php#Type4
A collection of tutorials on Serebii forums. It's a pokemon site, but there are several good thorough guides.
     http://www.serebiiforums.com/showthread.php?59110-Sprite-Tutorials-56K-Warning!
I tutorial by... gas13(?). He actually has several, and they are very thorough and well thought out.
     http://gas13.ru/v3/tutorials/sywtbapa_almighty_grass_tile.php

Wednesday, June 27, 2012

8: Mario Posing

Our character has a face now, but he has an odd tendency to run while jumping in the air. Fixing this next part is pretty easy. How do we stop Tanner from running in the air? How do you determine if he is in the air?

place_meeting(x,y,obj)

Jackpot, sorta. We could just as easily add this to our animation code, but I would rather avoid unnecessary checks when a variable will do just fine. Let's add a new one to the fold:

inair = 0

Then introduce it to our gravity code:


if place_meeting(x,y+vspeed,obj_floor)
{
     move_contact_solid(270,vspeed)
     vspeed = 0
     doublejump = 1
     inair = 0
}
     else
     {
          vspeed += 2
          inair = 1
     }


There we go. No we have a variable we can call whenever we need to know if Tanner is touching the ground. Now all we need to do is use this in our animation code:

if (inair = 0)
     then run and idle animation
else if (inair = 1)
     then in air animation


If you're following along, you'll soon get to feel the joy of rearranging your code to keep it looking pretty as you add if statements. For now though, we'll just focus on the in air portion. This next portion is a little weird, mainly because I found a goofy way of doing it. First off, we can add:

if (inair = 1)
{
     image_speed = 0
     sprite_index = spr_tinair
}


We know that inair contains 4 frames, but each is intended as a completely different graphic.



Therefore the first thing we do is set the speed to 0. Next, we need to check if Tanner is actually rising or falling. We could possibly use prevy, but we have something else at our disposal that's very helpful, vspeed.

if (inair = 1)
{
     image_speed = 0
     sprite_index = spr_tinair
     if (vspeed < 0)
     {
          image_index = 0
     }
     else if (vspeed > 0)
     {
          image_index = 2
     }
}


We're almost there. Tanner is rising and falling, but he's always facing left. It's time to put face to use, but how? We could add more if statements, but it will look pretty cluttered, and be a bit repetitive (something that's going to be unavoidable later anyway, but stick with me). How about just adding face to image_index?


if (inair = 1)
{
     image_speed = 0
     sprite_index = spr_tinair
     if (vspeed < 0)
     {
          image_index = 0
          image_index += face
     }
     else if (vspeed > 0)
     {
          image_index = 2
          image_index += face
     }
}


Think about it. The variable face is always 0 for left and 1 for right. I arranged the frames in spr_tinair so that the first frame was left, and the second was right. Adding face works perfectly, and now that we know we can do this, we might be able to put it to use at some other point.

With that all done, our animation code (at least for movement) is perfect. Next time, I touch on some small debugging. And  for completion sake, here's the full code:


if (inair = 0)
{
     if (playerdir = 0)

     {
          sprite_index = spr_trunl
          image_speed = (1/3)
     }
     else if (playerdir = 1)
     {
          sprite_index = spr_trunr
          image_speed = (1/3)
     }
     else if (playerdir = 2)
     {
          image_speed = 0
          if (face = 0)
          {
               sprite_index = spr_tidlel
          }
          else if (face = 1)
          {
               sprite_index = spr_tidler
          }
     }
}

else if (inair = 1)
{


     image_speed = 0
     sprite_index = spr_tinair
     if (vspeed < 0)
     {
          image_index = 0
          image_index += face
     }
     else if (vspeed > 0)
     {
          image_index = 2
          image_index += face
     }
}


Here's the gm81 file:
     https://www.dropbox.com/s/70ubcxv1cb76ju6/8%20Mario%20Posing.gm81
Here's the executable:
     https://www.dropbox.com/s/ddy7ztx0fcc4guz/8%20Mario%20Posing.exe



Monday, June 25, 2012

7: Run Tanner Run

Welcome back. Last time, we came up with some fancy new variables, and now, we've got to put them to use.

prevx
prevy
playerdir
prevplayerdir
face


I've already explained what these variables are for, but they aren't built into Game Maker. If we want them to do what we intend, we'll have to do it manually. The "prev" line of variables are just used to compare old variables to new ones. Therefore, to make them work, we just have to type:

prevx = x
prevy = y
prevplayerdir = playerdir


The most important part here is placement. We want to put the above code at the very beginning of our "Step" Event, before all our keyboard checks and the like. This way, the "prev" line of variables will be identical to the x, y, and playerdir of the previous frame. Then the rest of the code can mess with the current x and y, and we can compare them afterwards.

The next bit of code is actually going to be put into a new Event, called "End Step". Using "End Step" just guarantees that all movement and collision processing is done already, and all our animation code is applied to the correct situation. This next part is where I got a bit overwhelmed myself, but it's always important to take things one at a time. For now, let's start by checking the player's direction. Remember this statement?


if player is moving leftward
     set character sprite to run left
if player is moving rightward
     set character sprite to run right
if player is not moving
     set character sprite to idle


Ignoring the part about setting the character sprite, let's use this as a guideline:

if (prevx > x)
{
     playerdir = 0
     face = 0
}
else if (prevx < x)
{
     playerdir = 1
     face = 1
}
else if (prevx == x)
{
      playerdir = 2
}


With this done, we now have a piece of code that let's us ask about the player's direction and orientation, and then store that information into our two variables for later use. Unlike adding similar code to the keyboard checking, we're actually basing our information on what is happening instead of what we assume will happen. With this in our hands, the next part, actually changing the character's sprite, is fairly easy. Of course, I had to dig up some new variables built into Game Maker, and here they are:

sprite_index          //A non-numeric string variable that defines which sprite the object is using
image_speed         //A variable that determines the speed at which the sprite switches frames
image_index         //A variable that says which frame the sprite is on


These are fairly self explanatory, although I often find myself mixing them up. The only particularly odd thing to note is image_speed. The number in image_speed is the number of frames of animation per step (and default number of steps per second is 30 in Game Maker). In other words, you generally want to enter a fraction, or your animation will either skip frames or just play extremely fast. Anyway, let's get to coding:


if (playerdir = 0)
{
     sprite_index = spr_trunl
     image_speed = (1/3)
}
else if (playerdir = 1)
{
     sprite_index = spr_trunr
     image_speed = (1/3)
}
else if (playerdir = 2)
{
     image_speed = 0
     if (face = 0)
     {
          sprite_index = spr_tidlel
     }
     else if (face = 1)
     {
          sprite_index = spr_tidler
     }
}


The first two if's seem pretty straightforward. If the player is moving left, give him the left graphic and set his speed to one frame every three steps. If the player is moving right, do the same, but with the right graphic. The second is a little wierder, but not too complex. If the player is standing still, we set the image_speed to 0 (although a bit arbitrary, considering the idle graphics are one frame each. I think originally they were together, but I left it in anyway). Then we check his orientation, and set the graphic to the left or right idle graphic accordingly.

There is one other bit of code I want to add, if only for my own sake. It isn't anything too important, but some people may get annoyed if I didn't add this:

if (prevplayerdir != playerdir)
{
     image_index = 0
}


What does this do? Well, "!=" basically is the same as the NOT operator. In other words, if the player's previous direction is different from his current direction, then the animation gets set to the beginning. This is something that's barely noticeable, but without it, when the player switches from idle to run, or from left run to right run, they will continue mid animation. Again, not something too big, but I wanted to add it anyway.

Now that our hero can run, we have to teach him to stop running midair, and learn proper aerial form. Next time, we add rising and falling graphics to the mix.

Here is the gml81 file:
     https://www.dropbox.com/s/3sye6imavpflnet/7%20Run%20Tanner%20Run.gm81
Here is the executable:
     https://www.dropbox.com/s/5mxbbbzszjecynh/7%20Run%20Tanner%20Run.exe

Saturday, June 23, 2012

6: Think Ahead, and the Headaches Come

I'll be honest. Up until this point, I've known exactly what to do because I've read enough instruction books and internet guides to know exactly what to do. After finishing the movement aspect, I had to get creative and just start making it up as I went. This is the point where what I do works, but I secretly hope someone comes along and points out a more efficient way to program.

Today, we're talking about adding animation to our characters. I almost always see tutorials mention this aspect briefly, but never in depth. In all fairness, the reason for the lack of instructions for this sort of thing is probably the same reason as the lack of AI tutorials. Some code is going to be subjective not only to your game, but the way you program things. However, that's why I started this blog in the first place, so let's get started.

First, we need some graphics. I'm a terrible artist, but I want the graphics to at least look somewhat distinctive. Fortunately, I found a pretty awesome platform character template made by Chumbucket (he started a newer one, but I found the original to be pretty useful).

This is Tanner. He's pretty lame, I agree.
There's our exciting little hero, with his wife beater shirt, blue jeans, buzz cut hair, and a wooden sword. Not much to look at, but hey, that's not the point. He has 4 key graphics we want to apply: Idle, Running, Jumping, and Falling. Adding them into Game Maker can be a bit troublesome. Then again, arranging frames of animation can always be frustrating trying to get the frames to line up perfectly. It's possibly harder in Game Maker because you can only view one frame at a time when editing. Best I can recommend is to add the graphics in as best you can, and just take the time to adjust them later.





When I name sprites I tend to follow the same formula of spr_[object's first letter][quick description][suffix]. The formula seems a little convoluted, but I think it leads to short names, such as spr_trunr (or, sprite of Tanner, running right) that are easy to remember. You may also notice that I clumped the jumping and falling sprites together, both right and left, in the spr_inair. I actually discovered a neat trick later that let's me save some time doing this, but we'll get to that later.

We'll take it one animation at a time, starting with running. An easy fix would be to tack on a "change sprite" command to our horizontal movement code. The problem there is that the character would continue running unless you adding more code, probably along the lines of:

if keyboard_check_released(vk_right)
     set character sprite to idle right

Unfortunately, that creates more problems. Perhaps there is a genuine fix for this method, but I found a way I like much better. Instead of adding to the movement code, we'll add code to the "End Step" Event and do something akin to this:

if player is moving leftward
     set character sprite to run left
if player is moving rightward
     set character sprite to run right
if player is not moving
     set character sprite to idle


This is a bit vague. In fact, it almost seems a little obvious of a statement, since it's what we want ultimately. The question we should be asking is, how does the game know the character is moving left or right? In the earlier example, we used the fact that the player was pressing a key, but the game has no built in way of know the character's movement because we're just making it warp 8 pixels to the left or right instead of using the hspeed variable. There is a way, but first, we should add some new variables in the create event:

prevx = 0
prevy = 0
playerdir = 2       // 0 means left, 1 means right, 2 means neutral
prevplayerdir = 2
face = 1              // 0 means left, 1 means right


The "prev" variables are used for checking the character's movement. By comparing the old variable to the current ones, you can check for movement a little easier. For example, if you asked:

if (prevx < x)


Then you are asking if the character is moving to the right.  The playerdir and face variables are really for convenience, but we can put them to good use later on. There is already a built in direction variable in every object made in Game Maker, but it's degree based and may actually change based on the player's hspeed and vspeed. Playerdir is just called playerdir so I don't get the two variables mixed up. Face is similar to playerdir, but it's important to remember the distinction between the two. Face is about the character's orientation, while playerdir is about the character's actual movement. At this point, the difference is not too important, aside from the idle graphic, which while neutral in direction, can either be facing left or right.


I'm going to stop here for now. I apologize for the lengthy wait between posts. From now on, posts may be shorter, but they'll be more consistent. Thanks for your patience.

Tuesday, June 19, 2012

5: Jumping Complex

Before we go any further, I've decided to do something different as I go along. This entire time, I've just been  typing in instructions, and expected people to learn just by reading it, or by following along themselves. That's fairly unreasonable, so I've taken the time to add the .gm81 file and executable to the end of each post where I add code. The executable is there if you don't have Game Maker, and would only like to see the end result (and the glitches). The .gm81 is the source file Game Maker can read, so you can see exactly how I've set things up.

The reason I wasn't doing this before is due to the fact that I'm much farther along than what we've been over. Every example picture I've show, and code is actually me going back through an extra copy of the game and deleting anything we haven't discussed yet. All files are uploaded using DropBox, so you don't have to be attacked by ads and the like. I'd also like to apologize about the executable, as I'm running Game Maker Light. I plan on getting the official version eventually, but until then, these files have the annoying watermark.

Now back to our feature presentation.

The first thing I want to add today is double jumping, but this time, I want the player to be able to do so once. Let's bring up the old code.


if keyboard_check_pressed(vk_up)
{
     if place_meeting(x,y+1,obj_floor)
     {
          vspeed = -27
     }
}


If we look at how our jump code works right now, it only works if the character is on the ground. In order to make sure it works in the air, we need to add an exception.

if keyboard_check_pressed(vk_up)
{
     if place_meeting(x,y+1,obj_floor)
     {
          vspeed = -27
     }
     else if something                                                // exception
     {
          vspeed = -20                                                 // double jump is weaker due to personal preference
     }
}


What exactly is this exception? Well, how about a variable? We can call it doublejump. When the player touches the ground, the variable becomes 1. When the player jumps midair, the variable becomes 0.


if keyboard_check_pressed(vk_up)
{
     if place_meeting(x,y+1,obj_floor)
     {
          vspeed = -27
     }
     else if (doublejump == 1)
     {
          vspeed = -20
          doublejump = 0
     }
}


if place_meeting(x,y+vspeed,obj_floor)
{
     move_contact_solid(270,vspeed)
     vspeed = 0
     doublejump = 1
}
     else
     {
          vspeed += 2
     }


Typing all of this will technically work, but we've got one last thing to do before it works. If you decide to make your own variable (and believe me, you will often), you have to declare it. So in the Create event, add a script that simply says:

doublejump = 1


The number is irrelevent here. Any custom variable must be declared in the create event. If you didn't do that, as soon as the game attempts to do anything with the variable, it declares an error and shuts down.

The next element I want to touch is Dynamic Jumping. If you've played quite a few Platformer games, this is an element you see all the time, but rarely think too much about. We want the player to be able to control their jump height based on how long they hold the jump key. First off, let me introduce a new command.

keyboard_check_released(key)


What we want to do is program so that when the player releases the up key, they stop their upward momentum.

if keyboard_check_released(vk_up)
{
     vspeed = 0
}


That would work, right? Well, not really. If the vspeed becomes 0 instantly every time the player lets go of the up key, the character would stop in midair, even if they were falling. So let's double up the conditions just like we did with the basic jumping code.

if keyboard_check_released(vk_up)
{
     if (vspeed < 0)
     {
          vspeed = 0
     }
}


The "vspeed < 0" condition checks if the character has upward moment before stopping the vertical movement. This does need to be adjusted a bit though, as the character's jump will appear a tad jerky. I want the character to still rise slightly after the key is released, so I want the vspeed to be set to -10.


if keyboard_check_released(vk_up)
{
     if (vspeed < 0)
     {
          vspeed = -10
     }
}


This brings up one final, easy to fix problem. If the player releases the key when their vspeed is between -10 and 0, they will actually gain jump height. In order to remove this, we just change:


if keyboard_check_released(vk_up)
{
     if (vspeed < -10)
     {
          vspeed = -10
     }
}


And there we go. With that out of the way, we are completely done with movement, at least for now. Next, we add some actual graphics, and turn our little rectangle into a real boy.

Here is the Game Maker file:
     https://www.dropbox.com/s/7ylg2uhvucq4hrv/5%20Jumping%20Complex.gm81
Here is the executable file:
     https://www.dropbox.com/s/ovezllkl6cnkqrj/5%20Jumping%20Complex.exe

Sunday, June 17, 2012

4: Polishing Up Gravity

There's nothing more thrilling than figuring out how to program something, then finding out it's buggy as hell and having to spend hours making it work perfectly. It can be an endless source of frustration, but a game that feels buggy and unpolished is going to be quickly shutdown and put in the Recycle Bin, no matter how much content you put into it.

Before we get to the nitty gritty though, I think we should address the huge issue staring us straight in the face, namely that our main character is able to jump in the air infinitely. Let's Review:


if keyboard_check_pressed(vk_up)
{
     vspeed = -27
}


It's a pretty basic command, with a pretty simple solution to our problem. If we don't want him to jump in the air, then we just have to make sure he's standing on the ground.

if keyboard_check_pressed(vk_up)
{
     if place_meeting(x,y+1,obj_floor)
     {
          vspeed = -27
     }
}


Yup, just add a second if statement checking if the player is touching the ground. There is another way to write this, using the "AND" statement. Doing so saves space, but I wrote it this way for something later. For now, we need to deal with another big problem. Right before landing, the character jitters to the ground.


if place_meeting(x,y+vspeed,obj_floor)
{
     vspeed = 0
}
     else
     {
          vspeed += 2
     }


If you want to fix the problem, you need to figure out what exactly is causing it. In this case, just think it through frame by frame:

x = distance from floor
Every frame, the game checks the character's falling speed, and checks to see if in the next frame, he'll move into the floor. If he is, the game removes his vertical speed. This means that the next frame, the code checks the character's vertical speed again... which is now 0. If the vertical speed is zero, and the character isn't standing inside the ground, he'll fall again. It does this several more times until the character is finally on the floor. This brings up two big problems. The first is getting the character to stop freezing mid-air. The second is fixing the collision check so the character doesn't have to stand INSIDE the ground.

The first is actually pretty easy to fix, thanks to a really handy command built into Game Maker:


move_contact_solid(dir,maxdist)


I love this command. Basically, it moves the object right up against the nearest solid in the direction you type. For the direction, you have to type a number, as in degrees. So for us, we need down, which is 270 degrees (if you haven't done much geometry, just remember 0 is east, 90 is north, 180 is west, and 270 is south). The second argument it wants is maxdist, which in this case, we just use the vspeed variable.


if place_meeting(x,y+vspeed,obj_floor)
{
     move_contact_solid(270,vspeed)
     vspeed = 0
}
     else
     {
          vspeed += 2
     }


Doing this fixes the entire problem. This character no longer jitters right before touches the ground. I'm sure this perfect programming won't come back to bite me in the butt later.

Foreshadowing!


Anyway, let's take a step back and finally give our walls some kind of purpose. We won't worry about "move_contact_solid()" in this case, if only because it's not noticeable at all.



if keyboard_check(vk_right)
{
     if not place_meeting(x+8,y,obj_wall)
     {
          x += 8
     }
}
    else
    {
        if keyboard_check(vk_left)
        {
             if not place_meeting(x-8,y,obj_wall)
             {
                  x -= 8
              }
          }
     }


Okay, so this part looks like a horrible mess of brackets and if statements. This is only a small sign of how crowded the if, then's can become, so learning to read this is important. Just remember when typing these, to do like I do and line up corresponding brackets together (or something else if you format code differently than me) so you can keep track of everything.

Well, there we go. Now we've got the bare basics of mobility covered. Next though, we give our character the ability to double jump ONCE, and let the player control the strength of the jump.

EDIT:
     This is the Game Maker file:
          https://www.dropbox.com/s/shkliu9jnvzfw13/4%20Polishing%20Up%20Gravity.gm81
     This is the executable:
          https://www.dropbox.com/s/a47hichwe2z0lup/4%20Polishing%20Up%20Gravity.exe

Saturday, June 16, 2012

So Sleepy

Well, no progress to be made for today. Today, I got to ride in a packed van for 14 hours, getting home from vacation, and now I'm feeling pretty tired.

Unless I'm unable to post, I'll be adding to the blog daily, or at least every other day. Any new progress with the programming will have a number next to it, that way newcomers won't have to dig through pointless posts to find what they really came for. The rest is just filler, but I'll try and post about relevant things, such as small guides I found helpful or indie games that showcase Game Maker's abilities.

Except for today. Today, I sleep.

Friday, June 15, 2012

3: Rise and Fall

Well, now that the rectangle can move horizontally, it's time to tackle the signature aspect of platforming games, jumping. It only gets more complex from here, but we've got to get the basics down before we can tackle the good stuff.

Before we even touch the up key and jumping though, I want to tackle falling. After all, if you let the character jump, he'd continue on to infinity. You may have noticed that early on, I placed the player pretty high up. I did so to test gravity. Let's approach this just like we did last time, shall we? All of this code can go just below last post's code.

Gravity exists.


Er... well, sure, but what is gravity? A force that constantly pulls objects towards the ground is about as simplistic as I can put it. We're not programming realistic physics here, so all we need to do is code so that the player acts like gravity is affecting him.

vspeed += 2


There we go. Vspeed is a handy variable built into every object Game Maker creates. It adds the vspeed variable to the current y of the object every frame. Adding to the y means the object shifts downward, and as an added bonus, by constantly adding to the vspeed instead of just setting it to 2 or just adding to y manually, the character falls faster every frame. Problem solved, right?

Er...




Okay, so all we did was make the poor guy plunge into the center of the earth, but hey, you have to start somewhere. I think you know where this is going.

When character touches the ground, STOP!


Don't forget, IF, THEN.

if the character touches the ground
     then stop him from moving down


This seems like a pretty simple command, but for me, it's another moment where I had to search around the help files, looking for the commands I wanted specifically. The command is "place_meeting(x,y,obj)". Basically, this function checks if there would be collision between the object it is written in, and the object written at "obj". The catch here is that it checks for a hypothetical collision, assuming that the object it's typed into was placed at the x and y you type in. It may be easier to understand if I gave an example.

if place_meeting(25,35,obj_wall)


In other words, if the object was placed at the coordinates 25,35, would it collide with the wall?

For us though, it gets even more complicated.

if place_meeting(x,y+vspeed,obj_floor)
{
     vspeed = 0
}
     else
     {
          vspeed += 2
     }


Want to know why exactly I typed "(x,y+vspeed,obj_floor)"? Well, x and y were entered to keep the collision check relative to my position and added vspeed to y. This literally means it's checking for a collision vspeed pixels below the character's position.

There we go then, our happy little rectangle can now fall daintily onto the floor. Unfortunately, it's trapped on the ground until we teach it to jump. This is the easy part. Think about it for a second...

if player presses up
     then give him upward momentum


Now translate:

if keyboard_check_pressed(vk_up)             // pressed prevents player from holding down the key
{
     vspeed = -27                                          // number is whatever you want, I just liked how 27 felt
}


With that, the character now has the ability to move around by moving, jumping, and falling. We did good, right?

Right?





If you try and type the above commands into Game Maker they will work, but you'll immediately notice several issues. For one thing, your character jitters right before landing on the ground, and for another, you can jump infinitely. Even by B-grade game standards, it's pretty abysmal. We have to fix these issues, but for now, take a moment and try to figure out how to do so yourself. Next time, we fix the choppy platforming, and finally stop the player from walking through the walls.

EDIT:
     Here is the Game Maker file:
          https://www.dropbox.com/s/1xug8y6z276buyv/3%20Rise%20and%20Fall.gm81
     Her is the executable:
          https://www.dropbox.com/s/g0wwrwmfktqnhqz/3%20Rise%20and%20Fall.exe

Thursday, June 14, 2012

2: Goodbye Drag n Drop

Now that we've got a basic set up, let's get to the real stuff. Today, we're going to make our special little rectangle move to the left and the right. Nothing difficult, but it's still a challenge for first timers. First things first, we open up obj_tanner's interface and drag an "Execute Code" action into a "Step" event. I can easily recall the next moment in my mind.


Every time I see this, my mind goes just as blank.
I'm not an idiot. I know what kind of commands I need to type. Unfortunately, I have no idea what exactly those commands are, or what way I need to type them. It's a little sad to admit, but I spent about five hours reading guides just to get a general idea of how to program, and find all the command lists. Before I spit out the commands, let's think what we want to accomplish.

Let the player move their character right and left


Very simple command, but the computer doesn't speak English. Computers talk in IF, THENS, so let's translate a bit.

If the player presses right or left
     Then move their character right or left


Getting closer, but if you translated that to GML literally, the character is going to move randomly left or right if the player presses either button.

If the player presses right
     Then move their character right
If the player presses left
     Then move their character left


There we go. Programming is an endless stream of IF statements, so you'd better get used to them. Next, let's actually use some GML commands.

If keyboard_check(vk_right)
{
     Then move their character right
}
If keyboard_check(vk_left)
{
     Then move their character left
}


Okay, the way I typed it isn't how it has to be written, but I like typing it C style, since it keeps things nice and orderly. As you can probably guess though "move their character" isn't a legitimate GML command. There are built in "movement" functions within GML, but sometimes the easiest solution is the best.


If keyboard_check(vk_right)
{
     x += 8
}
If keyboard_check(vk_left)
{
     x -= 8
}


If the newest addition doesn't make any sense, the command "+=" adds the following number to the preceding variable. In other words, add 8 to x. So in layman's terms, as long as the player is pressing right, it constantly adds 8 to the character's x placement, warping it to the right, but at 30 frames per second it looks like it's moving fairly smoothly.

There you have it. The most basic of commands, and something anybody who has made games before can do without a second thought. I still wanted to linger on it, just for the sake of showing some basic logic used in programming.





Whether you're following along in Game Maker, are pretty old hat with programming, or are just that perceptive, you might have noticed a big problem with the above code. If you didn't notice it, look at it again, and think (and no, it has nothing to do with the walls).

Think you've got it? Try tapping both the left and right arrow keys at the same time.

If you press both keys at the same time, both IF statements are performed. It's not a terrible problem, especially considering we're only adding and subtracting from the character's x, meaning pressing both keys just freezes him in place, but if more complex movement elements such as acceleration were used, it could really cause some bugs. There's an extremely easy fix for this though, and it is only one word.



If keyboard_check(vk_right)
{
     x += 8
}
else
{
     If keyboard_check(vk_left)
     {
          x -= 8
     }
}


With the else command entered, the computer always ignore the left key if the right key is already held down. Problem solved. Join me next time when we add gravity to the mix, and teach our little rectangle to jump.

EDIT:
     Here's the Game Maker file:
          https://www.dropbox.com/s/ak8gt8pi63wml2x/2%20Goodbye%20Drag%20n%20Drop.gm81

     Here's the executable:
          https://www.dropbox.com/s/48aoltwaf7s1lys/2%20Goodbye%20Drag%20n%20Drop.exe

Wednesday, June 13, 2012

1: Starting Out

The first question you're probably asking is "What the heck kind of game are you making?" I don't plan on going into too much detail, but I think a great game to learn the basics with would be a 2D Platformer. Instead of making a more generic platformer such as Mario, though, and because I'm trying to teach programming instead of level design (which I'll admit I'm terrible at), I want the game to be more combat based, and take place in an arena style map.

I'm hoping this will force me to learn how to, and eventually teach how to program:
     Basic Platforming Engine (including Double Jump, and Dynamic Jump)
     Non-bullet Attacks (including Sequence Attacks, Aerial Attacks, and Multi-Hit Attacks)
     Damage Physics (including Launching and Hit-Stun)
     Grabbing (how to keep it from looking silly)
     AI (nothing insanely complex, but still one of the biggest challenges)
     HUDs (score keeping, health meters, etc.)

This probably leaves out some aspects, but a huge reason I've started this blog is because some of the above elements are really difficult to find help or guides for, partly because it's very subjective to YOUR game and coding style. Again, I'm hoping to teach you how to code for yourself, not copy and paste what I make.

That out of the way, let's open up Game Maker and put it to use.

You'll miss this screen looking so bare.
Before we can even test our project, we need a map. Before we can even build a map, we need objects. Before we can even program objects, we need some sprites to be able to see the objects. I suppose I could spend a few hours whipping up some terrible character sprites, but I've got a much better solution.

I <3 boxes.
Right now, I don't need to worry about character animation, and since I don't use precision collision checking (and I would almost never recommend it), the game pretty much sees objects as rectangles anyway. I do want to be able to differentiate the objects, so I made three sprites. The first is the player's object, a thin rectangle that will later become the player's mask (something that will come up later). The second two are separate sprites for the floor and wall. As you can see, I name sprites with "spr_" at the beginning. I find this keeps everything organized better and prevents name overlap.

Next I make the objects. No picture is needed this time, I just make three separate objects called obj_tanner, obj_floor, and obj_wall, then apply their sprites. The only confusion may be on "tanner", but it's a habit of mine to name the player object the character name instead of "player".

Finally, the map itself. I'm not worried about resolution or anything special, I just want to make a small map for testing purposes.

As you can see here, I've made it about as simple as possible. The floor is slightly elevated just for aesthetic purposes. The walls are placed just off the screen. There's no roof, but until I put in something that could possibly launch the player over the walls, I'm not too concerned.

And that... just about wraps up the basic set up. At this point, it's nothing complex, and unless you've never used Game Maker, shouldn't take you more than a half an hour. Next post however, we get our player to move left and right, and learn some basic GML commands.

Tuesday, June 12, 2012

Prologue

Let's talk about game programming.

Anyone can create a game design. I've got notebooks and folders filled with them, and even though only 10 percent of them are worth giving a once over, what holds people back? A large amount of laziness is the typical problem, and I'm no stranger to it, but knowing how to create the game is a huge roadblock in the first place. Unfortunately, programming can be pretty daunting to beginners.

Fortunately, there exist a multitude of simplistic game makers with fairly little restriction that provide an excellent framework to start with.

This is where I come in. I originally started using RPG Maker when I was younger, but when I found out I could program action combat and other unique systems with it, I lost interest in the RPG elements. This ended up being extremely frustrating, as trying to do anything complex found me tearing out my hair at the engine's event based programming and the clunky interface. No one to blame but myself for expecting an RPG Maker to do everything. I later found Game Maker, and instantly enjoyed the easy and very flexible tools. Not wanting to do anything simple, I found myself frustrated with my own inexperience, and while I knew the basic processes behind programming a game, I didn't know a programming language itself. Game Maker has a easy to read and learn language called GML (Game Maker Language), and I immediately knew I could use it to start out.

After embarrassingly taking 5 hours to learn the most basic commands and form just to get my little rectangle shaped character to move left and right, I realized that while I could read tutorials all day to expand my knowledge of GML, I still was struggling to think like a programmer. After about 2 weeks of work, I had a small character running about and swinging a sword, and decided I wanted to do something and have some fun. I was going to start a blog, and journal the thought process of programming a game. A lot of tutorials teach what to type, and I hope to teach what to think.

Thus starts my descent into the world of video game programming, and perhaps a small trip into loonyville.  I thank anyone who reads this and adds their two cents, and hope you gain some knowledge from my crash course experiment. 

Next post, we talk basics.