fix report
This commit is contained in:
132
README2.md
132
README2.md
@@ -0,0 +1,132 @@
|
||||
# Structural Design Patterns
|
||||
|
||||
|
||||
## Author: Schipschi Daniil / FAF-223
|
||||
|
||||
----
|
||||
|
||||
## Objectives:
|
||||
|
||||
* Learn about Structural Design Patterns
|
||||
* Pick a domain to implement them in
|
||||
* Implement at least 3 patterns in my code
|
||||
|
||||
|
||||
## Used Design Patterns:
|
||||
|
||||
* Facade
|
||||
* Bridge
|
||||
* Flyweight
|
||||
|
||||
|
||||
## Implementation
|
||||
|
||||
* **Facade**
|
||||
> I used the ___Facade___ pattern to simplify the management of multiple game systems. The `GameSystemsFacade` class provides a single interface to handle all subsystems, reducing complexity in the main game loop.
|
||||
>
|
||||
> The facade manages these systems:
|
||||
>
|
||||
> - Projectiles
|
||||
> - Visual effects
|
||||
> - Enemies
|
||||
> - Input
|
||||
> - Camera
|
||||
> - Particles
|
||||
> - Cleanup
|
||||
> - Interface
|
||||
> - Player
|
||||
>
|
||||
> Here's the implementation:
|
||||
> ```java
|
||||
> public class GameSystemsFacade {
|
||||
> private static GameSystemsFacade instance;
|
||||
> private final ProjectileHandler projectileHandler;
|
||||
> private final SpaceVFXHandler spaceVFXHandler;
|
||||
> // ... other handlers ...
|
||||
>
|
||||
> public void update(float delta) {
|
||||
> step();
|
||||
> renderClear();
|
||||
> spaceVFXHandler.render();
|
||||
> projectileHandler.cycle(delta);
|
||||
> // ... other updates ...
|
||||
> }
|
||||
> }
|
||||
> ```
|
||||
> The facade pattern reduces the complexity of system management by providing a single update method instead of requiring multiple system calls in the main game loop.
|
||||
|
||||
* **Bridge**
|
||||
> I implemented the ___Bridge___ pattern in the enemy system to separate enemy types from their behaviors. This separation allows independent modification of both aspects without affecting each other.
|
||||
>
|
||||
> Here's the implementation:
|
||||
> ```java
|
||||
> public class EnemyEntity extends Entity {
|
||||
> protected EnemyBehavior behavior; // <--- One Bridged Attribute
|
||||
> protected EnemyType type; // <--- Second Bridged Attribute
|
||||
>
|
||||
> public EnemyEntity(World world, EnemyType type, Behaviors behaviorType,
|
||||
> Vector2 playerPosition, TripleInt options) {
|
||||
> super(world, type.getTexturePath(), type.getSize());
|
||||
> this.type = type;
|
||||
> this.behavior = behaviorType.createBehavior(options.one(),
|
||||
> options.two(),
|
||||
> options.thr());
|
||||
> initializePosition(playerPosition);
|
||||
> behavior.init(this);
|
||||
> }
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> The benefits of this pattern include:
|
||||
> - Independent creation of enemy types and behaviors
|
||||
> - Easy addition of new enemy types or behaviors
|
||||
> - Flexible combination of types and behaviors
|
||||
|
||||
* **Flyweight**
|
||||
> I used the ___Flyweight___ pattern to optimize memory usage when handling multiple projectiles. The pattern shares common data between projectile instances instead of duplicating it.
|
||||
>
|
||||
> Here's the flyweight implementation:
|
||||
> ```java
|
||||
> public class ProjectileFlyweight {
|
||||
> private static final Map<Boolean, ProjectileFlyweight> flyweights = new HashMap<>();
|
||||
> private final Sprite sprite;
|
||||
> private final float size;
|
||||
> private final float defaultSpeed;
|
||||
> private final boolean isEnemy;
|
||||
>
|
||||
> public static ProjectileFlyweight get(boolean isEnemy) {
|
||||
> return flyweights.computeIfAbsent(isEnemy, ProjectileFlyweight::new);
|
||||
> }
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> And its usage in projectiles:
|
||||
> ```java
|
||||
> public class Projectile extends Entity {
|
||||
> private final ProjectileFlyweight flyweight;
|
||||
>
|
||||
> public Projectile(World world, boolean isEnemy) {
|
||||
> super(world, isEnemy ? ENEMY_TEXTURE : PLAYER_TEXTURE, 5f);
|
||||
> this.flyweight = ProjectileFlyweight.get(isEnemy);
|
||||
> }
|
||||
> // ... other code
|
||||
>
|
||||
>
|
||||
>
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> This pattern efficiently manages memory by sharing common resources between multiple projectile instances.
|
||||
|
||||
|
||||
## Conclusions
|
||||
|
||||
The implementation of these structural patterns significantly improved the organization and efficiency of my game project:
|
||||
|
||||
The Facade pattern simplified system management by providing a unified interface for all game subsystems. This reduced complexity in the main game loop and made the codebase more maintainable.
|
||||
|
||||
The Bridge pattern created a flexible enemy system by separating enemy types from their behaviors. This separation allows for independent modification and extension of both aspects, making the system more modular and easier to expand.
|
||||
|
||||
The Flyweight pattern optimized memory usage in the projectile system by sharing common resources between instances. This optimization is particularly important when dealing with numerous projectiles simultaneously.
|
||||
|
||||
These patterns work together to create a more organized, efficient, and maintainable game architecture. The implementation demonstrates the practical benefits of using structural patterns to solve common game development challenges.
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package org.lumijiez.bugger;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
import org.lumijiez.bugger.entities.Player;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
import org.lumijiez.bugger.handlers.*;
|
||||
import org.lumijiez.bugger.util.GameSystemsFacade;
|
||||
|
||||
@@ -20,6 +21,18 @@ public class Bugger {
|
||||
public static int kills = 0;
|
||||
|
||||
private Bugger() {
|
||||
spriteBatch.getProjectionMatrix().setToOrtho2D(0, 0,
|
||||
Gdx.graphics.getWidth(),
|
||||
Gdx.graphics.getHeight());
|
||||
|
||||
uiBatch.getProjectionMatrix().setToOrtho2D(0, 0,
|
||||
Gdx.graphics.getWidth(),
|
||||
Gdx.graphics.getHeight());
|
||||
|
||||
shapeRenderer.getProjectionMatrix().setToOrtho2D(0, 1,
|
||||
Gdx.graphics.getWidth(),
|
||||
Gdx.graphics.getHeight());
|
||||
|
||||
Player.getInstance().setPlayer(world, 100, 100);
|
||||
this.world.setContactListener(new CollisionHandler());
|
||||
}
|
||||
@@ -40,6 +53,12 @@ public class Bugger {
|
||||
CleanupHandler.getInstance().disposeAll();
|
||||
}
|
||||
|
||||
public void resize(int width, int height) {
|
||||
spriteBatch.getProjectionMatrix().setToOrtho2D(0, 0, width, height);
|
||||
uiBatch.getProjectionMatrix().setToOrtho2D(0, 0, width, height);
|
||||
shapeRenderer.getProjectionMatrix().setToOrtho2D(0, 0, width, height);
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ public class GameScreen implements Screen {
|
||||
|
||||
@Override
|
||||
public void resize(int w, int h) {
|
||||
bugger.resize(w, h);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,7 +8,7 @@ public class Main extends Game {
|
||||
@Override
|
||||
public void create() {
|
||||
setScreen(new GameScreen());
|
||||
Gdx.graphics.setResizable(false);
|
||||
Gdx.graphics.setResizable(true);
|
||||
Gdx.graphics.setTitle("Bugger");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.lumijiez.bugger.entities.enemies;
|
||||
|
||||
public enum Enemies {
|
||||
STALKER("Stalker"),
|
||||
WASP("Wasp"),
|
||||
ULTRON("Ultron"),
|
||||
GOLEM("Golem"),
|
||||
STELLAR("Stellar");
|
||||
|
||||
private final String className;
|
||||
|
||||
Enemies(String className) {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,46 +2,45 @@ package org.lumijiez.bugger.entities.enemies;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
import org.lumijiez.bugger.Bugger;
|
||||
import org.lumijiez.bugger.entities.Entity;
|
||||
import org.lumijiez.bugger.entities.Player;
|
||||
import org.lumijiez.bugger.handlers.EnemyProjectileHandler;
|
||||
import org.lumijiez.bugger.entities.enemies.behaviors.Behaviors;
|
||||
import org.lumijiez.bugger.entities.enemies.behaviors.EnemyBehavior;
|
||||
import org.lumijiez.bugger.entities.enemies.types.EnemyType;
|
||||
import org.lumijiez.bugger.util.data.TripleInt;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
public class EnemyEntity extends Entity {
|
||||
private float shootTimer = 0.0f;
|
||||
private static final Random random = new Random();
|
||||
protected EnemyBehavior behavior;
|
||||
protected EnemyType type;
|
||||
|
||||
public EnemyEntity(World world, String texturePath, float size) {
|
||||
super(world, texturePath, size);
|
||||
public EnemyEntity(World world, EnemyType type, Behaviors behaviorType, Vector2 playerPosition, TripleInt options) {
|
||||
super(world, type.getTexturePath(), type.getSize());
|
||||
this.type = type;
|
||||
this.behavior = behaviorType.createBehavior(options.one(), options.two(), options.thr());
|
||||
initializePosition(playerPosition);
|
||||
behavior.init(this);
|
||||
}
|
||||
|
||||
private void initializePosition(Vector2 playerPosition) {
|
||||
float angle = random.nextFloat() * 2 * (float) Math.PI;
|
||||
float spawnX = playerPosition.x + (float) Math.cos(angle) * (type.getSpawnRadius() + type.getSize());
|
||||
float spawnY = playerPosition.y + (float) Math.sin(angle) * (type.getSpawnRadius() + type.getSize());
|
||||
this.body = createBody(spawnX, spawnY);
|
||||
this.body.setUserData(this);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
Vector2 playerPos = Player.getInstance().getPosition();
|
||||
follow(playerPos);
|
||||
}
|
||||
|
||||
private void follow(Vector2 playerPos) {
|
||||
Vector2 direction = playerPos.cpy().sub(body.getPosition()).nor();
|
||||
float speed = 10f;
|
||||
body.setLinearVelocity(direction.scl(speed));
|
||||
|
||||
float angle = direction.angleDeg() + 270f;
|
||||
body.setTransform(body.getPosition(), angle * (float) Math.PI / 180f);
|
||||
|
||||
shootTimer += Bugger.deltaTime;
|
||||
|
||||
float shootCooldown = 2.0f;
|
||||
if (shootTimer >= shootCooldown) {
|
||||
EnemyProjectileHandler.getInstance().shootEnemyProjectile(this.body.getPosition(), 50f);
|
||||
shootTimer = 0.0f;
|
||||
if (behavior != null) {
|
||||
behavior.update(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
update();
|
||||
render();
|
||||
render(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void render() {
|
||||
super.render(0,0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.lumijiez.bugger.entities.enemies;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class Golem extends EnemyEntity {
|
||||
private static final Random random = new Random();
|
||||
|
||||
public Golem(World world, Vector2 playerPosition) {
|
||||
super(world, "images/golem.png", 30f);
|
||||
float spawnRadius = 100;
|
||||
float angle = random.nextFloat() * 2 * (float) Math.PI;
|
||||
float spawnX = playerPosition.x + (float) Math.cos(angle) * (spawnRadius + size);
|
||||
float spawnY = playerPosition.y + (float) Math.sin(angle) * (spawnRadius + size);
|
||||
this.body = createBody(spawnX, spawnY);
|
||||
this.body.setUserData(this);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.lumijiez.bugger.entities.enemies;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class Stalker extends EnemyEntity {
|
||||
private static final Random random = new Random();
|
||||
|
||||
public Stalker(World world, Vector2 playerPosition) {
|
||||
super(world, "images/stalker.png", 10f);
|
||||
float spawnRadius = 100;
|
||||
float angle = random.nextFloat() * 2 * (float) Math.PI;
|
||||
float spawnX = playerPosition.x + (float) Math.cos(angle) * (spawnRadius + size);
|
||||
float spawnY = playerPosition.y + (float) Math.sin(angle) * (spawnRadius + size);
|
||||
this.body = createBody(spawnX, spawnY);
|
||||
this.body.setUserData(this);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.lumijiez.bugger.entities.enemies;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class Stellar extends EnemyEntity {
|
||||
private static final Random random = new Random();
|
||||
|
||||
public Stellar(World world, Vector2 playerPosition) {
|
||||
super(world, "images/stellar.png", 15f);
|
||||
float spawnRadius = 100;
|
||||
float angle = random.nextFloat() * 2 * (float) Math.PI;
|
||||
float spawnX = playerPosition.x + (float) Math.cos(angle) * (spawnRadius + size);
|
||||
float spawnY = playerPosition.y + (float) Math.sin(angle) * (spawnRadius + size);
|
||||
this.body = createBody(spawnX, spawnY);
|
||||
this.body.setUserData(this);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.lumijiez.bugger.entities.enemies;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class Ultron extends EnemyEntity {
|
||||
private static final Random random = new Random();
|
||||
|
||||
public Ultron(World world, Vector2 playerPosition) {
|
||||
super(world, "images/ultron.png", 10f);
|
||||
float spawnRadius = 100;
|
||||
float angle = random.nextFloat() * 2 * (float) Math.PI;
|
||||
float spawnX = playerPosition.x + (float) Math.cos(angle) * (spawnRadius + size);
|
||||
float spawnY = playerPosition.y + (float) Math.sin(angle) * (spawnRadius + size);
|
||||
this.body = createBody(spawnX, spawnY);
|
||||
this.body.setUserData(this);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.lumijiez.bugger.entities.enemies;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.*;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class Wasp extends EnemyEntity {
|
||||
private static final Random random = new Random();
|
||||
|
||||
public Wasp(World world, Vector2 playerPosition) {
|
||||
super(world, "images/wasp.png", 5f);
|
||||
float spawnRadius = 100;
|
||||
float angle = random.nextFloat() * 2 * (float) Math.PI;
|
||||
float spawnX = playerPosition.x + (float) Math.cos(angle) * (spawnRadius + size);
|
||||
float spawnY = playerPosition.y + (float) Math.sin(angle) * (spawnRadius + size);
|
||||
this.body = createBody(spawnX, spawnY);
|
||||
this.body.setUserData(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.lumijiez.bugger.entities.enemies.behaviors;
|
||||
|
||||
public enum Behaviors {
|
||||
FOLLOW(FollowBehavior.class),
|
||||
DEFENSIVE(DefensiveBehavior.class);
|
||||
|
||||
private final Class<? extends EnemyBehavior> behaviorClass;
|
||||
|
||||
Behaviors(Class<? extends EnemyBehavior> behaviorClass) {
|
||||
this.behaviorClass = behaviorClass;
|
||||
}
|
||||
|
||||
public EnemyBehavior createBehavior(float param1, float param2, float param3) {
|
||||
try {
|
||||
return behaviorClass.getDeclaredConstructor(float.class, float.class, float.class)
|
||||
.newInstance(param1, param2, param3);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to create behavior: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.lumijiez.bugger.entities.enemies.behaviors;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import org.lumijiez.bugger.Bugger;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
import org.lumijiez.bugger.entities.enemies.EnemyEntity;
|
||||
import org.lumijiez.bugger.handlers.EnemyProjectileHandler;
|
||||
|
||||
public class DefensiveBehavior implements EnemyBehavior {
|
||||
private final float preferredDistance;
|
||||
private final float moveSpeed;
|
||||
private final float shootCooldown;
|
||||
private float shootTimer = 0.0f;
|
||||
|
||||
public DefensiveBehavior(float preferredDistance, float moveSpeed, float shootCooldown) {
|
||||
this.preferredDistance = preferredDistance;
|
||||
this.moveSpeed = moveSpeed;
|
||||
this.shootCooldown = shootCooldown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(EnemyEntity enemy) {
|
||||
shootTimer = 0.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(EnemyEntity enemy) {
|
||||
Vector2 playerPos = Player.getInstance().getPosition();
|
||||
Vector2 enemyPos = enemy.getPosition();
|
||||
Vector2 direction = playerPos.cpy().sub(enemyPos);
|
||||
float currentDistance = direction.len();
|
||||
|
||||
float distanceDiff = currentDistance - preferredDistance;
|
||||
direction.nor();
|
||||
|
||||
if (Math.abs(distanceDiff) > 1.0f) {
|
||||
Vector2 movement = direction.scl(Math.min(moveSpeed, Math.abs(distanceDiff) * 0.5f));
|
||||
enemy.getBody().setLinearVelocity(movement.cpy().scl(Math.signum(distanceDiff)));
|
||||
} else {
|
||||
enemy.getBody().setLinearVelocity(Vector2.Zero);
|
||||
}
|
||||
|
||||
float angle = direction.angleDeg() + 270f;
|
||||
enemy.getBody().setTransform(enemyPos, angle * (float) Math.PI / 180f);
|
||||
|
||||
shootTimer += Bugger.deltaTime;
|
||||
if (shootTimer >= shootCooldown && Math.abs(distanceDiff) < 10f) {
|
||||
EnemyProjectileHandler.getInstance().shootEnemyProjectile(enemyPos, 40f);
|
||||
shootTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.lumijiez.bugger.entities.enemies.behaviors;
|
||||
|
||||
import org.lumijiez.bugger.entities.enemies.EnemyEntity;
|
||||
|
||||
public interface EnemyBehavior {
|
||||
void update(EnemyEntity enemy);
|
||||
void init(EnemyEntity enemy);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.lumijiez.bugger.entities.enemies.behaviors;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import org.lumijiez.bugger.Bugger;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
import org.lumijiez.bugger.entities.enemies.EnemyEntity;
|
||||
import org.lumijiez.bugger.handlers.EnemyProjectileHandler;
|
||||
|
||||
public class FollowBehavior implements EnemyBehavior {
|
||||
private float shootTimer = 0.0f;
|
||||
private final float shootCooldown;
|
||||
private final float moveSpeed;
|
||||
private final float projectileSpeed;
|
||||
|
||||
public FollowBehavior(float shootCooldown, float moveSpeed, float projectileSpeed) {
|
||||
this.shootCooldown = shootCooldown;
|
||||
this.moveSpeed = moveSpeed;
|
||||
this.projectileSpeed = projectileSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(EnemyEntity enemy) {
|
||||
shootTimer = 0.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(EnemyEntity enemy) {
|
||||
Vector2 playerPos = Player.getInstance().getPosition();
|
||||
Vector2 direction = playerPos.cpy().sub(enemy.getPosition()).nor();
|
||||
|
||||
enemy.getBody().setLinearVelocity(direction.scl(moveSpeed));
|
||||
|
||||
float angle = direction.angleDeg() + 270f;
|
||||
enemy.getBody().setTransform(enemy.getPosition(), angle * (float) Math.PI / 180f);
|
||||
|
||||
shootTimer += Bugger.deltaTime;
|
||||
if (shootTimer >= shootCooldown) {
|
||||
EnemyProjectileHandler.getInstance().shootEnemyProjectile(enemy.getPosition(), projectileSpeed);
|
||||
shootTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.lumijiez.bugger.entities.enemies.types;
|
||||
|
||||
public interface EnemyType {
|
||||
String getTexturePath();
|
||||
float getSize();
|
||||
float getSpawnRadius();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.lumijiez.bugger.entities.enemies.types;
|
||||
|
||||
public enum EnemyTypes implements EnemyType {
|
||||
STALKER("images/stalker.png", 10f, 100f),
|
||||
GOLEM("images/golem.png", 30f, 120f),
|
||||
STELLAR("images/stellar.png", 15f, 100f),
|
||||
WASP("images/wasp.png", 8f, 80f),
|
||||
ULTRON("images/ultron.png", 20f, 150f);
|
||||
|
||||
private final String texturePath;
|
||||
private final float size;
|
||||
private final float spawnRadius;
|
||||
|
||||
EnemyTypes(String texturePath, float size, float spawnRadius) {
|
||||
this.texturePath = texturePath;
|
||||
this.size = size;
|
||||
this.spawnRadius = spawnRadius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTexturePath() {
|
||||
return texturePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSpawnRadius() {
|
||||
return spawnRadius;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.lumijiez.bugger.entities;
|
||||
package org.lumijiez.bugger.entities.player;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input;
|
||||
@@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.physics.box2d.*;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import org.lumijiez.bugger.entities.Entity;
|
||||
import org.lumijiez.bugger.handlers.CameraHandler;
|
||||
|
||||
import static org.lumijiez.bugger.Bugger.shapeRenderer;
|
||||
@@ -1,27 +1,35 @@
|
||||
package org.lumijiez.bugger.entities.weapons;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.Sprite;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.*;
|
||||
import org.lumijiez.bugger.Bugger;
|
||||
import org.lumijiez.bugger.entities.Entity;
|
||||
import org.lumijiez.bugger.pools.ProjectileFlyweight;
|
||||
|
||||
import static org.lumijiez.bugger.pools.ProjectileFlyweight.ENEMY_TEXTURE;
|
||||
import static org.lumijiez.bugger.pools.ProjectileFlyweight.PLAYER_TEXTURE;
|
||||
|
||||
public class Projectile extends Entity {
|
||||
private static final String ENEMY_TEXTURE = "images/enemyblaze.png";
|
||||
private static final String PLAYER_TEXTURE = "images/blaze.png";
|
||||
|
||||
protected float timeAlive = 0f;
|
||||
protected boolean isEnemy;
|
||||
protected float speed = 5000f;
|
||||
protected float speed;
|
||||
private final ProjectileFlyweight flyweight;
|
||||
|
||||
public Projectile(World world, boolean isEnemy) {
|
||||
super(world, isEnemy ? ENEMY_TEXTURE : PLAYER_TEXTURE, 5f);
|
||||
this.flyweight = ProjectileFlyweight.get(isEnemy);
|
||||
this.isEnemy = isEnemy;
|
||||
this.speed = flyweight.getDefaultSpeed();
|
||||
this.body = createBody(0, 0);
|
||||
}
|
||||
|
||||
public Projectile(World world, Vector2 position, Vector2 direction, boolean isEnemy) {
|
||||
super(world, isEnemy ? ENEMY_TEXTURE : PLAYER_TEXTURE, 5f);
|
||||
this.flyweight = ProjectileFlyweight.get(isEnemy);
|
||||
Vector2 offsetPosition = position.cpy().add(direction.nor().scl(5f + 1f));
|
||||
this.isEnemy = isEnemy;
|
||||
this.speed = flyweight.getDefaultSpeed();
|
||||
this.body = createBody(offsetPosition.x, offsetPosition.y);
|
||||
this.body.setTransform(offsetPosition, (float) (direction.angleRad() + Math.toRadians(270f)));
|
||||
this.body.setLinearVelocity(direction.nor().scl(speed));
|
||||
@@ -30,6 +38,7 @@ public class Projectile extends Entity {
|
||||
|
||||
public Projectile(World world, Vector2 position, Vector2 direction, boolean isEnemy, float speed) {
|
||||
super(world, isEnemy ? ENEMY_TEXTURE : PLAYER_TEXTURE, 5f);
|
||||
this.flyweight = ProjectileFlyweight.get(isEnemy);
|
||||
Vector2 offsetPosition = position.cpy().add(direction.nor().scl(5f + 1f));
|
||||
this.isEnemy = isEnemy;
|
||||
this.speed = speed;
|
||||
@@ -48,7 +57,7 @@ public class Projectile extends Entity {
|
||||
|
||||
Body body = world.createBody(bodyDef);
|
||||
PolygonShape shape = new PolygonShape();
|
||||
shape.setAsBox(size / 2, size + 5);
|
||||
shape.setAsBox(flyweight.getSize() / 2, flyweight.getSize() + 5);
|
||||
|
||||
FixtureDef fixtureDef = new FixtureDef();
|
||||
fixtureDef.shape = shape;
|
||||
@@ -59,6 +68,7 @@ public class Projectile extends Entity {
|
||||
return body;
|
||||
}
|
||||
|
||||
|
||||
public void init(Vector2 position, Vector2 direction, boolean isEnemy) {
|
||||
this.isEnemy = isEnemy;
|
||||
this.body.setTransform(position, (float) (direction.angleRad() + Math.toRadians(270f)));
|
||||
@@ -87,7 +97,15 @@ public class Projectile extends Entity {
|
||||
}
|
||||
|
||||
public void render() {
|
||||
super.render(0, 5);
|
||||
Sprite spriteToRender = flyweight.getSprite();
|
||||
spriteToRender.setOrigin(flyweight.getSize() / 2, flyweight.getSize() / 2);
|
||||
spriteToRender.setSize(flyweight.getSize(), flyweight.getSize() + 5);
|
||||
spriteToRender.setPosition(body.getPosition().x - flyweight.getSize() / 2,
|
||||
body.getPosition().y - flyweight.getSize() / 2);
|
||||
spriteToRender.setRotation(body.getAngle() * (180f / (float) Math.PI));
|
||||
Bugger.spriteBatch.begin();
|
||||
spriteToRender.draw(Bugger.spriteBatch);
|
||||
Bugger.spriteBatch.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,6 +3,9 @@ package org.lumijiez.bugger.factories;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
import org.lumijiez.bugger.entities.enemies.*;
|
||||
import org.lumijiez.bugger.entities.enemies.behaviors.Behaviors;
|
||||
import org.lumijiez.bugger.entities.enemies.types.EnemyTypes;
|
||||
import org.lumijiez.bugger.util.data.TripleInt;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@@ -10,22 +13,22 @@ public class EnemyFactory {
|
||||
private static final Random random = new Random();
|
||||
|
||||
public static EnemyEntity createRandomEnemy(World world, Vector2 position) {
|
||||
int enemyType = random.nextInt(Enemies.values().length);
|
||||
int enemyType = random.nextInt(EnemyTypes.values().length);
|
||||
|
||||
return getEnemyEntity(Enemies.values()[enemyType], world, position);
|
||||
return getEnemyEntity(EnemyTypes.values()[enemyType], world, position);
|
||||
}
|
||||
|
||||
public static EnemyEntity createEnemy(Enemies enemyType, World world, Vector2 position) {
|
||||
public static EnemyEntity createEnemy(EnemyTypes enemyType, World world, Vector2 position) {
|
||||
return getEnemyEntity(enemyType, world, position);
|
||||
}
|
||||
|
||||
private static EnemyEntity getEnemyEntity(Enemies enemy, World world, Vector2 position) {
|
||||
private static EnemyEntity getEnemyEntity(EnemyTypes enemy, World world, Vector2 position) {
|
||||
return switch (enemy) {
|
||||
case STALKER -> new Stalker(world, position);
|
||||
case WASP -> new Wasp(world, position);
|
||||
case ULTRON -> new Ultron(world, position);
|
||||
case GOLEM -> new Golem(world, position);
|
||||
case STELLAR -> new Stellar(world, position);
|
||||
case STALKER -> new EnemyEntity(world, EnemyTypes.STALKER, Behaviors.FOLLOW, position, new TripleInt(10, 10, 10));
|
||||
case WASP -> new EnemyEntity(world, EnemyTypes.WASP, Behaviors.FOLLOW, position, new TripleInt(10, 10, 10));
|
||||
case ULTRON -> new EnemyEntity(world, EnemyTypes.ULTRON, Behaviors.FOLLOW, position, new TripleInt(10, 10, 10));
|
||||
case GOLEM -> new EnemyEntity(world, EnemyTypes.GOLEM, Behaviors.FOLLOW, position, new TripleInt(10, 10, 10));
|
||||
case STELLAR -> new EnemyEntity(world, EnemyTypes.STELLAR, Behaviors.DEFENSIVE, position, new TripleInt(150, 10, 1));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.lumijiez.bugger.handlers;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
import org.lumijiez.bugger.Bugger;
|
||||
import org.lumijiez.bugger.entities.Player;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
|
||||
public class CameraHandler {
|
||||
private static CameraHandler instance;
|
||||
@@ -12,11 +12,11 @@ public class CameraHandler {
|
||||
private final OrthographicCamera uiCam;
|
||||
|
||||
private CameraHandler() {
|
||||
cam = new OrthographicCamera(160, 90);
|
||||
cam = new OrthographicCamera((float) (Gdx.graphics.getWidth() / 3), (float) (Gdx.graphics.getHeight() / 3));
|
||||
cam.position.set(Player.getInstance().getPosition().x / 2f, Player.getInstance().getPosition().y / 2f, 0);
|
||||
cam.update();
|
||||
|
||||
uiCam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
|
||||
uiCam = new OrthographicCamera((float) (Gdx.graphics.getWidth() * 1.5), (float) (Gdx.graphics.getHeight() * 1.5));
|
||||
uiCam.position.set(uiCam.viewportWidth / 2, uiCam.viewportHeight / 2, 0);
|
||||
uiCam.update();
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package org.lumijiez.bugger.handlers;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.physics.box2d.*;
|
||||
import org.lumijiez.bugger.Bugger;
|
||||
import org.lumijiez.bugger.entities.Player;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
import org.lumijiez.bugger.entities.enemies.EnemyEntity;
|
||||
import org.lumijiez.bugger.entities.weapons.Projectile;
|
||||
import org.lumijiez.bugger.util.CollisionAction;
|
||||
import org.lumijiez.bugger.util.CollisionPair;
|
||||
import org.lumijiez.bugger.util.functional.CollisionAction;
|
||||
import org.lumijiez.bugger.util.data.CollisionPair;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -48,8 +47,11 @@ public class CollisionHandler implements ContactListener {
|
||||
ParticleHandler instance = ParticleHandler.getInstance();
|
||||
Player player = Player.getInstance();
|
||||
|
||||
float viewWidth = CameraHandler.getInstance().getUICamera().viewportWidth;
|
||||
float viewHeight = CameraHandler.getInstance().getUICamera().viewportHeight;
|
||||
|
||||
instance.playSmallBoom(player.getPosition().x, player.getPosition().y);
|
||||
instance.playHit(Gdx.graphics.getWidth() - 100, Gdx.graphics.getHeight() - 60);
|
||||
instance.playHit( viewWidth - 100, viewHeight - 60);
|
||||
}
|
||||
|
||||
private void handleEnemyHit(Projectile ray, EnemyEntity enemy) {
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.lumijiez.bugger.handlers;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import org.lumijiez.bugger.entities.Player;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
import org.lumijiez.bugger.entities.weapons.Projectile;
|
||||
import org.lumijiez.bugger.pools.ProjectilePool;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.lumijiez.bugger.handlers;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import org.lumijiez.bugger.entities.Player;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
|
||||
public class InputHandler {
|
||||
private static InputHandler instance;
|
||||
@@ -26,6 +26,10 @@ public class InputHandler {
|
||||
InterfaceHandler.getInstance().toggleDebug();
|
||||
}
|
||||
|
||||
if (Gdx.input.isKeyJustPressed(Input.Keys.ESCAPE)) {
|
||||
Gdx.app.exit();
|
||||
}
|
||||
|
||||
if (Gdx.input.isButtonJustPressed(Input.Buttons.RIGHT)) {
|
||||
float numRays = 8;
|
||||
float radius = 0.5f;
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import org.lumijiez.bugger.Bugger;
|
||||
import org.lumijiez.bugger.entities.Player;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
|
||||
public class InterfaceHandler {
|
||||
private final BitmapFont bitmapFont;
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import org.lumijiez.bugger.Bugger;
|
||||
import org.lumijiez.bugger.entities.Player;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
|
||||
public class ParticleHandler {
|
||||
private static ParticleHandler instance;
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import org.lumijiez.bugger.entities.Player;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
import org.lumijiez.bugger.entities.weapons.Projectile;
|
||||
import org.lumijiez.bugger.pools.ProjectilePool;
|
||||
|
||||
|
||||
@@ -3,14 +3,14 @@ package org.lumijiez.bugger.handlers;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.physics.box2d.World;
|
||||
import org.lumijiez.bugger.Bugger;
|
||||
import org.lumijiez.bugger.entities.Player;
|
||||
import org.lumijiez.bugger.entities.enemies.Enemies;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
import org.lumijiez.bugger.entities.enemies.types.EnemyTypes;
|
||||
import org.lumijiez.bugger.factories.EnemyFactory;
|
||||
|
||||
public class SpawnerHandler {
|
||||
private static SpawnerHandler instance;
|
||||
private float enemySpawnTimer = 0f;
|
||||
private static final float ENEMY_SPAWN_INTERVAL = 0.5f;
|
||||
private static final float ENEMY_SPAWN_INTERVAL = 1f;
|
||||
|
||||
private SpawnerHandler() {}
|
||||
|
||||
@@ -31,13 +31,13 @@ public class SpawnerHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public void spawn(Enemies enemy) {
|
||||
public void spawn(EnemyTypes enemy) {
|
||||
World world = Bugger.getInstance().getWorld();
|
||||
Vector2 playerPos = Player.getInstance().getPosition();
|
||||
EnemyHandler.getInstance().getEnemies().add(EnemyFactory.createEnemy(enemy, world, playerPos));
|
||||
}
|
||||
|
||||
public void spawn(Enemies enemy, World world, Vector2 position) {
|
||||
public void spawn(EnemyTypes enemy, World world, Vector2 position) {
|
||||
EnemyHandler.getInstance().getEnemies().add(EnemyFactory.createEnemy(enemy, world, position));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.lumijiez.bugger.pools;
|
||||
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.Sprite;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ProjectileFlyweight {
|
||||
private static final Map<Boolean, ProjectileFlyweight> flyweights = new HashMap<>();
|
||||
private final Sprite sprite;
|
||||
private final float size;
|
||||
private final float defaultSpeed;
|
||||
private final boolean isEnemy;
|
||||
public static final String ENEMY_TEXTURE = "images/enemyblaze.png";
|
||||
public static final String PLAYER_TEXTURE = "images/blaze.png";
|
||||
|
||||
ProjectileFlyweight(boolean isEnemy) {
|
||||
this.sprite = new Sprite(new Texture(isEnemy ? ENEMY_TEXTURE : PLAYER_TEXTURE));
|
||||
this.size = 5f;
|
||||
this.defaultSpeed = 5000f;
|
||||
this.isEnemy = isEnemy;
|
||||
}
|
||||
|
||||
public static ProjectileFlyweight get(boolean isEnemy) {
|
||||
return flyweights.computeIfAbsent(isEnemy, ProjectileFlyweight::new);
|
||||
}
|
||||
|
||||
public Sprite getSprite() {
|
||||
return sprite;
|
||||
}
|
||||
|
||||
public float getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public float getDefaultSpeed() {
|
||||
return defaultSpeed;
|
||||
}
|
||||
|
||||
public boolean isEnemy() {
|
||||
return isEnemy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.lumijiez.bugger.util;
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.GL20;
|
||||
import org.lumijiez.bugger.Bugger;
|
||||
import org.lumijiez.bugger.entities.Player;
|
||||
import org.lumijiez.bugger.entities.player.Player;
|
||||
import org.lumijiez.bugger.handlers.*;
|
||||
|
||||
import static org.lumijiez.bugger.Bugger.spriteBatch;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.lumijiez.bugger.util;
|
||||
package org.lumijiez.bugger.util.data;
|
||||
|
||||
public record CollisionPair(Class<?> typeA, Class<?> typeB) {
|
||||
public boolean matches(Object objA, Object objB) {
|
||||
34
core/src/main/java/org/lumijiez/bugger/util/data/Triple.java
Normal file
34
core/src/main/java/org/lumijiez/bugger/util/data/Triple.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package org.lumijiez.bugger.util.data;
|
||||
|
||||
public class Triple<A, B, C> {
|
||||
private final A first;
|
||||
private final B second;
|
||||
private final C third;
|
||||
|
||||
public Triple(A first, B second, C third) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
this.third = third;
|
||||
}
|
||||
|
||||
public A first() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public B second() {
|
||||
return second;
|
||||
}
|
||||
|
||||
public C third() {
|
||||
return third;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Triple{" +
|
||||
"first=" + first +
|
||||
", second=" + second +
|
||||
", third=" + third +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.lumijiez.bugger.util.data;
|
||||
|
||||
public class TripleInt extends Triple<Integer,Integer,Integer> {
|
||||
|
||||
public TripleInt(int first, int second, int third) {
|
||||
super(first, second, third);
|
||||
}
|
||||
|
||||
public int one() {
|
||||
return super.first();
|
||||
}
|
||||
|
||||
public int two() {
|
||||
return super.second();
|
||||
}
|
||||
|
||||
public int thr() {
|
||||
return super.third();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "IntTriple{" +
|
||||
"first=" + one() +
|
||||
", second=" + two() +
|
||||
", third=" + thr() +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.lumijiez.bugger.util;
|
||||
package org.lumijiez.bugger.util.functional;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CollisionAction {
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.lumijiez.bugger.util;
|
||||
package org.lumijiez.bugger.util.functional;
|
||||
|
||||
import org.lumijiez.bugger.entities.Entity;
|
||||
import org.lumijiez.bugger.entities.EntityType;
|
||||
Reference in New Issue
Block a user