I have something kind of
private AxisAlignedBB boundingBox = new AxisAlignedBB(-0.34D, 0D, -0.34D, 1.34D, 3.24D, 1.34D);
#Override
public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, World worldIn, BlockPos pos)
{
return boundingBox;
}
#Override
public AxisAlignedBB getSelectedBoundingBox(IBlockState state, World worldIn, BlockPos pos)
{
return boundingBox.offset(pos);
}
#Override
public boolean isFullCube(IBlockState state) {
return false;
}
#Override
public boolean isOpaqueCube(IBlockState state) {
return false;
}
in the class of my tile entity. And when i'm trying to walk through the middle of block, the collision bounding box works correct, but when i try to jump on the block, i get stuck in it, trying to fall through. Also i get stuck in the same block if i try to walk into the block from the corners or trying to stand on the whole construction: i fall until i reach the height of 2D and then glitches begin. Corners of the block act as if there was no bounding box for the corners. Is it possible to make block bounding boxes work correct?
The block and its bounding box.
Actual working (or partially working) area.
I would recommend using dummy blocks for this. When your block is placed, spawn dummy blocks in the required areas. When your block, or the dummy blocks, are broken, break the entire structure of dummies and true blocks.
Related
hey am a beginner in Libgdx. i am a bit confused about disposing the stuff.
Texture brickTexture;
Array<Brick> bricks;
public Game {
brickTexture = new Texture("brick.png");
bricks = new Array<Brick>();
for (int i = 0; i < 10; i++) {
Brick brick = new Brick(i, brickTexture);
bricks.add(brick);
}
}
void dispose () {
brickTexture.dispose(); // brick texture loaded in this class
for (Brick brick : bricks) brick.brickTexture.dispose(); // disposing the public texture which was earlier passed on to the brick class
}
Should both of the lines be in the dispose method or only the first one ?
You only have to do this once. It's the same Texture object so when you dispose it on any reference no other object can use it anymore. It's disposed.
Also you might want to check out AssetManager class, which handles disposing stuff for you.
You are using "bricktexture" for every "Brick" in the ArrayList, so you are basically pointing to the same object so you should only dispose "bricktexture" once.
If you also want to "free" the array, probably you should call
bricks.clear();
Which will become empty (as with no elements inside).
public class Player {
private Sprite enemy;
public Rectangle bounds;
private SpriteBatch batch;
private float deltaTime;
private float timer;
private ArrayList<Sprite> enemies;
private Iterator<Sprite> enemyIterator;
private ArrayList<Vector2> posCoordinate;
Sprite newEnemy;
public void create(){
batch=new SpriteBatch();
timer=0;
enemy=new Sprite(new Texture(Gdx.files.internal("spr_player.png")));
bounds=new Rectangle(200,700,82,80);
enemies=new ArrayList<Sprite>();
posCoordinate=new ArrayList<Vector2>();
newEnemy=Pools.obtain(Sprite.class);
}
public void update(){
deltaTime=Gdx.graphics.getDeltaTime();
enemyIterator=enemies.iterator();
timer+=1*deltaTime;
if(timer>=1f){
newEnemy(); //method called every second
timer-=1;
}
}
public void newEnemy(){
Vector2 position=Pools.obtain(Vector2.class); //vector2 is created for each enemy every second.
position.set(200,700);
posCoordinate.add(position);
newEnemy=Pools.obtain(Sprite.class); //enemy created every second
newEnemy.set(enemy);
enemies.add(newEnemy);
}
public void draw(SpriteBatch batch){
//this is where the enemy position is set and movement
for(Sprite enemy:enemies){
enemy.draw(batch);
}for(Vector2 position:posCoordinate){
newEnemy.setPosition(position.x,position.y);
position.y-=2;
}
}
}
newEnemy() method is being called every second that's why a new sprite is being rendered every second.
Basically what I'm trying to do is that when a new enemy is spawned, it must move downward until it goes outside the screen.But what is happening is that the enemy will only move for one second.
I think you've confused things by introducing the member variable newEnemy. You have a method that creates a new enemy and adds it to your enemies list, and after that, there should not be a reason to reference it separately from the list, so you should just allow the newEnemy reference to be discarded.
Therefore, you should remove the Sprite newEnemy line from your class, and just declare it within the newEnemy() method.
Also, there's no need for your list of Vector2's for positions, because the Sprite class already stores a position. You just need to move the individual sprites. So remove everything related to posCoordinate as well. Your newEnemy() method should just look like this:
private void newEnemy(){
Sprite newEnemy = Pools.obtain(Sprite.class);
newEnemy.set(enemy); //I recommend renaming your `enemy` variable to something like `prototypeEnemy` for clarity
newEnemy.setPosition(200, 700); //need to start it at correct location.
enemies.add(newEnemy);
}
Finally, in your draw method (which is the wrong place for updates) you're trying to move only the most recent enemy created, instead of moving all of them. Note that every iteration of the loop is affecting the same instance: newEnemy, which is only the last enemy you created.
Here's how I would revise your class.
1) The movement speed should be a constant, measured in world units per second, so declare something like this at the top of your class:
private static final float ENEMY_SPEED = -120f;
2) At the bottom of your update() method, you can add this to cause all of your enemies to move:
for (Sprite sprite : enemies){
sprite.translateY(deltaTime * ENEMY_SPEED);
}
3) Under that, you can add a check for when they are off screen, so you can remove them. The iterator instance must be used to avoid a ConcurrentModificationException.
Iterator<Sprite> enemyIterator = enemies.iterator();
while (enemyIterator.hasNext()){
Sprite sprite = enemyIterator.next();
if (sprite.getY() + sprite.getHeight() < screenBottom) //screenBottom is something you can calculate from your camera like camera.getPosition().y - camera.getHeight()/2
removeEnemy(sprite);
}
4) And to remove them, since you're using pooling, you should put them back in the pool when you finish with them
private void removeEnemy(Sprite sprite){
enemies.remove(sprite);
Pools.free(sprite);
}
5) In your draw method, remove the second for loop, now that we're handling the position update in the update method.
I have written the following code. I would like to stop drawings once object one the collision has occurred. Unfortunately, it only stops drawing the object only when the collision is occurring and then starts drawing the object again.
To give an example of what I am trying to learn is: player collects coin, coin disappears. if the player misses coin, the coin still appears on screen.
The idea is to learn the basic concepts before I start putting things together. Copying code without understanding is no fun. Thanks in advance.
batcher.begin();
if (egg.collected) {
batcher.draw(AssetLoader.textureEgg, eggRect.x, eggRect.y, eggRect.width, eggRect.height);
}
batcher.end();
My egg class:
public class Egg {
private Rectangle egg;
private Vector2 location;
public Egg(float x, float y){
location = new Vector2(x, y);
egg = new Rectangle(location.x, location.y, 10, 15);
}
public void update(float delta) {
egg.x--;
if (egg.x < -20) {
egg.x = 137;
};
}
public boolean collected = false;
public Rectangle getEgg() {
return egg;
}
public boolean isCollected() {
return collected;
}
}
The result of the above code is: The game crashes with following errors.
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.mygdx.gameworld.GameRenderer.render(GameRenderer.java:60)
at com.mygdx.screens.GameScreen.render(GameScreen.java:32)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:214)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:120)
Tenfour04 is right. Since collides is true when the two objects overlaps, it will stop drawing while they overlap and start to draw again. Save the return value to member variable.
Create a member variable in your Egg class to keep track of whether the egg has been collected:
public boolean collected = false;
If you want to practice good encapsulation, you could make this variable private and give it a getter and setter, but I'll keep it simple like this.
Then in what appears to be your game or screen class, you need to tell the egg when it's collected:
if (eggRect.overlaps(boundingRect))
egg.collected = true;
Now, you should only draw the egg if it is not collected:
batcher.begin();
if (!egg.collected){
batcher.draw(AssetLoader.textureEgg, eggRect.x, eggRect.y, eggRect.width, eggRect.height);
}
batcher.end();
By the way, it's kind of weird that your Egg class extends Rectangle, but you aren't using it as a Rectangle but rather as a container for some other Rectangle. You might as well remove "extends Rectangle".
I have around 1000 points (gps coordinates) which I want to visualize on a map using the Unfolding maps library. The track consists of colored lines (two points). I would like to color the lines based on the speed (if the speed on the track was below 20km/h it should be red otherwise green).
The following code, which represents a custom made line with one color, works:
class MyPolygonMarker extends SimplePolygonMarker {
public void draw(PGraphics pg, List<MapPosition> mapPositions) {
pg.pushStyle();
pg.strokeWeight(2);
pg.fill(255,0,0,0);
pg.stroke(#2688AD);
pg.beginShape();
for(int i=0; i<mapPositions.size();i++)
{
pg.vertex(mapPositions.get(i).x, mapPositions.get(i).y);
}
pg.endShape();
pg.popStyle();
}
}
So in the for loop I would like to put a if statement which checks the speed value. I tried with this:
class MyPolygonMarker extends SimplePolygonMarker {
public void draw(PGraphics pg, List<MapPosition> mapPositions) {
pg.pushStyle();
pg.strokeWeight(2);
pg.fill(255,0,0,0);
for(int i=0; i<mapPositions.size();i++)
{
Float speed_value = Float.parseFloat(lines[i].split("\t")[7]);
if(speed_value > 20)
{
pg.stroke(green);
pg.beginShape();
}
else
{
pg.stroke(red);
pg.beginShape();
}
pg.vertex(mapPositions.get(i).x, mapPositions.get(i).y);
}
pg.endShape();
pg.popStyle();
}
}
This only plots the initial point and nothing else. Could someone tell me what could be wrong?
It might be simply that you need to put the beginShape() before the for loop.
In any case, we are providing an example which seems to do something really close to what you are trying to achieve:
Take a look at ColoredLinesMarker.java for line markers with colors based on the speed. Note, how in that example we are reading the speed from the properties (you don't have to do it like this, but it is good practice).
You can find the full example (including the App and a custom reader for GPX files with speed data) here.
I am trying to make a move method to move units, but I'm stuck. Lets say I have a unit at position(3,1), and I want to move it to position(4,1). How do I implement the method? So far I have the code below. (I have a class representing units, but I want the moveUnit in another class (where it is now), that handles these kind of stuff).
Thanks
public boolean moveUnit( Position from, Position to ) {
return false;
}
Regarding the Position method, it is used like seen below, where I have a class with testcases using JUnit
#Test
public void shouldBePossibleToMoveUnits() {
Unit u = game.getUnitAt(new Position(2, 0));
boolean moved = game.moveUnit(new Position(2, 0), new Position(3, 0));
assertTrue("It should be possible to move units", moved);
assertNotNull("There should be a unit at 3, 0", u);
}
-------------------------------------UPDATE------------------------------
I have written this code to move the unit, but it does not work. Can someone see what I do wrong?
Unit unitFrom = ((UnitImpl) getUnitAt(from));
if(unitFrom == null) { return false; }
Unit unitTo = ((UnitImpl) getUnitAt(to));
unitFrom = unitTo;
unitFrom = null;
The unit does not get moved to the new position
Depending on how your Unit class is set up, this is what you want your method to look like:
public boolean moveUnit(Unit unitToMove, Position moveTo) {
unitToMove.setPosition(moveTo);
return true;
}
This assumes that Unit has an internal method to keep track of its position via a Position object. You're wanting to move the Unit, so you need to pass it as one of the variables.
If you want the Game class to internally get the unit, and just have it move a unit at a given position, do this:
public boolean moveUnit(Position unitPosition, Position moveTo) {
Unit unitToMove = getUnitAt(unitPosition);
if (unitToMove == null) {
//If no Unit exists at the given position, return false
return false;
}
unitToMove.setPosition(moveTo);
return true;
}
Lets say I have a unit at position(3,1), and I want to move it to position(4,1).
This means you want to end with that unit at (4,1) and no unit at (3,1).
If the unit keeps track of it's position, update that pointer.
If positions keep track of their unit, update those two pointers.