Losing Steam, Second Wind

I just finished Level 12 out of 17 of the GPC. The momentum I built up going into Level 5 has been slowing to a crawl as I stumbled over structural incongruitiesweak examples, bugs, and project file configuration issues.

The Groove (or Rhythm or Flow…)

I am most productive when I find my ‘groove’. This happens when I’ve overcome my learning curve, have developed a pattern of work,  then get into a rhythm where I can knock out task after task by reusing the same steps.

Jimmy Diresta explains that first time you try something is the most difficult; you ‘go to school’ on the first one, and get progressively better and better – by time you finish, you’re an expert.

Matthew Inman made an incredible post on this subject, describing the agony and joy of creation…a few non sequiturs aside, he eventually gets to the meat of issue – how great and wonderful things can result from sweating over tasks that are often tedious and frustrating in and of themselves.

My problem is that I’m a perfectionist. If I encounter something that isn’t working to my satisfaction, I can’t ignore it – I have to ‘fix’ it. Maybe this is a characteristic of a good programmer, but it’s utterly frustrating when I’m working on it, and enormously satisfying when I get something to work properly…

The trouble, it seems, is that the content is getting thinner and thinner,  and the issues referenced above that are breaking my ‘flow’ are getting more and more numerous. At a guess, I’d say that these last few videos were produced at a busier time than the others, and as a result, he simply didn’t have the time required to carefully plan and produce them as well as he’d like.

Whatever the reason, I have to remind myself that no matter how annoyed I get with this course, it’s still free of charge, and of far superior quality to any other GML ‘tutorials’ on YouTube. More importantly, distractions, bugs and problem solving (especially when the problem is more complex than it first appeared) are all part of programming – so I’d best get used to them 🙂 .

That said, on with the lessons…

###

Levels 9-11 (Doesn’t that look ominous?)

Level 9 was more or less a rehash of Level 7, focusing on instance IDs, along with another ‘cheat sheet’ from the resource folder. The two share a lot of parallels, and might be better off merged into one big lesson rather than two disjointed ones. There was even a loop snuck into one of the project files to create more enemies, but that wasn’t covered as part of the lesson.

Level 10 was one of the shortest lessons so far, and anyone who attempted to include a sound as suggested in Challenge 10-01 part C will discover that they’ll need to enable the New Audio Engine (Global Game Settings > General > Use New Audio Engine) before they’ll hear anything.

Level 11 was a letdown. I was really looking forward to Lists, but the only output method covered was the number of total items in the list (e.g. the ds_list_size function). The examples in the lessons didn’t really fit my concept of ‘inventory’ – that is, being able to output all the values in the list, or how many of each unique value there were (e.g. 2 Burgers, 2 Apples etc.). I suspect that this will be covered later in Level 13 (Loops).

###

This brings us up to…

Level 12: Grid Game Concepts

Grid games can cover everything from board games (checkers, chess etc.) to turn-based and real-time strategy games to classic video games like Namco’s Pac-Man.

In all cases, movement in a grid game is fixed rather than free form. GPC 12-01-A covers movement, and attempts to tackle the issue of getting hung on on corners due to the collision geometry.

The Lesson’s Solution:

Make the sprites equally sized (32×32 pixels in this case) and use a collision mask of 32×32 to ensure that they stay within the confines of the maze corridors. That’s a good start.

Next, he introduces how to manually code keyboard and collision events inside a Step event like so:

if keyboard_check(vk_right)=true and place_meeting(x+4,y,o_block)=false {
 x=x+4
 }
 
if keyboard_check(vk_left)=true and place_meeting(x-4,y,o_block)=false {
 x=x-4 
 }

if keyboard_check(vk_up)=true and place_meeting(x,y-4,o_block)=false {
 y=y-4 
 }

if keyboard_check(vk_down)=true and place_meeting(x,y+4,o_block)=false {
 y=y+4 
 }

What the code is actually doing is checking to see if the player object will collide with a wall object (o_block), and if not (false), advance the player 4 pixels in the direction given.

Why this is an unsatisfactory approach:

Since are moving the player 4 pixels at a time, you have to manually tap back and forth until you are perfectly aligned or you will still get hung up on corners. This isn’t much of a problem when moving around 90 degree turns, becomes an issue when trying to get through ‘four-way’ and ‘T’ intersections.

How to fix it using only what we’ve covered so far up though Level 12:

When I set out to tackle this, the logic went something like so…

  1. Find a location 32 pixels (one character or tile length) ahead of whatever direction I was going
  2. Move to that location
  3. Stop moving when you reach it

I tried using the move_towards_point function using a variable (e.g. target=o_player.x+32) in conjunction with distance_to_point but found that it target would always be 32 pixels further ahead, so it would never close the gap and would move in that direction infinitely. The solution would have to be something relative to, but external from the player object.

That’s when it hit me; why not use another object? So here’s what I did (coded in the o_player object)…

Press D-Key Event:

//create a new object as a waypoint for the player to move towards
//move towards the target's coordinates at a speed of '4'
target=instance_create(x+60, y, o_target)
move_towards_point (target.x,target.y,4)

Collision with o_target Event:

//Destroy the o_target object on collision
with other {
instance_destroy()
}

//Stop the player
speed=0

Some of you may be looking at that code and scratching your heads – why 60 pixels? Well after lots of trial and error, I worked out that in order to move 32 pixels from where you were, you’d have to include the width/height of the player object (+32 pixels), giving you a total of 64.

When I tried 64, I found that I was stopping just short of where I needed to be, and worked out that the collision wasn’t actually detected when the edges of the two object met, but when the player object had overlapped it by the designated speed (4 pixels). So, 64-4=60, which places you at exactly 32 pixels over every time you press the key.

Once I had that working, it was time to clean up the code and put some utility conditions in it to prevent a keystroke from changing direction before you got to your destination, an additional event to stop you when you hit a wall, and to destroy any target objects you can’t reach (i.e. behind a wall) and some additional variables to be able to control the distance (pdist) and speed (pspd).

In the Press D-Key Event:

// check to see if character is moving
if moving=0 {
//set moving to true & destroy the old target
 moving=1
 with o_target {
 instance_destroy()
 }
//move target right by 'pdist' pixels at a speed of 'pspd'
 target=instance_create(x+pdist,y,o_target)
 move_towards_point(target.x,target.y,pspd)
}

Add moving=0 to the end of the o_target and o_block collision events and that’s pretty much it! Now using the Key Press event rather than just the Keyboard event will cause you to take a single step 32 pixels in whatever direction you are heading assuming you adjust the +/- pdist variable depending on whether you are going left (x-pdist), right (x+pdist), up (y-pdist) or down (y+pdist).

So once I got everything working, I swapped the WASD Events over from Key Press back to Keyboard and viola, true grid movement!

 

Image Credit: Don Quixote, oil on canvas painting by Jean-Baptiste-Camille Corot, 1868.

Published by

Yousef

IT Manager by trade, game developer by heart.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.