New to this need some help

Started by
13 comments, last by N=1 11 years, 7 months ago
Hi,

I am pretty new to game development. I used to mess with RPG Maker when I was a kid and used the RMXP and VX to write some code and have made a batle system in that so I have some experience I guess. Anyways, I am learning to program games in Java using Slick2D. I have made a Pong clone and am now on to a more adventerous project. It is a side-scrolling space shooter. I have a good start so far I have a player ship that I can move, I have enemies that I can spawn. Collision is working. But I have a few questions.

1) I have a level class that contains all the Arrays that hold my objects. One of the Arrays holds the bullets. Currently I have two different types of weapons the player can use. You start with a machine gun and can upgrade to a plasma missile (Ooooh!). Anywys I am usure of a good way of adding the weapons to the array in a clean manner. Right now each of my weapon types has a create method that will create a weapon of its type at the position of the owner and move in the direction the owner is facing. It seems bad to me to have a object have a create method that crates a copy of itslef.

Here is how it works basically (This is from the update method of my level object):



if (player.getState() == GameEntity.State.shooting){

try{
bullets.add(player.createBullet());
}catch(Exception e){
System.out.println("Cant make a bullet");
}

}


and in my player object:


public BaseWeapon createBullet() throws SlickException{
Vector2f position = this.getPosition();
int direction = getDirection();

if (direction == 1){
return weapon.create(direction,(int)( position.x + bulletOffset.x), (int)(position.y + bulletOffset.y));
}else{
return weapon.create(direction, (int)(position.x), (int)(position.y + bulletOffset.y));
}
}


and finally in my weapon class (this is the machine gun):


public BaseWeapon create(int direction, int x, int y)
throws SlickException {
// TODO Auto-generated method stub
return new MachineGun(direction,x,y);
}


It seems like a bad way of doing it, but I am not sure how to have it determine what wepaon the player has and then create an object of that type and add it to the array other than making a method that returns the type and going through an if statement for each type. That would be a headache.

2.) Hopefully this one will be easier... In my player method I have the left mouse control shooting. All it does is set the state to shooting and the level object checks to see if a object is in the shooting state and then it creates a bullet from the code above. Sometimes if I double click or click quickly it gets stuck in the shooting state and it will fire an endless stream of bullets until I click again can you see why?


if (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON) && getState() != GameEntity.State.overheated){

if(getFire() == 0){
System.out.println("Fire!");
setFire(getFireRate());
increaseHeat(getWeaponHeatRate());
setState(GameEntity.State.shooting);
}else{
setState(GameEntity.State.idle);
System.out.println("no fire");
setFire(getFire() - 1);
}
}


If you need/want to see more code I'll glady upload the source.

Thanks for any input

Nick
Advertisement

1) I have a level class that contains all the Arrays that hold my objects. One of the Arrays holds the bullets. Currently I have two different types of weapons the player can use. You start with a machine gun and can upgrade to a plasma missile (Ooooh!). Anywys I am usure of a good way of adding the weapons to the array in a clean manner. Right now each of my weapon types has a create method that will create a weapon of its type at the position of the owner and move in the direction the owner is facing. It seems bad to me to have a object have a create method that crates a copy of itslef.


This doesn't really make sense. You have an array which holds the bullets. Then you go on to talk about how you're trying to figure out "a good way of adding weapons to the array". What array? Is there an array for weapons as well?

If so, can't you just take the weapon the player has (referring to it by its BaseWeapon type) and add it to the array? There seems to be no reason to copy the weapon.
Poor explination on my part.

I use weapons and bullets interchangably. I have an array that contains the bullets in my level object, used for updating/deleting/whatever. Weapon is simply a variable on my Player Object that holds the type of bullet to fire.

I tired to do what you said but I am still unsure of exactly how to implement it...

I created a fire function but its not working as expected. Ill show you some of the relevant code:

This is from my GameEntity class which is the parent class of the Player/Enemies. I set the direction to the players dirction and the position of it to the players position plus and offset so i looks like its coming out of the right spot.


public BaseWeapon fire(){
Vector2f position = getPosition();

weapon.setDirection(getDirection());
weapon.setLife(0);

if (getDirection() == 1){
weapon.setPosition(position.x + bulletOffset.x, position.y + bulletOffset.y);
}else{
weapon.setPosition(position.x, position.y + bulletOffset.y);
}

return weapon;
}


In my level I made a simple change (changed form the create to fire);


if (player.getState() == GameEntity.State.shooting){

try{
bullets.add(player.fire());
System.out.println("Bullets:" + bullets.size());
}catch(Exception e){
System.out.println("Cant make a bullet");
}

}


It works for a hot minute but then it stops adding bullets. I'm guessing it beacuse its pass by reference in Java, but I havnt figured out a work around.

Thanks
Nick
1) Intuitively, I think I would divide it into following classes:


class Player
{
Weapon weapon;
// ...
}
interface Weapon
{
Bullet shoot(...);
// ...
}

abstract class Bullet
{
Vector2f position;
int direction;
// ...
}

class MachineGun implements Weapon { /*...*/ }
class MachineGunBullet extends Bullet { /*...*/ }

class RocketLauncher implements Weapon { /*...*/ }
class RocketLauncherBullet extends Bullet { /*...*/ }


2) Ideally, your:

setState(GameEntity.State.idle);

Should be triggered by a "mouse up" event to avoid any confusion / synchronisation problems.
The following seems also to make more sense to me:

if (input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON) && getState() != GameEntity.State.overheated){

if(getFire() == 0){
System.out.println("Fire!");
setFire(getFireRate());
increaseHeat(getWeaponHeatRate());
setState(GameEntity.State.shooting);
}
}else{
setState(GameEntity.State.idle);
System.out.println("no fire");
setFire(getFire() - 1);
}

Hero-

thanks that makes some sense to me I just never am really sure when to use interfaces or just use interitance, I read about it but if I think about it too much it starts to give me a headache. I know it is a "Can-do this" v.s. "Is-a" situation. A question remains however...


class Player
{
Weapon weapon;
// ...
}


Is weapon referring to the interface here or an actual weapon object such as "MachineGun" or "RocketLauncher"?

Also the "mouse-up" event is huge thank you for that!
I think be-the-hero.net's proposal makes sense. For bonus points, you could consider having the Weapon itself keep track of its heat and the fire (delay) counter.
Verik-

Yes I am liking the thoughts expressed in the post, not 100% sure how to implement it yet but that's the fun part right? ;P (I think I have an idea)

The only thing about the heat is that it effects everything about the ship. In my game I want it to be the left mouse button shoots and the right mouse activates a shield to defend against damage. You cant shoot and use the shield at the same time but they both add the the heat value of the ship. If it hits the ceiling the ship overheads and you cant fire/use shields and you move and 1/4 your speed. Ideally when I get things up and running killing enemies will get you "credits" which you can use to upgrade you ship for better weapons/shields/heat/speed but that is WAAAAYYYY down the road

But thanks again to everyone for the comments/help!
Ok very cool, I have it working like be-the-hero.net suggested. I learned some cool things about interfaces and how to use them. I didnt make it so the weapon keeps track of its fireRate yet but that is on the to do list.

Another question I have is where should I handle player movement... in the object itself? in the Level class? I have a camera class that handles scrolling but I am only using it for moving objects on-screen and determining if I should draw them or not. The way I have things set up right now the player doesnt really move left or right the camera translates everything and keeps the player in the middle of the screen, however the player will need to move vertically... suggestions? does it matter?
Good to hear you are learning things, that's what it is all about!

Ideally I'd create a separate (new) class that handles input, possibly the same class that also controls the frame rate and signals the camera to paint the scene (if I got it right), so a sort of main game controller or game loop class.

Now if you detect that a mouse button is pressed, you can call the appropriate method in the player object to tell it that the (user) wants to fire a bullet or activate the shield. The player object itself can then decide if it is overheated or not. (So the game state actually becomes a player state, which seems more in line with what it is.)

The same goes for movement. Have the game loop call the player object to tell it that the user wants to move it up or down. Let the player object decide how fast this move will take place (if at all). Does this make sense to you?
Tip 1: always prefer interfaces to inheritance
An interface defines what functionalities an object should provide
Inheritance is a "is a" relationship, and a way of reusing code among similar objects.

As for the rest, in what classes you should put what method, the best is to follow your intuition where it fits the best.
There is no golden rule for that, it is too case specific. In the process of doing it, you'll certainly acquire a better feeling of what to place where.
Tip 2: Refactoring and improving the code as you go is always a good idea. The time it costs now will be saved several times in the future.

This topic is closed to new replies.

Advertisement