ENIGMA Development Environment
Website is in read-only mode due to a recent attack.

Pages: 1
  Print  
Author Topic: How to connect space ship object to bullet object for that ship with instance id  (Read 3603 times)
Offline (Unknown gender) intygamer
Posted on: January 03, 2014, 06:06:46 PM

Member
Joined: Mar 2013
Posts: 77

View Profile Email
I am making a 2 player space game where both players pick from the same roster of space ships and battle each other till one player is left.

I have the following objects.
Code: [Select]
obj_ship_parent  // All ship share this code
obj_ship1     //
obj_ship2     //  Unique code for each ship
obj_ship3     //
ect

obj_bullet_parent // All bullets share this code
obj_bullet1    //
obj_bullet2    // Unique code for each bullet
obj_bullet3    //
ect

obj_player1_start  // Start position for player1.  Used to set position for viewport to follow 2 players, zoom in and out.
obj_player2_start  // Start position for player2.   Used to set position for viewport to follow 2 players, zoom in and out.

obj_player1_explosion // When player is destoyed instance change to explosion
obj_player2_explosion // When player is destoyed instance change to explosion

obj_player_control  // Keyboard controls for both players to select and control ships.
                             // In create event: p1_ship = instance_create(p1_startx,p1_starty,obj_p1_start);
                                                         p2_ship = instance_create(p2_startx,p2_starty,obj_p2_start);
                             
                             // In keypress event players select their ship to battle with from their chosen fleet.
                             // if(instance_number(obj_p1_start) = 1)
                     //      {with (p1_ship) instance_change(obj_ship1,true);} // obj_ship1,obj_ship2,obj_ship3,ect
                             // if(instance_number(obj_p2_start) = 1)
                     //      {with (p2_ship) instance_change(obj_ship1,true);} // obj_ship1,obj_ship2,obj_ship3,ect
                     
p1_ship and p2_ship instances are not destroyed till end_game event.
They change from obj_p1_start or obj_p2_start to the selected ship object to explosion back to obj_p1_start or obj_p2_start
Question:  Need a connection between p1_ship (Player1) or p2_ship (player 2) instance which can access the selected ship objects variables with (.) operator to be able to the same way connect to bullet objects so I can set bullets direction with the image_angle.

Please let me know how I could restructure this so I can do it properly using parent child structure, or give me a link to source of same type of game which I have not found yet.

Thanks
Joe
Logged
Offline (Unknown gender) TheExDeus
Reply #1 Posted on: January 04, 2014, 02:16:22 PM

Developer
Joined: Apr 2008
Posts: 1860

View Profile
Quote
Need a connection between p1_ship (Player1) or p2_ship (player 2) instance which can access the selected ship objects variables with (.) operator
p1_ship and p2_ship already allow you to access its variables, as they are instance ID's. So p1_ship.x = 20 will set player 1 ship to x position 20. For bullets you do:
Code: [Select]
var bullet; bullet = instance_create(p1_ship.x, p1_ship.y, obj_bullet1);
bullet.image_angle = p1_ship.direction;
If you need to change bullet information later you can then add player's ID to the bullet (in the same code as before):
Code: [Select]
bullet.parent_player = p1_ship;And then in obj_bullet1's code (like step event):
Code: [Select]
image_angle = parent_player.direction;This would make the bullet look at the same direction as the player even after it has been shot (and will impact all obj_bullet1's).

I hope that is what you needed.
Logged
Offline (Unknown gender) intygamer
Reply #2 Posted on: January 04, 2014, 03:51:53 PM

Member
Joined: Mar 2013
Posts: 77

View Profile Email
Thanks TheExDeus, this is what I needed.

Code: [Select]
var bullet; bullet = instance_create(p1_ship.x, p1_ship.y, obj_bullet1);
bullet.image_angle = p1_ship.direction;

Some of ships will fire multiple bullets before first one hits a ship or goes outside view to be instance_destroy() freeing that instance id bullet.

Question:  Should I create a new instance id for each bullet?  bullet, bullet1, bullet2, ect.
Logged
Offline (Unknown gender) TheExDeus
Reply #3 Posted on: January 05, 2014, 07:36:41 AM

Developer
Joined: Apr 2008
Posts: 1860

View Profile
You mean new object for every bullet? I usually wouldn't, as I love to have as few objects as possible (often only one or two). But that does defeat the purpose of objects in general, so I guess it is ok and even encouraged to create one object per bullet type. But they should also be as modifiable as possible, so in case you just want to change the sprite and increase damage by 5 you wouldn't have to create new object.

Also, when you do instance_destroy() the instance id isn't freed. GM and ENIGMA just increase max_id whenever an instance is created but it is large enough (2,147,483,647 on a 32bit system) to not be a problem.
Logged
Offline (Male) Goombert
Reply #4 Posted on: January 05, 2014, 07:49:42 PM

Developer
Location: Cappuccino, CA
Joined: Jan 2013
Posts: 2993

View Profile
I think we need a second board here that is about help with actually developing games, I don't like mixing these with help topics about installation and stuff.
Logged
I think it was Leonardo da Vinci who once said something along the lines of "If you build the robots, they will make games." or something to that effect.

Offline (Unknown gender) intygamer
Reply #5 Posted on: February 06, 2014, 11:24:06 PM

Member
Joined: Mar 2013
Posts: 77

View Profile Email
You mean new object for every bullet? I usually wouldn't, as I love to have as few objects as possible (often only one or two). But that does defeat the purpose of objects in general, so I guess it is ok and even encouraged to create one object per bullet type. But they should also be as modifiable as possible, so in case you just want to change the sprite and increase damage by 5 you wouldn't have to create new object.

The following code is my bullet creation code and bullet collision.  Everything works good firing just 1 bullet and wait till hits the ship or is destroyed going off screen.  If I fire multiple bullets before the first hits the ship, the first bullets pass by the ship with no hp taken away and the very last bullet hits and destroys the ship with one bullet. 

Code: [Select]
// obj_switch_ship
// Player2 Spacebar Event:
if (recoil)
{
b1p2 = instance_create(p2_ship.x + lengthdir_x(p2_ship.turlen,
p2_ship.image_angle),p2_ship.y
+ lengthdir_y(p2_ship.turlen, p2_ship.image_angle),p2_ship.bullet);
b1p2.direction = p2_ship.image_angle;
b1p2.image_angle = b1p2.direction;
b1p2.player = p2_ship;
recoil = false;
alarm[0] = p2_ship.recoil_time;
}

// Player 1 Numpad3 Event:
if (recoil)
{
b1p1 = instance_create(p1_ship.x + lengthdir_x(p1_ship.turlen,
p1_ship.image_angle),p1_ship.y
+ lengthdir_y(p1_ship.turlen, p1_ship.image_angle),p1_ship.bullet);
b1p1.direction = p1_ship.image_angle;
b1p1.image_angle = b1p1.direction;
b1p1.player = p1_ship;
recoil = false;
alarm[0] = p1_ship.recoil_time;
}

// obj_bullet_parent
// Normal Step Event:
if(place_meeting(obj_switch_ship.b1p2.x, obj_switch_ship.b1p2.y, obj_switch_ship.p1_ship))
{
with (obj_switch_ship.b1p2) instance_change(obj_small_explosion,true);
obj_small_explosion.speed = 0;
obj_switch_ship.p1_ship.hp = (obj_switch_ship.p1_ship.hp - ap);
if(obj_switch_ship.p1_ship.hp < 0)
{
with (obj_switch_ship.p1_ship) instance_change(obj_p1_explosion,true);
}
}

if(place_meeting(obj_switch_ship.b1p1.x, obj_switch_ship.b1p1.y, obj_switch_ship.p2_ship))
{
with (obj_switch_ship.b1p1) instance_change(obj_small_explosion,true);
obj_small_explosion.speed = 0;
obj_switch_ship.p2_ship.hp = (obj_switch_ship.p2_ship.hp - ap);
if(obj_switch_ship.p2_ship.hp < 0)
{
with (obj_switch_ship.p2_ship) instance_change(obj_p2_explosion,true);
}
}

I think what is happening is the instance id number of the first bullets change as new ones are created leaving the last one with the instance id the code checks.  If I assign a variable to each bullet instance I think I would get pretty complicated.

What would be a good way to remedy this.

Thanks
Joe
 
Logged
Offline (Unknown gender) TheExDeus
Reply #6 Posted on: February 07, 2014, 11:26:44 AM

Developer
Joined: Apr 2008
Posts: 1860

View Profile
You seem to be doing it unnecessarily complicated.

The problem here is that you check specific bullet in the step event. You don't need to do that as the b1p2 and b1p1 is only used to add direction and parent to bullets. Normally b1p2 and b1p1 would be temporary to the script and you can forget about it.

Put this in obj_bullet_parent collision event with obj_switch_ship:
Code: [Select]
if (other.id != p1_ship){ //Check if we hit the enemy and not ourselves
        instance_create(x,y,obj_small_explosion); //Create explosive in our position - you cannot change local variables immediately after instance_change(),
                                                                           // and I don't see why you would even want to use that function.
other.hp -= ap; //Reduce player hp
if(other.hp < 0){ //This should probably be done in obj_switch_ship step event
{
with (other) instance_change(obj_p1_explosion,true);
}
}
        instance_destroy(); //Actually destroy the bullet
}
You shouldn't also have different explosion objects for different players. You shouldn't even have a different explosion objects. Just create one which allows setting the size and such.

I made you simple example on how I would do this: https://dl.dropboxusercontent.com/u/21117924/Enigma_Examples/ShipAndBulletParentingExample/ships_example.gmk
You move one ship with arrow keys and fire with space. You move the other ship with WAD and fire with enter.
« Last Edit: February 07, 2014, 11:55:07 AM by TheExDeus » Logged
Offline (Unknown gender) intygamer
Reply #7 Posted on: February 09, 2014, 04:00:27 PM

Member
Joined: Mar 2013
Posts: 77

View Profile Email
TheExDeus, Thank you very much for writing that gmk file for me!   :)  That was awesome and helped me learn different techniques.  I will use it for a framework for my game.

I am thinking about using your gmk file, making obj_player a parent object and making all the different ships child objects of that parent.  You did not say anything about limiting those to one object.  I will keep one bullet and one explosion object.

Thanks
Joe


« Last Edit: February 09, 2014, 06:07:54 PM by intygamer » Logged
Offline (Unknown gender) TheExDeus
Reply #8 Posted on: February 09, 2014, 06:00:01 PM

Developer
Joined: Apr 2008
Posts: 1860

View Profile
Quote
That was awesome and helped me learn different techniques.
No problem.

Quote
making obj_player a parent object and making all the different ships child objects of that parent.
I personally don't use parenting at all and I would probably just use the 1 object, but I guess if you plan to have many ships (and ships which have many different abilities), then it makes sense to make them individual objects.

Quote
I will keep one bullet and one explosion object.
Reason I suggest that is because they usually don't change that much. Like an explosion object can have different size (scale), color or sprite. No reason to create several objects just for that. Just create a script somewhat like this:
Code: [Select]
//scr_create_explosion(x,y,size,color,sprite)
var inst;
inst = instance_create(argument0,argument1,obj_explosion);
inst.size = argument2;
inst.image_blend = argument3;
inst.sprite_index = argument4;
Then just call the script. You can make the explosion object as complicated or simple as you want, but they usually still have the most things common. The same with many other objects - bullets (which usually change in appearance, speed, damage and other common attributes) or even ships. In many games ships change in appearance, their reload time for guns, the type of bullets they shoot and so on, so I just create bunch of variables that change all that.
I once made a tower defense game (https://www.dropbox.com/s/ie1ki5l1bb6efv4/TD_08.png) and in it all turrets and all enemies were 1 object. And they even had many different abilities - like there was a turret that could freeze and slow the enemy and the way enemy died was even based on those effects (like frozen enemies shattered). And I would basically do it the same way now. Another one I made with very few objects was this (https://www.dropbox.com/s/q0pqp3odqaubqnd/F%26I_03.png), so I'm not a big fan of large amount of objects.
« Last Edit: February 09, 2014, 06:02:12 PM by TheExDeus » Logged
Offline (Unknown gender) intygamer
Reply #9 Posted on: February 09, 2014, 06:14:52 PM

Member
Joined: Mar 2013
Posts: 77

View Profile Email
TheExDeus

I did not get this edit into my post before you responded to the one I was editing.  No hurry to respond, you gave me alot to work with.  Thanks for all the info you gave me in your last responce.

The reason I used instance_change() for p1_ship and p2_ship is because I am using views to follow and center the 2 ships.  The instances would change from p1_start for a starting position for view to the ship the player chooses to battle with to explosion after the ship has been destroyed back to p1_start to wait for player to select the next ship.  This way it will keep everything in view.

Please let me know if you have a suggestion to eliminate instance_change for p1_ship and p2_ship instances.

Here is the view code I am using.
Code: [Select]
view_dual script:
---------------------------------------
/// view_dual(object1, object2, padding)
var o1, o2, x1, x2, y1, y2, vw, vh, vb, vscale;
o1 = argument0; x1 = o1.x; y1 = o1.y
o2 = argument1; x2 = o2.x; y2 = o2.y
vb = argument2; vw = view_wport; vh = view_hport;
vscale = max(1, abs(x2 - x1) / (vw - vb * 2), abs(y2 - y1) / (vh - vb * 2))
view_wview = vscale * vw
view_hview = vscale * vh
view_xview = (x1 + x2 - view_wview) / 2
view_yview = (y1 + y2 - view_hview) / 2
---------------------------------------

obj_switch_ship Normal Step Event:
---------------------------------------
view_dual(p1_ship,p2_ship, 100);

Thanks for all your help!

Thanks
Joe
Logged
Offline (Unknown gender) TheExDeus
Reply #10 Posted on: February 10, 2014, 11:49:50 AM

Developer
Joined: Apr 2008
Posts: 1860

View Profile
I think using instance_change just for that is an overkill. What I would do is change the script to just take two sets of coordinates instead of objects. Like so:
Code: [Select]
view_dual script:
---------------------------------------
/// view_dual(x1,y1,x2,y2,padding)
var x1, x2, y1, y2, vw, vh, vb, vscale;
x1 = argument0; y1 = argument1;
x2 = argument2; y2 = argument3;
vb = argument4; vw = view_wport; vh = view_hport;
vscale = max(1, abs(x2 - x1) / (vw - vb * 2), abs(y2 - y1) / (vh - vb * 2));
view_wview = vscale * vw;
view_hview = vscale * vh;
view_xview = (x1 + x2 - view_wview) / 2;
view_yview = (y1 + y2 - view_hview) / 2;-
And use a controller object (I usually have at least one obj_controller in every project, it does most things) and make it have 4 variables that are updated. Like in step event:
Code: [Select]
if (instance_exists(p1_ship)){ x1 = p1_ship.x, y1 = p1_ship.y; } else { x1 = x2, y1 = y2; }
if (instance_exists(p1_ship)){ x2 = p2_ship.x, y2 = p2_ship.y; }  else { x2 = x1, y2 = y1; }
view_dual(x1,y1,x2,y2,100);
In the create event just init x1,y1,x2 and y2 with some default values. What this will do is show both ships in the view if both exist or just follow one if the other has died. If you still want the other to be followed (for example until explosion is done) then create alarms and use them in the "else" instead. What you can also do is just constantly show the place where the ship exploded (if you remove the "else" statements entirely).
Logged
Offline (Unknown gender) intygamer
Reply #11 Posted on: February 15, 2014, 10:55:31 PM

Member
Joined: Mar 2013
Posts: 77

View Profile Email
TheExDeus, thanks for helping with the view_duel script.  It works good. :)  Your Tower Defense Game looks sweet! (Y)  I decided to make the ships 1 object too.

I made you simple example on how I would do this: https://dl.dropboxusercontent.com/u/21117924/Enigma_Examples/ShipAndBulletParentingExample/ships_example.gmk
You move one ship with arrow keys and fire with space. You move the other ship with WAD and fire with enter.

Using your ships_example.gmk, I am trying to allow players to choose the ship they want and choose again after there ship has been destroyed to fight whats left of the existing enemy ship. In obj_controller I moved the code from the create event to separate key events 1 for each player.  To prevent the players from creating more than one ship, I used if(!instance_exists(player1_id) which don't seem to work right.  The player to press the key first will create there ship and the other will not.

Is there a better way to do this?
Code: [Select]
//keypress 3 event:
if(!instance_exists(player1_id))
{
player1_id = instance_create(200,200,obj_player);
player1_id.player = 1; //Set player number, used only for controls
player1_id.image_blend = c_green; //Set color
}

-----------------------------------------------------------------
//keypad9 event:
if(!instance_exists(player2_id))
{
player2_id = instance_create(400,400,obj_player);
player2_id.player = 2; //Set player number, used only for controls
player2_id.image_blend = c_red; //Set color
}

Thanks for all your help!
Joe
Logged
Pages: 1
  Print