Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add particle animation, glow
This is implemented by reusing and extending the
TileAnimation code for the methods used by particles.
  • Loading branch information
sfan5 committed Jan 18, 2017
1 parent c5967f7 commit 7279f0b
Show file tree
Hide file tree
Showing 16 changed files with 311 additions and 78 deletions.
7 changes: 6 additions & 1 deletion doc/lua_api.txt
Expand Up @@ -4180,10 +4180,15 @@ The Biome API is still in an experimental phase and subject to change.
-- ^ vertical: if true faces player using y axis only
texture = "image.png",
-- ^ Uses texture (string)
playername = "singleplayer"
playername = "singleplayer",
-- ^ optional, if specified spawns particle only on the player's client
animation = {Tile Animation definition},
-- ^ optional, specifies how to animate the particle texture
glow = 0
-- ^ optional, specify particle self-luminescence in darkness
}


### `ParticleSpawner` definition (`add_particlespawner`)

{
Expand Down
37 changes: 37 additions & 0 deletions games/minimal/mods/experimental/init.lua
Expand Up @@ -523,6 +523,43 @@ minetest.register_craft({
}
})
minetest.register_craftitem("experimental:tester_tool_2", {
description = "Tester Tool 2",
inventory_image = "experimental_tester_tool_1.png^[invert:g",
on_use = function(itemstack, user, pointed_thing)
local pos = minetest.get_pointed_thing_position(pointed_thing, true)
if pos == nil then return end
pos = vector.add(pos, {x=0, y=0.5, z=0})
local tex, anim
if math.random(0, 1) == 0 then
tex = "default_lava_source_animated.png"
anim = {type="sheet_2d", frames_w=3, frames_h=2, frame_length=0.5}
else
tex = "default_lava_flowing_animated.png"
anim = {type="vertical_frames", aspect_w=16, aspect_h=16, length=3.3}
end
minetest.add_particle({
pos = pos,
velocity = {x=0, y=0, z=0},
acceleration = {x=0, y=0.04, z=0},
expirationtime = 6,
collisiondetection = true,
texture = tex,
animation = anim,
size = 4,
glow = math.random(0, 5),
})
end,
})
minetest.register_craft({
output = 'experimental:tester_tool_2',
recipe = {
{'group:crumbly','group:crumbly'},
}
})
--[[minetest.register_on_joinplayer(function(player)
minetest.after(3, function()
player:set_inventory_formspec("size[8,7.5]"..
Expand Down
5 changes: 5 additions & 0 deletions src/client.h
Expand Up @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "hud.h"
#include "particles.h"
#include "mapnode.h"
#include "tileanimation.h"

struct MeshMakeData;
class MapBlockMesh;
Expand Down Expand Up @@ -186,6 +187,8 @@ struct ClientEvent
bool collision_removal;
bool vertical;
std::string *texture;
struct TileAnimationParams animation;
u8 glow;
} spawn_particle;
struct{
u16 amount;
Expand All @@ -206,6 +209,8 @@ struct ClientEvent
bool vertical;
std::string *texture;
u32 id;
struct TileAnimationParams animation;
u8 glow;
} add_particlespawner;
struct{
u32 id;
Expand Down
18 changes: 18 additions & 0 deletions src/network/clientpackethandler.cpp
Expand Up @@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "network/clientopcodes.h"
#include "util/serialize.h"
#include "util/srp.h"
#include "tileanimation.h"

void Client::handleCommand_Deprecated(NetworkPacket* pkt)
{
Expand Down Expand Up @@ -896,9 +897,14 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
std::string texture = deSerializeLongString(is);
bool vertical = false;
bool collision_removal = false;
struct TileAnimationParams animation;
animation.type = TAT_NONE;
u8 glow = 0;
try {
vertical = readU8(is);
collision_removal = readU8(is);
animation.deSerialize(is, m_proto_ver);
glow = readU8(is);
} catch (...) {}

ClientEvent event;
Expand All @@ -912,6 +918,8 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
event.spawn_particle.collision_removal = collision_removal;
event.spawn_particle.vertical = vertical;
event.spawn_particle.texture = new std::string(texture);
event.spawn_particle.animation = animation;
event.spawn_particle.glow = glow;

m_client_event_queue.push(event);
}
Expand Down Expand Up @@ -943,12 +951,20 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)

bool vertical = false;
bool collision_removal = false;
struct TileAnimationParams animation;
animation.type = TAT_NONE;
u8 glow = 0;
u16 attached_id = 0;
try {
*pkt >> vertical;
*pkt >> collision_removal;
*pkt >> attached_id;

// This is horrible but required (why are there two ways to deserialize pkts?)
std::string datastring(pkt->getRemainingString(), pkt->getRemainingBytes());
std::istringstream is(datastring, std::ios_base::binary);
animation.deSerialize(is, m_proto_ver);
glow = readU8(is);
} catch (...) {}

ClientEvent event;
Expand All @@ -971,6 +987,8 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
event.add_particlespawner.vertical = vertical;
event.add_particlespawner.texture = new std::string(texture);
event.add_particlespawner.id = id;
event.add_particlespawner.animation = animation;
event.add_particlespawner.glow = glow;

m_client_event_queue.push(event);
}
Expand Down
2 changes: 1 addition & 1 deletion src/network/networkpacket.cpp
Expand Up @@ -63,7 +63,7 @@ void NetworkPacket::putRawPacket(u8 *data, u32 datasize, u16 peer_id)
m_data = std::vector<u8>(&data[2], &data[2 + m_datasize]);
}

char* NetworkPacket::getString(u32 from_offset)
const char* NetworkPacket::getString(u32 from_offset)
{
checkReadOffset(from_offset, 0);

Expand Down
5 changes: 4 additions & 1 deletion src/network/networkpacket.h
Expand Up @@ -41,12 +41,15 @@ class NetworkPacket
u16 getPeerId() { return m_peer_id; }
u16 getCommand() { return m_command; }
const u32 getRemainingBytes() const { return m_datasize - m_read_offset; }
const char* getRemainingString() { return getString(m_read_offset); }

// Returns a c-string without copying.
// A better name for this would be getRawString()
char* getString(u32 from_offset);
const char* getString(u32 from_offset);
// major difference to putCString(): doesn't write len into the buffer
void putRawString(const char* src, u32 len);
void putRawString(const std::string &src)
{ putRawString(src.c_str(), src.size()); }

NetworkPacket& operator>>(std::string& dst);
NetworkPacket& operator<<(std::string src);
Expand Down
2 changes: 1 addition & 1 deletion src/nodedef.cpp
Expand Up @@ -541,7 +541,7 @@ void ContentFeatures::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
if (tile->material_flags & MATERIAL_FLAG_ANIMATION) {
int frame_length_ms;
tiledef->animation.determineParams(tile->texture->getOriginalSize(),
&frame_count, &frame_length_ms);
&frame_count, &frame_length_ms, NULL);
tile->animation_frame_count = frame_count;
tile->animation_frame_length_ms = frame_length_ms;
}
Expand Down
74 changes: 62 additions & 12 deletions src/particles.cpp
Expand Up @@ -54,7 +54,9 @@ Particle::Particle(
bool vertical,
video::ITexture *texture,
v2f texpos,
v2f texsize
v2f texsize,
const struct TileAnimationParams &anim,
u8 glow
):
scene::ISceneNode(smgr->getRootSceneNode(), smgr)
{
Expand All @@ -71,7 +73,9 @@ Particle::Particle(
m_material.setTexture(0, texture);
m_texpos = texpos;
m_texsize = texsize;

m_animation = anim;
m_animation_frame = 0;
m_animation_time = 0.0;

// Particle related
m_pos = pos;
Expand All @@ -84,6 +88,7 @@ Particle::Particle(
m_collisiondetection = collisiondetection;
m_collision_removal = collision_removal;
m_vertical = vertical;
m_glow = glow;

// Irrlicht stuff
m_collisionbox = aabb3f
Expand Down Expand Up @@ -142,6 +147,18 @@ void Particle::step(float dtime)
m_velocity += m_acceleration * dtime;
m_pos += m_velocity * dtime;
}
if (m_animation.type != TAT_NONE) {
m_animation_time += dtime;
int frame_length_i, frame_count;
m_animation.determineParams(
m_material.getTexture(0)->getSize(),
&frame_count, &frame_length_i, NULL);
float frame_length = frame_length_i / 1000.0;
while (m_animation_time > frame_length) {
m_animation_frame++;
m_animation_time -= frame_length;
}
}

// Update lighting
updateLight();
Expand All @@ -166,16 +183,32 @@ void Particle::updateLight()
else
light = blend_light(m_env->getDayNightRatio(), LIGHT_SUN, 0);

m_light = decode_light(light);
m_light = decode_light(light + m_glow);
}

void Particle::updateVertices()
{
video::SColor c(255, m_light, m_light, m_light);
f32 tx0 = m_texpos.X;
f32 tx1 = m_texpos.X + m_texsize.X;
f32 ty0 = m_texpos.Y;
f32 ty1 = m_texpos.Y + m_texsize.Y;
f32 tx0, tx1, ty0, ty1;

if (m_animation.type != TAT_NONE) {
const v2u32 texsize = m_material.getTexture(0)->getSize();
v2f texcoord, framesize_f;
v2u32 framesize;
texcoord = m_animation.getTextureCoords(texsize, m_animation_frame);
m_animation.determineParams(texsize, NULL, NULL, &framesize);
framesize_f = v2f(framesize.X / (float) texsize.X, framesize.Y / (float) texsize.Y);

tx0 = m_texpos.X + texcoord.X;
tx1 = m_texpos.X + texcoord.X + framesize_f.X * m_texsize.X;
ty0 = m_texpos.Y + texcoord.Y;
ty1 = m_texpos.Y + texcoord.Y + framesize_f.Y * m_texsize.Y;
} else {
tx0 = m_texpos.X;
tx1 = m_texpos.X + m_texsize.X;
ty0 = m_texpos.Y;
ty1 = m_texpos.Y + m_texsize.Y;
}

m_vertices[0] = video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0,
c, tx0, ty1);
Expand Down Expand Up @@ -210,7 +243,9 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
float minexptime, float maxexptime, float minsize, float maxsize,
bool collisiondetection, bool collision_removal, u16 attached_id, bool vertical,
video::ITexture *texture, u32 id, ParticleManager *p_manager) :
video::ITexture *texture, u32 id, const struct TileAnimationParams &anim,
u8 glow,
ParticleManager *p_manager) :
m_particlemanager(p_manager)
{
m_gamedef = gamedef;
Expand All @@ -234,6 +269,8 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
m_vertical = vertical;
m_texture = texture;
m_time = 0;
m_animation = anim;
m_glow = glow;

for (u16 i = 0; i<=m_amount; i++)
{
Expand Down Expand Up @@ -309,7 +346,9 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env)
m_vertical,
m_texture,
v2f(0.0, 0.0),
v2f(1.0, 1.0));
v2f(1.0, 1.0),
m_animation,
m_glow);
m_particlemanager->addParticle(toadd);
}
i = m_spawntimes.erase(i);
Expand Down Expand Up @@ -363,7 +402,9 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env)
m_vertical,
m_texture,
v2f(0.0, 0.0),
v2f(1.0, 1.0));
v2f(1.0, 1.0),
m_animation,
m_glow);
m_particlemanager->addParticle(toadd);
}
}
Expand Down Expand Up @@ -494,6 +535,8 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client,
event->add_particlespawner.vertical,
texture,
event->add_particlespawner.id,
event->add_particlespawner.animation,
event->add_particlespawner.glow,
this);

/* delete allocated content of event */
Expand Down Expand Up @@ -529,13 +572,16 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client,
event->spawn_particle.vertical,
texture,
v2f(0.0, 0.0),
v2f(1.0, 1.0));
v2f(1.0, 1.0),
event->spawn_particle.animation,
event->spawn_particle.glow);

addParticle(toadd);

delete event->spawn_particle.pos;
delete event->spawn_particle.vel;
delete event->spawn_particle.acc;
delete event->spawn_particle.texture;

break;
}
Expand Down Expand Up @@ -564,6 +610,8 @@ void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* s
// Texture
u8 texid = myrand_range(0, 5);
video::ITexture *texture;
struct TileAnimationParams anim;
anim.type = TAT_NONE;

// Only use first frame of animated texture
if (tiles[texid].material_flags & MATERIAL_FLAG_ANIMATION)
Expand Down Expand Up @@ -605,7 +653,9 @@ void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* s
false,
texture,
texpos,
texsize);
texsize,
anim,
0);

addParticle(toadd);
}
Expand Down

1 comment on commit 7279f0b

@paramat
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sfan5 you forgot to update documentation in networkprotocol.h

TOCLIENT_SPAWN_PARTICLE = 0x46,

However i will update it as i am working on particles.

Please sign in to comment.