add particles.emit(...) (WIP)
This commit is contained in:
parent
9728c674fc
commit
c8187c5f25
8
res/content/base/scripts/world.lua
Normal file
8
res/content/base/scripts/world.lua
Normal file
@ -0,0 +1,8 @@
|
||||
function on_block_broken(id, x, y, z, playerid)
|
||||
particles.emit({x+0.5, y+0.5, z+0.5}, 100, {
|
||||
lifetime=1.0,
|
||||
spawn_interval=0.0001,
|
||||
explosion={4, 4, 4},
|
||||
texture="blocks:"..block.get_textures(id)[1]
|
||||
})
|
||||
end
|
||||
@ -66,7 +66,7 @@ void LevelScreen::initializeContent() {
|
||||
for (auto& entry : content->getPacks()) {
|
||||
initializePack(entry.second.get());
|
||||
}
|
||||
scripting::on_frontend_init(hud.get());
|
||||
scripting::on_frontend_init(hud.get(), worldRenderer.get());
|
||||
}
|
||||
|
||||
void LevelScreen::initializePack(ContentPackRuntime* pack) {
|
||||
|
||||
@ -12,18 +12,17 @@
|
||||
Emitter::Emitter(
|
||||
const Level& level,
|
||||
std::variant<glm::vec3, entityid_t> origin,
|
||||
Particle prototype,
|
||||
ParticlesPreset preset,
|
||||
const Texture* texture,
|
||||
float spawnInterval,
|
||||
const UVRegion& region,
|
||||
int count
|
||||
)
|
||||
: level(level),
|
||||
origin(std::move(origin)),
|
||||
prototype(std::move(prototype)),
|
||||
prototype({this, 0, glm::vec3(), preset.velocity, preset.lifetime, region}),
|
||||
texture(texture),
|
||||
spawnInterval(spawnInterval),
|
||||
count(count),
|
||||
preset() {
|
||||
preset(std::move(preset)) {
|
||||
this->prototype.emitter = this;
|
||||
}
|
||||
|
||||
@ -36,6 +35,7 @@ void Emitter::update(
|
||||
const glm::vec3& cameraPosition,
|
||||
std::vector<Particle>& particles
|
||||
) {
|
||||
const float spawnInterval = preset.spawnInterval;
|
||||
if (count == 0 || (count == -1 && spawnInterval < FLT_EPSILON)) {
|
||||
return;
|
||||
}
|
||||
@ -67,7 +67,7 @@ void Emitter::update(
|
||||
particle.emitter = this;
|
||||
particle.random = random.rand32();
|
||||
particle.position = position;
|
||||
particle.velocity += glm::ballRand(1.0f) * explosion;
|
||||
particle.velocity += glm::ballRand(1.0f) * preset.explosion;
|
||||
particles.push_back(std::move(particle));
|
||||
timer -= spawnInterval;
|
||||
if (count > 0) {
|
||||
@ -76,10 +76,6 @@ void Emitter::update(
|
||||
}
|
||||
}
|
||||
|
||||
void Emitter::setExplosion(const glm::vec3& magnitude) {
|
||||
explosion = magnitude;
|
||||
}
|
||||
|
||||
bool Emitter::isDead() const {
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
@ -31,24 +31,22 @@ struct Particle {
|
||||
|
||||
class Texture;
|
||||
|
||||
using EmitterOrigin = std::variant<glm::vec3, entityid_t>;
|
||||
|
||||
class Emitter {
|
||||
const Level& level;
|
||||
/// @brief Static position or entity
|
||||
std::variant<glm::vec3, entityid_t> origin;
|
||||
EmitterOrigin origin;
|
||||
/// @brief Particle prototype
|
||||
Particle prototype;
|
||||
/// @brief Particle
|
||||
const Texture* texture;
|
||||
/// @brief Particles spawn interval
|
||||
float spawnInterval;
|
||||
/// @brief Number of particles should be spawned before emitter deactivation.
|
||||
/// -1 is infinite.
|
||||
int count;
|
||||
/// @brief Spawn timer used to determine number of particles
|
||||
/// to spawn on update. May be innacurate.
|
||||
float timer = 0.0f;
|
||||
/// @brief Random velocity magnitude applying to spawned particles.
|
||||
glm::vec3 explosion {8.0f};
|
||||
|
||||
util::PseudoRandom random;
|
||||
public:
|
||||
@ -57,9 +55,9 @@ public:
|
||||
Emitter(
|
||||
const Level& level,
|
||||
std::variant<glm::vec3, entityid_t> origin,
|
||||
Particle prototype,
|
||||
ParticlesPreset preset,
|
||||
const Texture* texture,
|
||||
float spawnInterval,
|
||||
const UVRegion& region,
|
||||
int count
|
||||
);
|
||||
|
||||
@ -77,10 +75,7 @@ public:
|
||||
const glm::vec3& cameraPosition,
|
||||
std::vector<Particle>& particles
|
||||
);
|
||||
|
||||
/// @brief Set initial random velocity magitude
|
||||
void setExplosion(const glm::vec3& magnitude);
|
||||
|
||||
|
||||
/// @return true if the emitter has spawned all particles
|
||||
bool isDead() const;
|
||||
};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#include "ParticlesRenderer.hpp"
|
||||
|
||||
#include "assets/Assets.hpp"
|
||||
#include "assets/assets_util.hpp"
|
||||
#include "graphics/core/Shader.hpp"
|
||||
#include "graphics/core/Texture.hpp"
|
||||
#include "graphics/render/MainBatch.hpp"
|
||||
@ -18,17 +17,7 @@ ParticlesRenderer::ParticlesRenderer(
|
||||
)
|
||||
: batch(std::make_unique<MainBatch>(1024)),
|
||||
level(level),
|
||||
settings(settings) {
|
||||
auto region = util::get_texture_region(assets, "blocks:grass_side", "");
|
||||
emitters.push_back(std::make_unique<Emitter>(
|
||||
level,
|
||||
glm::vec3(0, 80, 0),
|
||||
Particle {nullptr, 0, glm::vec3(), glm::vec3(), 5.0f, region.region},
|
||||
region.texture,
|
||||
0.002f,
|
||||
-1
|
||||
));
|
||||
}
|
||||
settings(settings) {}
|
||||
|
||||
ParticlesRenderer::~ParticlesRenderer() = default;
|
||||
|
||||
@ -68,21 +57,22 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
|
||||
auto iter = vec.begin();
|
||||
while (iter != vec.end()) {
|
||||
auto& particle = *iter;
|
||||
auto& preset = particle.emitter->preset;
|
||||
|
||||
update_particle(particle, delta, chunks);
|
||||
|
||||
glm::vec4 light(1, 1, 1, 0);
|
||||
if (particle.emitter->preset.lighting) {
|
||||
if (preset.lighting) {
|
||||
light = MainBatch::sampleLight(
|
||||
particle.position, chunks, backlight
|
||||
);
|
||||
light *= 0.8f + (particle.random % 200) * 0.001f;
|
||||
light *= 0.9f + (particle.random % 100) * 0.001f;
|
||||
}
|
||||
batch->quad(
|
||||
particle.position,
|
||||
right,
|
||||
up,
|
||||
glm::vec2(0.3f),
|
||||
preset.size,
|
||||
light,
|
||||
glm::vec3(1.0f),
|
||||
particle.region
|
||||
@ -128,3 +118,7 @@ void ParticlesRenderer::render(const Camera& camera, float delta) {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticlesRenderer::add(std::unique_ptr<Emitter> emitter) {
|
||||
emitters.push_back(std::move(emitter));
|
||||
}
|
||||
|
||||
@ -31,6 +31,8 @@ public:
|
||||
|
||||
void render(const Camera& camera, float delta);
|
||||
|
||||
void add(std::unique_ptr<Emitter> emitter);
|
||||
|
||||
static size_t visibleParticles;
|
||||
static size_t aliveEmitters;
|
||||
};
|
||||
|
||||
@ -44,6 +44,7 @@
|
||||
#include "ChunksRenderer.hpp"
|
||||
#include "ModelBatch.hpp"
|
||||
#include "Skybox.hpp"
|
||||
#include "Emitter.hpp"
|
||||
|
||||
bool WorldRenderer::showChunkBorders = false;
|
||||
bool WorldRenderer::showEntitiesDebug = false;
|
||||
@ -534,6 +535,10 @@ void WorldRenderer::drawBorders(
|
||||
lineBatch->flush();
|
||||
}
|
||||
|
||||
void WorldRenderer::addEmitter(std::unique_ptr<Emitter> emitter) {
|
||||
particles->add(std::move(emitter));
|
||||
}
|
||||
|
||||
void WorldRenderer::clear() {
|
||||
renderer->clear();
|
||||
}
|
||||
|
||||
@ -8,8 +8,6 @@
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Emitter.hpp"
|
||||
|
||||
class Level;
|
||||
class Player;
|
||||
class Camera;
|
||||
@ -27,6 +25,7 @@ class PostProcessing;
|
||||
class DrawContext;
|
||||
class ModelBatch;
|
||||
class Assets;
|
||||
class Emitter;
|
||||
struct EngineSettings;
|
||||
|
||||
namespace model {
|
||||
@ -109,5 +108,7 @@ public:
|
||||
bool pause
|
||||
);
|
||||
|
||||
void addEmitter(std::unique_ptr<Emitter> emitter);
|
||||
|
||||
void clear();
|
||||
};
|
||||
|
||||
@ -31,6 +31,7 @@ extern const luaL_Reg itemlib[];
|
||||
extern const luaL_Reg jsonlib[];
|
||||
extern const luaL_Reg mat4lib[];
|
||||
extern const luaL_Reg packlib[];
|
||||
extern const luaL_Reg particleslib[];
|
||||
extern const luaL_Reg playerlib[];
|
||||
extern const luaL_Reg quatlib[]; // quat.cpp
|
||||
extern const luaL_Reg timelib[];
|
||||
|
||||
44
src/logic/scripting/lua/libs/libparticles.cpp
Normal file
44
src/logic/scripting/lua/libs/libparticles.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "api_lua.hpp"
|
||||
|
||||
#include "logic/scripting/scripting_hud.hpp"
|
||||
#include "graphics/render/WorldRenderer.hpp"
|
||||
#include "graphics/render/Emitter.hpp"
|
||||
#include "assets/assets_util.hpp"
|
||||
#include "engine.hpp"
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
static int l_emit(lua::State* L) {
|
||||
EmitterOrigin origin;
|
||||
if (lua::istable(L, 1)) {
|
||||
origin = lua::tovec3(L, 1);
|
||||
} else {
|
||||
origin = static_cast<entityid_t>(lua::tointeger(L, 1));
|
||||
}
|
||||
int count = lua::tointeger(L, 2);
|
||||
auto preset = lua::tovalue(L, 3);
|
||||
auto extension = lua::tovalue(L, 4);
|
||||
|
||||
ParticlesPreset particlesPreset {};
|
||||
particlesPreset.deserialize(preset);
|
||||
if (extension != nullptr) {
|
||||
particlesPreset.deserialize(extension);
|
||||
}
|
||||
auto& assets = *engine->getAssets();
|
||||
auto region = util::get_texture_region(assets, particlesPreset.texture, "");
|
||||
auto emitter = std::make_unique<Emitter>(
|
||||
*level,
|
||||
std::move(origin),
|
||||
std::move(particlesPreset),
|
||||
region.texture,
|
||||
region.region,
|
||||
count
|
||||
);
|
||||
renderer->addEmitter(std::move(emitter));
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg particleslib[] = {
|
||||
{"emit", lua::wrap<l_emit>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@ -4,6 +4,7 @@
|
||||
#include "engine.hpp"
|
||||
#include "files/files.hpp"
|
||||
#include "frontend/hud.hpp"
|
||||
#include "graphics/render/WorldRenderer.hpp"
|
||||
#include "objects/Player.hpp"
|
||||
#include "lua/libs/api_lua.hpp"
|
||||
#include "lua/lua_engine.hpp"
|
||||
@ -14,10 +15,14 @@ using namespace scripting;
|
||||
static debug::Logger logger("scripting-hud");
|
||||
|
||||
Hud* scripting::hud = nullptr;
|
||||
WorldRenderer* scripting::renderer = nullptr;
|
||||
|
||||
void scripting::on_frontend_init(Hud* hud) {
|
||||
void scripting::on_frontend_init(Hud* hud, WorldRenderer* renderer) {
|
||||
scripting::hud = hud;
|
||||
scripting::renderer = renderer;
|
||||
|
||||
lua::openlib(lua::get_main_state(), "hud", hudlib);
|
||||
lua::openlib(lua::get_main_state(), "particles", particleslib);
|
||||
|
||||
for (auto& pack : engine->getContentPacks()) {
|
||||
lua::emit_event(
|
||||
|
||||
@ -8,20 +8,20 @@
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class Hud;
|
||||
class WorldRenderer;
|
||||
|
||||
namespace scripting {
|
||||
extern Hud *hud;
|
||||
extern WorldRenderer* renderer;
|
||||
|
||||
void on_frontend_init(Hud *hud);
|
||||
void on_frontend_init(Hud* hud, WorldRenderer* renderer);
|
||||
void on_frontend_render();
|
||||
void on_frontend_close();
|
||||
|
||||
/**
|
||||
* Load package-specific hud script
|
||||
* @param env environment id
|
||||
* @param packid content-pack id
|
||||
* @param file script file path
|
||||
*/
|
||||
/// @brief Load package-specific hud script
|
||||
/// @param env environment id
|
||||
/// @param packid content-pack id
|
||||
/// @param file script file path
|
||||
void load_hud_script(
|
||||
const scriptenv &env, const std::string &packid, const fs::path &file
|
||||
);
|
||||
|
||||
@ -4,17 +4,32 @@
|
||||
|
||||
dv::value ParticlesPreset::serialize() const {
|
||||
auto root = dv::object();
|
||||
root["texture"] = texture;
|
||||
root["collision"] = collision;
|
||||
root["lighting"] = lighting;
|
||||
root["max_distance"] = maxDistance;
|
||||
root["spawn_interval"] = spawnInterval;
|
||||
root["lifetime"] = lifetime;
|
||||
root["acceleration"] = dv::to_value(acceleration);
|
||||
root["explosion"] = dv::to_value(explosion);
|
||||
root["size"] = dv::to_value(size);
|
||||
return root;
|
||||
}
|
||||
|
||||
void ParticlesPreset::deserialize(const dv::value& src) {
|
||||
src.at("texture").get(texture);
|
||||
src.at("collision").get(collision);
|
||||
src.at("lighting").get(lighting);
|
||||
src.at("max_distance").get(maxDistance);
|
||||
src.at("spawn_interval").get(spawnInterval);
|
||||
src.at("lifetime").get(lifetime);
|
||||
if (src.has("acceleration")) {
|
||||
dv::get_vec(src["acceleration"], acceleration);
|
||||
}
|
||||
if (src.has("size")) {
|
||||
dv::get_vec(src["size"], size);
|
||||
}
|
||||
if (src.has("explosion")) {
|
||||
dv::get_vec(src["explosion"], explosion);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,8 +11,20 @@ struct ParticlesPreset : public Serializable {
|
||||
bool lighting = true;
|
||||
/// @brief Max distance of actually spawning particles.
|
||||
float maxDistance = 32.0f;
|
||||
/// @brief Particles spawn interval
|
||||
float spawnInterval = 0.1f;
|
||||
/// @brief Particle life time
|
||||
float lifetime = 5.0f;
|
||||
/// @brief Initial velocity
|
||||
glm::vec3 velocity {};
|
||||
/// @brief Velocity acceleration
|
||||
glm::vec3 acceleration {0.0f, -16.0f, 0.0f};
|
||||
/// @brief Random velocity magnitude applying to spawned particles.
|
||||
glm::vec3 explosion {2.0f};
|
||||
/// @brief Particle size
|
||||
glm::vec3 size {0.1f};
|
||||
/// @brief Texture name
|
||||
std::string texture = "";
|
||||
|
||||
dv::value serialize() const override;
|
||||
void deserialize(const dv::value& src) override;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user