Archived

This topic is now archived and is closed to further replies.

FreJa

fire weapon....

Recommended Posts

FreJa    154
Hi, I was just experiencing some things in a 2D game to use in another game... In this experience you have ship that should fire whenever you press SPACE... but it doesn''t... look at the code: Player.cpp
  
#include "Player.h"

CPlayer::CPlayer()
{
	health = 100.0f;
	xPos = 0.0f;
	yPos = -6.5;
}

CPlayer::~CPlayer()
{}

void CPlayer::Draw()
{
	glPushMatrix();

		glTranslatef(xPos, yPos, -18.0);
		glBegin(GL_QUADS);
			glVertex2f(-0.2, -0.2);
			glVertex2f(0.2, -0.2);
			glVertex2f(0.2, 0.2);
			glVertex2f(-0.2, 0.2);
		glEnd();

	glPopMatrix();
}

void CPlayer::ChangeDirection(int direction)
{
	if(direction == 1)		//Right

	{
		xPos += 0.01f;
	}
	if(direction == 2)		//Left

	{
		xPos -= 0.01f;
	}
}

void CPlayer::Fire()
{
	CRocket *Rocket = new CRocket;

	Rocket->xPos = xPos;
	Rocket->yPos = yPos;

	Rocket->Draw();	
}
  
Rocket.cpp
  
#include "Rocket.h"

CRocket::CRocket()
{
	xPos = 0.0;
	yPos = -6.5;
}

CRocket::~CRocket()
{}

void CRocket::Draw()
{
	glPushMatrix();
		glColor3f(1.0, 0.0, 0.0);
		glTranslatef(xPos, yPos, -18.0);
		glBegin(GL_QUADS);
			glVertex2f(-0.04, -0.04);
			glVertex2f(0.04, -0.04);
			glVertex2f(0.04, 0.04);
			glVertex2f(-0.04, 0.04);
		glEnd();
		glColor3f(1.0, 1.0, 1.0);
	glPopMatrix();

	yPos += 0.01f;
}
  
MainWnd.cpp
  
#include "MainWnd.h"

CDirectInput	DirectInput;
CPlayer			*Player;
CRocket			*Rocket;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool CApp::Initialize()
{
     glClearColor(0.0, 0.0, 0.0, 0.0);

	if(!DirectInput.Initialize(glWindow.window.hWnd, glWindow.application.hInstance, true, IS_USEKEYBOARD | IS_USEMOUSE)) return false;

	Player = new CPlayer;
	Rocket = new CRocket;

	return true;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CApp::GameCycle()
{
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_SMOOTH);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	Player->Draw();
	
	glFlush();
}	

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CApp::Deinitialize()
{
	DirectInput.Unload();
	
	delete Player;	
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void CApp::GetInput()
{
	DirectInput.Update();

	if (!inputInUse)
	{
		// quit

		if (DirectInput.KeyDown(DIK_ESCAPE))
			glWindow.TerminateApplication(&glWindow.window);

		if(DirectInput.KeyDown(DIK_RIGHT))	Player->ChangeDirection(1);

		if(DirectInput.KeyDown(DIK_LEFT))	Player->ChangeDirection(2);

		if(DirectInput.KeyDown(DIK_SPACE))	Player->Fire();

		if (DirectInput.KeyDown(DIK_L))		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		if (DirectInput.KeyDown(DIK_F))		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		if (DirectInput.KeyDown(DIK_P))		glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
	}
}
  
See the problem? Thanks a lot

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
I haven''t looked at it closely, but one thing is immediately apparent..

Your rocket class will only ever be drawn once.. because you construct the CRocket class in the Fire() method and draw it then, but the Fire() method is only called once, when the space button is pressed down.

I would suggest maintaining a Rocket pointer in your CPlayer class. Then construct the rocket and store its pointer in the CPlayer class. That way, you could do something like this in your Player::Draw() method:

if ( Rocket ) // Rocket is CRocket pointer in CPlayer class
{
Rocket->Draw();
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Well, you are right in that you only want to _construct_ the rocket when the space button is pressed, so that is where you would set up the pointer with a new operator or something like that, and then destruct it when the rocket is out of range...

But, because your CApp::GameCycle() function calls glClear() to clear the frame buffer each frame, you need to draw the rocket every frame, not just when it''s constructed...

Share this post


Link to post
Share on other sites
FreJa    154
Well... I think it''s kinda working right now, as when I press space the rocket appears, but it isn''t affected by the translation (yPos += 0.01f), so it remains on the same spot..... why is that?

Share this post


Link to post
Share on other sites
stephanh    174
Why should it move? Every time you press your fire button and Fire is invoked you create a new Rocket instance, forgetting about the old one (-> memory leak)

CRocket *Rocket = new CRocket;
Rocket->xPos = xPos;
Rocket->yPos = yPos;
Rocket->Draw();

So Draw for each instance is only called once.

You have to create a list of all active rockets, assign each rocket a lifetime (or whatever) and update them until they "die". And perhaps re-read the chapter about dynamic memory allocation and pointers.

Share this post


Link to post
Share on other sites
FreJa    154
This is starting to get on my nerves.... I really can''t find a way to make this work!

If I do this:

CRocket *Rocket = new CRocket;
Rocket->Draw();

and in CRocket::Draw() do yPos += 0.01f

shouldn''t it create a new instance of CRocket, and affect it with yPos+=0.01f ??????

Share this post


Link to post
Share on other sites
HellRiZZer    308
Here's what I would do:

    
class CRocket
{

...
....
bool m_bCreated;
CVector m_Speed;

virtual void Draw();
virtual void Update();
};

class CPlayer
{
...
....
CRocket rockets[MAX_ROCKETS];
virtual void Draw();
virtual void Update();
void Fire(CVector speed, CVector start_pos);
};

// ROCKET RELATED

void CRocket::Draw()
{
// Draw rocket code

}

void CRocket::Update()
{
// Update position based on given speed

if(m_Pos.y > 800)
{
m_bCreated = false;
Destroy(); // Basically this has to de-initialize all variables you use for CRocket class

}
else
m_Pos+=m_Speed;
}

// PLAYER RELATED

void CPlayer::Draw()
{
// Do your drawing for player


for (int i=0; i<MAX_ROCKETS; i++)
{
if(rockets[i].m_bCreated)
rockets[i].Draw();
}
}

void CPlayer::Update()
{
// Update player variables based on input, its X, Y and Z poss

// Similar to ChangeDirection


for (int i=0; i<MAX_ROCKETS; i++)
{
if(rockets[i].m_bCreated)
rockets[i].Update();
}
}

void CPlayer::Fire(CVector dir, CVector start_pos)
{
// Find free rocket

for (int i=0; i<MAX_ROCKETS; i++)
{
if(!rockets[i].m_bCreated)
{
rockets[i].m_Pos = start_pos;
rockets[i].m_Speed = dir;
rockets[i].m_bCreated = true;
break;
}
}
}




" Do we need us? "


Ionware Productions - Games and Game Tools Development

[edited by - HellRiZZer on March 16, 2003 4:34:05 PM]

Share this post


Link to post
Share on other sites
FreJa    154
Just another doubt:
if I do something like this:


  
void CPlayer::Fire()
{
Rocket = new CRocket;

Rocket->xPos = xPos;
Rocket->yPos = yPos++;

Rocket->Draw();

if(Rocket->yPos >= (glWindow.window.init.height-38)-5)
{
DeleteRocket();
}
}

void CPlayer::DeleteRocket()
{
delete Rocket;
}


it won''t work... but shouldn''t it work? because I press space, it is created a new instance of CRocket, and if the position of that rocket is X, it will delete it... and when I press again it will be created another instance of CRocket, and if the position .......... bla bla bla ?

Share this post


Link to post
Share on other sites
Trienco    2555
quote:
Original post by FreJa


    
void CPlayer::Fire()
{
Rocket = new CRocket;

Rocket->xPos = xPos;
Rocket->yPos = yPos++;

Rocket->Draw();

if(Rocket->yPos >= (glWindow.window.init.height-38)-5)
{
DeleteRocket();
}
}

void CPlayer::DeleteRocket()
{
delete Rocket;
}


it seems to get worse. you wont get away without a function that will process the rocket in every frame. how is it supposed to move across the screen, if its yPos is only changed once at creation?

also checking if the rocket is outside the screen in the function that creates it is quite pointless, because if it is, then the ship itself was already outside and you have a problem. having a function just to call delete seems pretty unnecessary too.

looking at your code it seems that for some reason you still expect parts of fire() to be executed each frame on its own. this wont happen. what does happen is:
you press space -> a rocket with a pointless constructor is created -> its position is set to the ships position (and im quite sure you dont really want the ship to move forward every time you fire a rocket, so dont use the ++ operator) -> your rocket is drawn (for this and only this single frame alone, so it will disappear before you even see it) -> its checked for out of screen (rather pointless, either check that first and dont create it at all or ignore it and let the update function care about it)

im not sure what you expect this to do, but applying movement and drawing only once is about the same as doing nothing.
remove all movements and checks and whatever from this function, because it belongs into another function that will be called every frame. the only thing that belongs here is the creation of the rocket. also a cleaner constructor would be this:

CRocket::CRocket(float x, float y) : xPos(x), yPos(y) {}

then i see:

glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glTranslatef(xPos, yPos, -18.0);
glBegin(GL_QUADS);
glVertex2f(-0.04, -0.04);
glVertex2f(0.04, -0.04);
glVertex2f(0.04, 0.04);
glVertex2f(-0.04, 0.04);
glEnd();
glColor3f(1.0, 1.0, 1.0);
glPopMatrix();

are you really sure you want to use the previous matrix and apply a translation to it? given your usage of xPos i would expect that you set the matrix to identity first.

adding the movement here is ok (not exactly good practice, but at least it would work). put that out of screen check here too and make sure that draw is called every frame.

also to avoid memory leaks you have to keep new rockets from being created before the old one is deleted. so dont create one: if (Rocket) return;

this means you have to know when no rocket exists. when deleting it:

delete Rocket;
Rocket=0;


somehow it feels like your coming from a c++ builder (or similar like delphi etc.) background and are used to do typical windows apps.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
If you wanted multiple rockets, I''d suggest using a linked list to store all your rockets you''ve created, and during the GameUpdate cycle, iterate through the linked list updating the positions of the rockets, deleting/exploding the ones that collide or go out of range. That''s a long run-on sentence.

Ideally you''d have a list like this for all objects in the game for collision detection.

(silencer)

Share this post


Link to post
Share on other sites
Jirka    122
I havent read all of the posts, but i think the problem is that you draw the rocket only once. When you press space the rocket is drawn, thats ok, but then u have to draw it every single frame untill the rocket will die or something like that.
So everytime the rocket is drawn, the position will change
(yPos += 0.01f

Share this post


Link to post
Share on other sites