Need help with programming logic for 2D side view shooter

Started by Sparkplug.Creations, Thu 03/09/2009 21:29:45

Previous topic - Next topic

Sparkplug.Creations

Hello,

I am working on a very small game, one playable character, one enemy and one weapon. I have player movement done and I attempted to figure out how to allow the player to fire their weapon with the spacebar and only half succeeded.

Right now, when players press spacebar, the missile moves from left to right. What I am stuck on, is the logic (and where to place the code) for expanding this so that when players press spacebar, a new missile object is created and behaves independently of other, previously fired missiles.

Here's what I think I need:
1. On key press events must be in the global script (this works already)

2. When spacebar is pressed, create a new missile object (how do I do that?)

3. Run a function controlling the motion of the missile object. How fast it moves and when to loop around to left of screen when it exits on right side. (Where do I write this function? Room script? I have this code working on my room placed missile object.)

4. Collision detection between missile object, enemy character and player character. (What functions are needed and where do I write them?)

Summary
How do I create new missile objects upon key presses and control them independently of others?

Thanks for the help,

-Reid
Reid Kimball - Game Designer
__________________________________
Sparkplug Creations - Play for a Change!
http://sparkplugcreations.org/

Tijne

1. Using the on_key_press function:

2.  Depending on exactly what you want it to be able todo, it so far sounds like you could just make a seperate character for the "Missle".  When it's fired you could change it's room to wherever it's suppose to be fired.

3.  Then, you could manage how it reacts, moves, or 'comes back out from the other side' inside the Repeatedly_Execute function.

4.  To check for collisions, I'm pretty certain there's a cRoger.IsCollidingWith(cMissle) function which you could also put in the Repeatedly_Execute function.


Hope it helped. ^_^

Akatosh

I advise you to look into user-created structs and functions. There is literally no way to create new objects without these two. Characters work only as long as there is a finite, set amount of bullets you want to deal with; otherwise, that sort of breaks down.

Wonkyth

For this reason, it would probably be better to use dynamic sprites instead of characters.
"But with a ninja on your face, you live longer!"

Khris

One way is to use an array struct to keep track of all missiles on screen, then draw them on a blank GUI each game loop. Collision detection is going to have to be coordinate-based in this case.

Code: ags
// header

struct missile {
  int x, y, speed;
  bool on;
};

// main script

missile m[100];


In on_key_press, look for a free slot ( m[j].on == false ) and set start coords and speed (negative for right-to-left movement).
In rep_ex, for each missile that's on, add speed to x, then check if it collided with something or went off-screen.
Then, draw all missiles to a (global) DynamicSprite and set it as GUI background.

Sparkplug.Creations

Thanks for the replies everyone. I'm so not ready to do what I wanted. I have decided to scale back and only allow one missile to be fired but that missile will be permanent, constantly looping on screen and changing elevation randomly until it hits the player's own plane (goal is to avoid it).

-Reid

Reid Kimball - Game Designer
__________________________________
Sparkplug Creations - Play for a Change!
http://sparkplugcreations.org/

Scorpiorus

I'd go with using characters to simulate bullets so not to complicate things too much for a start.

Check some code from that thread for the basics on how to iterate through characters and test each one for collision with a bullet.

And here is an example of code that allows firing several bullets in a row.

at the top of the main global script
Code: ags

#define MAX_BULLETS 3

Character* bullets[ MAX_BULLETS ]; // array storing characters working as bullets

// this function is "automatically" called when some bullet hits some character;
// here we can actually react to hits and do something useful!
function OnHit( Character *bullet, Character *enemy )
{
    enemy.SayBackground( "Ouch!" );
    //enemy.Animate(...);
}

// this function looks if there are free bullets left in the bullets[] array -
// those characters who reserved as bullets but not used at the moment
// and returns one of them so we could use it to fire another bullet!
Character* GetFreeBullet( )
{
    int i=0;
    while ( i < MAX_BULLETS )
    {
        if ( bullets[i].Room == 0 ) return bullets[i]; // free bullet found, return it!
        i++;
    }
    
    return null; // no free bullet available
}

// fires a bullet (typically should be called from the on_key_press() function);
// this function also returns false if no free bullets available at the moment
bool Fire( )
{
    Character* b = GetFreeBullet( ); // try to get a new bullet
    
    if ( b != null ) // if found, bring it here and fire somewhere (eg. bullet.Move)
    {
        b.ChangeRoom( player.Room, player.x, player.y );
        b.Move( b.x+100, b.y, eNoBlock, eAnywhere ); // can be adjusted to fire somewhere else
        return true;
    }
    
    return false; // no free bullets to fire at the moment
}

// this function checks if any of the bullets hits any of the characters
// it only checks how things are going for the current moment,
// so it must be called repeatedly to keep us informed;
// each time it detects a hit this function calls OnHit() where we can handle the process!
function CheckHitting( )
{
    int i=0;
    while ( i < MAX_BULLETS ) // go through each bullet...
    {
        if ( bullets[i].Room != 0 ) // ...but consider only those which are in use ATM
        {
            int j=0;
            while ( j < Game.CharacterCount ) // with each bullet go through each character
            {
                if (   ( character[j].Name != "bullet"        ) // bullet can't hit another bullet
                    && ( character[j] != player               ) // bullet can't hit player
                    && ( bullets[i].Room == character[j].Room ) // bullet must be in the same room
                    && ( AreThingsOverlapping( bullets[i].ID, character[j].ID ) ) // hit check
                   )
                {
                    bullets[i].StopMoving( );
                    OnHit( bullets[i], character[j] ); // notify us about hit by calling OnHit
                }
                
                j++; // goto next character number from the standart character[] array
            }
        }
        
        if ( bullets[i].Moving == false ) bullets[i].ChangeRoom(0); // mark is as free (move to room 0)
        
        i++; // goto next bullet number from our custom bullets[] array
    }
}


within function game_start()
Code: ags

cBullet1.Name = "bullet"; // we mark each bullet this way to recognize them easier!
cBullet2.Name = "bullet"; // another way would be to write a special function which
cBullet3.Name = "bullet"; // looks if a character is actually a bullet by looking into the bullets[] array
    
bullets[0] = cBullet1; // assign bullet-characters (must assign as many as we have in MAX_BULLETS)
bullets[1] = cBullet2; // assign bullet-characters
bullets[2] = cBullet3; // assign bullet-characters


with function repeatedly_execute()
Code: ags

CheckHitting( ); // put it here to check for hitting repeatedly!


with in function on_key_press()
Code: ags

if ( keycode == eKeySpace ) Fire( ); // try firing another one if space key is pressed!


Initially, each of the bullet-characters must be in Room 0 (means they are free and available to fire one). AGS Editor should automatically put all newly created characters in room 0, though.

Just browse the code to try and see how the logic goes. Iterations in two nested while loops in CheckHitting basically do the thing.

See if it can be of some help :)

Wonkyth

Depending on the speed of the bullets, you should only need two or three bullets per thing that can shoot.
"But with a ninja on your face, you live longer!"

suicidal pencil

#8
Quote from: Scorpiorus on Sat 05/09/2009 03:28:20
I'd go with using characters to simulate bullets so not to complicate things too much for a start.

Room objects are much better choices

That said, http://www.adventuregamestudio.co.uk/yabb/index.php?topic=38590.0

This is what I think you are trying to achieve. Feel free to rip my code.

Basically, the logic you are looking for is thus: When the space bar is pressed, create a bullet at the specific player location. Every frame, move the bullet and check for collisions. If the collisions end up true, do function x.

The problems of creating the bullet were solved by making an existing object within the room a bullet, and moving it across the room, checking for collisions. When a collision is detected, it releases the object, so it can be used as a bullet again.

Here's the function that created the bullet, and the function that moves it. On their own, they will not work, because there are references to global variables, and other functions.

Code: ags

function GunFire()
{
  if(player.Loop != 1)
  {
    if(player.Loop != 2)
    {
      if(direction == true)
      {
        //firing RIGHT!!!
        //I made sure that object 39 is not used as an enemy, so it can be used as a bullet. 
        //I also need to make sure that the player is ACTUALLY FIRING HIS GUN
        bulletlock = true;
        if(object[39].Graphic == 0)
        {
          object[39].X = player.x;
          object[39].Y = player.y - 75;
          object[39].Graphic = 130;  
        }
        else return 0;
      }
      else
      {
        //firing LEFT!
        bulletlock = true;
        if(object[39].Graphic == 0)
        {
          object[39].X = player.x - player.BlockingWidth;
          object[39].Y = player.y - 75;
          object[39].Graphic = 130;
        } 
        else return 0;
      }
    }
  }
}

.
.
.

//This will move all of the objects on screen
function ObjectMove()
{
  //this moves and controls all of the enemies
  int enemy_number = 0;
  while(enemy_number < 39)
  {
    if(object[enemy_number].Graphic != 0)
    {
      if(object[enemy_number].X < player.x) object[enemy_number].X++;
      else object[enemy_number].X--;
    }
    enemy_number++;
  }
  //this controls the bullet
  if(object[39].Graphic != 0)
  {
    if(direction == true)
    {
      //The player is facing right
      object[39].X += 100; //move the bullet
      if(object[39].X <= 800)
      {
        int object_check = 0;
        while(object_check <= 38)
        {
          if(object[39].IsCollidingWithObject(object[object_check]))
          {
            DoDamage(object_check);
            return 0;
          }
          else object_check++;
        }
        return 0;
      }
      else 
      {
        object[39].Graphic = 0;
        bulletlock = false;
      }
    }
    else
    {
      //The player is facing left
      object[39].X -= 100; //move the bullet
      if(object[39].X >= 0)
      {
        int object_check = 0;
        while(object_check <= 38)
        {
          if(object[39].IsCollidingWithObject(object[object_check]))
          {
            DoDamage(object_check);
            return 0;
          }
          else object_check++;
        }
        return 0;
      }
      else 
      {
        object[39].Graphic = 0;
        bulletlock = false;
      }
    }
  }
}


Vince Twelve

#9
Quote from: suicidal pencil on Tue 08/09/2009 20:39:05
Quote from: Scorpiorus on Sat 05/09/2009 03:28:20
I'd go with using characters to simulate bullets so not to complicate things too much for a start.

Room objects are much better choices

Only if the gun can only be fired in one room.  Otherwise, you'll have to create the bullet objects in every playable room.  Apart from this being slightly more work, you may want or need that object for something else in the room.  In this case, characters are much better choices.  You can create as many of them as you want (only need to make them once) and they can all be used regardless of what other objects are in use in the room.

Edit: clarification

suicidal pencil

Quote from: Vince Twelve on Tue 08/09/2009 21:17:49

Only if the gun can only be fired in one room.  Otherwise, you'll have to create the bullet objects in every playable room.  Apart from this being slightly more work, you may want or need that object for something else in the room. 

scripted correctly, and with the correct assumptions in game play, you could do the same thing with characters that you could do with Objects. I'm not sure, but you could probably have a set of global functions to deal with all the objects in all the rooms, with the only extra work being setting aside an object for use.

My game that I put up as example demonstrates the point, with room objects 0-38 used for enemies, and 39 for the bullet. I took distinct advantage of the time between bullet fires to move the bullet, making it so that only one object is needed.


Wonkyth

...Unless you wanted slower moving bullets, like if you wanted the player to have to time their shooting of the gun, and to allow dodging and the like.
"But with a ninja on your face, you live longer!"

suicidal pencil

Quote from: wonkyth on Wed 09/09/2009 11:47:00
...Unless you wanted slower moving bullets, like if you wanted the player to have to time their shooting of the gun, and to allow dodging and the like.

How so? I don't see how an object moves any slower than a character, or why you would want to time shooting the gun.

I'm pretty sure that I'm misunderstanding you; could you be clearer?

Khris

Just think of any random boss fight where the boss hurls energy balls at you.
Pretty much every Mega-Man boss fight depends heavily on timing and dodging.

Wonkyth

Yeah, that's what I was thinking.

SP: I was talking about your second paragraph, not the first.
"But with a ninja on your face, you live longer!"

Cpt Ezz

i Haven't tested this but i have thought of a much easyer way of making a bullet........hope this is right.

Code: ags

\\before fadein
cbullet.visable = false
cbullet.x = cego.x \\i know that isn't right but i can't remember the right thing
cbullet.y = cego.y \\ "                  " "                     "

\\repeat ex
if (iskeypressed(ekeyspacebar)){
cbullet.move/walk(cbullet.x, What ever Y cordinate you want,........); \\ use .walk if you have a \\animation for it, otherwise use move
}
if (cbullet.iscollidingwithchar(cEnemy){
cEnemy.say("hey that hurt") \\or what ever
}


so thats how i would do it but again i haven't tested it so be worned it might not work


SMF spam blocked by CleanTalk