Absolutely not. Your weapon does 1 damage starting out and is a little inaccurate. You will be able to permanently upgrade weapons after each level. The crawler things have hp ranging from 8-12. I may change things a little. Balance is a work-in-progress. Wondering if anyone has found the shotgun in the level? And then maybe use it with some other powers you can get. 
Particles are super simple. Keeping things simple will keep things fast. Here is basically the particle class from the game.
protected Vector2 loc;
protected Vector2 vel;
protected Vector2 acc;
//private Vector2 rot;
protected Vector2 size;
protected Vector2 maxSize;
protected Vector2 growth;
protected Vector2 life;
private Color color;
public double friction = 1;
protected boolean ultSize = false;
protected boolean defaultSize = true;
public boolean fadeIn = false;
The Vector2 class is basically a vector2f opengl type class that holds to doubles and has some nice vector math methods. Protected vars as I have some place hold particle sub-classes. PhysicsParticle, Image Particle, AnimatedParticle etc.
Update method.
public boolean update(){
vel.add(acc);
loc.add(vel);
size.add(growth);
if(fadeIn)
life.x++;
else
life.x--;
vel.x *= (friction);
vel.y *= (friction);
/*rot.x += rot.y;
if(rot.x > 360)
rot.x = 0;
if(rot.x < 0)
rot.x = 360;*/
if(life.x <= 0){
life.x = 0;
return true;
}
if(fadeIn)
if(life.x >= life.y)
{
life.x = life.y;
fadeIn = false;
}
if(defaultSize){
if(size.x >= maxSize.x){
if(size.y >= maxSize.y)
size.y = maxSize.y;
else
size.x = maxSize.x;
}
if(size.y >= maxSize.y) //Note: we already checked if both x and y are bigger.
size.y = maxSize.y;
if(size.x <= 0)
if(size.y <= 0)
return true;
else
size.x = 1;
if(size.y <= 0)
size.y = 1;
return false; // we are done
}
if(ultSize){ // We will shrink and grow back and forth
if(size.x > maxSize.x){
size.x = maxSize.x;
growth.x *= -1;
}
if(size.y > maxSize.y){
size.y = maxSize.y;
growth.y *= -1;
}
if(size.x <= 0){
size.x = 1;
growth.x *= -1;
}
if(size.y <= 0){
size.y = 1;
growth.y *= -1;
}
}
else{ //We stop growing or shrinking.
if(size.x > maxSize.x)
size.x = maxSize.x;
if(size.y > maxSize.y)
size.y = maxSize.y;
if(size.x <= 0){
size.x = 1;
growth.x = 0;
}
if(size.y <= 0){
size.y = 1;
growth.y = 0;
}
}
//loc.x = (int)loc.x;
//loc.y = (int)loc.y;
return false;
}
The update can be much much more complex. It is the rendering in java2D that will slow things down. Here is the render method.
public void render(Graphics g){
if(!Global.bounds.contains(loc.x,loc.y))
return;
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) (life.x/life.y)));
//g2d.setTransform(AffineTransform.getRotateInstance(rot.x/Globals.scale, loc.x, loc.y));
g2d.setColor(color);
g2d.fillRect((int)((loc.x-(size.x/2))), (int)((loc.y-(size.y/2))), (int)size.x, (int)size.y);
g2d.dispose();
}
Add in a BI reference and call drawImage instead of fillRect and you have a very doable particle system. Rotation is in there but not needed. I am culling the particles and tiles. So if the camera does not see them, they will not be rendered. Normally you would have an emitter class that will manage emitting particle but in this game I just have some methods that emit single or multiple particles.
The physics is kinda wonky. All of the blocks are in a list and then I check each particle with each block to see if there is a collision and then resolve it. This part is slow. I can speed this up by making a grid base spacial partitioning system so I only check blocks in the particles area. Per-pixel collision is vastly overrated. Just use some bounding boxes and you will be fine. If you want some complex stuff, use box2D. No need reinventing the wheel too much.
If you would like, I can PM you the source of the system used in this game and then a much more robust opengl based system for learning. (Tip: once you get a basic system working, look at libgdx’s or Unity3D’s particle system source. Very enlightening.)