Kami - Java 3D voxel platformer

Latest jar (v4) : jar : http://www.java-gaming.org/user-generated-content/members/244457/kami4.jar


Hello :).
Here’s my new project. It’s heavily relying on the 3d voxel engine I built in my last project and is trying to make a 3D version of the grappling hook + jet pack demo I made in early 2015.

So far, just finished up the basic collision detection and movement. (wasd to move, tap space to jump, press down space while walking into walls to climb, and press down space to jet pack).
Short term goals will be to add the grappling hook, a mini game mode (floor is rising lava, get to the exit before lava rises too high), and adding particles for the jet pack smoke.

Feedback much appreciated.

Git hub in case someone would like to try it out: https://github.com/mahhov/Kami

RYF9sE0F-bY

Looks pretty cool! :slight_smile:

Could you supply a jar to quickly test with?

Thanks.

Sure. I’ve added the jar to dropbox (v1) https://www.dropbox.com/s/my35r1l0298b4g3/Kami.jar

Fair warning though, it is far from bug free. there’s definitely issues with aiming the grappling hook when the camera is below the ground surface, or there’s a building between the camera and your character. Also, the world is generated randomly every time it’s ran, so if a structure spawns on top of you, you’ll just have to restart the app.

Very cool ;D

I get a solid 50-60 fps.

Would be neat to see a PS1 styled game made with this. Something like Bugs Bunny: Lost in time :point: :point:

new jar (v2): http://www.java-gaming.org/user-generated-content/members/244457/kami.jar

Awesome. I only get like 30fps on my laptop, so hearing that is a relief.

Here’s a status update.
Major update is the addition of grappling hook (press shift or click the mouse button), it will shoot out to wherever your camera is pointing and pull the character towards itself once it’s attached.
Also minor adjustments to smoke particles movement, terrain generation (higher structures, more tapered tops, and some random colors), and character physics. Also, the camera now has an adjustable height (adjusted with Z and X).

Next steps are to add run time terrain generation / infinite terrain. Some kind of demo game mode (like the lava idea or feel free to make suggestions). And maybe some sort of cell shading, which is going to be interesting since this is all cpu rendered, with no graphic libraries.

By the way, the character physics are governed by 3 lines of constants at the top of the character.Character class, so feel free to adjust them and play around and let me know what values seem to work nicely.
The character physics are basically vx/vy *= friction, vz = (vz - gravity) * friction. Collision damper is multiplied to velocities when you collide into the edge of structures or the ground. Jump acc determines how much to add to vz when you press jump. Run acc is how fast you move while on the ground; air run acc is while you’re in the air (jetting or hooking); climb acc is for when you’re climbing structures. Jump mult is multiplied to vx and vy when you jump. Hook speed is how fast the hook shoots out, hook friction 1 just means the hook does not slow down as it shoots forward, and hook gravity 0 means gravity does not apply to the hook. Hook acc determines how strongly the hook pulls the character towards itself once attached.


	private static final double FRICTION = 0.9, AIR_FRICTION = 0.97, CLIMB_FRICTION = .99, GRAVITY = .05, COLLISION_DAMPER = .1;
	private static final double JUMP_ACC = .2, RUN_ACC = .1, AIR_RUN_ACC = .04, JET_ACC = .04, CLIMB_ACC = .055, JUMP_MULT = 1.5;
	private static final double HOOK_SPEED = .2, HOOK_FRICTION = 1, HOOK_GRAVITY = 0, HOOK_ACC = .05;

Also feel free to adjust the default terrain color (line 15 of terrain.terrainModule.FullGray class) and let me know what seems to work, because I’m not fond of the gray theme going on at the moment.

When I run it, the game flickers a lot. Are you double buffering?

On this version I only get about 30 fps. Quite a bit lower than the previous build :frowning:

Actually, I was initially double buffering, but got into flickering issues, and ended up putting in a temporary fix, where it’s constantly creating new buffered images every single frame. So it’s weird that it still flickers. Though the bigger issue I’ll look into is what I was doing wrong with double buffering in the first place.

I’m not sure why the fps would be affected this build. It may be because this build has a larger terrain map. This version terrain is 400x400x50. I believe, but need to confirm, previous build was 200x200x100, so terrain volume has has doubled.

buddyBro, that’s an awful “fix” do you understand how much garbage you’ll be creating per second?

To do double buffering, create a bufferedimage of the dimensions of the screen.
Ex-for a 640x480 screen: new BufferedImage(640,480,BufferedImage.TYPE_INT_RGB);
Then use the Graphics object of this image (that is gotten from image.getGraphics()) and use that to render your game.
Then, at the end of the frame, draw this image onto the Component, whether that component is a JFrame, Frame, Canvas, Panel, etc, it doesnt matter just do component.getGraphics().drawImage(image, 0, 0, null);

Yep, I understand. that’s exactly what I was doing before this temporary fix. I’ll give it another shot, and if I continue having issues, I’ll post the actual relevant code and see if there’s some issue I’m missing.

so here’s the drawing logic highlighted.

On initialization:
canvas = new BufferedImage(IMAGE_SIZE, IMAGE_SIZE, 1);
brush = (Graphics2D) canvas.getGraphics();

The loop is basically:

clear (brush.clearRect)
draw (a combination of brush.setColor and brush.fillPolygon)
repaint (JFrame graphics.drawImage(canvas))
sleep (10 ms)

http://pastebin.java-gaming.org/b63b74338511f

And it’s flickering. I purposely put the sleep in between the draw and the clear so to make sure it had time finishing drawing before the canvas was cleared.
Increasing buffer count to like 10 definitely helps reduce the flicker but does not eliminate it. I feel like there’s something wrong with the code if I need to use 10+ buffers to avoid flickering.
I’m sure there’s something I’m missing, I’ll keep looking at it, but if anyone notices something obvious, please let me know.

update:
I’ve noticed if I use new Color(0f, 0f, 0f, .1f) instead of Color.black when clearing the canvas, the flicker does not go away. Which indicates that it’s not being caused by erasing the canvas prior to it completing drawing to JFrame screen. It makes me think that maybe JFrame.repaint() does not guarantee to call JFrame.paint(Graphics) immediately / synchronously. I’ll continue trying out stuff.

Yeah I would not use repaint() to draw to the frame.
Firstly, make sure the frame/component that you’re drawing on has setIgnoreRepaint(b) set to true.
This ignores native repaint calls
Also, you ONLY need 1 buffer.
Don’t wait at the end of the loop.
Instead of painter.repaint();
call painter.paint() directly, remove the graphics parameter and use the graphics object of the Frame that the painter inherits.

[quote]call painter.paint() directly, remove the graphics parameter and use the graphics object of the Frame that the painter inherits.
[/quote]
Yep that fixed it, thank you :). Yes, the code on github, only uses 1 buffer; using multiple buffers was just to highlight the issue.

I’m not sure what you mean by: [quote]Don’t wait at the end of the loop.
[/quote]
When trying to use JFrame.getGrpahics, I see it is null prior to calling JFrame.pack(). At what point in time is the JFrame graphics object actually created? Is it safe to assume, it’ll always be created after the pack() is called, or should I simply add a “if (g == null) g = getGraphics()” check to the top of my paint call?


Painter(int frameSize, int imageSize, Controller controller) {
		FRAME_SIZE = frameSize;
		IMAGE_SIZE = imageSize;
		canvas = new BufferedImage(IMAGE_SIZE, IMAGE_SIZE, TYPE_INT_RGB);
		brush = (Graphics2D) canvas.getGraphics();
		getContentPane().setSize(FRAME_SIZE, FRAME_SIZE);
		
		System.out.println(this.getGraphics()); // null
		pack();
		System.out.println(this.getGraphics()); // sun.java2d.SunGraphics2D[font=java.awt.Font[family=Lucida Grande,name=Lucida Grande,style=plain,size=13],color=java.awt.SystemColor[i=9]]
		
		borderSize = getHeight();
		setSize(FRAME_SIZE, FRAME_SIZE + borderSize);
		setLocationRelativeTo(null);
		addMouseListener(controller);
		addKeyListener(controller);
		addMouseMotionListener(controller);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setIgnoreRepaint(true);
		setVisible(true);
		frameBrush = this.getGraphics();
	}

Hm… that’s peculiar. I’ve always found that the graphics object is non-null once setVisible(true) is called on the component or its parent. But yes, you can just check if the graphics object is null when you call paint() and return if it is null.

By “dont wait at the end of the loop” i mean that part with the wait(10). Unless that’s your own function with a Thread.sleep in there.
You don’t want to use Object.wait(10), you want to do Thread.sleep(10)

yes, wait(10) is just a wrapper for Thread sleep, because I didn’t like the try catch polluting the main loop and because it’s used twice. I didn’t even realize it was not a good name choice until you pointed out it’s name is shared by the Object.wait, I’ll be sure to rename it.

static void wait(int howLong) {
		try {
			Thread.sleep(howLong);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

Here are videos of the latest build which should have flickering fixed.

.jar (v3) http://www.java-gaming.org/user-generated-content/members/244457/kami3.jar

grappling hook

NVmEy0zmtOA

particles

lP_OfwwcZcQ

Yup the flickering is fixed good job :slight_smile:

That grappling hook looks really cool! I’m very impressed by the performance with all those particles ,especially with using Java2D :o

Thanks :slight_smile:

It takes about 12,000 particles on my laptop until fps starts dropping sub 20. Keep in mind each cube drawn is only a few algebraic expressions and 3 fill polygon calls, so not that expensive. Essentially, screenX = x perpendicular to camera normal / distance from camera, screenY = y perpendicular to camera / distance from camera, so the math is not computationally heavy at all. It’s more the traversing the world grid that takes time.

Even the following code snippet takes 0.03970144 seconds (that’s 25 fps). So if I need to stay 50+ fps, I need to double performance, either by minimizing the amount of unnecessary world grid traversal, or by making sure each grid location traversed takes less time than computing i * j / k takes. Since the second solution isn’t going to happen, i.e. each grid traversal is defiantly going to involve more than 1 double multiplication and 1 double division, minimizing how much of the world is traversed each frame becomes big priority.


System.out.println("Begin timing");
		double time = System.nanoTime();
		double x = 0;
		for (int i = 0; i < 400; i++)
			for (int j = 0; j < 400; j++)
				for (int k = 0; k < 50; k++)
					x += i * j / (k + 1.1);
		double etime = System.nanoTime();
		System.out.println("end timing. time: " + ((etime - time) / 1000000000L) + " ... x: " + x);

That’s a 400x400x50 = 8,000,000 iterations.
Since max draw distance is set to 163 with the current fog configuration, using simply a “traverse only world coordinates x-163 to x+163, and y-163 to y+163, and z-163 to z+163”, would be 34,645,976, would be 4.330747 more iterations. So it becomes apparent, that we need smarter algorithm (8.7 times smarter) to get 50+ fps. Hence, my prior project Ot (which this project builds off of), which tried to optimize fps given large but sparse world. So the fact that we’re using Java2D isn’t that much of a hinderance since fill Polygon isn’t the bottleneck. In my prior project (Conxeline which optimized for small but very dense worlds like minecraft underground), the world traversal was much less of an issue, and yes switching to JOGL and LWJGL each gave about double the performance as Java2D.

The first steps towards runtime terrain generation.

G7m-0JDIU-o