particles, plus doubling fix

This commit is contained in:
Daniel
2024-10-16 01:01:10 +03:00
parent 75d30165be
commit 9f56a9af5b
10 changed files with 434 additions and 35 deletions

155
assets/particles/boom.p Normal file
View File

@@ -0,0 +1,155 @@
Sparks
- Delay -
active: false
- Duration -
lowMin: 0.0
lowMax: 300.0
- Count -
min: 200
max: 200
- Emission -
lowMin: 0.0
lowMax: 0.0
highMin: 90.0
highMax: 90.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Life -
lowMin: 0.0
lowMax: 0.0
highMin: 500.0
highMax: 500.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
independent: false
- Life Offset -
active: false
independent: false
- X Offset -
active: false
- Y Offset -
active: false
- Spawn Shape -
shape: point
- Spawn Width -
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 0.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Spawn Height -
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 0.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- X Scale -
lowMin: 0.0
lowMax: 0.0
highMin: 30.0
highMax: 30.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Y Scale -
active: false
- Velocity -
active: true
lowMin: 0.0
lowMax: 0.0
highMin: 30.0
highMax: 285.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Angle -
active: true
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 360.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Rotation -
active: true
lowMin: 0.0
lowMax: 360.0
highMin: -360.0
highMax: 360.0
relative: true
scalingCount: 2
scaling0: 0.0
scaling1: 1.0
timelineCount: 2
timeline0: 0.0
timeline1: 1.0
- Wind -
active: false
- Gravity -
active: true
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 0.0
relative: true
scalingCount: 2
scaling0: 0.0
scaling1: 1.0
timelineCount: 2
timeline0: 0.0
timeline1: 1.0
- Tint -
colorsCount: 3
colors0: 0.93333334
colors1: 1.0
colors2: 0.3764706
timelineCount: 1
timeline0: 0.0
- Transparency -
lowMin: 0.0
lowMax: 0.0
highMin: 1.0
highMax: 1.0
relative: false
scalingCount: 4
scaling0: 0.0
scaling1: 1.0
scaling2: 0.75
scaling3: 0.0
timelineCount: 4
timeline0: 0.0
timeline1: 0.2
timeline2: 0.8
timeline3: 1.0
- Options -
attached: false
continuous: false
aligned: false
additive: true
behind: false
premultipliedAlpha: false
spriteMode: single
- Image Paths -
particle-star.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,57 @@
package org.lumijiez.bugger;
import com.badlogic.gdx.physics.box2d.*;
import org.lumijiez.bugger.entities.Entity;
import org.lumijiez.bugger.entities.enemies.EnemyEntity;
import org.lumijiez.bugger.entities.weapons.Arrow;
public class GameContactListener implements ContactListener {
@Override
public void beginContact(Contact contact) {
Fixture fixtureA = contact.getFixtureA();
Fixture fixtureB = contact.getFixtureB();
if (isArrow(fixtureA) && isArrow(fixtureB)) {
return;
}
if (isArrow(fixtureA) && isEntity(fixtureB)) {
Arrow arrow = (Arrow) fixtureA.getBody().getUserData();
EnemyEntity enemy = (EnemyEntity) fixtureB.getBody().getUserData();
if (arrow != null) {
arrow.destroy();
enemy.destroy();
}
}
if (isArrow(fixtureB) && isEntity(fixtureA)) {
Arrow arrow = (Arrow) fixtureB.getBody().getUserData();
EnemyEntity enemy = (EnemyEntity) fixtureA.getBody().getUserData();
if (arrow != null) {
arrow.destroy();
enemy.destroy();
}
}
}
@Override
public void endContact(Contact contact) {
}
@Override
public void preSolve(Contact contact, Manifold manifold) {
}
@Override
public void postSolve(Contact contact, ContactImpulse impulse) {
}
private boolean isArrow(Fixture fixture) {
return fixture.getBody().getUserData() instanceof Arrow;
}
private boolean isEntity(Fixture fixture) {
return fixture.getBody().getUserData() instanceof EnemyEntity;
}
}

View File

@@ -1,13 +1,18 @@
package org.lumijiez.bugger; package org.lumijiez.bugger;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Screen; import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.*; import com.badlogic.gdx.physics.box2d.*;
import com.badlogic.gdx.utils.Array;
import org.lumijiez.bugger.entities.Entity;
import org.lumijiez.bugger.entities.Player; import org.lumijiez.bugger.entities.Player;
import org.lumijiez.bugger.entities.enemies.EnemyEntity;
import org.lumijiez.bugger.entities.enemies.Wasp; import org.lumijiez.bugger.entities.enemies.Wasp;
import org.lumijiez.bugger.entities.weapons.Arrow;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -15,10 +20,12 @@ import java.util.List;
public class GameScreen implements Screen { public class GameScreen implements Screen {
private final World world; private final World world;
private final Player player; private final Player player;
public static final SpriteBatch spriteBatch = new SpriteBatch();; public static final SpriteBatch spriteBatch = new SpriteBatch();
private List<Wasp> enemies; private final List<EnemyEntity> enemies;
private float enemySpawnTimer = 0f; // Timer to manage enemy spawning private Array<Arrow> arrows;
private static final float ENEMY_SPAWN_INTERVAL = 2f; private Array<Entity> entitiesToDestroy;
private float enemySpawnTimer = 0f;
private static final float ENEMY_SPAWN_INTERVAL = 0.5f;
private final Box2DDebugRenderer debugRenderer = new Box2DDebugRenderer(); private final Box2DDebugRenderer debugRenderer = new Box2DDebugRenderer();
public GameScreen() { public GameScreen() {
@@ -26,6 +33,9 @@ public class GameScreen implements Screen {
player = Player.getInstance(); player = Player.getInstance();
player.setPlayer(world, 100, 100); player.setPlayer(world, 100, 100);
enemies = new ArrayList<>(); enemies = new ArrayList<>();
arrows = new Array<>();
entitiesToDestroy = new Array<>();
world.setContactListener(new GameContactListener());
} }
@Override @Override
@@ -38,24 +48,55 @@ public class GameScreen implements Screen {
Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1); Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
world.step(1 / 2f, 6, 2); world.step(1f, 6, 2);
if (Gdx.input.isButtonJustPressed(Input.Buttons.LEFT)) {
Arrow arrow = player.shootArrow();
arrows.add(arrow);
}
for (Arrow arrow : arrows) {
if (!arrow.isMarkedToDestroy()) {
arrow.update(delta);
arrow.render();
} else {
entitiesToDestroy.add(arrow);
}
}
for (EnemyEntity enemy : enemies) {
if (enemy.isMarkedToDestroy()) {
entitiesToDestroy.add(enemy);
}
}
for (Entity entity : entitiesToDestroy) {
world.destroyBody(entity.getBody());
if (entity instanceof Arrow) arrows.removeValue((Arrow) entity, true);
if (entity instanceof EnemyEntity) {
Gdx.app.log("EFFECT", "PLAYED");
ParticleManager.getInstance().playEffect(entity.getBody().getPosition().x, entity.getBody().getPosition().y);
enemies.remove(entity);
}
}
entitiesToDestroy.clear();
ParticleManager.getInstance().update(delta);
player.render(); player.render();
ParticleManager.getInstance().render(spriteBatch);
enemySpawnTimer += delta; enemySpawnTimer += delta;
if (enemySpawnTimer >= ENEMY_SPAWN_INTERVAL) { if (enemySpawnTimer >= ENEMY_SPAWN_INTERVAL) {
enemies.add(new Wasp(world, Player.getInstance().getPosition())); enemies.add(new Wasp(world, Player.getInstance().getPosition()));
enemySpawnTimer = 0; // Reset the timer enemySpawnTimer = 0;
} }
// Move enemies towards the player for (EnemyEntity enemy : enemies) {
for (Wasp enemy : enemies) {
enemy.moveTowards(player.getPosition()); enemy.moveTowards(player.getPosition());
} enemy.render();
// Render player and enemies
player.render(); // Call the player's render method
for (Wasp enemy : enemies) {
enemy.render(); // Render each enemy
} }
debugRenderer.render(world, spriteBatch.getProjectionMatrix()); debugRenderer.render(world, spriteBatch.getProjectionMatrix());

View File

@@ -0,0 +1,61 @@
package org.lumijiez.bugger;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.graphics.g2d.ParticleEffectPool;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.Array;
public class ParticleManager {
private static ParticleManager instance;
private final ParticleEffectPool particleEffectPool;
private final Array<ParticleEffectPool.PooledEffect> activeEffects;
private ParticleManager() {
ParticleEffect effect = new ParticleEffect();
effect.load(Gdx.files.internal("particles/boom.p"), Gdx.files.internal("particles"));
effect.scaleEffect(0.2f);
particleEffectPool = new ParticleEffectPool(effect, 1, 20);
activeEffects = new Array<>();
}
public static ParticleManager getInstance() {
if (instance == null) {
instance = new ParticleManager();
}
return instance;
}
public void playEffect(float x, float y) {
ParticleEffectPool.PooledEffect newEffect = particleEffectPool.obtain();
newEffect.setPosition(x, y);
newEffect.start();
activeEffects.add(newEffect);
}
public void update(float delta) {
for (int i = activeEffects.size - 1; i >= 0; i--) {
ParticleEffectPool.PooledEffect effect = activeEffects.get(i);
effect.update(delta);
if (effect.isComplete()) {
effect.free();
activeEffects.removeIndex(i);
}
}
}
public void render(SpriteBatch spriteBatch) {
spriteBatch.begin();
for (ParticleEffectPool.PooledEffect effect : activeEffects) {
effect.draw(spriteBatch);
}
spriteBatch.end();
}
public void dispose() {
for (ParticleEffectPool.PooledEffect effect : activeEffects) {
effect.free();
}
activeEffects.clear();
}
}

View File

@@ -12,6 +12,7 @@ public abstract class Entity {
protected Sprite sprite; protected Sprite sprite;
protected final float size; protected final float size;
protected World world; protected World world;
protected boolean markedToDestroy = false;
public Entity(World world, String texturePath, float size) { public Entity(World world, String texturePath, float size) {
this.world = world; this.world = world;
@@ -49,4 +50,18 @@ public abstract class Entity {
public Vector2 getPosition() { public Vector2 getPosition() {
return body.getPosition(); return body.getPosition();
} }
public void destroy() {
if (!markedToDestroy) {
markedToDestroy = true;
}
}
public boolean isMarkedToDestroy() {
return markedToDestroy;
}
public Body getBody() {
return body;
}
} }

View File

@@ -2,21 +2,16 @@ package org.lumijiez.bugger.entities;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input; import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World; import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import org.lumijiez.bugger.entities.weapons.Arrow;
public class Player extends Entity { public class Player extends Entity {
private static Player instance; private static Player instance;
private final float speed = 5f; private final float speed = 5f;
private Player() { private Player() {
super(null, "images/wasp.png", 50f); // World will be set later super(null, "images/wasp.png", 50f);
} }
public static Player getInstance() { public static Player getInstance() {
@@ -62,4 +57,16 @@ public class Player extends Entity {
body.setTransform(body.getPosition(), angle * (float) Math.PI / 180f); body.setTransform(body.getPosition(), angle * (float) Math.PI / 180f);
sprite.setRotation(body.getAngle() * (180f / (float) Math.PI)); sprite.setRotation(body.getAngle() * (180f / (float) Math.PI));
} }
public Arrow shootArrow() {
Vector2 direction = new Vector2();
float mouseX = Gdx.input.getX();
float mouseY = Gdx.input.getY();
Vector2 mousePosition = new Vector2(mouseX, Gdx.graphics.getHeight() - mouseY);
direction.set(mousePosition).sub(getPosition()).nor();
Arrow arrow = new Arrow(world, getPosition(), direction);
arrow.body.setUserData(arrow);
return arrow;
}
} }

View File

@@ -0,0 +1,25 @@
package org.lumijiez.bugger.entities.enemies;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.World;
import org.lumijiez.bugger.entities.Entity;
public class EnemyEntity extends Entity {
private final float speed = 50f;
public EnemyEntity(World world, String texturePath, float size) {
super(world, texturePath, size);
}
public void moveTowards(Vector2 target) {
Vector2 direction = target.cpy().sub(body.getPosition()).nor();
body.setLinearVelocity(direction.scl(speed / 100f));
float angle = direction.angleDeg() + 270f;
body.setTransform(body.getPosition(), angle * (float) Math.PI / 180f);
}
public void render() {
super.render();
}
}

View File

@@ -2,12 +2,12 @@ package org.lumijiez.bugger.entities.enemies;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.*; import com.badlogic.gdx.physics.box2d.*;
import org.lumijiez.bugger.ParticleManager;
import org.lumijiez.bugger.entities.Entity; import org.lumijiez.bugger.entities.Entity;
import java.util.Random; import java.util.Random;
public class Wasp extends Entity { public class Wasp extends EnemyEntity {
private final float speed = 50f;
private static final Random random = new Random(); private static final Random random = new Random();
public Wasp(World world, Vector2 playerPosition) { public Wasp(World world, Vector2 playerPosition) {
@@ -17,17 +17,6 @@ public class Wasp extends Entity {
float spawnX = playerPosition.x + (float) Math.cos(angle) * (spawnRadius + size); float spawnX = playerPosition.x + (float) Math.cos(angle) * (spawnRadius + size);
float spawnY = playerPosition.y + (float) Math.sin(angle) * (spawnRadius + size); float spawnY = playerPosition.y + (float) Math.sin(angle) * (spawnRadius + size);
this.body = createBody(spawnX, spawnY); this.body = createBody(spawnX, spawnY);
} this.body.setUserData(this);
public void moveTowards(Vector2 target) {
Vector2 direction = target.cpy().sub(body.getPosition()).nor();
body.setLinearVelocity(direction.scl(speed / 100f));
float angle = direction.angleDeg() + 270f;
body.setTransform(body.getPosition(), angle * (float) Math.PI / 180f);
}
public void render() {
super.render();
} }
} }

View File

@@ -0,0 +1,49 @@
package org.lumijiez.bugger.entities.weapons;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.*;
import org.lumijiez.bugger.entities.Entity;
public class Arrow extends Entity {
private final float speed = 5000f;
private final float lifetime = 3f;
private float timeAlive = 0f;
public Arrow(World world, Vector2 position, Vector2 direction) {
super(world, "images/wasp.png", 10f);
Vector2 offsetPosition = position.cpy().add(direction.nor().scl(size + 15f));
this.body = createBody(offsetPosition.x, offsetPosition.y);
this.body.setLinearVelocity(direction.nor().scl(speed));
}
protected Body createBody(float x, float y) {
BodyDef bodyDef = new BodyDef();
bodyDef.position.set(x, y);
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.gravityScale = 0;
Body body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(size / 2, size / 2);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.isSensor = true;
body.createFixture(fixtureDef);
shape.dispose();
return body;
}
public void update(float delta) {
timeAlive += delta;
if (timeAlive >= lifetime || isMarkedToDestroy()) {
destroy();
}
}
public void render() {
super.render();
}
}