Hello,
Shooting bullets based on the player rotation was causing a little problem to me, and am sure that it will cause problems for other new developers here, so i decided to share a full example on how to shoot bullets based on the player rotation.
1st, like every Java 2D game we create our main class
there is nothing fancy here to explain
//this is the game window
package rot;
import javax.swing.JFrame;
public class RotateME extends JFrame {
public static final int WIDTH = 800, HEIGHT = 600;
public RotateME() {
add(new Board());
setTitle("rotate me please");
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(true);
setVisible(true);
}
public static void main(String[] args) {
new RotateME();
}
}
now we create the bullet class
package rot;
public class Bullet {
private double x, y, a; // x,y and angle
private int w, h; //width and height
// constructor
public Bullet(double x, double y, double a, int w, int h) {
this.x = x;
this.y = y;
this.a = a;
this.w = w;
this.h = h;
}
// returning all the necessary value of this class
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getA() {
return a;
}
public int getW() {
return w;
}
public int getH() {
return h;
}
// setting the values
public void setA(double aa) {
this.a = aa;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public void setW(int w) {
this.w = w;
}
public void setH(int h) {
this.h = h;
}
// move toward the angle
// //forward
public void moveForward(int speed) {
x += Math.cos(a)*speed;
y += Math.sin(a)*speed;
}
}
and the player class, i almost commented everything, i hope it’s clear for you
//this is the hero class
package rot;
import java.awt.Image;
import java.awt.Rectangle;
import java.util.ArrayList;
import javax.swing.ImageIcon;
public class Hero {
private double x, y, a; // x,y and angle
private int w, h, tmpLoad; // width and height and reloading counter (for
// shooting)
private ArrayList bullets; // this will hold our bullets
private String img = "res/hero.png"; // this is the path of the image
private Image image; //and this is the image
// constructor
public Hero(double x, double y, double a, int w, int h) {
this.x = x;
this.y = y;
this.a = a;
this.w = w;
this.h = h;
bullets = new ArrayList();
tmpLoad = 0;
ImageIcon ii = new ImageIcon(img);
image = ii.getImage();
}
// returning all the necessary value of this class
public Image getI() {
return image;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getA() {
return a;
}
public int getW() {
return w;
}
public int getH() {
return h;
}
public Rectangle getBounds() {
return new Rectangle((int) x, (int) y, w, h);
}
public ArrayList getBullets() {
return bullets;
}
// setting the values
public void setA(int aa) {
a = Math.toRadians(aa);
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
// move toward the angle
// //forward
public void moveForward(int sx, int sy) {
x += Math.cos(a) * sx;
y += Math.sin(a) * sy;
}
// //backward
public void moveBackword(int sx, int sy) {
x -= Math.cos(a) * sx;
y -= Math.sin(a) * sy;
}
/*
* firing load = how much time you wait between 2 bullets number = how many
* bullet you shot in a single shot spread = distance between 2 bullets
*/
public void fire(int load, int number, int spread) {
// if reloading time is done
if (tmpLoad == 0) {
for (int i = 0; i < number; i++) {
// setting the bullet
Board.bullet.setX(x + w);
Board.bullet.setY(y + h / 2);
Board.bullet.setA(a + ((spread * (i - 1)) / 2));
Board.bullet.setW(5);
Board.bullet.setH(5);
// adding the bullet to the array list
bullets.add(new Bullet(Board.bullet.getX(),
Board.bullet.getY(), Board.bullet.getA(), Board.bullet
.getW(), Board.bullet.getH()));
}
//reset the reload time
tmpLoad = load;
} else {
tmpLoad -= 1;
}
}
}
and this is the game board :
package rot;
//importing what we need
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import javax.swing.JPanel;
public class Board extends JPanel implements Runnable {
public static Bullet bullet;
private Thread loop; // the loop
private Hero hero;
private ArrayList bullets;
private int tmpAngle, sx, sy, reload, numToShoot, spread, bWidth,
bHeight;
private boolean moveForward, canForward, canBackward, moveBackward, left,
right, fire, special;
// constructor
public Board() {
init();
addKeyListener(new Controll());
addMouseListener(new Mouse());
setFocusable(true);
setBackground(new Color(0, 0, 0));
setDoubleBuffered(true);
setFocusable(true);
}
// initialisation
private void init() {
hero = new Hero(400, 300, 0, 50, 30);
tmpAngle = 0;
special = fire = left = right = moveForward = moveBackward = false;
canForward = canBackward = true;
sx = sy = 2;
bullet = new Bullet(0, 0, 0, 0, 0);
bullets = hero.getBullets();
reload = 30;
numToShoot = 1;
spread = 0;
loop = new Thread(this);
loop.start();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
AffineTransform old = g2d.getTransform();
// rotating the hero, rotation point is the middle of the square
g2d.rotate(hero.getA(), hero.getX() + hero.getW(),
hero.getY() + hero.getH() / 2);
// draw the image
g2d.drawImage(hero.getI(), (int) hero.getX(), (int) hero.getY(),
hero.getW(), hero.getH(), this);
g2d.setTransform(old);
// drawing the bullets
ArrayList bullets = hero.getBullets();
for (int i = 0; i < bullets.size(); i++) {
Bullet tmpB = (Bullet) bullets.get(i);
//playing with bullet colors
if (i % 2 == 0) {
g2d.setColor(new Color(150, 130, 100));
} else {
g2d.setColor(new Color(60, 20, 120));
}
g2d.fillRect((int) tmpB.getX(), (int) tmpB.getY(), tmpB.getW(),
tmpB.getH());
}
// in case you have other things to rotate
g2d.setTransform(old);
}
public void play() {
// if the hero get off the screen
// we make it appear from the opposite side of the screen
if (hero.getX() > 800) {
hero.setX(0);
} else if (hero.getX() < -100) {
hero.setX(800);
}
if (hero.getY() > 600) {
hero.setY(0);
} else if (hero.getY() < -100) {
hero.setY(600);
}
// moving bullets
ArrayList tmpBs = hero.getBullets();
for (int i = 0; i < tmpBs.size(); i++) {
Bullet tmpB = (Bullet) tmpBs.get(i);
tmpB.moveForward(3);
if (tmpB.getX() > RotateME.WIDTH || tmpB.getX() < 0
|| tmpB.getY() > RotateME.HEIGHT || tmpB.getY() < 0) {
tmpBs.remove(i);
}
}
// check if shooting
if (fire) {
hero.fire(reload, numToShoot, spread);
}
if (special) {
hero.fire(5, 3, 2);
}
// changing the hero angle
if (left) {
tmpAngle -= 1;
}
if (right) {
tmpAngle += 1;
}
// setting the hero angle
hero.setA(tmpAngle);
// this is just to keep the angle between 0 and 360
if (tmpAngle > 360) {
tmpAngle = 0;
} else if (tmpAngle < 0) {
tmpAngle = 360;
}
// moving the hero
if (moveForward) {
if (canForward) {
hero.moveForward(sx, sy);
}
}
if (moveBackward) {
if (canBackward) {
hero.moveBackword(sx, sy);
}
}
}
// game key controll
// (my keyboard is AZERTY so ignore the multiple key in
// the if statement
private class Controll extends KeyAdapter {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == e.VK_UP || e.getKeyCode() == e.VK_Z
|| e.getKeyCode() == e.VK_W) {
moveForward = true;
}
if (e.getKeyCode() == e.VK_DOWN || e.getKeyCode() == e.VK_S) {
moveBackward = true;
}
if (e.getKeyCode() == e.VK_LEFT || e.getKeyCode() == e.VK_Q
|| e.getKeyCode() == e.VK_A) {
left = true;
}
if (e.getKeyCode() == e.VK_RIGHT || e.getKeyCode() == e.VK_D) {
right = true;
}
if (e.getKeyCode() == e.VK_SHIFT) {
fire = true;
}
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == e.VK_UP || e.getKeyCode() == e.VK_Z
|| e.getKeyCode() == e.VK_W) {
moveForward = false;
}
if (e.getKeyCode() == e.VK_DOWN || e.getKeyCode() == e.VK_S) {
moveBackward = false;
}
if (e.getKeyCode() == e.VK_LEFT || e.getKeyCode() == e.VK_Q
|| e.getKeyCode() == e.VK_A) {
left = false;
}
if (e.getKeyCode() == e.VK_RIGHT || e.getKeyCode() == e.VK_D) {
right = false;
}
if (e.getKeyCode() == e.VK_SHIFT) {
fire = false;
}
}
}
// mouse control
private class Mouse extends MouseAdapter {
public void mousePressed(MouseEvent e) {
if (e.getButton() == e.BUTTON1) {
fire = true;
}
if (e.getButton() == e.BUTTON3) {
special = true;
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton() == e.BUTTON1) {
fire = false;
}
if (e.getButton() == e.BUTTON3) {
special = false;
}
}
}
// the wors game loop ever
@Override
public void run() {
while (true) {
repaint();
play();
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
now before you are finish, you may want to use my hero :
http://s4.postimg.org/kyixw0lo9/hero.png
in case you faced a problem during this line of code
private String img = "res/hero.png"; // this is the path of the image
make sure that you created a folder named “res” in your workspace project, then in eclipse
-right click to your main folder project --> refresh
-the new folder would appear, right click on it —> Build Path --> use as resource folder
and this is how the final result should look like (this is the special shot 8) )
http://s23.postimg.org/wg5csab6z/Sans_titre.png
i hope i was helpful :
thank you for reading