Skip to content
This repository has been archived by the owner on Sep 29, 2024. It is now read-only.

Commit

Permalink
fix: properly implement memory barriers
Browse files Browse the repository at this point in the history
  • Loading branch information
LPkkjHD committed Jun 14, 2024
1 parent a0f3ec5 commit ae642c6
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ public Body getBody() {
return body;
}

public void setBody(Body body) {
this.body = body;
}

public short getCollisionMask() {
return collisionMask;
}

public boolean isRemove() {
return remove;
}
Expand Down
35 changes: 2 additions & 33 deletions game/core/src/main/de/dhbw/tinf22b6/gameobject/bullet/Bullet.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.badlogic.gdx.physics.box2d.World;
import de.dhbw.tinf22b6.gameobject.GameObject;
import de.dhbw.tinf22b6.util.Constants;
import de.dhbw.tinf22b6.util.EntitySystem;
import de.dhbw.tinf22b6.world.Box2dWorld;
import de.dhbw.tinf22b6.world.WorldParser;

Expand All @@ -19,8 +20,6 @@ public abstract class Bullet extends GameObject {
protected boolean active;
protected float angle;
protected float r;
// shitty mutex implementation
private static boolean canCreateBullet = true;
// be careful when adjusting this parameter, as this is not the range in tiles but rather a
// counting of delta times
// speed until the "range" is reached
Expand All @@ -35,37 +34,7 @@ public Bullet(String region, Vector2 position, float angle, int damage, short ma
speed = 3;
width = 3;
height = 6;
// This is arcane wizardry! It might fix the crash which happened at random when
// the player gets into the range of multiple enemies at the same time, and they start shooting
// in the same tick - effectively locking up the world (inserting body) and causing a data race
// this "fix" works for me and needs throughout testing as I suspect it breaking something further
// when the #render() call is done and the body is not created yet.
new Thread(() -> {
World world = Box2dWorld.instance.getWorld();
boolean isLocked;
do {
isLocked = world.isLocked();
} while (isLocked);
boolean canCreate;
do {
canCreate = canCreateBullet;
} while (!canCreate);
canCreateBullet = false;
body = world.createBody(WorldParser.getDynamicBodyDef(pos.x + width / 2, pos.y + height / 2));
PolygonShape polygonShape = new PolygonShape();
polygonShape.setAsBox(3 - 2, 3 - 2);

FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = polygonShape;
fixtureDef.filter.categoryBits = collisionMask;
fixtureDef.isSensor = true;

body.createFixture(fixtureDef).setUserData(this);
body.setBullet(true);
polygonShape.dispose();
canCreateBullet = true;
})
.start();
EntitySystem.instance.addBulletToQueue(this);
}

@Override
Expand Down
16 changes: 1 addition & 15 deletions game/core/src/main/de/dhbw/tinf22b6/gameobject/enemy/Enemy.java
Original file line number Diff line number Diff line change
Expand Up @@ -384,26 +384,12 @@ public Vector2 angleToVector(Vector2 outVector, float angle) {
return SteeringUtils.angleToVector(outVector, angle);
}

/**
* Overwrites the base call by spawning an AmmoBox at the target
* location where the Enemy died. Also, I wanted to try out
* Java 8s new CompletableFuture feature.
*
* @param remove specifies whether this Enemy shall be removed
*/
@Override
public void setRemove(boolean remove) {
Vector2 position = new Vector2(body.getPosition());
position.x /= TILE_SIZE;
position.y /= TILE_SIZE;
CompletableFuture.supplyAsync(() -> {
boolean locked;
do {
locked = Box2dWorld.instance.getWorld().isLocked();
} while (locked);
EntitySystem.instance.add(new AmmoBox(position, new Rectangle(3, 2, 10, 10)));
return true; // we have return something
});
EntitySystem.instance.addAmmoBoxToQueue(position);
super.setRemove(remove);
}
}
33 changes: 24 additions & 9 deletions game/core/src/main/de/dhbw/tinf22b6/util/EntitySystem.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,53 @@
package de.dhbw.tinf22b6.util;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import de.dhbw.tinf22b6.gameobject.GameObject;
import de.dhbw.tinf22b6.gameobject.Player;
import de.dhbw.tinf22b6.gameobject.bullet.Bullet;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class EntitySystem {
public enum EntityType {
AMMO
}

public static final String TAG = EntitySystem.class.getName();
public static final EntitySystem instance = new EntitySystem();
private List<GameObject> gameObjects;
private List<Bullet> syncBulletsToBeCreated;
private List<Vector2> syncAmmoBoxesToBeCreated;

// singleton: prevent instantiation from other classes
private EntitySystem() {}

public void init(List<GameObject> objectList) {
this.gameObjects = objectList;
this.syncBulletsToBeCreated = Collections.synchronizedList(new ArrayList<>());
this.syncAmmoBoxesToBeCreated = Collections.synchronizedList(new ArrayList<>());
Gdx.app.debug(TAG, "initialized with size: " + gameObjects.size());
}

public List<GameObject> getGameObjects() {
return new ArrayList<>(gameObjects);
}

public List<Vector2> getSyncAmmoBoxesToBeCreated() {
return syncAmmoBoxesToBeCreated;
}

public void addAmmoBoxToQueue(Vector2 ammoBox) {
this.syncAmmoBoxesToBeCreated.add(ammoBox);
}

public void addBulletToQueue(Bullet bullet) {
syncBulletsToBeCreated.add(bullet);
}

public List<Bullet> getSyncBulletsToBeCreated() {
return syncBulletsToBeCreated;
}


public void add(GameObject object) {
this.gameObjects.add(object);
}
Expand All @@ -43,8 +62,4 @@ public Player getPlayer() {
}
return null;
}

public void spawn(EntityType entityType, Vector2 pos, Rectangle rectangle) {
Thread thread = new Thread(() -> {});
}
}
40 changes: 40 additions & 0 deletions game/core/src/main/de/dhbw/tinf22b6/world/WorldController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@
import com.badlogic.gdx.*;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Cursor;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import de.dhbw.tinf22b6.gameobject.GameObject;
import de.dhbw.tinf22b6.gameobject.Player;
import de.dhbw.tinf22b6.gameobject.bullet.Bullet;
import de.dhbw.tinf22b6.gameobject.interaction.AmmoBox;
import de.dhbw.tinf22b6.screen.GameScreen;
import de.dhbw.tinf22b6.util.CameraHelper;
import de.dhbw.tinf22b6.util.EntitySystem;
import de.dhbw.tinf22b6.util.PlayerStatistics;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

public class WorldController extends InputAdapter {
private static final String TAG = WorldController.class.getName();
Expand Down Expand Up @@ -89,6 +96,39 @@ public void update(float deltaTime) {
player.getMotionVector().x = motionX;
player.getMotionVector().y = motionY;

List<Bullet> bullets = EntitySystem.instance.getSyncBulletsToBeCreated();

synchronized (bullets) {
bullets.forEach(bullet -> {
float width = 3;
float height = 6;
bullet.setBody(
world.createBody(
WorldParser.getDynamicBodyDef(
bullet.getPos().x + width / 2,
bullet.getPos().y + height / 2)));
PolygonShape polygonShape = new PolygonShape();
polygonShape.setAsBox(3 - 2, 3 - 2);

FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = polygonShape;
fixtureDef.filter.categoryBits = bullet.getCollisionMask();
fixtureDef.isSensor = true;

bullet.getBody().createFixture(fixtureDef).setUserData(bullet);
bullet.getBody().setBullet(true);
polygonShape.dispose();
});
bullets.clear();
}

List<Vector2> ammoBoxPosition = EntitySystem.instance.getSyncAmmoBoxesToBeCreated();

synchronized (ammoBoxPosition) {
ammoBoxPosition.forEach(ammoBox -> EntitySystem.instance.add(new AmmoBox(ammoBox, new Rectangle(3, 2, 10, 10))));
ammoBoxPosition.clear();
}

world.step(deltaTime, 6, 2);

// tick objects
Expand Down

0 comments on commit ae642c6

Please sign in to comment.