|
@@ -1,12 +1,16 @@
|
|
|
#include "Entity.h"
|
|
|
+#include "Dimension.h"
|
|
|
+#include "Game.h"
|
|
|
+#include "BlockType.h"
|
|
|
|
|
|
Entity::Entity( const EntityType* zType, Framework::Vec3<float> location, int dimensionId, int entityId )
|
|
|
: Inventory( location, true ),
|
|
|
speed( 0, 0, 0 ),
|
|
|
- faceDir( 1, 0 ),
|
|
|
+ faceDir( 1, 0, 0 ),
|
|
|
zEntityType( zType ),
|
|
|
currentDimensionId( dimensionId ),
|
|
|
removed( 0 ),
|
|
|
+ gravityMultiplier( 1.f ),
|
|
|
id( entityId )
|
|
|
{}
|
|
|
|
|
@@ -15,7 +19,126 @@ void Entity::onDeath()
|
|
|
|
|
|
void Entity::tick( const Dimension* zDimension, Game* zGame )
|
|
|
{
|
|
|
- // TODO
|
|
|
+ Vec3<float> oldPos = location;
|
|
|
+ // current block cooredinates
|
|
|
+ int px = (int)floor( location.x );
|
|
|
+ int py = (int)floor( location.y );
|
|
|
+ int pz = (int)floor( location.z );
|
|
|
+ // falling down
|
|
|
+ speed.z -= (zDimension->getGravity() * gravityMultiplier) / 30.f;
|
|
|
+ // movement in current tick
|
|
|
+ Vec3<float> frameSpeed = speed / 30.f;
|
|
|
+ // loop through all collided blocks
|
|
|
+ bool needCollisionCheck = 1;
|
|
|
+ while( needCollisionCheck )
|
|
|
+ {
|
|
|
+ needCollisionCheck = 0;
|
|
|
+ // collision to neighbor of current block current block
|
|
|
+ if( speed.x > 0 )
|
|
|
+ {
|
|
|
+ float xt = ((float)px + 1.f - oldPos.x) / frameSpeed.x;
|
|
|
+ Vec3<float> tmp = oldPos + frameSpeed * xt;
|
|
|
+ if( xt <= 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
|
|
|
+ {
|
|
|
+ if( !getDefaultBlock( zGame->zBlockAt( Vec3<int>{ px + 1, py, pz }, zDimension->getDimensionId() ) )->isPassable() )
|
|
|
+ {
|
|
|
+ frameSpeed.x = frameSpeed.x * (xt - 0.1f);
|
|
|
+ speed.x = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ px++;
|
|
|
+ needCollisionCheck = 1;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if( speed.x < 0 )
|
|
|
+ {
|
|
|
+ float xt = ((float)px - oldPos.x) / frameSpeed.x;
|
|
|
+ Vec3<float> tmp = oldPos + frameSpeed * xt;
|
|
|
+ if( xt <= 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
|
|
|
+ {
|
|
|
+ if( !getDefaultBlock( zGame->zBlockAt( Vec3<int>{ px - 1, py, pz }, zDimension->getDimensionId() ) )->isPassable() )
|
|
|
+ {
|
|
|
+ frameSpeed.x = frameSpeed.x * (xt - 0.1f);
|
|
|
+ speed.x = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ px--;
|
|
|
+ needCollisionCheck = 1;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if( speed.y > 0 )
|
|
|
+ {
|
|
|
+ float yt = ((float)py + 1.f - oldPos.y) / frameSpeed.y;
|
|
|
+ Vec3<float> tmp = oldPos + frameSpeed * yt;
|
|
|
+ if( yt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
|
|
|
+ {
|
|
|
+ if( !getDefaultBlock( zGame->zBlockAt( Vec3<int>{ px, py + 1, pz }, zDimension->getDimensionId() ) )->isPassable() )
|
|
|
+ {
|
|
|
+ frameSpeed.y = frameSpeed.y * (yt - 0.1f);
|
|
|
+ speed.y = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ py++;
|
|
|
+ needCollisionCheck = 1;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if( speed.y < 0 )
|
|
|
+ {
|
|
|
+ float yt = ((float)py - oldPos.y) / frameSpeed.y;
|
|
|
+ Vec3<float> tmp = oldPos + frameSpeed * yt;
|
|
|
+ if( yt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f )
|
|
|
+ {
|
|
|
+ if( !getDefaultBlock( zGame->zBlockAt( Vec3<int>{ px, py - 1, pz }, zDimension->getDimensionId() ) )->isPassable() )
|
|
|
+ {
|
|
|
+ frameSpeed.y = frameSpeed.y * (yt - 0.1f);
|
|
|
+ speed.y = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ py--;
|
|
|
+ needCollisionCheck = 1;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if( speed.z > 0 )
|
|
|
+ {
|
|
|
+ float zt = ((float)pz + 1.f - oldPos.z) / frameSpeed.z;
|
|
|
+ Vec3<float> tmp = oldPos + frameSpeed * zt;
|
|
|
+ if( zt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f )
|
|
|
+ {
|
|
|
+ if( !getDefaultBlock( zGame->zBlockAt( Vec3<int>{ px, py, pz + 1 }, zDimension->getDimensionId() ) )->isPassable() )
|
|
|
+ {
|
|
|
+ frameSpeed.z = frameSpeed.z * (zt - 0.1f);
|
|
|
+ speed.z = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ pz++;
|
|
|
+ needCollisionCheck = 1;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if( speed.z < 0 )
|
|
|
+ {
|
|
|
+ float zt = ((float)pz - oldPos.z) / frameSpeed.z;
|
|
|
+ Vec3<float> tmp = oldPos + frameSpeed * zt;
|
|
|
+ if( zt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1 )
|
|
|
+ {
|
|
|
+ if( !getDefaultBlock( zGame->zBlockAt( Vec3<int>{ px, py, pz - 1 }, zDimension->getDimensionId() ) )->isPassable() )
|
|
|
+ {
|
|
|
+ frameSpeed.z = frameSpeed.z * (zt - 0.1f);
|
|
|
+ onFall( speed.z );
|
|
|
+ speed.z = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ pz--;
|
|
|
+ needCollisionCheck = 1;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ location += frameSpeed;
|
|
|
}
|
|
|
|
|
|
void Entity::api( Framework::StreamReader* zRequest, NetworkResponse* zResponse )
|
|
@@ -23,6 +146,14 @@ void Entity::api( Framework::StreamReader* zRequest, NetworkResponse* zResponse
|
|
|
// TODO: answer api requests
|
|
|
}
|
|
|
|
|
|
+void Entity::onFall( float collisionSpeed )
|
|
|
+{
|
|
|
+ if( collisionSpeed > 5 )
|
|
|
+ {
|
|
|
+ // TODO: take damage
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void Entity::setPosition( Framework::Vec3<float> pos )
|
|
|
{
|
|
|
location = pos;
|
|
@@ -73,7 +204,7 @@ Framework::Vec3<float> Entity::getSpeed() const
|
|
|
return speed;
|
|
|
}
|
|
|
|
|
|
-Framework::Vec2<float> Entity::getFaceDir() const
|
|
|
+Framework::Vec3<float> Entity::getFaceDir() const
|
|
|
{
|
|
|
return faceDir;
|
|
|
}
|
|
@@ -83,6 +214,11 @@ Framework::Vec3<float> Entity::getPosition() const
|
|
|
return location;
|
|
|
}
|
|
|
|
|
|
+float Entity::getGravityMultiplier() const
|
|
|
+{
|
|
|
+ return gravityMultiplier;
|
|
|
+}
|
|
|
+
|
|
|
int Entity::getCurrentDimensionId() const
|
|
|
{
|
|
|
return currentDimensionId;
|