Hello all,
I am starting out with a little pong game to get me going on this JME stuff (which I love thusfar),
and have gotten the collision down for the hit:
//BALL WITH RIGHT PADDLE
if (s.getWorldBound().intersects(boxr.getWorldBound())){
System.out.println("Collision");
balldir=(balldir*-1);
}
Working good. I'm basically reversing the x direction (balldir) for the paddles, and the z direction (for top/bottom walls).
But I want to make it a little more interesting, where if you hit it more towards the edges, it will go out at a harder angle, to avoid the same constant path around and around.
One way I thought of was to create maybe 3/5 different boxes for each paddle, then changing the z value based on that, lower for outside, and higher for in the middle.
Is there a better way? Like using some way of finding out where the collision takes place on the one bounding box? Is this tough? And how would this be done?
Thanks!!!
My game thusfar…
import com.jme.app.SimpleGame;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jme.math.Vector3f;
import com.jme.bounding.BoundingSphere;
import com.jme.bounding.BoundingBox;
import com.jme.renderer.ColorRGBA;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
/**
- Started Date: Jul 20, 2004<br><br>
*
- Simple Node object with a few Geometry manipulators.
*
-
@author Jack Lindamood
/
public class test5 extends SimpleGame {
float ballx=0, bally=0, ballz=0;
float padlx=-5, padly=0, padlz=0;
float padrx=5, padry=0, padrz=0;
int balldir=-1;
int ballang=1;
Box boxl, boxr, boxt, boxb;
Sphere s;
public static void main(String[] args) {
test5 app = new test5();
app.setDialogBehaviour(SimpleGame.ALWAYS_SHOW_PROPS_DIALOG);
app.start();
}
protected void simpleInitGame() {
Vector3f pos = new Vector3f(0.0f, 10.0f, 10.0f);
Vector3f left = new Vector3f( -1.0f, 0.0f, 0.0f);
Vector3f up = new Vector3f(0.0f, 0.7f, -0.7f);
Vector3f dir = new Vector3f(0.0f, -0.7f, -0.7f);
/**
Vector3f pos = new Vector3f(0.0f, 10.0f, 10.0f);
Vector3f left = new Vector3f( -1.0f, 0.0f, 0.0f);
Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
Vector3f dir = new Vector3f(0.0f, 0.0f, -1.0f);
/
/ Move our camera to a correct place and orientation. /
cam.setFrame(pos, left, up, dir);
//cam.setLocation(new Vector3f(0.0f, 0.0f, 10.0f));
//LEFT PADDLE
boxl=new Box("My Box",new Vector3f(0,0,0),new Vector3f(0.5f,0.5f,2));
// Give the box a bounds object to allow it to be culled
boxl.setModelBound(new BoundingBox());
// Calculate the best bounds for the object you gave it
boxl.updateModelBound();
// Move the box 2 in the y direction up
boxl.setLocalTranslation(new Vector3f(padlx,padly,padlz));
// Give the box a solid color of blue.
boxl.setSolidColor(ColorRGBA.blue);
//RIGHT PADDLE
boxr=new Box("My Box",new Vector3f(0,0,0),new Vector3f(0.5f,0.5f,10));
// Give the box a bounds object to allow it to be culled
boxr.setModelBound(new BoundingBox());
// Calculate the best bounds for the object you gave it
boxr.updateModelBound();
// Move the box 2 in the y direction up
//boxr.setLocalTranslation(new Vector3f(padrx,padry,padrz));
boxr.setLocalTranslation(new Vector3f(5,0,-5));
// Give the box a solid color of blue.
boxr.setSolidColor(ColorRGBA.red);
//BALL
s=new Sphere("My sphere",10,10,0.5f);
// Do bounds for the sphere, but we'll use a BoundingBox this time
BoundingSphere.useExactBounds=true;
s.setModelBound(new BoundingSphere());
s.updateModelBound();
BoundingSphere.useExactBounds=false;
// Move the box 2 in the y direction up
s.setLocalTranslation(new Vector3f(ballx,0,ballz));
// Give the sphere random colors
s.setRandomColors();
// Make a node and give it children
//TOP WALL
boxt=new Box("My Box",new Vector3f(0,0,0),new Vector3f(10.0f,0.5f,0.5f));
// Give the box a bounds object to allow it to be culled
boxt.setModelBound(new BoundingBox());
// Calculate the best bounds for the object you gave it
boxt.updateModelBound();
// Move the box 2 in the y direction up
boxt.setLocalTranslation(new Vector3f(-5,0,-5));
// Give the box a solid color of blue.
boxt.setSolidColor(ColorRGBA.green);
//BOTTOM WALL
boxb=new Box("My Box",new Vector3f(0,0,0),new Vector3f(10.0f,0.5f,0.5f));
// Give the box a bounds object to allow it to be culled
boxb.setModelBound(new BoundingBox());
// Calculate the best bounds for the object you gave it
boxb.updateModelBound();
// Move the box 2 in the y direction up
boxb.setLocalTranslation(new Vector3f(-5,0,5));
// Give the box a solid color of blue.
boxb.setSolidColor(ColorRGBA.green);
Node n=new Node("My Node");
n.attachChild(s);
n.attachChild(boxl);
n.attachChild(boxr);
n.attachChild(boxt);
n.attachChild(boxb);
// Make the node and all its children 5 times larger.
//n.setLocalScale(5);
// Remove lighting for rootNode so that it will use our
//basic colors.
lightState.detachAll();
rootNode.attachChild(n);
// Adds the "u" key to the command "padlUp"
KeyBindingManager.getKeyBindingManager().set("padlUp", KeyInput.KEY_Z);
// Adds the "u" key to the command "padlDown"
KeyBindingManager.getKeyBindingManager().set("padlDown", KeyInput.KEY_X);
// Adds the "c" key to the command "getSpecs"
KeyBindingManager.getKeyBindingManager().set("getSpecs", KeyInput.KEY_V);
}
protected void simpleUpdate(){
//if the padlUp command was activated
if (KeyBindingManager.getKeyBindingManager().isValidCommand("padlUp",true)){
//More padl Up
padlz=padlz+.01f;
boxl.setLocalTranslation(new Vector3f((padlx),(padly),(padlz)));
}
//if the padlDown command was activated
if (KeyBindingManager.getKeyBindingManager().isValidCommand("padlDown",true)){
//Move padl Up
padlz=padlz-.01f;
boxl.setLocalTranslation(new Vector3f((padlx),(padly),(padlz)));
}
//if the getSpecs command was activated
if (KeyBindingManager.getKeyBindingManager().isValidCommand("getSpecs",true)){
//Get Specs
System.out.println("Cam Loc:" + cam.getLocation());
System.out.println("Cam Left:" + cam.getLeft());
System.out.println("Cam Up:" + cam.getUp());
System.out.println("Cam Dir:" + cam.getDirection());
//System.out.println("Node at:" + b.getCenter());
}
///////////////////////
//COLLISION CHECKS
//BALL WITH LEFT PADDLE
if (s.getWorldBound().intersects(boxl.getWorldBound())){
System.out.println("Collision");
balldir=(balldir-1);
}
//BALL WITH RIGHT PADDLE
if (s.getWorldBound().intersects(boxr.getWorldBound())){
System.out.println("Collision");
balldir=(balldir-1);
}
//BALL WITH TOP WALL
if (s.getWorldBound().intersects(boxt.getWorldBound())){
System.out.println("Collision");
ballang=(ballang*-1);
}
//BALL WITH BOTTOM WALL
if (s.getWorldBound().intersects(boxb.getWorldBound())){
System.out.println("Collision");
ballang=(ballang*-1);
}
//END COLLISION CHECKS
//////////////////////
ballx=ballx+(balldir*.01f);
ballz=ballz+(ballang*.01f);
s.setLocalTranslation(new Vector3f(ballx,0,ballz));
}
}
BMan1010 said:
One way I thought of was to create maybe 3/5 different boxes for each paddle, then changing the z value based on that, lower for outside, and higher for in the middle.
I think this would be ok, to keep your current setup...
BMan1010 said:
Is there a better way? Like using some way of finding out where the collision takes place on the one bounding box? Is this tough? And how would this be done?
What about using the distance between paddle and ball along a suited axis? - that would be pretty simple.
It is possible to compute intersecting triangles but this does not help alot here.
Sure there is a better way :) using jmephysics, I would consider the 'best' ;) - but it's probably not the easiest (though not tough, too).
Some people have done a pong-like game with jmephysics - you can search for 'prick' here in the forums.
Thanks irrisor,
I'll probably stick with the multiple boxes to check different areas for now, trying to take baby stpes
One of my eventual steps will be to work the physics engine in somehow to get an understanding of how that works, etc.
// initing
PhysicsWorld.create();
DynamicPhysicsObject ball = new DynamicPhysicsObject(ball, 1);
PhysicsWorld.getInstance().addObject(ball);
DynamicPhysicsObject paddle1 = new DynamicPhysicsObject(paddle1, 1);
PhysicsWorld.getInstance().addObject(paddle1);
DynamicPhysicsObject paddle2 = new DynamicPhysicsObject(paddle2 , 1);
PhysicsWorld.getInstance().addObject(paddle2);
in the update method:
PhysicsWorld.update(tpf);
up, down arrows clicked:
if (up) {
paddle1.addForce(0, 10, 0);
} else if (down) {
paddle2.addForce(0, -10, 0);
}
Any simpler? :roll:
DP
If you use the physics system, won't the ball bounce off the paddle the same way no matter where it strikes the paddle? That is, the paddle is traditionally flat. So the ball striking the paddle will have the same Normal no matter where on the paddle it hits. (At least that's what I see in my mind's eye, never done it to confirm). So if you do use the physics system (and my hypothesis is correct, which is by no means given), you might want to add a bit of a "bulge" to the paddle the ball hitting the paddle on the edge will shoot off more to the side then it would for the center.
ok…
// iterate through the PhysicsCollisionResults and on ball/paddle contact do:
Vector3f ballPos = ball.getSpatial().getWorldTranslation();
Vector3f paddlePos = ball.getSpatial().getWorldTranslation();
float distance = ballPos.distance(paddlePos);
if (ballPos.y > paddlePos.y) {
ball.addForce(0, distance * multiplier, 0);
} else if (ballPos.y < paddlePos.y) {
ball.addForce(0, -distance * multiplier, 0);
}
DP
I would not add forces as described by DP, but use a sphere as physics type (with a quite large radius) - that should result in a similar behaviour to the one I expect from a pong paddle…
true, except if you do add a sphere, the ball would not even touch the paddle…making you use dummy objects. Also, with my method, you can have an ovally distributed force area whereas a sphere would be hard to control.
Im trying to keep it simple for the fella, he thought the physics was complicated and it would be simpler if he did it using the maths way, im just showing him that jmephysics isn't that complicated…
DP
Hmm… isn't it easiest after all to just calculate yourself? In fact, do you even need to use the collision system? Just check each update if the ball has crosses the "paddle line", if it has check what it's previous location was so you can interpolate almost exactly where it crossed and calculate the angle and exact time it hit the paddle. Do the same for the paddle and you can calculate yourself which way you want the ball to bounce back.
That said, to "learn" jME it's good to use collision detection or even physics, but to build a good pong game… eg. could physics handle something like this yet?
http://www.2flashgames.com/f/f-178.htm
It's a 3D Pong that uses the speed and direction the paddle is travelling when the ball hits it to give the ball a "spin". Mind you, if it could (or can already?) I'd be very impressed.
It can, and its pretty easy too. On contact, in the CallBack class, add some Motion1 and Motion2 to the contact and your done. It needs pretty good knowledge to actually know these exist, but they are there…
DP
Ah yes, but you'll need to calculate the forces yourself with each collision right? You're only really using physics for the collision and for applying force that will make it travel with a curve I assume. Will this make the sphere actually spin?
torque, angular velocity and moments of inertia are calculated by ODE automatically upon collision. So you dont need to do anything besides set those Motion values without any force calculations. These values are obtained by trial and error to see whats good for your game. And yes, it will spin, rotate and do magical stuff! :-o
DP
Well I am impressed. I'd say drop the "calculate yourself" method and go with physics!
I'd love to see a "curve ball" game in 3D. Hell, I might make it myself if noone else does.
Wow, just saw a bunch of new posts were added to this thread, great conversations, great community, why I love this engine thusfar.
The jme physics seems very powerful, I am definately going to try adding this to my game.
So far I had just threw 5 boxes out there and was doing it manually, outside two send it back at 30 degrees, next two in at 45 degrees, and middle goes back at 60 degrees (may need tweaking on angles when I get it all working). Seems to be alright for now, but the curvy ball seems like a sweet idea. And just learning to integrate jme physics in will definately be a step I'm going to put in here as I learn that piece of the engine.
I'm pretty much taking baby steps right now, trying to comment/document what I'm doing as I go along, and saving each incremental version. Make it a tutorial and post it somewhere eventually maybe, for newbies like me.
Just so I know I am understanding, is the idea to make the paddles a more oval shape, versus straight, then it will bounce off it more dynamically? Or am I missing something here.
Hey DP (or whoever else knows),
Is there a good link/tutorial on the physics? Or does the main odejava documents cover this? (Guess I could go look myself).
Your posted code makes sense and doesn't look too tough. I have no idea how to attach the physics object to my paddles though
(I'm guessing I still use a square mesh? Eventually I want to import models to be the paddles and "ball").
I'll take a look around though. But if anyone has any "must view" links, it would be appreciated
There is no tutorial at this time - please have a look at the Tests. The very basics are in SimpleTest.
Hmm,
Well, I was giving the node new location values and then, using either of the two commands,
the node moved along the new path…
n.setLocalTranslation(new Vector3f(ballx,0,ballz));
n.updateGeometricState(0.0f, true);
//n.updateRenderState();
OR
n.setLocalTranslation(new Vector3f(ballx,0,ballz));
//n.updateGeometricState(0.0f, true);
n.updateRenderState();
Thanks for above help. Moving right along here
This is I'm sure a jme 101 questions, but I can't figure out how to move a node and it's contents.
It doesn't appear it works with a simple:
n.setLocalTranslation(new Vector3f(x,y,x));
(n being my node name).
Is this where the spatials come into play, or the controllers?
I can see from the starter pdf how to set them up for a constant rotation, etc.
But I'm looking more to manually control a group of objects attached to a node on my own, at given times, like
on input from keyboard.
(ducks from fruits and vegetables being thrown).
thanks again!
What fruits :roll:
… have You done an UpdateGeometricState() on the node n is in after setting the LocalTranslation
( SimpleGame does this for You on the root node already i think ) ?
and if Youre using physics dont't forget a SyncWithGraphical(n) to tell the physics system too.