Jmonkey Collision Detection - java

I am new to Jmonkey programming and I would like to ask a question about collision interaction as my code seems to finds collisions possibly from the terrain and i do not know how to solve this out. My goal is player as a first person to be detected if he collides with an enemie's ghost control to display a message as an output. My code displays a continues collision and then it crashes...
package test;
//imports...
public class test extends SimpleApplication
implements ActionListener,PhysicsTickListener{
private MotionPath path;
private MotionPath path2;
private MotionTrack motionTrack;
private MotionTrack motionTrack2;
private AnimChannel channel2;
private AnimControl control2;
private AnimControl control3;
private AnimChannel channel3;
private BulletAppState bulletAppState;
private RigidBodyControl landscape;
private CharacterControl player;
private Vector3f walkDirection = new Vector3f();
private boolean left = false, right = false, up = false, down = false;
private TerrainQuad terrain;
private Material mat_terrain;
private GhostControl ghost;
static test app;
Material matMarker;
public static void main(String[] args) {
app = new test();
app.start();
}
float displacement=60;
int score = 0;
int robotHealth=0;
Geometry mark;
Node shootables;
Node pickUpObject1;
BitmapText hudText;
#Override
public void simpleInitApp() {
createScene();
enemies();
pickUptype1();
initCrossHairs(); // a "+" in the middle of the screen to help aiming
initKeys(); // load custom key mappings
initMark(); // a red sphere to mark the hit
hudText = new BitmapText(guiFont, false);
hudText.setSize(guiFont.getCharSet().getRenderedSize()); // font size
hudText.setColor(ColorRGBA.Red); // font color
hudText.setLocalTranslation(600, 700, 0); // position
guiNode.attachChild(hudText);
DirectionalLight sun2 = new DirectionalLight();
sun2.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f));
int width = settings.getWidth(); //width is the width of the gui
int height = settings.getHeight(); //height is the height of the gui
}
protected Geometry makeCube(String name, float x, float y, float z) {
Box box = new Box(new Vector3f(x, y, z), 3f, 3f, 3f);
Geometry cube = new Geometry(name, box);
Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
Texture tex_ml = assetManager.loadTexture("Interface/Logo/Monkey.jpg");
mat1.setTexture("ColorMap", tex_ml);
cube.setMaterial(mat1);
return cube;
}
private PhysicsSpace getPhysicsSpace() {
return bulletAppState.getPhysicsSpace();
}
/**
* This is the main event loop--walking happens here.
* We check in which direction the player is walking by interpreting
* the camera direction forward (camDir) and to the side (camLeft).
* The setWalkDirection() command is what lets a physics-controlled player walk.
* We also make sure here that the camera moves with player.
*/
#Override
public void simpleUpdate(float tpf) {
hudText.setText("SCORE \n" + " " + score);// the text
Vector3f camDir = cam.getDirection().clone().multLocal(0.6f);
Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f);
walkDirection.set(0, 0, 0);
if (left) { walkDirection.addLocal(camLeft); }
if (right) { walkDirection.addLocal(camLeft.negate()); }
if (up) { walkDirection.addLocal(camDir); }
if (down) { walkDirection.addLocal(camDir.negate()); }
player.setWalkDirection(walkDirection);
cam.setLocation(player.getPhysicsLocation());
path.setCycle(true); // Make path a complete circuit
path2.setCycle(true);
motionTrack.setLoopMode(LoopMode.Loop);
motionTrack2.setLoopMode(LoopMode.Loop);
}
public Node robot(){
Node monster = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml");
monster.scale(1.5f, 1.5f, 1.5f);
monster.rotate(0.0f, -3.0f, 0.0f);
// Create a appropriate physical shape for it
return monster;
}
public void createScene(){
/** Set up Physics */
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
//bulletAppState.getPhysicsSpace().enableDebug(assetManager);
flyCam.setMoveSpeed(100);
setUpKeys();
terrain = new TerrainQuad("my terrain", 65, 513, heightmap.getHeightMap());
/** 6. Add physics: */
// We set up collision detection for the scene by creating a
// compound collision shape and a static RigidBodyControl with mass zero.*/
CollisionShape terrainShape =
CollisionShapeFactory.createMeshShape((Node) terrain);
landscape = new RigidBodyControl(terrainShape, 0);
terrain.addControl(landscape);
CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1);
player = new CharacterControl(capsuleShape, 0.05f);
player.setJumpSpeed(20);
player.setFallSpeed(30);
player.setGravity(30);
player.setPhysicsLocation(new Vector3f(145f, -28f, 10f));
player.setCollisionGroup(PhysicsCollisionObject.COLLISION_GROUP_01);
player.addCollideWithGroup(PhysicsCollisionObject.COLLISION_GROUP_01);
setUpLight();
rootNode.attachChild(SkyFactory.createSky( assetManager,
"Textures/Sky/Bright/BrightSky.dds", false));
}
public void enemies(){
shootables = new Node("Shootables");
rootNode.attachChild(shootables);
Node Robot1 = robot();
Node Robot2 = robot();
CapsuleCollisionShape capsule = new CapsuleCollisionShape(4f, 10f);
RigidBodyControl robot1Cap = new RigidBodyControl(capsule, 0.01f);
Robot1.addControl(robot1Cap);
getPhysicsSpace().add(robot1Cap);
bulletAppState.getPhysicsSpace().add(robot1Cap);
bulletAppState.getPhysicsSpace().enableDebug(assetManager);
robot1Cap.setMass(100f);
robot1Cap.setKinematic(true);
CapsuleCollisionShape capsule2 = new CapsuleCollisionShape(4f, 10f);
RigidBodyControl robot2Cap = new RigidBodyControl(capsule, 0.01f);
Robot2.addControl(robot2Cap);
getPhysicsSpace().add(robot2Cap);
bulletAppState.getPhysicsSpace().add(robot2Cap);
bulletAppState.getPhysicsSpace().enableDebug(assetManager);
robot2Cap.setMass(100f);
robot2Cap.setKinematic(true);
ghost = new GhostControl(
new BoxCollisionShape(new Vector3f(8f,8f,8f))); // a box-shaped ghost
Robot1.addControl(ghost);
ghost.setCollisionGroup(PhysicsCollisionObject.COLLISION_GROUP_01);
ghost.setCollideWithGroups(PhysicsCollisionObject.COLLISION_GROUP_01);
getPhysicsSpace().add(ghost);
getPhysicsSpace().addTickListener(this);
control2 = Robot1.getControl(AnimControl.class);
channel2 = control2.createChannel();
channel2.setAnim("Walk");
control3 = Robot2.getControl(AnimControl.class);
channel3 = control3.createChannel();
channel3.setAnim("Walk");
path = new MotionPath();
path.addWayPoint(new Vector3f(500f,-83f,3f));
path.addWayPoint(new Vector3f(350f,-79f, 3f));
path.enableDebugShape(assetManager,rootNode);
// Initialize our motionTrack object
motionTrack = new MotionTrack(Robot1, path);
motionTrack.setDirectionType(MotionTrack.Direction.Path);
// Enable the motionTrack
motionTrack.setEnabled(true);
path2 = new MotionPath();
path2.addWayPoint(new Vector3f(180f,-50f,-100f));
path2.addWayPoint(new Vector3f(200f, -55f, -30f));
path2.enableDebugShape(assetManager,rootNode);
// Initialize our motionTrack object
motionTrack2 = new MotionTrack(Robot2, path2);
motionTrack2.setDirectionType(MotionTrack.Direction.Path);
// Enable the motionTrack
motionTrack2.setEnabled(true);
shootables.attachChild(Robot1);
shootables.attachChild(Robot2);
}
public void physicsTick(PhysicsSpace space, float f) {
if (ghost.getOverlappingObjects().size() > 0) {
final Vector3f bPoint = ghost.getPhysicsLocation();
try {
app.enqueue(new Callable<Boolean>() {
public Boolean call() throws Exception {
app.addMarker(bPoint);
return true;
}
});
} catch (Exception ex) {
}
}
}
public void pickUptype1(){
pickUpObject1 = new Node("pickUpObject1");
rootNode.attachChild(pickUpObject1);
Node cube1 = new Node();
cube1.attachChild(makeCube("the Deputy", 220f, -63f, -150f));
Node cube2 = new Node();
cube2.attachChild(makeCube("the Deputy2", 410f, -89f, -270f));
RigidBodyControl floor_phy = new RigidBodyControl(0.0f);
cube1.addControl(floor_phy);
RigidBodyControl floor_phy2 = new RigidBodyControl(0.0f);
cube2.addControl(floor_phy2);
bulletAppState.getPhysicsSpace().add(floor_phy);
bulletAppState.getPhysicsSpace().add(floor_phy2);
pickUpObject1.attachChild(cube1);
pickUpObject1.attachChild(cube2);
}
}

You include a lot of unnecessary code and judging from the style you are new to programming in general, I edited your question to make it readable so people could try and help (didn't fix the indenting though that would have taken far too much patience. The code should be stripped down to include only the physics code, member variables and setup for context. If your ghost control didn't rest on top of the ground it would fall through and leave your robot so its going to be constantly colliding with the ground or falling through the void after an initial pass through the ground.
You should be using getOverlappingObjects() to get the list of objects it's colliding with and then checking that list for the characters representation in the physics space.
Also this below is bad form. If your method is going to throw an exception you should know what it can throw and throw those exact exceptions and handle each one. Otherwise you're basically strapping on body armour and running around with your eyes closed because believe you won't get hurt.
public Boolean call() throws Exception
Also your enemies function is poorly designed. Functions should preferably be small, and should definitely only fulfill one purpose, whereas your function creates a node with shootables, creates two enemies and sets up controls.
Creating the node and attaching it to the root node should be in the constructor or an initialise function that is called near the start. And then you should have a function called something like addEnemy that adds a single enemy. For example:
/*
* adds an enemy and returns a reference to that enemy
*/
Spatial addEnemy()
{
//Characters are spatials typically in JMonkey
Spatial enemy=new Spatial();
CapsuleCollisionShape collisionShape=new CapsuleCollisionShape(4.0f, 10.0f);
CharacterControl characterControl = new CharacterControl(collisionShape, stepHeight);
enemy.addControl(characterControl);
getPhysicsSpaceState(characterControl);
shootables.attachChild(enemy);
}
Now you notice this is really different right?
Well in JMonkey Characters use Spatials (a class derived from node) and also they don't use rigid body physics, things like terrain are too bumpy, instead they use character controls and these keep them facing upright so they don't topple and allow you to set walk direction and view direction. The character control also gives access to a collision shape that you can run collides with on to get when character controls collide with each other.
For controlling your Spatial you'll want to subclass AbstractControl, using that you can get access to other controls and update your Spatial every so often. In my game all character are Spatials with different skins set the difference is in the controls.
The player has:
CharacterControl
//to send keyboard input to the character controller to move it
KeyboardControl
GunControl
Whereas the AI has
CharacterControl
//does path planning to get a route and steers character control along it
RouteController
GunControl
//AI to determine where/if I want to walk, what to shoot at, where to aim
BehaviourControl
You should be splitting a lot of this functionality into a path to make it easier to maintain, learning more about how the JMonkey API works by looking at examples and also learning how Object Oriented design works and how to structure things so they are easy to read and easy to maintain. If you're interested the book clean code by Robert C Martin is a great guide on a clean maintainable coding style :)
Any questions feel free to ask

Related

Why will my geometry not appear? (jMonkeyEngine)

I'm just now picking up jMonkeyEngine and I've encountered an issue I can't seem to solve.
In the simpleInitApp method in the main class, I can use the following code to successfully render a box:
Box playerBase = new Box(Vector3f.ZERO,1f,1f,1f);
Geometry playerBaseGeom = new Geometry("playerBase", playerBase);
Transform fixBaseHeight = new Transform(
new Vector3f(0f,(0.5f * 2f),0f));
playerBaseGeom.setLocalTransform(fixBaseHeight);
Material playerBaseMaterial = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
playerBaseMaterial.setColor("Color", ColorRGBA.Yellow);
playerBaseGeom.setMaterial(playerBaseMaterial);
rootNode.attachChild(playerBaseGeom);
I tried to use a class called Tower to be able to spawn several boxes representing towers (for a simple tower defense game). The tower class looks like this:
public class Tower {
private static final float HEIGHT = 0.5f;
private static final float WIDTH = 0.2f;
private static final float DEPTH = 0.2f;
private Geometry towerGeom;
private Material towerMaterial;
private Box tower;
public Tower(AssetManager assetManager, float x_coord, float z_coord) {
tower = new Box();
towerGeom = new Geometry("tower", tower);
towerMaterial = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
towerMaterial.setColor("Color", ColorRGBA.Green);
towerGeom.setMaterial(towerMaterial);
towerGeom.setLocalTranslation(x_coord, (0.5f * .5f),z_coord);
towerGeom.setLocalScale(WIDTH, HEIGHT, DEPTH);
}
public Geometry getGeometry() {
return towerGeom;
}
}
In the main class, in the simpleInitApp method, I tried to use my new Tower class like this:
List <Tower> towers = new ArrayList<Tower>();
towers.add(new Tower(assetManager, 10f,8f));
for(Tower t:towers) {
rootNode.attachChild(t.getGeometry());
}
However, no cube is rendered. Why? I used the exact same procedure shown in the beginning, which worked.
The Box() constructor is meant for serialization only and doesn't initialize the mesh. The constructor in your upper example is deprecated. Use:
tower = new Box(0.5f, 0.5f, 0.5f);
This will create a cube of the size 1x1x1 centered at [0, 0, 0].
Also, make sure you look at the tower. With the default camera position and the tower at [10, 0, 8], it will be placed behind you.
getCamera().lookAt( new Vector3f(10f, 0, 8f), Vector3f.UNIT_Y );
I recommend consulting the jME source code for this kind of problem so you can be sure whats going on.

How do i create a grid map on a png image with java?

The thing is that i'm helping a friend with a java project for the universty, and we have to create a remake of MSX's Knightmare. The game is pretty developed already but we don't know how to create the collision with the scenary's stuff, like the columns and the bridge over the river. In order to do this i thought that we could just create a logical "grid-mapping" over the png (the whole level is this image, invoked on the game like a plain image) and do the logic on it, just a boolean logic.
So the basic way, that i suggest to do, is a 2D array with this grid calculated on our minds. Is there some tool that we could use in order to do this easier or automated somehow?
Knightmare original version video
And this is the image that we are using on the game
I am going to try answering the title question, which seemed like the important one.
I wrote a little platform game in Java some time ago, and there I wrote a method called comprobarColisiones() (check collisions) which I call everytime
// Check collisions
comprobarColisiones();
h.mover(pasadas); //Move hero
// Moving enemies
if (h.x > en.getX()){
en.mover(h.getdx(), h.getIzq(),pasadas);
}
if (h.x> en2.getX()){
en2.mover(h.getdx(), h.getIzq(),pasadas);
}
// Moving static objects (rocks)
roca1.mover(h.getdx(),h.getIzq());
roca2.mover(h.getdx(),h.getIzq());
roca3.mover(h.getdx(),h.getIzq());
// REPAINTING
repaint();
// A time calculation that I use to control the game speed somewhere
tiempoAnteriorTipito = System.currentTimeMillis();
When I mean "static objects" it's just to differentiate objects with self-movement with those that just scroll as long as the hero moves, in your game (as in mine's) there probably will not be any static object (well, probably the scores and stuff), even rocks will scroll.
public void comprobarColisiones(){
// Getting bounds
Rectangle r1 = en.getBounds();
Rectangle r2 = en2.getBounds();
Rectangle rec_roca1 = roca1.getBounds();
Rectangle rec_roca2 = roca2.getBounds();
Rectangle rec_roca3 = roca3.getBounds();
// Getting bounds and resolving collisions with shooting objects
ArrayList martillos = Heroe.getMartillos();
for (int i = 0; i < martillos.size(); i++) {
Martillo m = (Martillo) martillos.get(i);
Rectangle m1 = m.getBounds();
if (r1.intersects(m1) && en.vive())
{
en.setVive(false);
m.visible = false;
}
else if (r2.intersects(m1)&& en2.vive())
{
en2.setVive(false);
m.visible = false;
}
}
// Checking if hero touches enemies
Rectangle heroecuad = h.getBounds();
if (heroecuad.intersects(r1)&&en.vive()){
perdio = true;
System.out.println("PERDIO CON EL ENEMIGO 1");
}
if (heroecuad.intersects(r2)&&en2.vive()){
perdio = true;
System.out.println("PERDIO CON EL ENEMIGO 2");
}
// Checking if hero touches static objects
if(heroecuad.intersects(rec_roca1)){
System.out.println("CHOCO ROCA 1");
}
if(heroecuad.intersects(rec_roca2)){
System.out.println("CHOCO ROCA 2");
}
if(heroecuad.intersects(rec_roca3)){
System.out.println("CHOCO ROCA 3");
}
}
I created enemies and static stuff and placed them when I load the escenario, just like this:
en = new Enemigo(800, ALTURA_PISO+8);
en2 = new Enemigo(900, ALTURA_PISO+8);
roca1 = new Roca(1650, ALTURA_PISO+17);
roca2 = new Roca(2200, ALTURA_PISO+17);
roca3 = new Roca(3400, ALTURA_PISO+17);
// Being the first number the initial X-Pos and the second the initial Y-Pos, this will change everytime the hero moves, of course
Probably in your game, you'll define any area of the map as explorable, and add some ghost objects to check intersection with the hero and stop his movement. For what I could see, water and columns should NOT be explorable by your hero.
Hope this would give you some ideas.

Randomizing Vertex Locations JUNG

I have created a java program of which starts with 1 vertex and from there it adds one vertice and 2 edges per cycle. It uses the Static Layout
Layout<Number, Number> staticLayout = new StaticLayout<Number, Number>(g, layout);
vv = new VisualizationViewer<Number, Number>(staticLayout, new Dimension(550, 550));
This is going to sound very un-technical, but the graph just doesn't look random enough, basically what i mean by this, is that every time it gets run they always seems to cluster a lot all the way around the edges of the graph, while very few get anywhere near the center. My program typically uses 100 generated verties and i will end up with half a dozen in the center and the others all round the edges.
Below is a random example that i just created just now.
Perhaps if someone could confirm that this is actually random, or if not if there is a way to get around this problem or if I've set something up wrong. As i wish to have the nodes as random as possible.
Any help would be appreciated.
Thanks
Below is the relevant code to the applet. involving its set up.
public class AnimatingAddNodeDemo extends JApplet {
//create a graph
Graph<Number, Number> ig = Graphs.synchronizedUndirectedGraph(new UndirectedSparseMultigraph<Number, Number>());
ObservableGraph<Number, Number> og = new ObservableGraph<Number, Number>(ig);
og.addGraphEventListener(new GraphEventListener<Number, Number>() {
public void handleGraphEvent(GraphEvent<Number, Number> evt) {
//System.err.println("got " + evt);
}
});
this.g = og;
//create a graphdraw
layout = new FRLayout<Number, Number>(g);
layout.setSize(new Dimension(600, 600));
setSize(700, 700);
Relaxer relaxer = new VisRunner((IterativeContext) layout);
relaxer.stop();
relaxer.prerelax();
Layout<Number, Number> staticLayout = new StaticLayout<Number, Number>(g, layout);
vv = new VisualizationViewer<Number, Number>(staticLayout, new Dimension(550, 550));
JRootPane rp = this.getRootPane();
rp.putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
getContentPane().setLayout(new BorderLayout());
}
Integer v_prev = null;
public void process() {
vv.getRenderContext().getPickedVertexState().clear();
vv.getRenderContext().getPickedEdgeState().clear();
try {
if (g.getVertexCount() < 100) {
//add a vertex
Integer v1 = nodeCount;
g.addVertex(v1);
nodeCount++;
System.out.println("adding vertex " + v1);
vv.getRenderContext().getPickedVertexState().pick(v1, true);
j.setText(myText);
// wire it to some edges
if (v_prev != null) {
Integer edge = edgeCount;
//vv.getRenderContext().getPickedEdgeState().pick(edge, true);
// let's connect to a random vertex, too!
int rand = (int) (Math.random() * (edgeCount-1)); // because there is a 0 node
while (v1.equals(rand)) {
System.out.println("avoided connecting to myself");
rand = (int) (Math.random() * (edgeCount-1)); // because there is a 0 node
}
edgeCount++;
g.addEdge(edge, rand, v1); //add an edge called var1, between the nodes var2 and var3
vv.getRenderContext().getPickedEdgeState().pick(edge, true);
System.out.println("Adding edge " + edge + " between " + rand + " & " + v1 + "()");
}
v_prev = v1;
layout.initialize();
Relaxer relaxer = new VisRunner((IterativeContext) layout);
relaxer.stop();
relaxer.prerelax();
vv.getRenderContext().getMultiLayerTransformer().setToIdentity();
vv.repaint();
} else {
done = true;
}
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
AnimatingAddNodeDemo and = new AnimatingAddNodeDemo();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(and);
and.init();
and.start();
frame.pack();
//frame.setVisible(true);
}
}
The reason your graph isn't random likely stems from the fact that you are passing a FRLayout to the constructor.
layout = new FRLayout<Number, Number>(g);
// ...
Layout<Number, Number> staticLayout = new StaticLayout<Number, Number>(g, layout);
You could make your own random layout class by extending AbstractLayout. But, according to the JavaDoc, StaticLayout will randomly layout nodes if you exclude the second constructor argument.
Layout<Number, Number> staticLayout = new StaticLayout(Number, Number>(g);
I Didn't get to a conclusion on whether or not it is random. So instead when i create each vertex i decided to set the particular co-ordinate of the vertex using layout.setLocation(v1, x, y)
With making x and y using math.random() and multiplying it by the width and height of my applet.
Therefore i now know that it is random.
EDIT
This actually seemed to work, however it actually did not, I had to remove the FRLayout.
It turns out FRLayout will not let you set your own locations because of what the algorithm does.
FRLayout is a force directed Layout that will reposition the vertices
according to the topology of the graph.
So i therefore changed the FRLayout to StaticLayout, removed a few things that worked only with FRLayout and it works correctly now.

Collision Detection Tmx Maps using libgdx (java)

So I'm trying to implement collision detection in my game and I have a layer in the tmx file called Collision. The LIBGDX onsite tutorials doesnt cover interaction with object layers and it was hard to figure out how to render the map in the first place. This is how I render my screen, I would like to learn how to get my collision layer and then get my sprite to interact with it.
#Override
public void render(float delta) {
translateCamera();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
renderer.setView(camera);
renderer.render(bgLayers);
// renderer.render();
batch.begin();
batch.draw(playerDirect, Gdx.graphics.getWidth() / 2,
Gdx.graphics.getHeight() / 2);
batch.end();
renderer.render(fgLayers);
}
There is a way to use the object layer. Don't give up hope!
One major advantage of this method over using tile properties is the ease with which you can generate fewer, larger bodies for improved efficiency in Box2d. Plus, even better, those bodies can be any shape you want! Rather than dozens of squared-off bodies, my sample level in my game now has just three funny-shaped (read more organic-looking) ChainShape-based bodies.
I answered the same question on GameDev the other day, after a serious hunt deep in the jungles of the Web. The tutorial I found didn't quite work for me as-is, so a little editing later I came up with this:
public class MapBodyBuilder {
// The pixels per tile. If your tiles are 16x16, this is set to 16f
private static float ppt = 0;
public static Array<Body> buildShapes(Map map, float pixels, World world) {
ppt = pixels;
MapObjects objects = map.getLayers().get("Obstacles").getObjects();
Array<Body> bodies = new Array<Body>();
for(MapObject object : objects) {
if (object instanceof TextureMapObject) {
continue;
}
Shape shape;
if (object instanceof RectangleMapObject) {
shape = getRectangle((RectangleMapObject)object);
}
else if (object instanceof PolygonMapObject) {
shape = getPolygon((PolygonMapObject)object);
}
else if (object instanceof PolylineMapObject) {
shape = getPolyline((PolylineMapObject)object);
}
else if (object instanceof CircleMapObject) {
shape = getCircle((CircleMapObject)object);
}
else {
continue;
}
BodyDef bd = new BodyDef();
bd.type = BodyType.StaticBody;
Body body = world.createBody(bd);
body.createFixture(shape, 1);
bodies.add(body);
shape.dispose();
}
return bodies;
}
private static PolygonShape getRectangle(RectangleMapObject rectangleObject) {
Rectangle rectangle = rectangleObject.getRectangle();
PolygonShape polygon = new PolygonShape();
Vector2 size = new Vector2((rectangle.x + rectangle.width * 0.5f) / ppt,
(rectangle.y + rectangle.height * 0.5f ) / ppt);
polygon.setAsBox(rectangle.width * 0.5f / ppt,
rectangle.height * 0.5f / ppt,
size,
0.0f);
return polygon;
}
private static CircleShape getCircle(CircleMapObject circleObject) {
Circle circle = circleObject.getCircle();
CircleShape circleShape = new CircleShape();
circleShape.setRadius(circle.radius / ppt);
circleShape.setPosition(new Vector2(circle.x / ppt, circle.y / ppt));
return circleShape;
}
private static PolygonShape getPolygon(PolygonMapObject polygonObject) {
PolygonShape polygon = new PolygonShape();
float[] vertices = polygonObject.getPolygon().getTransformedVertices();
float[] worldVertices = new float[vertices.length];
for (int i = 0; i < vertices.length; ++i) {
worldVertices[i] = vertices[i] / ppt;
}
polygon.set(worldVertices);
return polygon;
}
private static ChainShape getPolyline(PolylineMapObject polylineObject) {
float[] vertices = polylineObject.getPolyline().getTransformedVertices();
Vector2[] worldVertices = new Vector2[vertices.length / 2];
for (int i = 0; i < vertices.length / 2; ++i) {
worldVertices[i] = new Vector2();
worldVertices[i].x = vertices[i * 2] / ppt;
worldVertices[i].y = vertices[i * 2 + 1] / ppt;
}
ChainShape chain = new ChainShape();
chain.createChain(worldVertices);
return chain;
}
}
Assuming you've set things up so that the size of your tiles correspond to 1 square metre (1 square unit, if you prefer) in your Box2d World, the static Bodys this produces will be exactly where you drew them in Tiled. It was so satisfying to see this up and running, believe you me.
I'd reccomend adding blocked properties to the actual tiles themselves - you can add tile properties via the Tiled editor on the actual tileset. You can retrieve their properties on the tileset. I'm going to quote the documentation:
A TiledMap contains one or more TiledMapTileSet instances. A tile
set contains a number of TiledMapTile instances. There are multiple
implementations of tiles, e.g. static tiles, animated tiles etc. You
can also create your own implementation for special
Cells in a tile layer reference these tiles. Cells within a layer can
reference tiles of multiple tile sets. It is however recommended to
stick to a single tile set per layer to reduce texture switches.
Specifically, call getProperties on the tile in a tileset. This will retrieve the propeties - then you can compare to your custom attribute and this can tell you if a particular tile is blocked - then you can go ahead and implement your own collision logic.

How to create Boundaries from Sprites(AndEngine)

So i have sprites that are should be un-walkable for my character.
The problem is im not sure how to do this.
Here is what i am trying. I am having the sprites added to a Linked List when they are loaded from the level.
Then i iterate through the list to detect if the character is colliding with any of the unwalkable sprites/tiles.
I do this on the engines update thread which runs about every second.
Here is how i am doing this:
mScene.registerUpdateHandler(new IUpdateHandler(){
#Override
public void onUpdate(float pSecondsElapsed) {
Iterator<Sprite> wall_collision = unwalkable_Sprites.iterator();
while(wall_collision.hasNext()){
Sprite sprite = wall_collision.next();
if(character_sprite.collidesWith(sprite)){
}
}
}
#Override
public void reset() {
// TODO Auto-generated method stub
}
});
So the question is how do i position the character when it collides with the unwalkable tile so the character doesnt even cross over into the tile..To the user it should seem like a boundary.
Does anyone have any suggestions or know how i can do this?
Look into this example
use the same code for you un-walkable tiles as "ground" in example. You should use static bodies:
this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);
final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0.5f, 0.5f);
Here you can use Shape as in example or for example Sprite
//final Shape yourTile = new Rectangle(0, CAMERA_HEIGHT - 2, CAMERA_WIDTH, 2);
Sprite yourTile = new Sprite(...);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, yourTile, BodyType.StaticBody, wallFixtureDef);
Here you can find box2dExtension for AndEngine (it need for using Bodies)
Sorry for my English :) Hope this will help you.
P.S. and you don't need to check collisions for this issue anymore.

Categories