My Player Struct

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
mell1ej
Posts: 1
Joined: Thu Mar 19, 2009 10:54 pm

My Player Struct

Post by mell1ej »

Hello everybody :)

For the past few hours i have been working on this Player struct, most things are working fine but i have a few problems :(

1.) I have no idea how to modify the players (fpscamera) jumpheight after loading the camera.

2.) Crouching is not working as it is supposed to be, you get stuck after you crouch or cant get up again.

Now i was wondering if somebody could explain me these two things, and ofcource general tips are welcome aswell :D

Here is my code:

Code: Select all

// The Irrlicht examples where very usefull :)
struct Player : public IAnimationEndCallBack
{
	Player();
	Player(const string<char> &pName, WorldData* nWorldData);
	ISceneNodeAnimatorCollisionResponse* camCollisionResponse(IrrlichtDevice* device, ICameraSceneNode* camera);
	void OnAnimationEnd(IAnimatedMeshSceneNode* node);
	bool Load();	
	void Update();
	void Respawn();
	void Shoot();
	void Setpos(vector3df &pos, vector3df &rotation);
	void SetWeaponAnim(char* animation);
	void SetRunSpeed(float value);
	void SetRotateSpeed(float value);
	void SetJumpHeight(float value);
	void SetJumpSpeed(float value);
	void SetFlyMode(bool value);
	void SetGravity(vector3df &value);
	void ToggleCrouch(bool value);
	void ToggleCollision(bool value);

	WorldData* worldData;

	SKeyMap keyMap[10];

	ICameraSceneNode* camera;
	IAnimatedMeshSceneNode* WeaponNode;

	string<char> playerName;

	vector3df playerPosition, playerRotation, playerTarget, playerGravityForce, playerEllipsoidRadius, playerEllipsoidTranslation, weaponPosition, weaponRotation;
	vector3df defaultPlayerPosition, defaultPlayerRotation, defaultPlayerGravityForce, defaultPlayerEllipsoidRadius, defaultPlayerEllipsoidTranslation, defaultWeaponPosition, defaultWeaponRotation;

	float playerRunSpeed, playerRotateSpeed, playerJumpSpeed, playerJumpHeight, playerHeight;
	float defaultPlayerRunSpeed, defaultPlayerRotateSpeed, defaultPlayerJumpSpeed, defaultPlayerJumpHeight, defaultPlayerHeight;

	bool verticalMovement, crouching, collision;

	ISceneNodeAnimator* anim;
	ISceneNodeAnimatorCameraFPS* animFPS;
	ISceneNodeAnimatorCollisionResponse* animColResp;
};

Player::Player(){}

Player::Player(const string<char> &pName, WorldData* nWorldData)
{
	verticalMovement = true;
	crouching = false;

	playerName = pName;
	worldData = nWorldData;

	playerGravityForce = vector3df(0, -10.0f, 0);
	playerPosition = vector3df(50, 50, -60);
	playerRotation = vector3df(-70, 30, -60);
	playerEllipsoidRadius = vector3df(30, 50, 30);
	playerEllipsoidTranslation = vector3df(0, 30, 0);
	weaponPosition = vector3df(0, 0, 0);
	weaponRotation = vector3df(-90,-90,90);
	playerRunSpeed = 0.3f;
	playerRotateSpeed = 100.0f;
	playerJumpSpeed = 3.0f;
	playerJumpHeight = 200.0f;
	playerHeight = 50.0f;

	defaultPlayerPosition = playerPosition;
	defaultPlayerRotation = playerRotation;
	defaultPlayerGravityForce = playerGravityForce;
	defaultPlayerRunSpeed = playerRunSpeed;
	defaultPlayerRotateSpeed = playerRotateSpeed;
	defaultPlayerJumpSpeed = playerJumpSpeed;
	defaultPlayerJumpHeight = playerJumpHeight;
	defaultPlayerHeight = playerHeight;
	defaultPlayerEllipsoidRadius = playerEllipsoidRadius;
	defaultPlayerEllipsoidTranslation = playerEllipsoidTranslation;
	defaultWeaponPosition = weaponPosition;
	defaultWeaponRotation = weaponRotation;
}

ISceneNodeAnimatorCollisionResponse* Player::camCollisionResponse(IrrlichtDevice* device, ICameraSceneNode* camera)
{
	for (list<ISceneNodeAnimator*>::ConstIterator it = camera->getAnimators().begin(); it != camera->getAnimators().end(); ++it)
	{
		ISceneNodeAnimatorCollisionResponse* a = (ISceneNodeAnimatorCollisionResponse*) (*it);
		if (a->getType() == ESNAT_COLLISION_RESPONSE) return a;
	}

	return 0;
}

void Player::OnAnimationEnd(IAnimatedMeshSceneNode* node)
{
	worldData->Logger->log("Player::OnAnimationEnd()");
	SetWeaponAnim(0);
}

bool Player::Load()
{
	worldData->Logger->log("Player::Load()");

	keyMap[0].Action = EKA_MOVE_FORWARD;
	keyMap[0].KeyCode = KEY_UP;
	keyMap[1].Action = EKA_MOVE_FORWARD;
	keyMap[1].KeyCode = KEY_KEY_W;

	keyMap[2].Action = EKA_MOVE_BACKWARD;
	keyMap[2].KeyCode = KEY_DOWN;
	keyMap[3].Action = EKA_MOVE_BACKWARD;
	keyMap[3].KeyCode = KEY_KEY_S;

	keyMap[4].Action = EKA_STRAFE_LEFT;
	keyMap[4].KeyCode = KEY_LEFT;
	keyMap[5].Action = EKA_STRAFE_LEFT;
	keyMap[5].KeyCode = KEY_KEY_A;

	keyMap[6].Action = EKA_STRAFE_RIGHT;
	keyMap[6].KeyCode = KEY_RIGHT;
	keyMap[7].Action = EKA_STRAFE_RIGHT;
	keyMap[7].KeyCode = KEY_KEY_D;

	keyMap[8].Action = EKA_JUMP_UP;
	keyMap[8].KeyCode = KEY_SPACE; 

	keyMap[9].Action = EKA_CROUCH;
	keyMap[9].KeyCode = KEY_LSHIFT; 

	camera = worldData->smgr->addCameraSceneNodeFPS(0, playerRotateSpeed, playerRunSpeed, -1, keyMap, sizeof(keyMap), verticalMovement, playerJumpSpeed);
	camera->setName("First Person Camera");
	camera->setFarValue(10000.0f);

	IAnimatedMeshMD2* weaponMesh = (IAnimatedMeshMD2*)worldData->smgr->getMesh("gun.md2");
	if (weaponMesh == 0)
	{
		worldData->Logger->log("Failed to Load: Gun.md2");
		MessageBox(0, "Failed to Load: Gun.md2", "Load Error!", 0);
		return false;
	}

	if (weaponMesh->getMeshType() == EAMT_MD2)
	{
		char buf[64];
		for (s32 i = 0; i != weaponMesh->getAnimationCount(); i++)
		{
			sprintf_s(buf, sizeof(buf), "Animations for Gun.md2: %s", weaponMesh->getAnimationName(i));
			worldData->Logger->log(buf);
		}
	}

	ITexture* gunTexture = worldData->videoDriver->getTexture("gun.jpg");
	if (gunTexture == 0)
	{
		worldData->Logger->log("Failed to Load: Gun.jpg");
		MessageBox(0, "Failed to Load: Gun.jpg", "Load Error!", 0);
		return false;
	}

	WeaponNode = worldData->smgr->addAnimatedMeshSceneNode(weaponMesh, camera, -1, weaponPosition, weaponRotation); 
	WeaponNode->setMaterialTexture(0, gunTexture);
	WeaponNode->setLoopMode(false);
	WeaponNode->setMaterialFlag(EMF_LIGHTING, false);
	WeaponNode->setName("Weapon");

	//create a collision auto response animator
	anim = worldData->smgr->createCollisionResponseAnimator(worldData->triangleSelector, camera, playerEllipsoidRadius, playerGravityForce, playerEllipsoidTranslation);
	camera->addAnimator(anim);
	//anim->drop();

	list<ISceneNodeAnimator*>::ConstIterator animsFPSList = camera->getAnimators().begin(); 
	animFPS = (ISceneNodeAnimatorCameraFPS*)*animsFPSList;

	animColResp = camCollisionResponse(worldData->device, camera);

	Respawn();

	return true;
}

void Player::Update()
{
	playerPosition = camera->getPosition();
	playerRotation = camera->getRotation();
	playerTarget = camera->getTarget();

	if(playerPosition.Y < -10000.0f) Respawn();
}

void Player::Respawn()
{
	worldData->Logger->log("Player::Respawn()");

	Setpos(defaultPlayerPosition, defaultPlayerRotation);
	SetWeaponAnim("idle");
}

void Player::Setpos(vector3df &pos, vector3df &rotation)
{
	worldData->Logger->log("Player::SetPos()");

	camera->setPosition(pos);
	camera->setRotation(rotation);
	camera->OnAnimate(0);
}

void Player::SetWeaponAnim(char* name)
{
	worldData->Logger->log("Player::SetAnim()"); 

	char animation[64];

	if (name)
	{
		strcpy(animation, name);
		if (WeaponNode)
		{
			WeaponNode->setAnimationEndCallback(this);
			WeaponNode->setMD2Animation(animation);
		}
	}
	else
	{
		animation[0] = 0;
		if (WeaponNode) WeaponNode->setAnimationEndCallback(0);
	}
}

void Player::Shoot()
{
	//worldData->Logger->log("Player::Shoot()");

	vector3df start = camera->getPosition();
	vector3df end = (camera->getTarget() - start).normalize();

	start += end * 8.0f;
	end = start + (end * camera->getFarValue());

	SParticleImpact imp;
	imp.when = 0;

	triangle3df triangle;
	line3d<float> line(start, end);

	// get intersection point with map
	const ISceneNode* hitNode;
	if (worldData->collMan->getCollisionPoint(line, worldData->triangleSelector, end, triangle, hitNode))
	{
		// collides with wall
		vector3df out = triangle.getNormal();
		out.setLength(0.03f);

		imp.when = 1;
		imp.outVector = out;
		imp.pos = end;
	}
	else // doesnt collide with wall
	{
		start = camera->getPosition();
		end = (camera->getTarget() - start).normalize();

		end = start + (end * camera->getFarValue());
	}

	// create fire ball
	ISceneNode* node = worldData->smgr->addBillboardSceneNode(0, dimension2d<float>(25,25), start);

	node->setMaterialFlag(EMF_LIGHTING, false);
	node->setMaterialTexture(0, worldData->bulletTexture);
	node->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);

	float length = (end - start).getLength();
	float time = length / 2.0f;

	ISceneNodeAnimator* anim = worldData->smgr->createFlyStraightAnimator(start, end, time);
	node->addAnimator(anim);
	anim->drop();

	anim = worldData->smgr->createDeleteAnimator(time);
	node->addAnimator(anim);
	anim->drop();

	if (imp.when) // create impact note
	{
		imp.when = worldData->device->getTimer()->getTime() + time - 100;
		worldData->Impacts.push_back(imp);
	}

	worldData->irrKlang->play2D(worldData->ballSound);
}

void Player::SetRunSpeed(float value)
{
	worldData->Logger->log("Player::SetRunSpeed()");
	playerRunSpeed = value;

	animFPS->setMoveSpeed(playerRunSpeed);
}

void Player::SetRotateSpeed(float value)
{
	worldData->Logger->log("Player::SetRotateSpeed()");
	playerRotateSpeed = value;

	animFPS->setRotateSpeed(playerRotateSpeed);
}
void Player::SetJumpHeight(float value) // Not Working At All!
{
	worldData->Logger->log("Player::SetJumpHeight()");
	playerJumpHeight = value;

	//
}
void Player::SetJumpSpeed(float value)
{
	worldData->Logger->log("Player::SetJumpSpeed()");
	playerJumpSpeed = value;

	animColResp->jump(playerJumpSpeed);
}

void Player::SetFlyMode(bool value)
{
	worldData->Logger->log("Player::SetFlyMode()");

	verticalMovement = value;

	if(verticalMovement) SetGravity(vector3df(0, 0, 0));
	else SetGravity(defaultPlayerGravityForce);

	animFPS->setVerticalMovement(verticalMovement);
}

void Player::SetGravity(vector3df &value)
{	
	worldData->Logger->log("Player::SetGravity()");
	playerGravityForce = value;
	animColResp->setGravity(playerGravityForce);
}

void Player::ToggleCrouch(bool value) // Not Working Correctly!
{
	worldData->Logger->log("Player::ToggleCrouch()");
	crouching = value;

	if(crouching)
	{
		animColResp->setEllipsoidRadius(vector3df(30, 20, 30));
		animColResp->setEllipsoidTranslation(vector3df(0, 20, 0));

		SetRunSpeed(defaultPlayerRunSpeed / 4);
		SetJumpHeight(defaultPlayerJumpHeight / 3);
	}
	else
	{
		animColResp->setEllipsoidRadius(defaultPlayerEllipsoidRadius);
		animColResp->setEllipsoidTranslation(defaultPlayerEllipsoidTranslation);

		SetRunSpeed(defaultPlayerRunSpeed);
		SetJumpHeight(defaultPlayerJumpHeight);
	}
}

void Player::ToggleCollision(bool value)
{
	worldData->Logger->log("Player::ToggleCollision()");
	collision = value;

	if(collision) camera->addAnimator(anim);
	else camera->removeAnimator(anim);
}
Thank you :)

PS. You are free to use this in your own project if you want, even though it would be nice is you mention me somewhere :P
Asimov
Posts: 246
Joined: Thu Dec 04, 2014 7:41 pm
Contact:

Re: My Player Struct

Post by Asimov »

Hi mell,

I would be interested to know why you opted for a struct rather than a class?
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Re: My Player Struct

Post by sudi »

Asimov wrote:Hi mell,

I would be interested to know why you opted for a struct rather than a class?
Probably because they work the same and he wanted all functions and variables to be public.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Asimov
Posts: 246
Joined: Thu Dec 04, 2014 7:41 pm
Contact:

Re: My Player Struct

Post by Asimov »

Hi Sudi,

You can have public variables and functions in a class also.
Post Reply