Space Rocks Tutorial- Power Up issues

D

dcj64

Guest
Hi everyone,
I have been following the Space Rocks tutorial by FriendlyCosmonaut and have been learning a lot, however I am stuck on the power ups, the tutorial uses an older version of GM and I am having trouble implementing the power up features using scripts and the new method for passing values, I think thats what they are called?

I can get the ship to fire one bullet at a time and destroy enemy and asteroids correctly, I can also get the ship to fire three bullets at a time but only if that is set as the default, however the enemy also fire three bullets at a time.

I have tried changing the values being passed so many time with no success my head is spinning. I think my issue is I have not grasped what the initialise_bullet script is doing, it seems a script is calling another script within itself?

Tried implementing changes which were on the YouTube channel posts but that hasn't worked either, I have searched this forun as well as Reddit but can't find any other mention of this problem, is it just me?


If anyone has any ideas or can point me in the right direction I would be very greatful, many thanks.

obj_ship step event
Code:
if (keyboard_check_pressed(vk_space)){  //create bullets
    create_bullet(image_angle ,bulletSpd, faction, guns);
}
create bullet script
The gun type is correctly being initialised and changes when the ship collects a power up but no change in gun behaviour is happening?
Code:
/// @description create_bullet
function create_bullet( _dir, _spd, _fac, _gun_type){
    
    _gun_type = -1;
    if(argument_count > 3) _gun_type = argument[3];
    
//Choose gun type
switch(_gun_type){
    case powerups.three_bullets:
        var bulletID = instance_create_layer(x,y, "Instances", obj_bullet);
        initialise_bullet(bulletID, _dir, _spd, _fac);
    
    case powerups.two_bullets:
        audio_play_sound(snd_zap, 1, false);
        var _sep = 10;
        
        var bulletID = instance_create_layer(x+lengthdir_x(_sep, _dir+90),y+lengthdir_y(_sep,_dir+90), "Instances", obj_bullet);
        initialise_bullet(bulletID, _dir, _spd, _fac);
        
        var bulletID = instance_create_layer(x+lengthdir_x(_sep,_dir-90),y+lengthdir_y(_sep,_dir-90), "Instances", obj_bullet);
        initialise_bullet(bulletID, _dir, _spd, _fac);
        break;
        
    default:
        audio_play_sound(snd_zap, 1, false);
        var bulletID = instance_create_layer(x,y, "Instances", obj_bullet);
        initialise_bullet( bulletID, _dir, _spd, _fac);
        break;    
    }
}
I think var _creator = id is part of the problem, but not sure what? I think I am not 'defining' who the creator of the bullets is?

initialise_bullet script
Code:
///@description initialize_bullet
function initialise_bullet(bulletID, _dir,_spd,_fac){
    var _creator = id;

    with(bulletID){
        direction    = _dir;
        speed        = _spd;
        faction       = _fac;
        creator       = _creator;
        
        if(faction == factions.ally) image_blend = c_aqua;
        else if(faction == factions.enemy) image_blend = c_red;
        }
}
 
Hi, I'm new to GM too and I'm currently working on Space Rocks as well! If you are still struggling this is what I have done, works for 2 and 3 shots, I just need to code the rest of the powerups. Hope it helps!

obj_ship step event

GML:
if(keyboard_check_pressed(vk_space)){
    create_bullet(image_angle, bulletSpd, faction, guns);
}
create bullet script

Code:
/// @description create bullet
/// @arg direction
/// @arg speed
/// @arg faction
///@arg guntype
function create_bullet(_dir, _spd, _fac, _creator){

var _gun_type = -1;
if(argument_count > 3) _gun_type = argument[3];


//choose gun type /*
switch(_gun_type){
    
    case powerups.three_bullets:
        
        var inst = instance_create_layer(x,y, "Instances", obj_bullet);
        initialise_bullet(inst, _dir, _spd, _fac);
        
    
    case powerups.two_bullets:
    
        audio_play_sound(snd_zap, 1, false);
        var _sep = 12;
        
        var inst = instance_create_layer(x+lengthdir_x(_sep, _dir+90),y+lengthdir_y(_sep, _dir+90), "Instances", obj_bullet);
        initialise_bullet(inst,_dir,_spd,_fac);
        
        var inst = instance_create_layer(x+lengthdir_x(_sep, _dir-90),y+lengthdir_y(_sep, _dir-90), "Instances", obj_bullet);
        initialise_bullet(inst,_dir,_spd,_fac);
        
        
        break;
        
    
    case powerups.four_bullets:
        
        
        
            break;
            
    case powerups.star_bullets:
        
        
        
            break;
    
    default:
        
        audio_play_sound(snd_zap, 1, false);
        var inst = instance_create_layer(x,y, "Instances", obj_bullet);
        initialise_bullet(inst,_dir,_spd,_fac);
    }
        
        
}
initialise_bullet

Code:
function initialise_bullet(inst,_dir,_spd,_fac){
    
var _creator = id;
    
    with(inst){
    direction = _dir;
    speed = _spd;
    faction = _fac;
    creator = _creator;
        
    if(faction == factions.ally) image_blend = c_aqua;
    else if (faction == factions.enemy) image_blend = c_red;
    }
}
 

Rykin

Member
I think there are a number of changes that need to be made to the tutorial to update it for the new version of GMS. One of the issue that needs to be addressed is that you need to pass the id into the create_bullet function now as it no longer runs the script as the object that calls it so when you do the "var _creator = id;" creator will be undefined and your bullets will sometimes impact your own ship and be destroyed. In a similar vein I have no idea why calling the x and y variables of the creating object inside the function is still working, but that is probably a bug that needs to be addressed in GMS and is something that could cause these functions to break in the future. Because of this I have changed the function declaration for both create_bullet and initialise_bullet and this will require them to be updated everywhere they are called.

Here are my functions at the end of the Power-ups (3/3) tutorial.

GML:
function create_bullet(_x, _y, _dir, _spd, _fac, _creator, _gun_type){
    // make _gun_type an optional arguement
    if (_gun_type == undefined) _gun_type = -1;
    
    switch(_gun_type){
        case powerups.three_bullets:
            initialise_bullet(obj_bullet, _x, _y, _dir, _spd, _fac, _creator);
            // no break
        case powerups.two_bullets:
            audio_play_sound(snd_zap, 1, false);
            var _sep = 12;
            initialise_bullet(obj_bullet, _x + lengthdir_x(_sep,_dir + 90), _y+ lengthdir_y(_sep,_dir + 90), _dir, _spd, _fac, _creator);
            initialise_bullet(obj_bullet, _x + lengthdir_x(_sep,_dir - 90), _y+ lengthdir_y(_sep,_dir - 90), _dir, _spd, _fac, _creator);
            break;
        
        case powerups.four_bullets:
            audio_play_sound(snd_zap, 1, false);
            var _sep = 7;
            var _bullet_angle;
            var i = 0;
            
            repeat(4){
                _bullet_angle = _dir + (i * 90);
                initialise_bullet(obj_bullet,
                    _x + lengthdir_x(_sep,_bullet_angle),
                    _y+ lengthdir_y(_sep,_bullet_angle),
                    _bullet_angle, _spd, _fac, _creator
                );
                i++;
            }
            break;
        
        case powerups.star_bullets:
            audio_play_sound(snd_zap, 1, false);
            var _sep = 7;
            var _bullet_angle;
            var i = 0;
            
            repeat(8){
                _bullet_angle = _dir + (i * 45);
                initialise_bullet(obj_bullet,
                    _x + lengthdir_x(_sep,_bullet_angle),
                    _y+ lengthdir_y(_sep,_bullet_angle),
                    _bullet_angle, _spd, _fac, _creator
                );
                i++;
            }
            break;
            
        case powerups.laser_bullets:
            audio_play_sound(snd_laser, 1, false);
            initialise_bullet(obj_laser, _x, _y, _dir, _spd, _fac, _creator);
            break;
        
        default:
            audio_play_sound(snd_zap, 1, false);
            initialise_bullet(obj_bullet, _x, _y, _dir, _spd, _fac, _creator);
            break;
    }       
}

function initialise_bullet(_obj, _x, _y, _dir, _spd, _fac, _creator){
    var inst = instance_create_layer(_x, _y, "Instances", _obj);
    with(inst){
        direction = _dir;
        speed = _spd;
        faction = _fac;
        creator = _creator;
        
        switch(faction){
            case factions.enemy:
                image_blend = c_red;
                break;
                
            case factions.ally:
                image_blend = c_aqua;
                break;
        }
    }
}
As you can see I also moved the instance_create_layer call into the initialise_bullet function which cuts down on having to call that like 20 times and I made the faction code into a switch statement which is better if you are going to implement more factions down the line.

There are only 3 places in the rest of the code that need to be changed now.
In obj_ship -> Step you will call "create_bullet(x, y, image_angle, bulletSpd, faction, id, guns);"
In obj_raider -> Step you will call "create_bullet(x, y, image_angle, 4, faction, id, -1);"
In obj_hunter -> Step you will call "create_bullet(x, y, image_angle, 8, faction, id, -1);"

The -1 at the end of the last two is in theory optional, but the way GML handles optional arguments is not as well developed as other languages I am more familiar with so I recommend not using them to avoid unwanted behavior in the future.
 

vGustaf

Member
Hi, I'm new to GM too and I'm currently working on Space Rocks as well! If you are still struggling this is what I have done, works for 2 and 3 shots, I just need to code the rest of the powerups. Hope it helps!

obj_ship step event

GML:
if(keyboard_check_pressed(vk_space)){
    create_bullet(image_angle, bulletSpd, faction, guns);
}
create bullet script

Code:
/// @description create bullet
/// @arg direction
/// @arg speed
/// @arg faction
///@arg guntype
function create_bullet(_dir, _spd, _fac, _creator){

var _gun_type = -1;
if(argument_count > 3) _gun_type = argument[3];


//choose gun type /*
switch(_gun_type){
   
    case powerups.three_bullets:
       
        var inst = instance_create_layer(x,y, "Instances", obj_bullet);
        initialise_bullet(inst, _dir, _spd, _fac);
       
   
    case powerups.two_bullets:
   
        audio_play_sound(snd_zap, 1, false);
        var _sep = 12;
       
        var inst = instance_create_layer(x+lengthdir_x(_sep, _dir+90),y+lengthdir_y(_sep, _dir+90), "Instances", obj_bullet);
        initialise_bullet(inst,_dir,_spd,_fac);
       
        var inst = instance_create_layer(x+lengthdir_x(_sep, _dir-90),y+lengthdir_y(_sep, _dir-90), "Instances", obj_bullet);
        initialise_bullet(inst,_dir,_spd,_fac);
       
       
        break;
       
   
    case powerups.four_bullets:
       
       
       
            break;
           
    case powerups.star_bullets:
       
       
       
            break;
   
    default:
       
        audio_play_sound(snd_zap, 1, false);
        var inst = instance_create_layer(x,y, "Instances", obj_bullet);
        initialise_bullet(inst,_dir,_spd,_fac);
    }
       
       
}
initialise_bullet

Code:
function initialise_bullet(inst,_dir,_spd,_fac){
   
var _creator = id;
   
    with(inst){
    direction = _dir;
    speed = _spd;
    faction = _fac;
    creator = _creator;
       
    if(faction == factions.ally) image_blend = c_aqua;
    else if (faction == factions.enemy) image_blend = c_red;
    }
}
this won't work anymore and always spawns with three_bullets as the default. any clue how to fix this?
 
I think there are a number of changes that need to be made to the tutorial to update it for the new version of GMS. One of the issue that needs to be addressed is that you need to pass the id into the create_bullet function now as it no longer runs the script as the object that calls it so when you do the "var _creator = id;" creator will be undefined and your bullets will sometimes impact your own ship and be destroyed. In a similar vein I have no idea why calling the x and y variables of the creating object inside the function is still working, but that is probably a bug that needs to be addressed in GMS and is something that could cause these functions to break in the future. Because of this I have changed the function declaration for both create_bullet and initialise_bullet and this will require them to be updated everywhere they are called.

Here are my functions at the end of the Power-ups (3/3) tutorial.

GML:
function create_bullet(_x, _y, _dir, _spd, _fac, _creator, _gun_type){
    // make _gun_type an optional arguement
    if (_gun_type == undefined) _gun_type = -1;
   
    switch(_gun_type){
        case powerups.three_bullets:
            initialise_bullet(obj_bullet, _x, _y, _dir, _spd, _fac, _creator);
            // no break
        case powerups.two_bullets:
            audio_play_sound(snd_zap, 1, false);
            var _sep = 12;
            initialise_bullet(obj_bullet, _x + lengthdir_x(_sep,_dir + 90), _y+ lengthdir_y(_sep,_dir + 90), _dir, _spd, _fac, _creator);
            initialise_bullet(obj_bullet, _x + lengthdir_x(_sep,_dir - 90), _y+ lengthdir_y(_sep,_dir - 90), _dir, _spd, _fac, _creator);
            break;
       
        case powerups.four_bullets:
            audio_play_sound(snd_zap, 1, false);
            var _sep = 7;
            var _bullet_angle;
            var i = 0;
           
            repeat(4){
                _bullet_angle = _dir + (i * 90);
                initialise_bullet(obj_bullet,
                    _x + lengthdir_x(_sep,_bullet_angle),
                    _y+ lengthdir_y(_sep,_bullet_angle),
                    _bullet_angle, _spd, _fac, _creator
                );
                i++;
            }
            break;
       
        case powerups.star_bullets:
            audio_play_sound(snd_zap, 1, false);
            var _sep = 7;
            var _bullet_angle;
            var i = 0;
           
            repeat(8){
                _bullet_angle = _dir + (i * 45);
                initialise_bullet(obj_bullet,
                    _x + lengthdir_x(_sep,_bullet_angle),
                    _y+ lengthdir_y(_sep,_bullet_angle),
                    _bullet_angle, _spd, _fac, _creator
                );
                i++;
            }
            break;
           
        case powerups.laser_bullets:
            audio_play_sound(snd_laser, 1, false);
            initialise_bullet(obj_laser, _x, _y, _dir, _spd, _fac, _creator);
            break;
       
        default:
            audio_play_sound(snd_zap, 1, false);
            initialise_bullet(obj_bullet, _x, _y, _dir, _spd, _fac, _creator);
            break;
    }      
}

function initialise_bullet(_obj, _x, _y, _dir, _spd, _fac, _creator){
    var inst = instance_create_layer(_x, _y, "Instances", _obj);
    with(inst){
        direction = _dir;
        speed = _spd;
        faction = _fac;
        creator = _creator;
       
        switch(faction){
            case factions.enemy:
                image_blend = c_red;
                break;
               
            case factions.ally:
                image_blend = c_aqua;
                break;
        }
    }
}
As you can see I also moved the instance_create_layer call into the initialise_bullet function which cuts down on having to call that like 20 times and I made the faction code into a switch statement which is better if you are going to implement more factions down the line.

There are only 3 places in the rest of the code that need to be changed now.
In obj_ship -> Step you will call "create_bullet(x, y, image_angle, bulletSpd, faction, id, guns);"
In obj_raider -> Step you will call "create_bullet(x, y, image_angle, 4, faction, id, -1);"
In obj_hunter -> Step you will call "create_bullet(x, y, image_angle, 8, faction, id, -1);"

The -1 at the end of the last two is in theory optional, but the way GML handles optional arguments is not as well developed as other languages I am more familiar with so I recommend not using them to avoid unwanted behavior in the future.
Not only did this save me a CRAP ton of cursing because I'm still an uber-noob... but it actually helped me understand a few more things about coding. I like Cosmonaut's videos but sometimes she goes a little fast and writes something and rewrites it a different way but then skips to somewhere else... this helped me connect with how scripts and arguments work a lot better.

Thanks a million and a half! :)
 
Top