Jump to content


Photo

2D Platformer- Gun Swapping Glitch


  • Please log in to reply
5 replies to this topic

#1 MatFang

MatFang

    GMC Member

  • New Member
  • 132 posts

Posted 10 October 2011 - 03:02 AM

I've been working on my 2Dimensional platformer and I have encountered a small problem. I've been creating multiple guns and options to swap the guns in the middle of a level/ field.

I've been tinkering with the code I have, and I've simplified most of it to see if it would make things easier. Though unfortunately, all the tinkering and testing isn't fixing my problem.

I want the player to be able to swap guns as much as they want (even if it's the same two guns over and over). Whenever I swap the character's gun about 3-4 times, the ability to swap just disappears. I can't swap the guns any more, but I can still pick them up. This is becoming a slight hazard because I plan to have many guns in the future and losing the ability to swap will frustrate players.

Below I've posted some of the code that I've been using within a script and the collision events of the three guns I already have. Maybe someone here will be able to fix the problem.

scr_toss()
if weapon_1 = "Pistol_A" then
{object = instance_create(other.x,other.y,obj_pistol)
weapon_1 = "None"}

if weapon_1 = "Submachine_A" then
{object = instance_create(other.x,other.y,obj_submachine)
weapon_1 = "None"}

if weapon_1 = "Shotgun_A" then
{object = instance_create(other.x,other.y,obj_shotgun)
weapon_1 = "None"}

obj_pistol
if keyboard_check_pressed(ord('X')) then 
{
switch (weapon_1)
{
    case "None": with(other)instance_destroy()
               weapon_1="Pistol_A"; break;
    case "Shotgun_A": scr_toss() 
               with(other)instance_destroy()
               weapon_1="Pistol_A"; break;
    case "Submachine_A": scr_toss()
               with(other)instance_destroy()
               weapon_1="Pistol_A"; break;
    default: exit;
}
}

obj_shotgun
if keyboard_check_pressed(ord('X')) then 
{
switch (weapon_1)
{
    case "None": with(other)instance_destroy()
               weapon_1="Shotgun_A"; break;
    case "Pistol_A": scr_toss()
               with(other)instance_destroy()
               weapon_1="Shotgun_A"; break;
    case "Submachine_A": scr_toss()
               with(other)instance_destroy()
               weapon_1="Shotgun_A"; break;
    default: exit;
}
}

obj_submachine
if keyboard_check_pressed(ord('X')) then 
{
switch (weapon_1)
{
    case "None": with(other)instance_destroy()
               weapon_1="Submachine_A"; break;
    case "Pistol_A": scr_toss() 
               with(other)instance_destroy()
               weapon_1="Submachine_A"; break;
    case "Shotgun_A": scr_toss()
               with(other)instance_destroy()
               weapon_1="Submachine_A"; break;
    default: exit;
}
}

  • 0

#2 kburkhart84

kburkhart84

    GMC Member

  • GMC Member
  • 1618 posts
  • Version:GM:Studio

Posted 10 October 2011 - 01:11 PM

First, I need to know what scr_toss() script is supposed to do.

Second, I notice that the first gun has 3 guns in the code, like you are allowed to switch, but the other two guns simply repeat the same gun in the code. Maybe that has something to do with your problem.

Third, I would recommend(to maybe make things easier in the long run, especially if you are adding more guns) that you put everything in one object. I don't mean this completely, but in general. For example, I would have one player object, that is responsible for grabbing input. It also tracks what weapon is currently in use. Then, you would have a couple ways to do it.

One, if the weapons are all fire and forget, as in none require "charging" the key or anything like that, you can simply create the correct bullet depending on the weapon that is in the variable.

Two, if weapons respond to input differently, for example, some weapons you charge, others rapid-fire by holding the key, others only fire once per keypress...that kind of thing, you would need different response to the input accordingly. I would have one script per weapon that would be responsible for that. Then, in the step event of the "player" object, you would put a switch statement, simply calling whatever script is responsible for the weapon that is currently selected.

If you do things like this in the same object, it allows you to keep things organized. For example, it is now easier to add weapons, because all you have to do it add a pair of lines to the switch statement, and add a script that checks the input.

...

Now, I don't know how your game works as far as choosing weapons, if you keep all of them as you pick them up, etc... but if you do the above ideas for weapon control, the rest should be made easier too.
  • 0

#3 MatFang

MatFang

    GMC Member

  • New Member
  • 132 posts

Posted 10 October 2011 - 02:57 PM

First, I need to know what scr_toss() script is supposed to do.

scr_toss() basically just makes the player toss the gun onto the field when switching guns.
When the player is already holding a gun for 'weapon_1' and chooses to swap the gun, this script will make a copy of the gun on the field so if the player decides to pick it up again then he/ she can.

Second, I notice that the first gun has 3 guns in the code, like you are allowed to switch, but the other two guns simply repeat the same gun in the code. Maybe that has something to do with your problem.

Actually, the reason the guns look like they're repeating is because it is placed in the collision event of 'obj_character'. When the player presses a key (X), then the code for the appropriate gun is called. The switch statement checks which gun the player is holding and acts depending on what is placed in the code.
For Example (obj_pistol):
if keyboard_check_pressed(ord('X')) then  
{switch (weapon_1) 
{ 
    case "None": with(other)instance_destroy() 
               weapon_1="Pistol_A"; break; 
    case "Shotgun_A": scr_toss()  
               with(other)instance_destroy() 
               weapon_1="Pistol_A"; break; 
    case "Submachine_A": scr_toss() 
               with(other)instance_destroy() 
               weapon_1="Pistol_A"; break; 
    default: exit; }}
In this code, it is checking first whether or not the player has pressed the key (X). This key is what causes the swapping.
Second, it checks whether the player is holding gun "None", or the player isn't holding one. If this is true, then the game makes the variable weapon_1 equal to the variable I used for holding a pistol, or "Pistol_A".
If the player is holding a gun, then it will skip case "None", and go to "Shotgun_A". The game checks if the variable weapon_1 is equal to "Shotgun_A", or if the player is holding a shotgun. If this is true, then the game executes the script scr_toss(), which makes a copy of the gun on the field. Then the game destroys the obj_pistol in the field. After, it makes weapon_1 equal "Shotgun_A", or makes the player hold a shotgun.
If the player isn't holding a shotgun, it skips straight to "Submachine_A" and repeats the above process.
The way this code is depends on what gun appears in the collision event. This code is slightly different when the player collides with obj_shotgun or obj_submachine, or basically your swapping between the different variables of "Pistol_A", "Shotgun_A", and "Submachine_A"

Third, I would recommend(to maybe make things easier in the long run, especially if you are adding more guns) that you put everything in one object. I don't mean this completely, but in general. For example, I would have one player object, that is responsible for grabbing input. It also tracks what weapon is currently in use. Then, you would have a couple ways to do it.

Everything I'm doing that revolves around weapons is within one object or in a few scripts. The object everything is in is obj_character.
obj_character has three different variables that detect how much ammunition the player has for a pistol, shotgun, and submachine gun (more to be made in the future). The object also detects what weapon is being held, seeing as how this is how I draw the sprites on the character.

Two, if weapons respond to input differently, for example, some weapons you charge, others rapid-fire by holding the key, others only fire once per keypress...that kind of thing, you would need different response to the input accordingly. I would have one script per weapon that would be responsible for that. Then, in the step event of the "player" object, you would put a switch statement, simply calling whatever script is responsible for the weapon that is currently selected.

I have this set in the step event of object obj_character. There are a couple of lines, which are:
if keyboard_check_pressed(vk_space) then
{scr_gun_shoot_unauto()}
if keyboard_check(vk_space) then
{scr_gun_shoot_auto()}
scr_gun_shoot_unauto() is for guns that are not rapidfire such as pistols and shotguns.
scr_gun_shoot_auto() is for guns that do have rapidfire such as submachine guns and assault rifles.

I hope this doesn't confuse anyone.

Edited by MatFang, 10 October 2011 - 03:00 PM.

  • 0

#4 MatFang

MatFang

    GMC Member

  • New Member
  • 132 posts

Posted 24 November 2011 - 02:01 AM

Bump post...
It seems that I'm not getting a lot of help... I'll try posting more/ clearer information.

Problem:
The problem I'm trying to solve in [Darkened], or my platformer, involves the swapping of weapons that I have currently in-game. There are three guns I called "Pistol_A", "Shotgun_A", and "Submachine_A". Whenever I collide with one of these three objects (Collisions handled through obj_character), and I press the 'X' key, the collision event will check if I have a gun or if I don't have a gun. After it does this, then it will execute the appropriate lines of code to swap the guns so the Player can use a different gun, and come back and swap if he/ she wishes. Now, whenever I collide with the guns, and swap them three to four (3-4) times, the game just bugs and I can't swap them again. This will eventually become frustrated to the players who will need this handy option to pass the game.

More In-Depth Details:
If I don't have a gun, then the collision event sets variable 'weapon_1' to the gun that the collision is performing for, and if there is a gun, more code comes into play.

First, the code will check if I'm holding one of the other two guns using a switch statement, and the code changes depending on which gun I am holding.

For Example:
If I currently hold "Pistol_A", the game will use a switch statement like this:
switch('weapon_1')
{
case "None": //Code here
case "Shotgun_A": //Code here
case "Submachine_A": //Code here
default: //Code Here
}

*This switch statement changes for each collision event*

case "None":
As explained above, if I am not holding any weapon, variable 'weapon_1' is set to the weapon I'm colliding with.

case "Shotgun_A":
If I am holding a shotgun, hince "Shotgun_A", then the game will execute scr_toss(), which causes obj_character to toss the weapon he/ she is currently holding (Ammunition Not Impacted).
Then the game sets variable 'weapon_1' to "Shotgun_A", and the Player can continue onward.

case "Submachine_A":
If I am holding a submachine gun, hince "Submachine_A", then the game will execute scr_toss(), which causes obj_character to toss the weapon he/ she is currently holding (Ammunition Not Impacted).
Then the game sets variable 'weapon_1' to "Submachine_A", and the Player can continue onward.

default:
The game exits the collision event code.
  • 0

#5 torigara

torigara

    GMC Member

  • GMC Member
  • 6483 posts

Posted 25 November 2011 - 06:40 AM

The problem is that you create an instance at the same position as the original one in scr_toss(). It sometimes executes a collision event immediately.

Suppose that you have a pistol. You walk on top of a submachinegun and press X. Now it executes the collision event with obj_submachine:
- it calls scr_toss that creates obj_pistol at the position where the submachinegun was.
- then destroy the submachinegun.

Note that now you're on top of obj_pistol. The next thing to happen is the collision event with obj_pistol - because it is there.
- since the X key is pressed in the same step, it calls scr_toss to drop a submachinegun.
- then destroy the pistol.

You end up in having the submachinegun that you had at the beginning. Whether this happens or not depends on the order GM executes collision events, so it sometimes works and sometimes not.

A quick way to fix it is to create the instance at the position that doesn't touch the player. E.g.:
instance_create(x + sprite_width, y, obj_pistol);
Other way is to clear the keyboard state so that it isn't executed again in the same step.
if (keyboard_check_pressed(ord('X')))
{
    keyboard_clear(ord('X'));
    // do the rest

By the way, each case of your switch statement does essentially the same thing. They can be simplified as follows:
// for obj_pistol
if (weapon_1 != "Pistol_A")
{
    if (weapon_1 != "None") scr_toss();
    with (other) instance_destroy();
    weapon_1 = "Pistol_A";
}

  • 1

#6 MatFang

MatFang

    GMC Member

  • New Member
  • 132 posts

Posted 26 November 2011 - 08:04 PM

The problem is that you create an instance at the same position as the original one in scr_toss(). It sometimes executes a collision event immediately.

Suppose that you have a pistol. You walk on top of a submachinegun and press X. Now it executes the collision event with obj_submachine:
- it calls scr_toss that creates obj_pistol at the position where the submachinegun was.
- then destroy the submachinegun.

Note that now you're on top of obj_pistol. The next thing to happen is the collision event with obj_pistol - because it is there.
- since the X key is pressed in the same step, it calls scr_toss to drop a submachinegun.
- then destroy the pistol.

You end up in having the submachinegun that you had at the beginning. Whether this happens or not depends on the order GM executes collision events, so it sometimes works and sometimes not.

A quick way to fix it is to create the instance at the position that doesn't touch the player. E.g.:

instance_create(x + sprite_width, y, obj_pistol);
Other way is to clear the keyboard state so that it isn't executed again in the same step.
if (keyboard_check_pressed(ord('X')))
{
    keyboard_clear(ord('X'));
    // do the rest


The keyboard_clear(ord('X')) works perfectly! Thank you so much, this helps me alot, not only in this project, but in my future ones as well!
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users