I'm trying to create a bullet hell type game similar to Touhou in Java.
I need some help getting started, like an example to follow. I tried my hand in it making it from scratch using JFrame, but my main problem is lag when creating bullets.
I have a bullet class, with parameters to make it go from A to B. But whenever the program creates or removes bullet objects (which are stored in an ArrayList) it freezes for a tiny fraction of a second, but this becomes very pronounced when there are many bullets.
Am I doing it wrong to use an ArrayList here? What guides are recommended to learn how to do this properly?
Here is my Bullet class:
import java.awt.Graphics;
public class Bullet
{
double x,y, xend, yend;
int width, height;
int life = 200;
private static final double speed = 8;
double dirX, dirY;
public Bullet(double x, double y, double xend, double yend, int width, int height)
{
this.x=x;
this.y=y;
this.xend = xend;
this.yend = yend;
this.width = width;
this.height = height;
dirX = speed*Math.cos(getAngle());
dirY = speed*Math.sin(getAngle());
}
public double getAngle()
{
double angle = (double) Math.toDegrees(Math.atan2(yend-y, xend - x));
if(angle < 0){
angle += 360;
}
System.out.println(angle);
return Math.toRadians(angle);
}
public void tick()
{
life--;
x+=dirX;
y+=dirY;
}
public void draw (Graphics g)
{
g.fillRect((int) Math.round(this.x),(int) Math.round(this.y),this.width,this.height);
}
}
And this is the code that is run when the user creates a bullet. It uses the mouseListener for the xend yend coordinates - finding the bullet's destination.
public void fireNormal(double xend, double yend)
{
Bullet bullet= new Bullet (x,y,xend,yend,5,5);
firedBullets.add(bullet);
}
}
I'm using a timer to refresh the game but it still isn't at a consistent speed because of the freezes.
ArrayList.add() should usually be extremely fast. Occasionally, when the implementation has to add new capacity, it will allocate a new backing array, copy the data from one to the other, before continuing. You can avoid this by specifying a suitable initial capacity in the ArrayList(int initialCapacity) constructor.
However you would need tens of thousands of entries for this to take long enough to add noticeable game lag.
ArrayList.remove(int index) has to shift all the entries above the removed item, down the backing array by one slot. However, this is highly optimised at the CPU level, and again should not add noticeable game lag unless you have tens of thousands of bullets.
ArrayList.remove(Object o) has to examine every element in turn, and run equals() on each one, until it finds the target element. Avoid this!
It's possible that the pauses you are seeing are due to garbage collection, and this could be because you're creating thousands of short-lived Bullet objects. These last from the moment they're fired until they go off screen. When they go out of scope, they remain in memory until the GC has to clear up thousands of them.
You could avoid this by maintaining an object pool of Bullets. There are libraries with object pool implementations, or you can roll your own using Collections.
In environments with tight memory constraints (like 8 bit games consoles) it's necessary to ensure a game runs within fixed memory, and this is similar to the kinds of things programs on those platforms would do.
However you should prove what your issue is, before trying to fix it, and for that you need to use a profiler such as VisualVM. This will show you where your execution is spending its time, and how it is using memory. Garbage collection in modern Java is very high-performing in most circumstances, though - don't assume it's the problem.
Related
Bit of back story on my project (because your probably going to say, "Just use OpenGL.")
a.k.a. The Reason I Hate OpenGL
So, my computer is around 7 years old, with OpenGL 3.30 on my hardware (Using an ATI Radeon HD 4300/4500), and I really wanted to make my own 3D game engine using OpenGL. Long story very short, shaders are broken for me (detail at bottom). So, I said screw it I'm going to make my own 3D renderer. I got the rendering done, but I need help on rotations.
The More Boring Story of why this happened
Well, the truth is I started making my own engine because my laptop was too old to follow the tutorial, so I started work on a 2D engine with a cool parallax system, then it hit me. The reason why I said the story about my computer being to old is because that is really when I started thinking about rotation on a whole different level.
The Code
This is where the problems started:
x = (float) ((x * Math.cos(Math.toRadians(main.cameraRot)) - z * Math.sin(Math.toRadians(main.cameraRot))));
z = (float) (z * Math.sin(Math.toRadians(main.cameraRot)) - x * Math.cos(Math.toRadians(main.cameraRot)));
I think I see the problem, I think I need to add zsin(cameraRot) to xcos(cameraRot)
I've even drawn out how Sine and Cosine functions work, mainly because I was also working on a water effect at the time, and I thought, "I should be able to use sin (and only sin) to rotate." I was wrong (obviously). I have also used a graphing calculator (TI-83+ from 1999, not 2011) to graph those functions (they were a bit different, and yes I used the graphing mode where you could input both X and Y values). I'm trying out some stuff right now, and I think I see the main problem. The Z rotation uses the X rotation, but the X rotation uses the Z coordinate (If that was complicated, I'll break it down: We need to use the original X value to calculate the rotation for the Z value, but we instead use the X value after it's changed to a rotated X, which would make a huge difference).
It doesn't work at all. cameraRot (rotation) is constantly increasing, but there is no effect.
Here's the code for rendering:
g.drawRect((int) (x / (z - main.camZ) - 256 / (z - main.camZ) / 2),(int) (0 - 256 / (z - main.camZ) / 2),(int) (256 / (z - main.camZ)),(int) (256 / (z - main.camZ)));
But it screws up rendering. Yes, I know that I'm drawing a square, but the previous one I made (on a laptop) was more complete, but used the same rendering algorithm and broke when I tried adding in rotations, every object appeared to be at 0,0,1.
Any suggestions on how to fix this?
Is it from the rendering or the equation? (I'm going to save you the trouble and tell you its the rotation equation.
Just a little side note, I accidentally made that rendering algorithm.
How the Shaders were Broken
I tried using uniforms with VertexShaders but they only work with Fragment Shaders. The tutorial I followed used "#version 330" (like me) but they had OpenGL version 4.3 (and they were using java) and I had version 3.30 (and used java).
okay so I was just dumb.
x = (float) ((x * Math.cos(Math.toRadians(main.cameraRot)) - z * Math.sin(Math.toRadians(main.cameraRot))));
z = (float) (z * Math.sin(Math.toRadians(main.cameraRot)) - x * Math.cos(Math.toRadians(main.cameraRot)));
The reason why I was dumb is because what you would do is (simplified, using doubles):
double tempX = x;
x = tempX * Math.cos(theta) - z * Math.sin(theta);
z = tempX * Math.sin(theta) + z * Math.cos(theta);
Two years later, and I've written this equation so many times now that it is literally going to haunt me forever. Even after I die.
Now to look at something I said:
I think I see the problem, I think I need to add zsin(cameraRot) to xcos(cameraRot)
Not even close. The whole issue I was had the order of z and x wrong for the z equation, as well as I didn't store the x in a temporary variable before doing the operations. If you don't do that, it doesn't rotate correctly on the z axis.
I might as well add in some notes to this obscure question that's actually quite easy to figure out. If you have 200 objects, each calling Math.sin() and Math.cos() twice each, that's highly inefficient. The very least you could do is store the resultant Math.sin() and Math.cos() values in their own variable, but that's just scratching the surface.
Instead of making it so each object calculates the sine and cosine individually, you make a Camera class that holds all the positional and rotational data for the camera, as well as the screen dimensions. This is so that a rectangle sized 1.0 x 1.0 is proportional to a screen. In non-square aspect ratios (e.g. 16:9, 4:3), you can see some stretching going on. The easy way to fix this is to pass the screen's width or height for both screenWidth and screenHeight. The harder way let's you use any FoV, but that's another day.
public class Camera {
// Position variables, X is horizontal, Y is vertical, Z is fordical (forward and backward)
private double x, y, z;
private double rot;
private double cos;
private double sin;
// Variables pertaining to the screen
private int screenWidth;
private int screenHeight;
public Camera(double x, double y, double z, double rot, int screenWidth, int screenHeight) {
setScreenDimensions(screenWidth, screenHeight);
setPosition(x, y, z);
setRotation(rot);
}
public void setScreenDimensions(int screenWidth, int screenHeight) {
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
}
public int getScreenWidth() {...}
public int getScreenHeight() {...}
public void setPosition(double x, double y, double z) {...}
public void setRotation(double rot) {
// Update the rotation variable
this.rot = rot;
// Update the trig values
cos = Math.cos(rot);
sin = Math.sin(rot);
}
// Position Getters
public double getX() {...}
public double getY() {...}
public double getZ() {...}
// Position Setters
public void setX(double x) {...}
public void setY(double y) {...}
public void setZ(double z) {...}
public double getRotation() { return rot; }
public double getCos() { return cos; }
public double getSin() { return sin; }
}
and then when you transform from world-space (3D) to screen-space (2D), you would do (using Java Swing because that's what I was using at the time of asking this question):
// somewhere in a class, probably the base GameObject class. If it's in an util class, make it "public static", and if it's in the Camera class, it would be "public".
protected Point transform(Camera camera, double x, double y, double z) {
double transX = x - camera.getX();
double transY = y - camera.getY();
double transZ = z - camera.getZ();
double rotX = transX * camera.getCos() - transZ * camera.getSin();
double rotZ = transX * camera.getSin() + transZ * camera.getCos();
int pointX = (transX * camera.getScreenWidth() ) / transZ;
int pointY = (y * camera.getScreenHeight()) / transZ;
return new Point(pointX, pointY);
}
Bam now we've optimized the rendering routine. At least, as far as a sane person would go. If you're really religious about optimization (like I sometimes am), you can probably do some crazy stuff. The real crazy stuff happens when you get to C++ and use pointers, but that's beyond the scope of this Java question. Hell, even going into the optimization part is sort of beyond the scope of the question, but it's my question and I think I reserve the right to answer it as I see fit, as long as it benefits anybody reading my answer.
note: I wrote this late at night so I apologize for any errors, will fix in the morning!
side-note: it's not like anybody's gonna read this anyways :)
Apologies if the title is not appropriate, was having trouble what to call this.
Scenario:
I have a universe type project in java where there are different types of things you can find in a universe (stars, planets, comets etc).
This is part of my university coursework and I'm stuck on one part
I have a class called Space_Object which is a superclass and all things found in the universe inherit it. The superclass has variables such as xPosition, yPosition.
I am currently stuck on trying to get planets to orbit around stars. I am trying to get the x,y coordinates of a star so that the planet can orbit around it (there can be multiple planets and stars). Right now I am passing the star that the planet will orbit around as a field whenever making a new planet.
I created getters inside of Planet to retrieve the x,y of the Star (which works). I am stuck on how can I use that x and y to alter the starting point of the planet. This is what I added to Universe class:
public void setCoordsOfPlanet(Planet planetObj)
{
planetObj.xPosition = planetObj.getSolarSystemX();
}
Which gave me an error of:
xPosition has private access in Space_Object
I am not allowed to make any of the fields public.
Planet class:
public class Planet extends Space_Object
{
private int distanceFromStar;
private int orbitSpeed;
static Star solarSystem;
public Planet(int disFromStar, int orbSpeed, Star solSystem, int objectDiameter, Color objectColor, Universe theUniverse)
{
super(0, 0, 0, 0, objectDiameter, objectColor, theUniverse);
distanceFromStar = disFromStar;
orbitSpeed = orbSpeed;
solarSystem = solSystem;
}
public int getSolarSystemX ()
{
return solarSystem.getXPosition();
}
public int getSolarSystemY ()
{
return solarSystem.getYPosition();
}
}
Just in case, the Space_Object constructor:
public Space_Object(int xPos, int yPos, int xVel, int yVel, int objectDiameter, Color objectColor, Universe theUniverse)
{
xPosition = xPos;
yPosition = yPos;
xSpeed = xVel;
ySpeed = yVel;
color = objectColor;
diameter = objectDiameter;
universe = theUniverse;
universeHeight = universe.getUniverseHeight();
universeWidth = universe.getUniverseWidth();
lifeTime = 1000000;
}
Am I approaching this from the completely wrong angle? I been trying to change things regarding this matter for past three hours and made no progress - any help is appreciated. If you need more code let me know.
PS: All items in the universe are objects and are represented as colour circles on a canvas.
If you are asking how do I modify private fields from another class: then all you need to do is to add setter methods in your Space_Object or Planet class, for example:
public class Planet {
...
public setCoor(int x, int y) {
this.xPosition = x;
this.yPosition = y;
}
}
Now you can call this method from the Star class: planet.setCoor(x, y)
If you want this method to only be accessible from classes of the same package only, remove public.
There are multiple issues here.
Programming stuff
Model of planetary rotation
Use of 'Solar System' when it should be 'Star System' :-) The Solar System is our star system; that's because our star is "Sol"
A1. You need xposition to have a method to set it.
A2a. There are no x and y for our solar system or even a star system. If you're going to model spinning galaxies and/or expanding universe (in which case the galaxies also move in 3d space away from each other,) then the star positions (or positions of any object for that matter) are not fixed.
A2b. If you're going with immobile stars and galaxies, a star (not its system) will have an x and a y.
A2c. A planet revolves around its star in a Kepler orbit with eccentricity greater than 0 and less than 1. To calculate the path, you need axis information for the orbit in addition to the star's location. Wikipedia will have the equations.
A2d. There is no starting position of a planet unless you plan to have planets with unstable orbits. (Or comets which will have their orbits modified during every revolution by the planets they pass by). Planets with stable orbits have always followed and will forever follow the same path (not really, but...) You can place the planet at any point on the orbit and give it appropriate initial velocity (=speed+direction) and watch it go. A3. Self-explanatory
Sounds like a fun project, especially you're animating the model onscreen. In such a case, you also need to decide on your system's clock-speed; the numbers of days that will pass in real time for each second of your simulation time. Additionally, you'll need to select your refresh frequency; how often will you update the screen.
I'm learning a lot more about Java 8 and its functional capabilities, and I wanted to do some more practice with it. Say, for example, I have the following imperative code which is for wrapping a circle around the bounds of the screen:
if (circle.getPosition().getX() > width + circle.getRadius()){
circle.getPosition().setX(-circle.getRadius());
}else if (circle.getPosition().getX() < -circle.getRadius()){
circle.getPosition().setX(width + circle.getRadius());
}
if (circle.getPosition().getY() > height + circle.getRadius()){
circle.getPosition().setY(-circle.getRadius());
}else if (circle.getPosition().getY() < -circle.getRadius()){
circle.getPosition().setY(height + circle.getRadius());
}
How could I go about trying to "Functionalize" it? Maybe some pseudo-code? It seems to me that mutability and state seem inherent in this example.
Is functional programming not a good fit for game development? I love the both, so I'm trying to combine them.
There is nothing inherent about the requirement for mutability in this example. The imperative approach is to modify an existing circles by applying side-effects which alter the state of an existing circle.
The functional approach is to have an immutable data structure and create a function that takes data from the first structure and creates a new structure. In your example, a functional approach would have the circle being immutable, i.e. no setX() or setY() methods.
private Circle wrapCircleAroundBounds(Circle circle, double width, double height) {
double newx = (circle.getPosition().getX() > width + circle.getRadius()) ? -circle.getRadius() : width + circle.getRadius()
double newy = (circle.getPosition().getY() > height + circle.getRadius()) ? -circle.getRadius() : height + circle.getRadius()
return new Circle(newx, newy)
}
Using Java8's functional features, you could then imagine mapping a list of circles to wrapped circles:
circles.stream().map(circ -> wrapCircleAroundBounds(circ, width, height))
The imperative and functional approaches have different advantages, the functional approach, for example, is intrisicaly threadsafe because of the immutability so you should be able to more readily parallelise this kind of code. For instance, one could equally safely write:
circles.parallelStream().map(circ -> wrapCircleAroundBounds(circ, width, height))
I don't think that functional programming is necessarily badly suited to game development but, although it has be done, it's certainly not a standard approach so you won't get the same level of library support if you're using a functional language.
As dfeuer states in his answer, Java's functional features are pretty primitive - you don't have support for algebraic data types, pattern matching, etc which will make it much easier to express problems in a functional style (at least once you get used to those idioms). I agree that at least reading a bit about Haskell, which has an excellent tutorial: http://learnyouahaskell.com/chapters would be a good way to get started. Unlike Scala, which is very much a multiparadigm language, you won't have OOP features to fall back on while you're learning the new style.
For your first point: You "functionalize" your example by thinking about what the code ought to achieve. And this is, you have a circle, and want to compute another circle based on some conditions. But for some reason your imperative upbringing makes you assume that the input circle and the output circle should be stored in the same memory locations!
For being functional, the first thing is to forget memory locations and embrace values. Think of every type the same way you think of int or java.lang.Integer or the other numeric types.
For an example, assume some newbie shows you some code like this:
double x = 3.765;
sin(x);
System.out.println("The square root of x is " + x);
and complains that sin doesn't seem to work. What would you think then?
Now consider this:
Circle myCircle = ....;
wrapAroundBoundsOfScreen(myCircle);
System.out.println("The wrapped-around circle is now " + myCircle);
You will have climbed the first step to functional programming when the latter code seems as absurd to you as the former. And yes, this does mean not to use certain features of the imperative language you are using, or use them extremely sparingly.
Here not much 'functionalization' applicable. But at least we can fight with mutability.
First of all pure functions. This will help to separate logic. Make it clear and easy to test.
Answer the question: what is your code do? It accepts some params and returns two params new x and y.
Next samples will be written with pseudo scala.
So you need a function that will be invoked two times for both x and y calculation.
def (xOrY: Int, widthOrHeight: Int, radius: Int): Int = {
if (x > widthOrHeight + radius) -1*radius else widthOrHeight + radius
// do your calculation here - return x or y values.
}
P.S> so far no matter where you want to apply functional style: as you need to do some business logic it's good to go with functional approach.
But do not try overcomplicate it as it does not help.
So what I would not do for this sample is next (pseudo scala goes next):
def tryToMakeMove(conditions: => Boolean, move: => Unit) = if (conditions) move()
/// DO NOT DO IT AT HOME :)
tryToMakeMove(circle.getPosition().getX() > width + circle.getRadius(), circle.getPosition().setX(-circle.getRadius())).andThen()
tryToMakeMove(circle.getPosition().getX() < -circle.getRadius()), circle.getPosition().setX(width + circle.getRadius()))
).andThen ... so on.
That how functional programs can looks like. I've created the higher-order function (that accepts other functions as an arguments and invoke it inside).
With this functions, i've invoked one be one operations you have to do...
But such functional style does not really help. At all. You should apply it properly only in a places where it's simplify the code.
You can write functional code in just about any programming language, but you can't easily learn functional programming in any language. Java in particular makes functional programming sufficiently painful that people who wanted to do functional programming in the JVM came up with Clojure and Scalaz. If you want to learn the functional way of thinking (what problems it deals with naturally and how, what problems are more awkward and how it manages them, etc.), I strongly recommend that you spend some time with a functional or mostly-functional language. Based on a combination of language quality, ease of sticking to functional idioms, learning resources, and community, my top pick would be Haskell and my next would be Racket. Others will of course have other opinions.
How could I go about trying to "Functionalize" it? Maybe some
pseudo-code? It seems to me that mutability and state seem inherent in
this example.
You could try to limit the mutability to a few functions, and also use final variables inside the functions (which forces you to use expressions rather than statements). Here's one possible way:
Position wrapCircle(Circle circle, int width, int height) {
final int radius = circle.getRadius();
final Position pos = circle.getPosition();
final int oldX = pos.getX();
final int x = (oldX > width + radius) ? -radius : (
(oldX < -radius) ? (width + radius) : oldX);
final int y = // similar
return new Position(x, y);
}
circle.setPosition(wrapCircle(circle, width, height));
Aside, I would make wrapCircle a method of the Circle class, to get:
circle.wrapCircle(width, height);
Or I could go one step further and define a getWrappedCircle method, that returns me a new circle instance:
Circle getWrappedCircle(width, height) {
newCircle = this.clone();
newCircle.wrapCircle(width, height);
return newCircle();
}
.. depending on how you intend to structure the rest of the code.
Tip: Use final keyword as often as you can in Java. It automatically lends to a more functional style.
Is functional programming not a good fit for game development? I love the both, so I'm trying to combine them.
Pure functional programming is slower, because it requires lots of copying / cloning of data. If performance is important, then you could definitely try a mixed approach, as shown above.
I would suggest using as much immutability as possible, followed by benchmarking, and then converting to mutability in only the performance critical sections.
Functional programming fits game development (why would not it?). The question is usually more about performance and memory consumption or even if any functional game engine can beat an existing non-functional one in those metrics. You are not the only person who loves functional programming and game development. Seems like John Carmack does too, watch his keynotes about the topics at Quakecon 2013 starting from 02:05. His notes here and here even give insight on how a functional game engine can be structured.
Setting theoretical foundation aside, there are usually two concepts perceived inherent in functional programming by a newcomer and from a practical prospect. They are data immutability and state absence. The former means that data never changes and the latter means every task is performed as if for the first time with no prior knowledge.
Considering that, you imperative code has two problems: the setters mutate the circle position and the code relies on outside values (a global state) of width and height. To fix them make your function return a new circle on each update and take the screen resolutions as arguments. Let's apply the first clue from the video and pass a reference to the static snapshot of the world and a reference to an entity being "updated" (it is simply this here) to an update function:
class Circle extends ImmutableEntity {
private int radius;
public Circle(State state, Position position, int radius) {
super(state, position);
this.radius = radius;
}
public int getRadius() {
return radius;
}
#Override
public ImmutableEntity update(World world) {
int updatedX = getPosition().getX();
if (getPosition().getX() > world.getWidth() + radius){
updatedX = -radius;
} else if (getPosition().getX() < -radius){
updatedX = world.getWidth() + radius;
}
int updatedY = getPosition().getX();
if (getPosition().getY() > world.getHeight() + radius){
updatedY = -radius;
} else if (getPosition().getY() < -radius) {
updatedY = world.getHeight() + radius;
}
return new Circle(getState(), new Position(updatedX, updatedY), radius);
}
}
class Position {
private int x;
private int y;
//here can be other quantities like speed, velocity etc.
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
class State { /*...*/ }
abstract class ImmutableEntity {
private State state;
private Position position;
public ImmutableEntity(State state, Position position) {
this.state = state;
this.position = position;
}
public State getState() {
return state;
}
public Position getPosition() {
return position;
}
public abstract ImmutableEntity update(World world);
}
class World {
private int width;
private int height;
public World(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
Now the tricky part is how to affect the state of the world and other entities. You can follow the second clue from the video and use event passing mechanism to pass such changes to and fro so the rest of the game knows about all the effects.
Obviously, you can keep only events and rely completely on them even when changing your circle positions. So, if you introduce sort of an id to your entities you will be able to pass MoveEntity(id, newPosition).
OK, it's time for us all to get over how new and shiny Java 8's functional features look. "Functionalizing" something is really not a valid goal to have.
However, the original code here has a good ol' object-oriented problem:
When you say circle.getPosition().setX(...), you are messing with the internal state of the circle (its position) without involving the object itself. That breaks encapsulation. If the circle class were properly designed, then the getPosition() method would return a copy of the position or an immutable position so that you couldn't do this.
That is the problem you really need to fix with this code...
How, then, should you do that?
Well, you could certainly come up with some functional interface in Circle, but honestly your code will be more readable if you just have circle.move(double x, double y);
I'm making a 2D platformer / shooter with LibGDX. I'm having this loop where holding fire-button down causes bullets to fly from the main character's gun the whole duration while the fire-button is pressed down (rapid fire). That part works perfectly and as intended. However, I'd like the rate of fire to be a bit slower. Currently the loop just adds a bullet to the world on each game frame which means the rate of fire is ridiculously high.
I've been trying to find a good way to do this, to no avail. Any suggestions would be vastly appreciated.
the loop:
if (keys.get(Keys.FIRE)) {
player.setState(State.FIRING);
world.addBullet(new Bullet(1f,1f,0));
}
You can use a delay mechanism by having a variable which counts down the time and every time it hits 0, you make one shot and reset the time, for example to 0.2f when you want the player to shoot every 0.2s:
private float fireDelay;
public void render(float deltaTime) {
fireDelay -= deltaTime;
if (keys.get(Keys.FIRE)) {
player.setState(State.FIRING);
if (fireDelay <= 0) {
world.addBullet(new Bullet(1f,1f,0));
fireDelay += 0.2;
}
}
}
Use a constant to hold the fire rate and add a timing mechanism, like so:
public static final long FIRE_RATE = 200000000L;
public long lastShot;
if(System.nanoTime() - lastShot >= FIRE_RATE) {
world.addBullet(new Bullet(1f,1f,0));
lastShot = System.nanoTime();
}
I have seen #noone s answer and it is correct. I just answer you, because i had to add the same to my game. What i did: I had a variable boolean attacking, which stores if you are holding firebutton. Then i had 2 more variables: float bps, which stores how many bullets you can shoot per second and float reloadTime, which stores how long it takes to reload an empty magazin, if you use one. I also store a long time and a boolean reloading. Time stores the TimeUtils.millis() of your last shot, the reloading stores if you are reloading the magazin or just shooting. Then in the attack method i call a method: public boolean readyToAttack(), in which i compare TimeUtils.millis() to my variable time. If reloading = true, TimeUtils.millis() - reloadTime has to bigger then time. If not, TimeUtils.millis() - (1000 / bps) has to be bigger then time. If this is the case the method returns true and i can shoot. Noones solution is simpler, but for me bps is easier to understand so i used this.
Hope it helps
Im trying to get a rectangle to move from a fixed location, to a click point in my game. I have it working to the point that im getting good coordinates from the e.getX and e.getY methods in the mouse listener class. I also have the rectangle moving in straight lines to the side or up and down by increasing and decreasing the positionX and Y values but i need a way to move it to any point that i click on, basically i need to set the change in x and y. The way i was thinking is to compute the rise and run of the line from the click points and the start point and then set the x and y values to the rise and run. If i do it this way, i need a way to decrease the rise and run values down to their lowest terms so it moves fluidly. Or if there is a way im not thinking of that you can offer any guidence that would be helpfull.
How are you drawing it at the moment? Below is a method I used to shoot bullets in a little game that I made/really should finish sometime.
This is by no means all the code you will need, and in some places there are better ways to do things (which I'm sure people will start to tell me in the comments section after :) ) but it should give you a basis to work from.
The one thing missing from this is regulating the speed at which it repaints (fps), sorry but I can't remember the simple way to do this right now (need to get back to my actual job!) Hope it helps.
The barebones of it will be something like this:
//these set out the current position of your rectangle
double recX, reYy, recH, recW;
//this gives something to manage speed
int speed;
public void paintComponent(Graphics g) {
g.drawRectangle(recX,rexY,recH,recW);
}
//here we work out the movement
public void clickedScreen(double x, double y){
double newX = x;
double newY = y;
//calculate the speed to move at
vX = newX - recX;
vY = newY - recY;
//get the distance
length = Math.sqrt((v1*v1)+(v2*v2));
//make it a unit vector
v1 = v1/length;
v2 = v2/length;
}
public moveRec(){
recX = recX+(v1*speed);
recY = recY+(v2*speed);
}
while(true) {
moveRec();
repaint();
}