Proof of concept video. Slick2D tank game

This is some proof of concept code for a tank game I’m writing in Java using Slick2D and lwjgl libraries.

Fraps is making this much jerkier than it actually is. I’m actually getting about 550 Frames per second and the animation is really smooth.

The first screen just shows a scrolling menu object I wrote. Not only does the text scroll but the selected text fades in as selected and out when unselected.

I’m running a two image tank over a tiled map. The bullets are coming out of the tank turret at the proper angle. Also, I’m cleaning up memory properly so when a bullet goes beyond the edge of the screen it is released and garbage collected. The debug text at the bottom shows the number of projectiles in memory at any point.

So far, it’s been pretty fun learning the Slick2D library.

It says video is private :frowning:

Try it now.

That’s odd, usually, a private video can be seen if I supply the URL. Private just means it won’t show up in a search.

Wicked nice! I so much want to get into Slick2D. Are you already familiar with the Java2D API? Just wondering what you think about Slick2D in comparison (so far).

I wrote this game entirely in Java2D and the tank game is in Slick. I’m getting much better Frames per second in Slick2D.

Slick has some oddness to it, they overloaded the Image class so any time you used a BufferedImage you now use their Image class. However, you load a class simply by handing it the file name and you’re done.

Slick handles the game loop for you.
Slick handles transitions. You’ll notice in the video that the first scene fades out and the new scene fades in. That entire transition is done with one line of code.


game.enterState(Level1.ID, new FadeOutTransition(Color.black, 300), new FadeInTransition(Color.black, 300));

Slick2D already has particle emmiters so you can do fire, smoke, and waterfall effects. It’s also quite easy to rotate individual images without having to deal with affine transforms manually.

It also can handle a tiled background made from The Tiled Editor. The code to load is is simply:


TiledMap tiledMap = new TiledMap("assets/common/images/Map2.tmx");

What it doesn’t have is a camera class to scroll around that map. There’s a class in the SLick2D forums which I used. I think it should be part of the core SLick2D API.

Apparently, everything in Slick2D is wrapping lwjgl so all the graphics calls are being done in OpenGL. This should mean that if I needed to use some sort of special OpenGL call I could do so. I don’t know enough about OpenGL yet to know if I can write shaders yet but that would be pretty darn cool. Imagine a tank game in the dark where you can only see what’s in the headlights.

The Tiled map creator which Slick2D uses so easily has some limitations though. I’d like to have buildings which can show different levels of damage. There isn’t, as far as I can tell, a way to turn individual tiles on or off for a tiled layer. I’d probably have to modify the Slick2D source code to do that. Also, each level must be loaded up front so they take up memory for the entire game. I’d rather see the level (or GameState class) take a string of the class name and as that level is requested it can lazy load it via Java Reflection. I’d also like to see a boolean for a GameState class where I can say it’s volatile. That way, when we move away from that level we can tell the engine that it’s ok to free up it’s memory usage.

Thanks for the details - that’s nice stuff. I’ll definitely look into Slick2D in the future.

That’s pretty cool. How are you handling the angle of fire (trajectory)?

It’s just catching the sine and cosine of the difference in X and Y locations between the center point of the turret and the mouse position.

However, there was a glitch because the tank and turret have an x/y location within the world, and the mouse’s x/y is within the view. Since the camera class is scrolling around the tiled map I could place the mouse directly on the tank and the mouse would say x=500, y=500 but the tank would say x=500, y=3000 because we’re near the bottom of the tiled map. So I had to get the current camera position and subtract that from the tank’s x/y position.

The other difficulty was that I could get the perfect starting position of the bullet such that it would appear at the tip of the cannon. It worked perfectly if the bullet was pointed straight up. But once I rotated the bullet to match the rotation of the turret the graphic of the bullet would move. So I had to calculate where the tip of the cannon is at it’s rotation, then calculate how far off the tip of the bullet would be once I rotated it by that many degrees, and then shift the bullet so it would move back to the tip of the tank turret. It’s not exactly perfect but it’s damn close.

If I make the movement rate of the bullet 0 and fire a bunch of them while turning the turret I should see a perfect circle of stationary bullets. What I get is an almost, but not perfect, circle. I’ll keep working on that.

I also had to remember that the sine and cosine of an angle return different positive or negative numbers depending on which quadrant you’re in so you have to adjust for that. But sending the bullets out properly rotated really adds a nice touch when firing non-round bullets.

I just found a much easier way to do this


	private void fireTurret() {
		double currentAngle = turret.getRotation();
		float bulletSpeed = 700;
//		float bulletSpeed = 0; // used for testing
		
		Bullet2 bullet = new Bullet2((int)0, (int)0, 0f, 0f);
		
		int halfBulletWidth = bullet.getImage().getWidth()/2;
		float theSine  = (float) (Math.sin(Math.toRadians(currentAngle)));
		float theCosine = (float) (Math.cos(Math.toRadians(currentAngle)));

		bullet.setDx(theSine * bulletSpeed);
		bullet.setDy(theCosine * bulletSpeed *-1);
		bullet.setXY(((int)getTankCenterX() -halfBulletWidth), ((int)getY() - bullet.getHeight())); 
		bullet.getImage().setCenterOfRotation(halfBulletWidth,bullet.getHeight() + (getHeight()/2) );
		bullet.getImage().rotate((float)currentAngle);
		
		gameLevel.getPlayerProjectilesToAddList().add(bullet);
		lastFire= 0;
	}

setCenterOfRotation takes an x and y location relative to the image’s current position. So it’s not an absolute X/Y position, it’s the number of pixels from the current x/y position. So, I just draw the image in the proper location as if the turret is pointing straight up, then I find the relative center, then I rotate the bullet to whatever angle the turret is currently rotated at. Also, I don’t have to deal with sines and cosines in different quadrants since I’m no longer doing a double rotation which used arctan. Now I just set the dx and dy (change in x and change in y) and let the bullet fly.

The bullet speed, by the way, as well as the Dx and Dy is in pixels per second. So when I do that bullet’s update I get the number of milliseconds since the last update and convert it to a percentage of a second.


	@Override
	public void doUpdate(int delta) {

		float slicePercent = ((float) delta) / 1000;

Then I just get the current x/y position, multiply dx by slicePercent and dy by slicePercent and add those numbers to X and Y and the bullet goes in the proper direction at the proper speed regardless of Frames Per Second.

All those rotate methods are part of the Slick2D library which call OpenGL via LWJGL so it’s very fast. I’m still getting about 400 to 425 FPS.

I have a new video here

I have mines which spew bullets. Tank projectiles which have particle emitter smoke trails behind them, and a block of 5 mines at the top of the page which spew about 1000 bullets from off screen. Oh, and check out the explosions! I’m using an explosion generator I found here which was written by Cliff Harris, the guy who wrote Gratuitous Space Battles.

As a proof of concept project I think it’s starting to come together.

And I have to say, after all the stress of building REST based stateless interfaces for legal matter management systems all day at work, this is vastly more fun.