LibGDX TiledMap - don't detect Collisions - java

first of all, sorry, because of my rusty English. Since i learnt German i forgot the English.
I'm doing tests with libGDX and my code doesn't detect any collisions.
In my Screen:
public Pantalla(SpriteBatch batch_1) {
batch = batch_1;
screenWidth = Gdx.graphics.getWidth();
screenHeight = Gdx.graphics.getHeight();
stage = new Stage(new StretchViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()),batch);
Gdx.input.setInputProcessor(stage);
camera = new OrthographicCamera();
camera.setToOrtho(false, 1000, 840);
camera.update();
mapas = new Mapas(camera);
// ACTORS
indiana_actor = new indiana_Actor();
//Here comes TOUCHPAD with Skin blaBlaBla...
if (touchpad.isTouched()) {
if (touchpad.getKnobX() > 120) {
indiana_actor.moveBy(32,0);
camera.translate(32, 0);
return; }
}
stage.addActor(indiana_actor);
stage.addActor(touchpad);
Gdx.input.setInputProcessor(stage);
}
public void render(float delta) {//TODO RENDER
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
mapas.MapasRender(camera,indiana_actor);
batch.begin();
batch.end();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
indiana_actor Class:
public indiana_Actor() {
W=Gdx.graphics.getWidth(); H=Gdx.graphics.getHeight();
bounds=new Rectangle((int)getX(), (int)getY(), (int)getWidth(), (int)getHeight());
}
Animation anim_temp;
#Override
public void draw(Batch batch, float parentAlpha) {
stateTime += Gdx.graphics.getDeltaTime();
batch.setColor(getColor());
batch.draw(Assets.indiana_stop_arriba, (W/2), (H/2), 110, 160);
bounds=new Rectangle((int)getX(), (int)getY(), (int)getWidth(), (int)getHeight());
}
and Mapas Class.
In these class i get the Objects in the "objetos" TiledLayer, and triying to check collisions with a for(...) in the renderer.
public Mapas(OrthographicCamera camera2){
map = new TmxMapLoader().load("terrain/prueba.tmx");
renderer = new OrthogonalTiledMapRenderer(map, 10);//ESCALA
renderer.setView(camera2);
collisionObjects = map.getLayers().get("objetos").getObjects();
collisionRects = new Array<Rectangle>();
collisionRects_total=collisionObjects.getCount();
int tileWidth = 32; // whatever your tile width is
int tileHeight = 32; // whatever your tile height is
for (int i = 0; i < collisionObjects.getCount(); i++) {
RectangleMapObject obj = (RectangleMapObject) collisionObjects.get(i);
Rectangle rect = obj.getRectangle();
collisionRects.add(new Rectangle(rect.x / tileWidth, rect.y / tileHeight, rect.width / tileWidth, rect.height / tileHeight));
}
}
public void MapasRender(OrthographicCamera camera2,indiana_Actor indi){
camera2.update();
renderer.setView(camera2);
renderer.render();
for (int i = 0; i < collisionRects_total; i++) {
Rectangle rect = collisionRects.get(i);
if (indi.bounds.overlaps(rect)){
Gdx.app.log("EVENTO", "MAPAS RENDER - COLISION!");
}if (rect.overlaps(indi.bounds)){
Gdx.app.log("EVENTO", "MAPAS RENDER - COLISION!");
}
}
}
I know (Through the logcat) that the
" for (int i = 0; i < collisionRects_total; i++) {
Rectangle rect = collisionRects.get(i); "
get always the objectsRectangle , but in the next line find any overlaps.
Is that a problem with the actor bounds-rectangle?A problem when moving actor through the map??....
Thanks in advance!!

Why dont U at first check if your rectangle for collision draw correctly on position. You can do that by calling
shapeRenderer.begin(ShapeType.Line);
shapeRenderer.setColor(Color.NAVY);
shapeRenderer.rect(object.getrect().x,
object.getrect().y,object.getrect().width,
object.getrect().height);
may be you draw collision rectangles at wrong position so collision will never occur.

Related

Processing 2,2,1 java. Reset position if inside 3d shape

i have made this code,with a 3d model,the model starts dismorph after 100 frames.I have a box shape that is moved with mouse,i want when ever the vertices be inside the box,to reset their position to the original position,and reconstruct the model,while the others dismorph. Always resetting the position when they are in the box,and move when they are not.Can anyone help me.Until now what it happens,is that when the vertices are inside the box they stop moving.
Thanks in Advance
import peasy.*;
import saito.objloader.*;
OBJModel model ;
OBJModel tmpmodel ;
PeasyCam cam;
float easing = 0.005;
float r;
float k =0.00001;
int VertCount;
PVector[] Verts;
PVector Mouse;
void setup()
{
size(800, 800, P3D);
frameRate(30);
noStroke();
model = new OBJModel(this, "Model2.obj", "absolute", TRIANGLES);
model.enableDebug();
model.scale(100);
model.translateToCenter();
tmpmodel = new OBJModel(this, "Model2.obj", "absolute", TRIANGLES);
tmpmodel.enableDebug();
tmpmodel.scale(100);
tmpmodel.translateToCenter();
cam = new PeasyCam(this, width/2, height/2, 0, 994);
}
void draw()
{
background(129);
lights();
int VertCount = model.getVertexCount ();
PVector[] Verts = new PVector[VertCount];
PVector[] locas = new PVector[VertCount];
float r =80;
PVector Mouse = new PVector(mouseX-width/2, mouseY-height/2, 0);
cam.setMouseControlled(true);
//println(frameCount);
pushMatrix();
translate(width/2, height/2, 0);
for (int i = 0; i < VertCount; i++) {
//PVector orgv = model.getVertex(i);
Verts[i]= model.getVertex(i);
arrayCopy(Verts, locas);
//PVector tmpv = new PVector();
if (frameCount> 100) {
float randX = random(-5, 5);
float randY = random(-5, 5);
float randZ = random(-5, 5);
PVector Ran = new PVector(randX, randY, randZ);
//float norX = abs(cos(k)) * randX;
//float norY = abs(cos(k)) * randY;
//float norZ = abs(cos(k)) * randZ;
if (Verts[i].x > Mouse.x - r/2 && Verts[i].x < Mouse.x + r/2) {
if (Verts[i].x > Mouse.y - r/2 && Verts[i].x < Mouse.y + r/2) {
if (Verts[i].x > Mouse.z - r/2 && Verts[i].x < Mouse.z + r/2) {
arrayCopy(locas, Verts);
}
}
} else {
Verts[i].x+=Ran.x;
Verts[i].y+=Ran.y;
Verts[i].z+=Ran.z;
if (Verts[i].x > width/2 || Verts[i].x < -width/2) {
Verts[i].x+=-Ran.x;
}
if (Verts[i].y > height/2 || Verts[i].y < -height/2) {
Verts[i].y+=-Ran.y;
}
if (Verts[i].z < -800/2 || Verts[i].z > 800/2) {
Verts[i].z+=-Ran.z;
}
}
tmpmodel.setVertex(i, Verts[i].x, Verts[i].y, Verts[i].z);
}
k+=0.0001;
}
pushMatrix();
translate(Mouse.x, Mouse.y, Mouse.z);
noFill();
stroke(255);
box(r);
popMatrix();
noStroke();
tmpmodel.draw();
popMatrix();
pushMatrix();
translate(width/2, height/2, 0);
noFill();
stroke(255);
box(width, height, 600);
popMatrix();
}
if you want to run it use the model from the saito obj example or the PshapeObj example.
There are a few things about your code that don't make a ton of sense (some comments might have helped with that). Why are you copying the array like that?
In any case, I would start simpler if I were you. I would adopt an object oriented approach, where you create a class that encapsulates a point's original position as well as its current position.
Here's an example that does this in two dimensions, but this approach generalizes to three dimensions:
ArrayList<MovingPoint> points = new ArrayList<MovingPoint>();
float circleDiameter = 200;
void setup(){
size(500, 500);
for(int i = 0; i < 100; i++){
points.add(new MovingPoint());
}
}
void draw(){
background(0);
noFill();
stroke(255, 0, 0);
ellipse(mouseX, mouseY, circleDiameter, circleDiameter);
fill(255);
stroke(255);
MovingPoint previousPoint = null;
for(MovingPoint mp : points){
mp.draw();
if(previousPoint != null){
line(previousPoint.current.x, previousPoint.current.y, mp.current.x, mp.current.y);
}
previousPoint = mp;
}
}
class MovingPoint{
PVector original;
PVector current;
public MovingPoint(){
original = new PVector(random(width), random(height));
current = original.copy();
}
void draw(){
if(dist(current.x, current.y, mouseX, mouseY) < circleDiameter/2){
//inside circle, reset position
current = original.copy();
}
else{
//outside circle, move randomly
current.x += random(-5, 5);
current.y += random(-5, 5);
}
ellipse(current.x, current.y, 10, 10);
}
}
You shouldn't have to go through the rigmarole of copying arrays. Just use a class that remembers each point's original and current positions, and then switch between them depending on the mouse position.
If you still can't get it working, please post another question that works from this example instead of your entire sketch. It's hard to help if we don't have access to the libraries you're using, so you're better off getting rid of them and narrowing the problem down to as few lines as possible. Good luck.

Libgdx Scaling coordinates for different devices

I have made a simple game where you click on a object and it should dissapear. It works fine on desktop with the dimensions 240 x 480 but on my phone the dimensions are wider like 1920 x 1080 so the touch down coordinates are different so on desktop it might log the touch 100 x 50 but if i tapped the same place on phone it would be 400 x 200 so i just want to scale them or use the same.
private double WidthScale = (272 / Gdx.graphics.getWidth());
private double HeightScale = (408 / Gdx.graphics.getHeight());
private Array<Rectangle> rockets;
private long lastDropTime = 0;
private float tap_X = 0;
private float tap_Y = 0;
public GameRenderer() {
cam = new OrthographicCamera();
cam.setToOrtho(false, 408, 272);
batch = new SpriteBatch();
rockets = new Array<Rectangle>();
spawnRocket();
}
public void render(){
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
cam.update();
batch.setProjectionMatrix(cam.combined);
batch.begin();
for(Rectangle rocket : rockets) {
batch.draw(AssetLoader.rocket ,rocket.x, rocket.y,
rocket.width, rocket.height);
}
batch.end();
if (Gdx.input.justTouched()){
tap_X = (int) (Gdx.input.getX() * HeightScale);
tap_Y = (int) ((Gdx.graphics.getHeight()-Gdx.input.getY()) * WidthScale);
Gdx.app.log("MyTag", String.valueOf(tap_X));
Gdx.app.log("MyTag", String.valueOf(tap_Y));
Gdx.app.log("MyTag", String.valueOf(HeightScale));
Gdx.app.log("MyTag", String.valueOf(WidthScale));
}
Iterator<Rectangle> iter = rockets.iterator();
while(iter.hasNext()) {
Rectangle rocket = iter.next();
rocket.y -= 70 * Gdx.graphics.getDeltaTime();
if(rocket.y + 32 < 0) iter.remove();
if (rocket.x < tap_X && tap_X < rocket.x + rocket.width) {
Gdx.app.log("MyTag", "getRekt");
if (tap_Y > rocket.y && tap_Y < rocket.y + rocket.height) {
Gdx.app.log("MyTag", "poo");
iter.remove();
}
}
}
if(TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRocket();
}
private void spawnRocket() {
Gdx.app.log("MyTag", "Rocket Spawned");
Rectangle rocket = new Rectangle();
rocket.x = MathUtils.random(0 , 272 - 16);
rocket.y = 408 + rocket.height;
rocket.height = 32;
rocket.width = 16;
rockets.add(rocket);
lastDropTime = TimeUtils.nanoTime();
}
In order to work with different screen sizes, you have to deal with viewports, there's an entirely section in libGDX wiki that shows how to work with it. A fast example could be the following (however, I suggest to read the wiki and try others viewports by yourself):
// Declare a viewport object
private Viewport v;
public GameRenderer() {
// initialize after your camera initialization
v = new FitViewport(408, 272, cam); // <- I have use a FitViewport
// but you can use others
// I guess you could remove the setToOrtho() but not too sure...
// ... rest of code
}
You have to properly dispose and update this object *
A thing you should consider is, when you use something like Gdx.input.getX() you are getting a screen current position, you have to transform this coordinate system to your world coordinate system. Wherever you use something like that you have to do the following:
Vector3 v = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
v = cam.unproject(v);
// now v has your coordinate world system and you can properly make use of it
// you can do now something like:
tap_x = (int) v.x;
tap_y = (int) v.y;
Hope you find this useful.

libGDX Strange Rendering Bug

I've recently started my first libGDX game, and it is all going well, everything renders fine but after about a minute nothing renders, the rendering calls are still made and the spritebatch works fine, I'm just left with a black screen, I have even changed the 'glClearColor()' to but I'm still left with a black screen. I've have no idea what this could be.
My main class:
#Override
public void create() {
Gdx.graphics.setDisplayMode(Settings.screenWidth, Settings.screenHeight, Settings.fullscreen);
Gdx.graphics.setVSync(Settings.VSync);
Gdx.graphics.setTitle("Trench Warfare");
batch = new SpriteBatch(1000);
previous = System.currentTimeMillis();
currentMap = new Map(this, 0);
currentMap.addObject(new ColourMapObject(this, 0));
}
private void update() {Settings.screenHeight, Settings.fullscreen);
Gdx.graphics.setVSync(Settings.VSync);
batch.setColor(new Color(Settings.brightness, Settings.brightness, Settings.brightness, 1.0f));
float delta = ((float)(System.currentTimeMillis() - previous)) / 1000.0f;
previous = System.currentTimeMillis();
currentMap.update(delta);
}
#Override
public void render() { //Always called
update();
Gdx.gl.glClearColor(1, 0, 0, 1); //Red colour still black screen.
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
currentMap.render(batch); //Basicly list of textures to be rendered, they never stop rendering (Being called) despite black screen.
batch.end();
batch.flush();
}
EDIT:
We've determined that after some time SpriteBatch render a black screen over the red clear colour, It also stops rendering the texture.
I've also determined that the SpriteBatch's tint or colour stays white even during the black screen.
EDIT, this code takes in a texture and then turns into a different texture with different colours:
public class ColourMapObject extends MapObject {
public enum Type {
Dirt,
Water,
Trench,
}
private Texture terrainMap;
private Texture trenchMap;
private Texture soldierMap;
private Texture buildingMap;
private Texture shipMap;
private int levelId;
private Texture finalTexture;
private Type[][] types;
public ColourMapObject(TrenchMain main, int levelId) {
super(main);
this.levelId = levelId;
//finalTexture = new Texture("/map" + String.valueOf(levelId) + "/terrainMap.png");
finalTexture = new Texture("black.png");
finalTexture.getTextureData().prepare();
loadMap(levelId);
}
private void loadMap(int levelId) {
//terrainMap = new Texture("/map" + String.valueOf(levelId) + "/terrainMap.png");
terrainMap = new Texture("terrainMap.png");
types = new Type[terrainMap.getWidth()][terrainMap.getHeight()];
terrainMap.getTextureData().prepare();
Pixmap pixmap = terrainMap.getTextureData().consumePixmap();
for(int x = 0; x < terrainMap.getWidth(); x++) {
for(int y = 0; y < terrainMap.getHeight(); y++) {
types[x][y] = RandomMapColour.getType(new Color(pixmap.getPixel(x, y)));
if(types[x][y] == null) types[x][y] = Type.Dirt;
}
}
// trenchMap = new Texture("/map" + String.valueOf(levelId) + "/trenchMap.png");
//
//
// soldierMap = new Texture("/map" + String.valueOf(levelId) + "/soldierMap.png");
//
//
// buildingMap = new Texture("/map" + String.valueOf(levelId) + "/buildingMap.png");
//
//
// shipMap = new Texture("/map" + String.valueOf(levelId) + "/shipMap.png");
}
#Override
public void update(float delta) {
super.update(delta);
Pixmap draw = new Pixmap(Settings.screenWidth, Settings.screenHeight, Format.RGB888);
float pX = (float)terrainMap.getWidth() / (float)draw.getWidth();
float pY = (float)terrainMap.getHeight() / (float)draw.getHeight();
for(int x = 0; x < draw.getWidth(); x++) {
for(int y = 0; y < draw.getHeight(); y++) {
switch(types[(int)((float)x * pX)][(int)((float)y * pY)]) {
case Dirt:
draw.drawPixel(x, y, RandomMapColour.getDirtColour());
break;
case Trench:
draw.drawPixel(x, y, RandomMapColour.getTrenchColour());
break;
case Water:
draw.drawPixel(x, y, RandomMapColour.getWaterColour());
break;
}
}
}
finalTexture = new Texture(draw);
}
#Override
public void render(SpriteBatch batch) {
super.render(batch);
float sx = ((float)TrenchMain.getScreenWidth()) / ((float)finalTexture.getWidth());
float sy = ((float)TrenchMain.getScreenHeight()) / ((float)finalTexture.getHeight());
batch.draw(finalTexture, 0, 0, 0, 0, finalTexture.getWidth(), finalTexture.getHeight(), sx, sy, 0, 0, 0, finalTexture.getWidth(), finalTexture.getHeight(), false, false);
}
I finally figuired it out, for those who are wonder, what I was doing was creating a new finalTexture every update with disposing of the old one.
Simply dispose of the texture.
finalTexture.dispose();

Centering map or camera 2D game

I've tried so many solutions that it's possible that my code is a bit mixed up, but whatever I try, it just won't work.
Basically I made a map with Tiled, where my player can run around and bump into stuff. I want the whole map to be visible for the whole time (it's 20 by 15, 64 pixels a tile). The camera doesn't need to move around or follow the player, it has to stay still at the center of the map.
The problem is that the map only shows in the upper right corner of the screen. When I centered the camera to the map itself it messed up the collission detection, (bumping into trees while they were not visible & walking through visible trees). So what I want to do is center the map to 0,0 where my camera also is (at least I think..).
Another thing I'd like to accomplish is that the size of the map gets resized to match different mobile phones. Tried to accomplish this with the stretchviewport, but haven't been able to test this.
public class PlayScreen implements Screen {
TiledMap map;
OrthogonalTiledMapRenderer mapRenderer;
OrthographicCamera cam;
float unitScale = 1 / 64f;
OrthogonalTiledMapRenderer renderer = new OrthogonalTiledMapRenderer(map, unitScale);
Viewport viewport;
public void show() {
map = new TmxMapLoader().load("maps/map.tmx");
mapRenderer = new OrthogonalTiledMapRenderer(map);
cam = new OrthographicCamera(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);
cam.setToOrtho(false);
viewport = new StretchViewport(1280, 960, cam);
bounds = new ArrayList<Rectangle>();
for(int i = 0; i < 20; i++){
for(int j = 0; j < 15; j++){
TiledMapTileLayer cur = (TiledMapTileLayer) map.getLayers().get(1);
Cell cell = new Cell();
Vector3 center = new Vector3(cur.getWidth() * cur.getTileWidth() / 2, cur.getHeight() * cur.getTileHeight() / 2, 0);
cam.position.set(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, 0);
cam.update();
if(cur.getCell(i,j) != null){ //null = first layer != --> if its not
cell = cur.getCell(i, j);
System.out.println(i + ", " + j + ", " + cell.getTile().getId());
bounds.add(new Rectangle(i * 64, j * 64, 64 , 64));
}
}
}
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
mapRenderer.setView(cam);
mapRenderer.render();
cam.position.set(0, 0, 0);
cam.update();
batch.setProjectionMatrix(cam.combined);
batch.begin();
batch.draw(player.getCurrentFrame(), player.getPosition().x , player.getPosition().y);
player.update();
for(int i = 0; i < bounds.size(); i++){
if(bounds.get(i).overlaps(player.getBounds())){
int x = (int)bounds.get(i).x / 64;
int y = (int)bounds.get(i).y / 64;
TiledMapTileLayer cur = (TiledMapTileLayer)map.getLayers().get(1);
Cell cell = cur.getCell(x, y);
if(cell.getTile().getProperties().containsKey("blocked")){
System.out.println("bush");
}
player.reAdjust();
}
}
batch.end();
}
public void resize(int width, int height) {
viewport.update(width, height);
}
Nevermind, I deleted: cam.position.set(0, 0, 0); and everything seems to work just fine. Guess I already made some changes what caused it to work, just didn't see it cause this was still around.

Drawing a CatmullRomSpline in libgdx with an endpoint and startpoint

So my goal is to draw a spline similar to this one (where the line goes through each point):
But the spline loops around (from the end point 2 back to the start point):
I tried changing the "continuous" boolean in the catmullromspline, but that resulted in only a dot being drawn in the center of the screen.
I also ended the line drawing when it hit the last point, but the result was ugly because the line was still curving at the start and end points.
I looked everywhere in the source code, and could not find a function that could prevent it from looping.
And as far as i know, bezier splines don't go through all the points (they only pass near them).
So what should I do?
Here's my code:
...
public class GameScreen implements Screen {
final game game;
float w=800;
float h=480;
OrthographicCamera camera;
long startTime;
Texture baseTexture=new Texture(Gdx.files.internal("white.png"));
public GameScreen(final game gam) {
this.game = gam;
startTime = TimeUtils.millis();
camera = new OrthographicCamera();
camera.setToOrtho(false, w, h);
setup();
}
//https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines
int k = 10000; //increase k for more fidelity to the spline
Vector2[] points = new Vector2[k];
Vector2 cp[] = new Vector2[]{
new Vector2(w/2, h), new Vector2(w/2, h/2),new Vector2(50, 50)
};
ShapeRenderer rope=new ShapeRenderer();
public void setup(){
CatmullRomSpline<Vector2> myCatmull = new CatmullRomSpline<Vector2>( cp, true);
for(int i = 0; i < k; ++i)
{
points[i] = new Vector2();
myCatmull.valueAt(points[i], ((float)i)/((float)k-1));
}
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl20.glLineWidth(50);
game.batch.begin();
rope.setAutoShapeType(true);
rope.begin();
for(int i = 0; i < k-1; ++i)
{
//rope.line(points[i], points[i+1]);
//shaper.line(myCatmull.valueAt(points[i], ((float)i)/((float)k-1)), myCatmull.valueAt(points[i+1], ((float)i)/((float)k-1)));
game.batch.draw(baseTexture, points[i].x, points[i].y, 5, 5);
}
rope.end();
for(int i=0;i<cp.length;i++){//draw the location of each point
game.font.draw(game.batch, "point "+i, cp[i].x, cp[i].y);
}
//logging systems
for(int i=0;i<20;i++){
if(Gdx.input.isTouched(i))
game.font.draw(game.batch, "x:"+Gdx.input.getX(i)+" y:"+Gdx.input.getY(i), 0, (game.font.getCapHeight()+10)*(i+1));
}
game.font.draw(game.batch, "fps:"+Gdx.graphics.getFramesPerSecond()+" log:"+log, 0, h-game.font.getCapHeight());
game.batch.end();
}
...

Categories