Skip to content

Commit

Permalink
Merge branch 'InteractionRewrite' of https://github.com/UQcsse3200/20…
Browse files Browse the repository at this point in the history
…24-studio-3 into InteractionRewrite
  • Loading branch information
StrayIntellectual committed Oct 14, 2024
2 parents 8739a45 + 1dc973d commit 797c532
Show file tree
Hide file tree
Showing 19 changed files with 484 additions and 673 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import com.csse3200.game.components.moral.MoralDayFour;
import com.csse3200.game.areas.map.Map;
import com.csse3200.game.services.InteractableService;
import com.csse3200.game.services.MapLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -249,6 +250,10 @@ public void create() {
// call load function based on the level argument
// return list of items to spawn based on the load function
// Baaed on lsit of items to spawn, spawn the items

// Create a new interactable service
ServiceLocator.registerInteractableService(new InteractableService());

loadAssets();
displayUI();
spawnTerrain();
Expand Down
159 changes: 24 additions & 135 deletions source/core/src/main/com/csse3200/game/components/SensorComponent.java
Original file line number Diff line number Diff line change
@@ -1,162 +1,51 @@
package com.csse3200.game.components;

import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.csse3200.game.entities.Entity;
import com.csse3200.game.physics.BodyUserData;
import com.csse3200.game.physics.PhysicsLayer;
import com.csse3200.game.physics.components.InteractionComponent;
import com.csse3200.game.physics.components.PhysicsComponent;
import com.csse3200.game.utils.math.Vector2Utils;
import com.csse3200.game.services.ServiceLocator;

import java.util.HashSet;
import java.util.Set;
import java.util.Vector;
import java.util.Map;
/**
* Finds the closest interactable object inside a range of the player
* Finds the closest interactable object inside a range of the player's position.
* This component is used everytime the player moves to update the nearby
* interactable entities.
*/
public class SensorComponent extends Component {
private final short targetLayer;
private final float sensorDistance;
private InteractionComponent interactionComponent;
private Set<Fixture> collidingFixtures = new HashSet<>();

private Fixture closestFixture = null;
private float closestDistance = -1f;
private static final float INTERACTION_RANGE = 1.15f;

/**
* Create a component that senses entities when it collides with them.
* @param targetLayer The physics layer of the target's collider
*/
public SensorComponent(short targetLayer, float sensorDistance) {
this.targetLayer = targetLayer;
this.sensorDistance = sensorDistance;
}
private Vector2 playerPosition;
private Map<Entity, Vector2> interactables;

@Override
public void create() {
entity.getEvents().addListener("collisionStart", this::onCollisionStart);
entity.getEvents().addListener("collisionEnd", this::onCollisionEnd);
this.interactionComponent = entity.getComponent(InteractionComponent.class);
super.create();
playerPosition = entity.getComponent(PhysicsComponent.class).getBody().getPosition();
interactables = ServiceLocator.getInteractableService().getInteractables();
}

/**
* Getters
* Updates the closest interactable object to the player.
* @return the closest interactable object to the player.
*/
public Entity getClosestInteractable() {
Entity closestEntity = null;

public InteractionComponent getInteractionComponent() {
return this.interactionComponent;
}

public short getTargetLayer() {
return this.targetLayer;
}
float closestDistance = Float.MAX_VALUE;

public Set<Fixture> getClosestFixtures() {
return this.collidingFixtures;
}

public int getNumFixtures() {
return this.collidingFixtures.size();
}
for (Map.Entry<Entity, Vector2> entry : interactables.entrySet()) {
Entity entity = entry.getKey();
Vector2 entityPosition = entry.getValue();

/**
* Called when the component collides with another collider
* @param me Should be the fixture that got collided with - aka this sensor component
* @param other The fixture that collided with this component
*/
public void onCollisionStart(Fixture me, Fixture other) {
if (interactionComponent.getFixture() != me) {
// Not triggered by me, so ignore
return;
}
// Check that the fixture has the correct target layer
if (!PhysicsLayer.contains(targetLayer, other.getFilterData().categoryBits)) {
// Doesn't match our target layer, ignore
return;
}
// Check if the collidingFixture is close enough sensor
if (isWithinDistance(other, sensorDistance))
{
// Update the collision set
collidingFixtures.add(other);
}
//Update the set of fixtures
updateFixtures();
}

/**
* Called when a collision has ended between 2 fixtures
* @param me Should be the fixture that got collided with - aka this sensor component
* @param other The fixture that this component stopped colliding with
*/
public void onCollisionEnd(Fixture me, Fixture other) {
if (interactionComponent.getFixture() != me) {
// Not triggered by interactionComponent, so ignore
return;
}
if (!PhysicsLayer.contains(targetLayer, other.getFilterData().categoryBits)) {
// Doesn't match our target layer, ignore
return;
}
// Remove the fixture if it was previously detected
collidingFixtures.remove(other);
//Update the set of fixtures
updateFixtures();
}
float distance = playerPosition.dst(entityPosition);

/**
* Removes any fixtures that are not in range of the sensor and updates the closest fixture
*/
private void updateFixtures() {
Set<Fixture> toRemove = new HashSet<>();
Fixture previousClosestFixture = closestFixture;
for (Fixture fixture : collidingFixtures) {
float dist = getFixtureDistance(fixture);
if (dist > sensorDistance) {
toRemove.add(fixture);
} else if (closestDistance < 0 || dist < closestDistance) {
closestDistance = dist;
closestFixture = fixture;
if (distance <= INTERACTION_RANGE && distance < closestDistance) {
closestDistance = distance;
closestEntity = entity;
}
}
collidingFixtures.removeAll(toRemove);

// If no colliding fixtures, then it is empty
if (collidingFixtures.isEmpty()) {
closestFixture = null;
closestDistance = -1f;
}


}


public Fixture getClosestFixture() {
return this.closestFixture;
}

/**
* Returns the distance from the sensor component to the given fixture
* @param fixture The object being measured
* @return The distance from the sensor object to the given fixture
*/
private float getFixtureDistance(Fixture fixture) {
Vector2 sensorPosition = interactionComponent.getFixture().getBody().getPosition();
Vector2 fixturePosition = fixture.getBody().getPosition();
return sensorPosition.dst(fixturePosition);
}

/**
* Determines whether the distance to the fixture is within the required distance
* @param fixture The object being measured
* @param distance The maximum distance the fixture can be away from the sensor component
* @return True: If the distance to the fixture is less than the provided distance, False: Otherwise
*/
public boolean isWithinDistance(Fixture fixture, float distance) {
return getFixtureDistance(fixture) <= distance;
return closestEntity;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private void showTooltip(TooltipInfo tooltipInfo) {
// Set the tooltip position above the interactable object based on viewport height
table.setPosition(screenPos.x*190, screenPos.y*190 + (viewportHeight * 0.05f)); // Adjust Y position relative to object and screen size

table.setVisible(true);
table.setVisible(false);
}

private void hideTooltip() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.util.ArrayList;
import java.util.Objects;

import com.csse3200.game.components.station.IngredientStationHandlerComponent;
import com.csse3200.game.components.station.StationMealComponent;
import com.csse3200.game.physics.components.PhysicsComponent;


Expand All @@ -30,25 +32,43 @@ public class InventoryDisplayHoverComponent extends RenderComponent {
private ArrayList<Texture> itemImages;
private Texture backgroundImage;
private Texture selectedBackgroundImage;
private boolean showKeys = false;
private boolean isMixingStation = false;
private boolean isBasket = false;
private Texture interactKeyImage;
private Texture combineKeyImage;
private Texture rotateKeyImage;
private ShapeRenderer shapeRenderer;
private Vector2 position;
private Vector2 scale;
private static final float X_OFFSET = 0.2f;
private static final float Y_OFFSET = 1.0F;
private static final float SLOT_WIDTH = 0.6f;
private static final float SLOT_HEIGHT = 0.6f;
private static final float KEY_WIDTH = 1.0f;
private static final float KEY_HEIGHT = 0.3f;

@Override
public void create() {
super.create();
backgroundImage = new Texture("images/inventory_ui/item_background.png");
selectedBackgroundImage = new Texture("images/inventory_ui/item_background_selected.png");
interactKeyImage = new Texture("images/inventory_ui/interact_key.png");
combineKeyImage = new Texture("images/inventory_ui/combine_key.png");
rotateKeyImage = new Texture("images/inventory_ui/rotate_key.png");
shapeRenderer = new ShapeRenderer();
ServiceLocator.getRenderService().register(this);

if (entity != null) {
// listener for when the InventoryComponent attached to this entity is updated
entity.getEvents().addListener("updateInventory", this::update);
entity.getEvents().addListener("updateInventory", this::updateDisplay);

entity.getEvents().addListener("showToolTip", this::showToolTip);
entity.getEvents().addListener("hideToolTip", this::hideToolTip);

isMixingStation = entity.getComponent(StationMealComponent.class) != null;
isBasket = entity.getComponent(IngredientStationHandlerComponent.class) != null;

// need to use the physics body position of the entity as
// the regular getPosition() on stations does not return the correct position.
position = entity.getComponent(PhysicsComponent.class).getBody().getPosition();
Expand Down Expand Up @@ -81,19 +101,68 @@ private void updateImages() {
}
}



/**
* Updates this InventoryDisplay to reflect the current state of the InventoryComponent
* of this component's parent entity.
*/
@Override
public void update() {

}

public void updateDisplay() {
updateImages();
}

/**
* Sets this component to display keybind tooltip icons
*/
private void showToolTip() {
this.showKeys = true;
}

/**
* Sets this component to hide keybind tooltip icons
*/
private void hideToolTip() {
this.showKeys = false;
}

@Override
public void draw(SpriteBatch batch) {
if (entity == null || position == null || scale == null)
return;

if (showKeys) {
batch.draw(interactKeyImage,
position.x,
position.y + 0.7f,
KEY_WIDTH,
KEY_HEIGHT
);
if (isMixingStation) {
batch.draw(rotateKeyImage,
position.x,
position.y + 0.4f,
KEY_WIDTH,
KEY_HEIGHT
);
batch.draw(combineKeyImage,
position.x,
position.y + 0.1f,
KEY_WIDTH,
KEY_HEIGHT
);
}
}

// If we have a basked don't draw the images
if (isBasket) {
return;
}

for (int i = 0; i < itemImages.size(); i++) {
// draw selected background image for the next item to be taken out
// (if there is more than 1 item displayed)
Expand Down Expand Up @@ -130,6 +199,11 @@ public void dispose() {
}
}

@Override
public int getLayer() {
return 3; // currently overlays the player, but decreasing this to 1 makes it hide behind the stations
}

@Override
public void setStage(Stage mock) {
// This function needed to exist but not needed to be implemented
Expand Down
Loading

0 comments on commit 797c532

Please sign in to comment.