Asteroids

I've been experimenting with the SFML library the past week, and decided to make an asteroids game. All's well so far. I've gotten an animated background composed of.. 150 stars with various size, alpha, and scales. and I've got my ship able to move around without fail.

Now I'm attempting to add laser support, so when i hit the space button the ship fires some lasers. I've got all the basic formula's i need to accomplish this, I just can't figure out a good way to implement it. I can't use stage.addChild in C++ like i can in flash. I attempted to give my player class a vector of lasers to manipulate itself, but that didn't seem to lead anywhere.

Any suggestions or tips would be wonderful (:
I'll post my code on my mediafire, there's way too much to put on a forum post.
http://www.mediafire.com/?kv99ee3xsskjo93

Thanks for all your help (:
Can you draw a line with thickness?
Hmm? I was hoping more to use a sprite for a laser.
So you're saying you can't draw a line with a sprite texture?
Last edited on
I'm a bit unsure what the question is, too. Can you clarify?
Mmh, i'm not sure what you're trying to get across L B.

What i'm trying to accomplish:
When the space key is hit, create a Laser, and pass it the ships position, and rotation, so it's placed in the right spot, then make it do what a laser does... fire.
That's easy enough to do, the issue is how to implement it. Since i can't just tell the game to add a laser, and have the laser delete itself when it's out of bounds.
One solution could be creating a global vector of lasers in my "game" class, but i really don't want to do that, since lasers aren't specific to the game, they're specific to the player. So i decided to try to put a vector of lasers inside my "player" class, to no avail. I'll give a quick snapshot of what i have

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//Laser.h/////////////////////////////////////
#include "Game.h"

class Laser
{
public:
	Laser();
	Laser(float x, float y, float rotation);
	void Init();

	void UpdateLaser();
	bool IsOutOfBounds(sf::RenderWindow &Window);

private:
	sf::Image Image;
	sf::Sprite Sprite;

	float vx;
	float vy;
};

//Laser.cpp///////////////////////////////////
#include "Laser.h"

Laser::Laser(float x, float y, float rotation)
{
	Init();
	
	Sprite.SetRotation(rotation); //set the rotation to the ships rotation
	vx -= sin(Game::DegreesToRadians(rotation)) * speed;   //set x velocity
	vy -= cos(Game::DegreesToRadians(rotation)) * speed;  //set y velocity

	Sprite.SetPosition(x + vx*2, y + vy*2); //set the position
}

void Laser::Init()
{
	if(!Image.LoadFromFile(image_laser)) //load the image from the file "image_laser" (defined in stdafx.h)
		Game::HandleError("Error loading laser image"); //if it fails, handle it.
	Sprite.SetImage(Image); //otherwise set the sprites image to Image.


        //Initialize variables
	vx = 0;
	vy = 0;
	speed = 20;
}

void Laser::UpdateLaser(sf::RenderWindow &Window)
{
	Sprite.Move(vx, vy); //translate the sprite
	Window.Draw(Sprite); //draw the sprite
}

bool Laser::IsOutOfBounds(sf::RenderWindow &Window)
{
        //if its out of bounds return true
	sf::Vector2f pos = Sprite.GetPosition();

	if(pos.x > Window.GetWidth() || pos.x < 0 || pos.y > Window.GetHeight() || pos.y < 0)
		return true;

	return false;
}


I need to figure a robust way to make multiple lasers, without creating a global vector in my game loop.
What i attempted was this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//excerpt from player.h
private:
    vector<Laser> lasers;
    vector<Laser>::iterator itr;


//excerpt from player.cpp
void Player::Fire()
{
    lasers.push_back(Laser(Sprite.GetPosition().x, Sprite.GetPosition().y, Sprite.GetRotation()));
}

void Player::CheckLaser()
{
    for(itr = lasers.begin(); itr != lasers.end() ++itr)
    {
        //check each laser if its out of bounds....
        //if it is do 
        lasers.erase(itr);

        //otherwise update the laser
        //i'm not sure how to go about that, would lasers[itr].UpdateLaser(); work?
    }
}


Now i'm not sure if that would even hold up, I've got little experience with iterators.
Last edited on
Abstract it.

Your game will have things that "update" every frame. Including:

- the player
- lasers
- asteroids
- anything else you want in the game


Make an abstract base class to encompass all of these things. Like "GameObject" or something:

1
2
3
4
5
6
7
8
9
10
11
12
13
class GameObject
{
public:
  // a function to update this object (run the game logic), move a little bit or whatever
  //  else it needs to do
  // return true if the object is to be destroyed
  // return false if the object survives another round
  virtual bool Update() = 0;


  // and whynot a function to draw too
  virtual void Draw(sf::RenderWindow& wnd);
};


Laser, Player, etc would all be derived from this class, and would implement their own Update and Draw functions.

You were on the right track here:
One solution could be creating a global vector of lasers in my "game" class,

But since you might be removing things from the middle of the vector, I'd probably go with a list instead. (also if it's in your "game" class then it's not global ;P)

Anyway it makes sense to have such a list in your Game or World or whatever class, as your game "has a" list of objects that need to be updated. ("has a" relationships imply a member var)

1
2
3
4
5
6
class Game
{
//...
  std::list<GameObject*> objects;
//...
};


Then running game logic is pretty simple:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void Game::RunLogic()
{
  std::list<GameObject*>::iterator i = objects.begin();
  whlie(i != objects.end())
  {
    // update the object
    if( (*i)->Update() )  // if it needs to be destroyed
    {
      delete *i;
      i = objects.erase(i);  // remove it from the list
    }
    else
      ++i;
  }
}



When you create a new object (like when the player fires a laser), just add the new object to the list.
Last edited on
Genius. Thanks so much for your input :D
I'll definitely give your idea's some thought.
also if it's in your "game" class then it's not global

Well, it'd be global to the game. And the idea of the game owning the lasers just sounded funny, i figure the player should own the lasers. But then again it might just be me.

Once again, thanks so much ^_^
-bump-

Okay, I'm stuck.. again. Instead of making a new thread i thought i'd just continue on this one.

I tried implementing what you said Disch, everything's perfect until it comes to adding things to the objects list. I'm stumped on finding a way to let outside classes or functions mess with the objects list... So i tried the following

1
2
3
4
5
6
class Game
{
///..........
        void AddObject(GameObject *obj);    //outside classes can't use AddObject without declaring an instance of game.
///..........
};


Then i did

1
2
3
4
5
6
class Game
{
///...........
        static void AddObject(GameObject *obj); //now this function can't access the object list.. lol
///...........
};


Thenn...
1
2
3
4
5
class Game
{
///...........
        static std::list<GameObject*> objects; //can't make lists static apparently
};


Now i'm just goofing off, and went into my background class and just went
 
Game::objects.push_back(new Star); // ... bleh 



Any ideas? aside putting std::list<GameObject*> objects; in a global header file?
I don't know why you say can't make lists static apparently. Please see my code snippets below. Assumption is outside can access GameObject class else how to call AddObject method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <list>
using namespace std;

class GameObject {
  public:
  int m_x;
  int m_y;
  GameObject() : m_x(0), m_y(0) {}
};

class Game {
  public:
  static void AddObjects(GameObject *obj);

  private:
  static list<GameObject *> objects;
};

list<GameObject *> Game::objects;

void Game::AddObjects(GameObject *obj) {
  if (obj) objects.push_back(obj);
}

int main() {
  Game::objects.push_back(new GameObject); //cannot access since it is private
  Game::AddObjects(new GameObject); //here no need an instance of Game class can access 
//AddObjects method

  return 0;
}
Last edited on
You don't want the list to be static. You want it to be a member of Game. I mean... you could make it static, and that would probably be simpler in the short term, but it makes an assumption that there will only ever be 1 game instance. That's not an unreasonable assumption, as it will most likely be the case -- but I like to avoid such assumptions if possible.

What you should do is give your objects a way to access the game. Or better... if not the "Game", then the "World" or "Environment". Odds are they'll need to interact with this environment anyway when they move around it (for collision detection and stuff)

So give your GameObjects a pointer to the Game when they're created. Then just have them hang on to it and access it as needed -- but try to keep accesses minimal.
I don't know why you say can't make lists static apparently
I don't know why either, just that when i do i get a compiler error... and now when i do it there's no error.. Compilers are tempermental.


Thanks for the idea's Disch. For now I'll leave the list as static until i can wrap my brain around that idea. :P

EDIT: Ohh, there's my error again. The one i get when i make my object list static
Game.obj : error LNK2001: unresolved external symbol "private: static class std::list<class GameObject *,class std::allocator<class GameObject *> > Game::objects" (?objects@Game@@0V?$list@PAVGameObject@@V?$allocator@PAVGameObject@@@std@@@std@@A)

Fun stuff. Alright, so how could i go about passing a pointer of my game instance (which is in another file in my main function) to every GameObject?
Last edited on
Topic archived. No new replies allowed.