Monday 1 December 2014

Unit 22 & 72 - Overcoming problems during development

I have decided to tackle the side of things I am less comfortable with first - namely the logic of Game Maker and it's interface. I have built some dummy sprites, objects, and a room:







Test sprites to help me to get to grips with Game Makers' gravity. I know can substitute these for the real game sprites later on. At the moment, understanding gravity is key.

First problem: friction between player and platforms

One of the first problems I have encountered during the development of my platform game concerns my main sprite 'sticking' to platforms. Why this is, I am not sure. I tried altering bounding boxes around the sprites. making them more precise in the hope that this could solve the problem. So far, nothing. I can only move left and right when I jump in the air. This implies that the problem is in the relationship between sprites and platforms:


My sprite 'sticking' to platforms and being unable to move


My sprite can jump fine, and even move left and right in the air.





Solving the problem - 3/12/14


Eventually, using this short script, I semi solved the problem of gravity and friction. The first step was to create several variables: gravity, horizontal speed, vertical speed, jump speed, and move speed 

In player object : CREATE EVENT
//Variables
grav = 0.2;
//Horizontal variable
hsp = 0;
//Vertical variable
vsp = 0;
//How fast to jump and move
jumpspeed = 8;
movespeed = 4;


The next step was to create a short script that first checks if certain keys have been pressed: Escape to exit game, left, right or up to jump. Following this, the code checks to see if left and right are pushed together. If so, the movement cancels out and does nothing. This is checked by left and  right both equaling 1. move will equal 1. If both keys are pushed at the same time move will equal 2 (1 + 1) and the movement cancels out.

Next, the horizontal move speed (hsp) is calculated. This is worked out by first checking to see if left or right has been pressed . hsp is initially set at 0. If left or right has been pressed it sets to 1.

hsp then has a new value applied to it using move (1 due to the playing pushing left or right) * movespeed (4). So, 1 * 4 = 4. hsp is now set to 4.

Next gravity is worked out. grav is already set to 0.2. Every time the player pushes up to jump, 0.2 will be added until it reaches a maximum of 10. After this the player will fall back to the ground. The code for this is worked out via a kind of loop - what the code is saying is:

"As long as the vertical speed is less than 10, take vsp (0.2) and add 0.2 every time up is pushed until it reaches a maximum total of 10. After this a gravity of 10 will cause the player to fall back to the ground."


If the player is already on the ground and jump has not been pressed, vsp = 0. Once up is pushed (so 1 is set) vsp is assigned a new value - 1 * -8.
Code inserted into player object: 

In player object : STEP EVENT
// End game

if keyboard_check(vk_escape){game_end()}
//////////////////////////////////////////////
// checks to see if key has been pushed
// this does not move player
//if pushed key_right = 1
key_right = keyboard_check(vk_right);

//if pushed key_left = 1
key_left =- keyboard_check(vk_left);

//if pushed key_jump = 1
key_jump = keyboard_check_pressed(vk_up);
//move is a temp variable 
// move = 1 for left or 1 for right
//if move =  2 cancels out movement  if left and right are pushed
move = key_left + key_right;

//hsp = if key_right or key_left has been pushed hsp =1
//move already = 1 from left or right  pushed
//1 = 1 * 4  up speed
hsp = move * movespeed;
//if you have pushed up gravity "0.2" will be added until to vsp =10
// then the play will drop
if (vsp <10){vsp += grav;}
//if your player is already on the ground vsp = 0 until up is pushed
if (place_meeting(x,y,obj_blk_4))
{
    // 1 = 1 + - 8 down speed
    vsp = key_jump * - jumpspeed
}

// co-ordinates of player on the screen
x += hsp;
y +=vsp;

The resulting problem of using this script was yes, the player moved, yes the player jumped, but unfortunately there was a 'sticking' issue when the top of the player hit the bottom of blocks. This was unacceptable to me, and looking at the code I felt sure that there must be a more streamlined solution.

The issue is finally solved - 9/12/14

I worked towards and eventually achieved the solution by writing this code and inserting it into the player object:





Comment: // initialise variables



grav = 0.2;   // (gravity)
hsp = 0; // (horizontal speed - set to empty because initially, it is just a container)
vsp = 0; // (vertical speed - set to empty because initially, it is just a container)
jumpspeed = 7; // (the amount of speed that will be added to the object in the up direction when we jump)
movespeed = 4; // (the amount of pixels that we move left and right when we press those keys)


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


Add Event
Step (This means that these events carried out by the object will happen every single frame of the game)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Drag in code box into actions panel


Add comment // get the player's input


Check player movement inputs - this is done by assigning the results of keyboard checks to variables.


Type this into the code box:


key_right = keyboard_check(vk_right);
// if key is pressed, this variable will equal 1, otherwise it will equal 0


key_left = -keyboard_check(vk_left);
// minus before keyboard check - this mens it will equal 0 or -1


key_jump = keyboard_check_pressed(vk_space);
// pressed means the computer checks to see if the button was pressed, but it
// was not pressed the frame before - i.e, literally just pressed jump button.
// Means you can't just hold the jump key down to continually jump



// React to inputs
move = key_left + key_right;
// -1 if left key is pressed, 1 if right key is pressed and 0 if neither is pressed
// If both are pressed it still equals 0



hsp = move * movespeed;
// As move (shown above )equals -1 or 1 and move speed = 4, this should set hsp in this instance to either - 4 or 4

if (vsp < 10) vsp += grav;
// vsp will add 0.2 to itself, up to a maximum of 10. This controls the falling rate
// of the player, otherwise the onscreen sprite would just pick up speed with every frame it falls
// with no limit



if (place_meeting(x,y+1,obj_wall))
// This is asking "Is there an object called wall 1 pixel below the player"?
{
    vsp = key_jump * -jumpspeed;
    // If jump key is pressed, this should set the jumpspeed to -7. If not, 0.
}


// Collision - Ordinarily in GM if you've collided with something, it's already too late
// What you need to do is get into the midst and logic of saying to the computer we are "ABOUT"
// to collide, do something NOW
// For example, our hsp here = 4. If we are three pixels from a wall, we need to ask the computer
// are we about to hit a wall to our right?
// If we are 3 pixels away, we move 1 pixel at a time until we can't move any further without hitting
// the wall and we reduce our speed to 0


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


// Horizontal collision
if (place_meeting(x+hsp,y,obj_wall))
{
    while (!place_meeting(x+sign(hsp),y,obj_wall))
   // sign will return 1 or -1 depending on whether hsp is positive or negative
   // so this would equate to x left or x right (-1 left or 1 right)
   // sign will multiply this by the horizontal speed -1 * 4 or 1 * 4. This gives the current amount of
   // pixels to move left or right for the horizontal speed.
  // So what you are saying is, if the player is not touching obj_wall, keep on moving 1 pixel
  // until it does. At which point reduce speed to 0 and stop. Same principle goes for vsp below.  
    {
        x += sign(hsp);
    }

    hsp = 0;

}
x += hsp;
// add horizontal speed to x co ordinate - move sprite left or right



// Vertical collision
if (place_meeting(x,y+vsp,obj_wall))
{
    while (!place_meeting(x,y+sign(vsp),obj_wall))
    // sign will return 1 or -1 depending on whether hsp is positive or negative
    {
        y += sign(vsp);
    }

    vsp = 0;
}
y += vsp;
// add vertical speed to y co ordinate - move sprite up and down


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
This code works perfectly and solves the problem - pixel perfect gravity. I went on to apply this code to every surface in the game to create a solid, interactive world.

 


More problems to write about in future blogs -
Sprite collision with walls and blocks (show code mistake and explain why)
Sprite resizing
Platforms and destructible. Switching from one state to another - the way I solved the problem.
Platform generator and its problem - sticking and turning a positive into a negative
Choosing the right power ups
Choosing and designing the games enemies

Creating Joe-bot and his reason to be in the game.
Fine tuning.


No comments:

Post a Comment