0
\$\begingroup\$

I'm going to be making a shooter-style game, on a navigatable map (All 2D). I'm a little unsure of how to handle the bullets: I see two main ways i could do it

I could have the bullet's x and y position be updated based on its trajectory, and then draw it using the formula

Screen.x - Bullet.x , Screen.y - bullet.y

This would draw the bullet relative to the players location, so that it would appear on the map

The other main method I am considering is drawing the bullet directly to the map image via the getGraphics() method. However, this seems like it could cause performance issues, as just testing this seemed to lag

(this was my test method)

public void Draw(Graphics g){
    image.getGraphics().drawRect(10,10,10,10);
    g.drawImage(image,0,0,null);
}

Adding in the drawRect line caused considerable lag - removing it made the game run fine

Are either of these a good way to handle drawing projectiles? If not, how else could I do it efficiently?

\$\endgroup\$
1
\$\begingroup\$

It would appear your rendering logic is completely flawed. Take a look at this question and it's answers, you appear to be doing some of the same errors I previously did.

Canvas - good rendering practices?

About Projectiles

Drawing one rectangle will literally never have any noticeable impact on your frames so there is obviously a flaw elsewhere, hopefully the above link will help you address that. Here's a basic run down on how you could implement your project system:

  1. First off, make yourself a class that can be the base class for all objects in your game... Let's call it... GameObject !

  2. GameObject is an abstract class and will have 2 methods that will be overwritten by classes which extend it.

  3. Next, create an object for your bullet, we can call it Bullet, this class wil extend GameObject.

  4. Now going back to yourGameObject class, add 2 abstract methods:

    public abstract void update();

    public abstract void render(Graphics2D g);

  5. Your GameObject class should also have 2 fields for holding the it's x and y positions respectively.

  6. Implement your abstract methods in your Bullet class and add your drawRect code. It should look something like this:

    public void render(Graphics2D g){
        g.drawRect(x, y, 5, 5);
    }
    
  7. Now you need a class to keep track of everything that exists in your game world. I usually name it Level or World. This will contain a List of all your GameObjects. Now in your main game loop simply go through all of the GameObjects stored in your world and update them, then run through again and render them all.

Rendering with camera offsets

When rendering a game world that's larger than the players window (Be it a monitor, JFrame, Canvas) you will want to be able to add an offset to the world being rendered, this can be achieved with an imaginary "camera".

I say imaginary because the camera doesn't quite work as you'd expect. Instead of the camera looking at a certain part of the world, the world instead translates itself to be within the frame of our camera! So let's say we have a Screen class with variables xScroll and yScroll.

Every time something is rendered we must subtract these two variables from the rendered location. This can be achieved in two ways:

Method 1: Encapsulate your Graphics2D Object With your Screen

This is my preferred method, it requires a bit of extra work on your part but makes the entire rendering system far far simpler. So as of now our abstract class GameObject has a render(Graphics2D g) method. We're going to change this to render(Screen screen), this new Screen class will keep a reference to a Graphics2D object and will have some methods that are the same as the underlying Graphics2D object with one addition, they will subtract the Screen's xScroll and yScroll. Example:

public void drawRect(int x, int y, int width, int height){
    g.drawRect(x-xScroll, y-yScroll, width, height);
}

After this you need only implement appropriate methods into your Screen class for whatever methods you want to encapsulate out of Graphics2D. Finally, update the two scroll variables in your main game loop to easily center the camera on your player.

Method 2: Simply subtract it in your render method

So this method is simpler but also doesn't respect Reuse or Encapsulation design patterns. But is great for just a simple game like yours.

Just simply add static variables xScroll and yScroll to your Screen class and subtract these in your Bullet's (and any other GameObjects you decide to add) render method. Example:

public void render(Graphics2D g){
    g.drawRect(x-Screen.xScroll, y-Screen.yScroll, 5, 5);
}

I hope this addresses all your problems :)

\$\endgroup\$
  • \$\begingroup\$ Thank you very much for the help! I'm going to implement these when I get a chance. The only other problem I had been having (I didnt include it in the post as I wasn't sure it was relevent) is when i tried drawing the bullets at bulletx-Screenx,bullety-screeny the bullets did draw on the screen, but because the screen follows the player, the player could essentially "control" the bullets, by moving around. If the bullet was going straight up, the player moving to the left or the right would also move the bullet, which is not what I had intended \$\endgroup\$ – Acuzik May 23 '16 at 13:24
  • \$\begingroup\$ I'll add to my answer to include a bit on using "cameras" \$\endgroup\$ – Shaun Wild May 23 '16 at 15:03
  • \$\begingroup\$ I've used this advice to rewrite my code from scratch last night - Already its much faster, and seems to much more efficient - thank you for the help! :) \$\endgroup\$ – Acuzik May 24 '16 at 12:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.