Skip to content

Commit

Permalink
Merge pull request Revolutionary-Games#281 from Revolutionary-Games/2…
Browse files Browse the repository at this point in the history
…75-compound-emission-refactor

Refactorings to emission positions
fixes Revolutionary-Games#275
  • Loading branch information
Moopli committed Feb 16, 2015
2 parents aa3dd7e + 3dfa4aa commit 34c4655
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 58 deletions.
60 changes: 8 additions & 52 deletions scripts/microbe_stage/microbe.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ BANDWIDTH_PER_ORGANELLE = 0.5 -- amount the microbes maxmimum bandwidth increase
BANDWIDTH_REFILL_DURATION = 1000 -- The amount of time it takes for the microbe to regenerate an amount of bandwidth equal to maxBandwidth
STORAGE_EJECTION_THRESHHOLD = 0.8
EXCESS_COMPOUND_COLLECTION_INTERVAL = 1000 -- The amount of time between each loop to maintaining a fill level below STORAGE_EJECTION_THRESHHOLD and eject useless compounds
ANGLE_RADIUS_DIVISION_COUNT = 4 -- How many pizza slices the microbes angles are divided into. Higher is more precision but also more errors. 4 Seems to give no significant errors
MICROBE_HITPOINTS_PER_ORGANELLE = 10
MINIMUM_AGENT_EMISSION_AMOUNT = 1
REPRODUCTASE_TO_SPLIT = 5
RELATIVE_VELOCITY_TO_BUMP_SOUND = 6
INITIAL_EMISSION_RADIUS = 2

function MicrobeComponent:__init(isPlayerMicrobe)
Component.__init(self)
Expand All @@ -42,10 +42,6 @@ function MicrobeComponent:__init(isPlayerMicrobe)
self.maxBandwidth = 0
self.remainingBandwidth = 0
self.compoundCollectionTimer = EXCESS_COMPOUND_COLLECTION_INTERVAL
self.angleRadiuses = {} -- Holds ANGLE_RADIUS_DIVISION_COUNT angles and their distances until outside of microbe
for i=0, ANGLE_RADIUS_DIVISION_COUNT+1 do
table.insert(self.angleRadiuses, 3) -- We need a buffer zone as now all ANGLE_RADIUS_DIVISION_COUNT quadrants can be expected to be filled
end
end

function MicrobeComponent:_resetCompoundPriorities()
Expand Down Expand Up @@ -126,33 +122,6 @@ function MicrobeComponent:regenerateBandwidth(logicTime)
self.remainingBandwidth = math.min(addedBandwidth, self.maxBandwidth)
end

-- Find for a number of angles, how far away from the microbe we need to eject to avoid self colliding (for example emitting an agent into the microbe itself)
-- A better for system should be devisable when we have microbe membranes
-- This should be called when changes are made to the microbe outside the editor
function MicrobeComponent:updateSafeAngles()
-- For each organelle find how far away from the microbe we have to eject at a given angle to avoid self collision
for _, organelle in pairs(self.organelles) do
local organelleX, organelleY = axialToCartesian(organelle.position.q, organelle.position.r)
local nucleusX, nucleusY = axialToCartesian(0, 0)
local deltaX = nucleusX - organelleX
local deltaY = nucleusY - organelleY
local dist = math.sqrt(deltaX^2 + deltaY^2)
local angle = math.atan2(deltaY, deltaX)
if (angle < 0) then
angle = angle + 2*math.pi
end
angle = (angle * 180/math.pi + 90) % 360
local angleScaled = angle / (360/ANGLE_RADIUS_DIVISION_COUNT)
local angleRoundedDown = math.floor(angleScaled)
local angleRoundedUp = math.ceil(angleScaled)
if dist > self.angleRadiuses[angleRoundedDown+1] then
self.angleRadiuses[angleRoundedDown+1] = dist
end
if dist > self.angleRadiuses[angleRoundedUp+1] then
self.angleRadiuses[angleRoundedUp+1] = dist
end
end
end

function MicrobeComponent:load(storage)
Component.load(self, storage)
Expand Down Expand Up @@ -184,7 +153,6 @@ function MicrobeComponent:load(storage)
local compound = compoundPriorities:get(i)
self.compoundPriorities[compound:get("compoundId", 0)] = compound:get("priority", 0)
end
self:updateSafeAngles()
end


Expand Down Expand Up @@ -576,7 +544,7 @@ function Microbe:emitAgent(compoundId, maxAmount)
agentVacuole:takeCompound(compoundId, amountToEject)
local i
for i = 1, particleCount do
self:ejectCompound(compoundId, amountToEject/particleCount, angle,angle, true)
self:ejectCompound(compoundId, amountToEject/particleCount, angle,angle)
end
end
end
Expand Down Expand Up @@ -615,7 +583,7 @@ function Microbe:storeCompound(compoundId, amount, bandwidthLimited)
end
local i
for i = 1, particleCount do
self:ejectCompound(compoundId, remainingAmount/particleCount, 160, 200, true)
self:ejectCompound(compoundId, remainingAmount/particleCount, 160, 200)
end
end
else
Expand Down Expand Up @@ -652,14 +620,6 @@ function Microbe:takeCompound(compoundId, maxAmount)
end


function Microbe:getSafeEmissionDistance(angle)
local angleScaled = angle / (360/ANGLE_RADIUS_DIVISION_COUNT)
local angleRoundedDown = math.floor(angleScaled)
local angleRoundedUp = math.ceil(angleScaled)
return math.max(self.microbe.angleRadiuses[angleRoundedDown+1], self.microbe.angleRadiuses[angleRoundedUp+1]) + 2
end


-- Ejects compounds from the microbes behind position, into the enviroment
-- Note that the compounds ejected are created in this function and not taken from the microbe
--
Expand All @@ -674,7 +634,7 @@ end
--
-- @param maxAngle
-- Relative angle to the microbe. 0 = microbes front. Should be between 0 and 359 and higher or equal than minAngle
function Microbe:ejectCompound(compoundId, amount, minAngle, maxAngle, useRadius)
function Microbe:ejectCompound(compoundId, amount, minAngle, maxAngle)
local chosenAngle = rng:getReal(minAngle, maxAngle)
-- Find the direction the microbe is facing
local yAxis = self.sceneNode.transform.orientation:yAxis()
Expand All @@ -686,10 +646,7 @@ function Microbe:ejectCompound(compoundId, amount, minAngle, maxAngle, useRadius
-- Take the mirobe angle into account so we get world relative degrees
local finalAngle = (chosenAngle + microbeAngle) % 360
-- Find how far away we should spawn the particle so it doesn't collide with microbe.
local radius = 0
if useRadius then
radius = self:getSafeEmissionDistance((chosenAngle+180)%360)
end
local radius = INITIAL_EMISSION_RADIUS
self.compoundEmitter:emitCompound(compoundId, amount, finalAngle, radius)
self.microbe:_updateCompoundPriorities()
end
Expand All @@ -704,15 +661,15 @@ function Microbe:kill()
local _amount = amount
while _amount > 0 do
ejectedAmount = self:takeCompound(compoundId, 2.5) -- Eject up to 3 units per particle
self:ejectCompound(compoundId, ejectedAmount, 0, 359, false)
self:ejectCompound(compoundId, ejectedAmount, 0, 359)
_amount = _amount - ejectedAmount
end
end
for compoundId, specialStorageOrg in pairs(self.microbe.specialStorageOrganelles) do
local _amount = specialStorageOrg.storedAmount
while _amount > 0 do
ejectedAmount = specialStorageOrg:takeCompound(compoundId, 3) -- Eject up to 3 units per particle
self:ejectCompound(compoundId, ejectedAmount, 0, 359, false)
self:ejectCompound(compoundId, ejectedAmount, 0, 359)
_amount = _amount - ejectedAmount
end
end
Expand Down Expand Up @@ -751,7 +708,6 @@ function Microbe:reproduce()
end
copy.rigidBody.dynamicProperties.position = Vector3(self.rigidBody.dynamicProperties.position.x, self.rigidBody.dynamicProperties.position.y, 0)
copy:storeCompound(CompoundRegistry.getCompoundId("atp"), 20, false)
copy.microbe:updateSafeAngles()
copy.microbe:_resetCompoundPriorities()
copy.entity:addComponent(SpawnedComponent())
if self.microbe.isPlayerMicrobe then
Expand Down Expand Up @@ -816,7 +772,7 @@ function Microbe:update(logicTime)
end
for compoundId, amount in pairs(excessCompounds) do
if amount > 0 then
self:ejectCompound(compoundId, amount, 160, 200, true)
self:ejectCompound(compoundId, amount, 160, 200)
end
end
-- Damage microbe if its too low on ATP
Expand Down
5 changes: 2 additions & 3 deletions scripts/microbe_stage/setup.lua
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ function microbeSpawnFunctionGeneric(pos, speciesName, aiControlled, individualN
end
end
microbe.microbe.speciesName = speciesName
microbe.microbe:updateSafeAngles()
return microbe
end

Expand Down Expand Up @@ -370,14 +369,14 @@ local function setupEmitter()
-- Emitter test
local testEmitter = CompoundEmitterComponent()
entity:addComponent(testEmitter)
testEmitter.emissionRadius = 1
testEmitter.emissionRadius = 1.5
testEmitter.maxInitialSpeed = 10
testEmitter.minInitialSpeed = 2
testEmitter.minEmissionAngle = Degree(0)
testEmitter.maxEmissionAngle = Degree(360)
testEmitter.particleLifeTime = 5000
local timedEmitter = TimedCompoundEmitterComponent()
timedEmitter.compoundId = CompoundRegistry.getCompoundId("glucose")
timedEmitter.compoundId = CompoundRegistry.getCompoundId("oxygen")
timedEmitter.particlesPerEmission = 1
timedEmitter.potencyPerParticle = 3.0
timedEmitter.emitInterval = 1000
Expand Down
47 changes: 47 additions & 0 deletions src/bullet/rigid_body_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
#include "scripting/luabind.h"
#include "engine/serialization.h"

#include <cmath>
#include <iostream>

using namespace thrive;

const int PI = 3.1416f;
const float PUSHBACK_DIST = 2.2f; //Used for incrementally pushing emissions out of the emitters body

////////////////////////////////////////////////////////////////////////////////
// RigidBodyComponent
////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -97,6 +101,8 @@ RigidBodyComponent::luaBindings() {
.def("clearForces", &RigidBodyComponent::clearForces)
.def_readonly("properties", &RigidBodyComponent::m_properties)
.def_readonly("dynamicProperties", &RigidBodyComponent::m_dynamicProperties)
.def_readwrite("pushbackEntity", &RigidBodyComponent::m_pushbackEntity)
.def_readwrite("m_pushbackAngle", &RigidBodyComponent::m_pushbackAngle)
;
}

Expand Down Expand Up @@ -229,6 +235,26 @@ RigidBodyInputSystem::shutdown() {
}



struct _ContactResultCallback : public btCollisionWorld::ContactResultCallback
{
bool collisionDetected = false;

btScalar addSingleResult(
btManifoldPoint&,
const btCollisionObjectWrapper*,
int ,
int ,
const btCollisionObjectWrapper*,
int ,
int)
{
collisionDetected = true;
return 0.0f;
}
};


void
RigidBodyInputSystem::update(int, int logicTime) {
for (EntityId entityId : m_impl->m_entities.removedEntities()) {
Expand Down Expand Up @@ -342,6 +368,27 @@ RigidBodyInputSystem::update(int, int logicTime) {
body->setAngularVelocity(btVector3(0,0,0));
rigidBodyComponent->m_toClearForces = false;
}
if(rigidBodyComponent->m_pushbackEntity != NULL_ENTITY) {
//To debug this in the future, in the context of emitter components
// set emission speeds on the emitter components to 0
RigidBodyComponent* otherEntityBody = m_impl->m_entities.entityManager()->getComponent<RigidBodyComponent>(rigidBodyComponent->m_pushbackEntity);
auto callback = _ContactResultCallback();
if (otherEntityBody) {
m_impl->m_world->contactPairTest(body, otherEntityBody->m_body, callback);
auto v = Ogre::Vector3(PUSHBACK_DIST*sin(rigidBodyComponent->m_pushbackAngle*(PI/180.0)),PUSHBACK_DIST*cos(rigidBodyComponent->m_pushbackAngle*(PI/180.0)),0);
while(callback.collisionDetected)
{
rigidBodyComponent->m_dynamicProperties.position = rigidBodyComponent->m_dynamicProperties.position + v;
btTransform transform;
rigidBodyComponent->getWorldTransform(transform);
body->setWorldTransform(transform);

callback.collisionDetected = false;
m_impl->m_world->contactPairTest(body, otherEntityBody->m_body, callback);
}
}
rigidBodyComponent->m_pushbackEntity = NULL_ENTITY;
}
body->applyDamping(logicTime / 1000.0f);
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/bullet/rigid_body_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,9 @@ class RigidBodyComponent : public Component, public btMotionState {
Properties
m_properties;

EntityId m_pushbackEntity = NULL_ENTITY;
float m_pushbackAngle = 0;

private:

friend class RigidBodyInputSystem;
Expand Down
9 changes: 6 additions & 3 deletions src/microbe_stage/compound_emitter_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ emitCompound(
Ogre::Vector3 emittorPosition,
double angle,
double radius,
CompoundEmitterComponent* emitterComponent
CompoundEmitterComponent* emitterComponent,
EntityId emittingEntityId
) {

Ogre::Vector3 emissionOffset(0,0,0);
Expand Down Expand Up @@ -235,6 +236,8 @@ emitCompound(
compoundRigidBodyComponent->m_properties.hasContactResponse = false;
compoundRigidBodyComponent->m_properties.kinematic = true;
compoundRigidBodyComponent->m_dynamicProperties.position = emittorPosition + emissionOffset;
compoundRigidBodyComponent->m_pushbackEntity = emittingEntityId;
compoundRigidBodyComponent->m_pushbackAngle = angle;
// Compound Component
auto compoundComponent = make_unique<CompoundComponent>();
compoundComponent->m_velocity = emissionVelocity;
Expand Down Expand Up @@ -270,7 +273,7 @@ CompoundEmitterSystem::update(int, int logicTime) {

for (auto emission : emitterComponent->m_compoundEmissions)
{
emitCompound(std::get<0>(emission), std::get<1>(emission), sceneNodeComponent->m_transform.position, std::get<2>(emission), std::get<3>(emission), emitterComponent);
emitCompound(std::get<0>(emission), std::get<1>(emission), sceneNodeComponent->m_transform.position, std::get<2>(emission), std::get<3>(emission), emitterComponent, value.first);
}
emitterComponent->m_compoundEmissions.clear();
if (timedEmitterComponent)
Expand All @@ -286,7 +289,7 @@ CompoundEmitterSystem::update(int, int logicTime) {
emitterComponent->m_minEmissionAngle.valueDegrees(),
emitterComponent->m_maxEmissionAngle.valueDegrees()
);
emitCompound(timedEmitterComponent->m_compoundId, timedEmitterComponent->m_potencyPerParticle, sceneNodeComponent->m_transform.position, angle, emitterComponent->m_emissionRadius, emitterComponent);
emitCompound(timedEmitterComponent->m_compoundId, timedEmitterComponent->m_potencyPerParticle, sceneNodeComponent->m_transform.position, angle, emitterComponent->m_emissionRadius, emitterComponent, value.first);
}
}
}
Expand Down

0 comments on commit 34c4655

Please sign in to comment.