pure virtual method called terminate called without an active exception - c++

I have an issue. I am making a game where i check if a projectile is below the screen, if true i want to delete that object. My problem is that when the projectile actually goes below sceen my game crashes with the error:
pure virtual method called terminate called without an active
exception
which i think is very wierd because my projectile class has nothing to do with a virtual method or abstract class. This is the update methods:
void GameScene::updateLogic() {
if (projectile) {
if (projectile -> position().y > 1200) {
t1Turn = true;
delete projectile;
}
else {
projectile->update();
}
}
}
void GameScene::draw() {
if (projectile) {
projectile->draw(_window);
}
}
The projectile pointer is set to nullptr in the constructor of the gamescene:
_p = nullptr;
The projectile class:
Projectile::Projectile(sf::Vector2f spawnPoint, sf::Vector2f initVel, Tank* target, bool& turn) : _spawnPoint(spawnPoint), _initVel(initVel), _target(target), _turn(turn) {}
Projectile::~Projectile(){}
void Projectile::update(){
if (_collisionBox.intersects(_target->getBox())) {
_target->removeHealth(20);
}
_elapsed = clock.getElapsedTime().asSeconds();
_time += _elapsed;
clock.restart();
dx = (_initVel.x * _time);
dy = (_initVel.y * _time + (1900*pow(_time, 2) / 2));
_position = sf::Vector2f(_spawnPoint.x+dx, _spawnPoint.y+dy);
_collisionBox = _projectileSprite.getGlobalBounds();
}
void Projectile::draw(sf::RenderWindow &window) {
_projectileSprite.setPosition(_position);
window.draw(_projectileSprite);
}
sf::Vector2f Projectile::position () {
return _position;
}
The projectile inherits from a sprite class but thats about it:
class Projectile : Sprites {
It has no association with a pure virtual method...
EDIT: When running the debugger it breaks at:
void Projectile::draw(sf::RenderWindow &window) { window <incomplete type>
_projectileSprite.setPosition(_position);
window.draw(_projectileSprite); <--------------------
}
But how can window be of incomplete type? What has that to do with a virtual method which the original error message say?

Related

How to simplify game loop with multiple classes

For my current project I have several classes defining levels for the game. All of the levels are of the following form:
class Level1
{
public:
Level1(int initialFrame);
void update(int frameCount, sf::RenderWindow* renderWindow);
void draw(sf::renderWindow* renderWindow);
bool finished;
};
Note that none of the definitions for the functions update and draw are the same between levels.
In main my loop looks something like this:
int main()
{
sf::RenderWindow renderWindow();
frames = 0;
progress = 0;
Level1* level1 = new Level1(0);
Level2* level2 = 0;
Level3* level3 = 0;
while (true) // Not actually like this, just put it here to illustrate my point
{
renderWindow.clear()
if (progress == 0)
{
level1->update(frames, &renderWindow)
level1->draw(&renderWindow)
if (level1->finished)
{
delete level1;
progress++;
level2 = new level2(frames);
}
}
if (progress == 1)
{
level2->update(frames, &renderWindow)
level2->draw(&renderWindow)
if (level2->finished)
{
delete level2;
progress++;
level3 = new level3(frames);
}
}
if (progress == 2)
{
level3->update(frames, &renderWindow)
level3->draw(&renderWindow)
if (level3->finished)
{
delete level3;
progress++;
}
}
frames++;
renderWindow.display();
}
}
So I wanted to simplify this as I have the similar blocks of code running over and over. To solve this I created a template as such:
template <class T>
void loop(T level, int frameCount, sf::RenderWindow* renderWindow, int* progress)
{
level->update(frameCount, renderWindow);
level->draw(renderWindow);
if (level->finished)
{
delete level;
*progress++;
}
}
This partly works, but I'm stuck on how to, a) Initialise the next level when one is finished in the template, and b) how to implement the template function in my game loop without using a check for progress, and manually programming in each level like I had before. Ideally I'd want something like a list of levels in the order I want them to be played, and progress could index which one I'm using the loop on, but I'm not sure how to implement that.
You should make a abstract base class of level:
class Level
{
public:
Level(int initialFrame);
virtual ~Level();
virtual void update(int frameCount, sf::RenderWindow* renderWindow) = 0;
virtual void draw(sf::renderWindow* renderWindow) = 0;
bool finished;
};
and let all your levels inherit from this class:
class Level1 : public Level
{
public:
Level1(int initialFrame);
void update(int frameCount, sf::RenderWindow* renderWindow) override;
void draw(sf::renderWindow* renderWindow) override;
};
And then just swap between them depending on the current progress.
Level* currentLevel = new Level1(0);
...
while (true)
{
currentLevel->update(frames, &renderWindow)
currentLevel->draw(&renderWindow)
if (currentLevel->finished)
{
delete currentLevel;
progress++;
switch(progress)
{
case 1: currentLevel = new Level2(...); break;
case 2: currentLevel = new Level3(...); break;
case 3: currentLevel = new Level4(...); break;
...
}
}
So you save yourself some if-blocks.
You're overthinking this.
Define a Level interface which is implemented by all your levels
class Level {
public:
virtual void update(int frameCount, sf::RenderWindow* renderWindow) = 0;
virtual void draw(sf::renderWindow* renderWindow) = 0;
virtual bool finished() = 0;
};
Then simply create a queue of levels and pop from it
auto Levels = std::queue<std::unique_ptr<Level>>();
Levels.push(std::make_unique<Level1>());
Levels.push(std::make_unique<Level2>());
Levels.push(std::make_unique<Level3>());
std::unique_ptr<Level> currentLevel = Levels.front();
Levels.pop();
while(true){
if(currentLevel->finished()){
if(Levels.empty()){
break;
currentLevel = std::move(Levels.front())
Levels.pop();
}
currentLevel->update(frames, &renderWindow)
currentLevel->draw(&renderWindow);
frames++;
renderWindow->display();
}
If you absolutely need to pass in the frames at construction time, or you don't want to allocate the memory ahead of time, you could make a list of functionals instead, where the function returns a std::unique_ptr<Level>.

Box2D Contact Listener Collision Only Works Intermittently

I have a dynamic body colliding with a dynamic body and a simple contact listener class shown below:
void myContactListener::BeginContact(b2Contact* contact)
{
void* bodyUserData = contact->GetFixtureA()->GetBody()->GetUserData();
if (bodyUserData)
{
static_cast<EnemyEntity*>(bodyUserData)->startContact();
}
bodyUserData = contact->GetFixtureB()->GetBody()->GetUserData();
if (bodyUserData)
{
static_cast<EnemyEntity*>(bodyUserData)->endContact();
}
}
void myContactListener::EndContact(b2Contact* contact)
{
void* bodyUserData = contact->GetFixtureA()->GetBody()->GetUserData();
if (bodyUserData)
static_cast<EnemyEntity*>(bodyUserData)->endContact();
bodyUserData = contact->GetFixtureB()->GetBody()->GetUserData();
if (bodyUserData)
static_cast<EnemyEntity*>(bodyUserData)->endContact();
}
Whenever I move either of the dynamic bodies into each other, a collision is always detected the first time as well as a stop of collision. However, if I try to collide them once again, it often doesn't detect any collision after the first time. It does sometimes though. What can I do to fix this? Nothing else in my code touches any Box2D code.
Here is my contact listener header file:
class myContactListener : public b2ContactListener
{
private:
public:
// Contact listener methods
void BeginContact(b2Contact* contact);
void EndContact(b2Contact* contact);
};
And the EnemyEntity Box2D method:
void EnemyEntity::createStarBox2DCollision(b2World *world)
{
enemyType = EnemyType::Star;
def.type = b2_dynamicBody;
def.position.Set(1000, 1000);
body = world->CreateBody(&def);
box.SetAsBox(rectShapeSize.x / 2, rectShapeSize.y / 2);
fixtureDef.shape = &box;
fixtureDef.density = 1.0;
fixtureDef.friction = 0.3;
body->CreateFixture(&fixtureDef);
body->SetUserData(this);
}
It looks like you should have
void myContactListener::BeginContact(b2Contact* contact)
{
...
static_cast<EnemyEntity*>(bodyUserData)->startContact();
}
}
rather than
void myContactListener::BeginContact(b2Contact* contact)
{
...
static_cast<EnemyEntity*>(bodyUserData)->endContact();
}
}
for both bodies, rather than only for A

replaceScene() messes up a public variable

I am porting a game from cocos2d-iphone 2.x to cocos2d-x 3.x.
Have to solve a few problems, including a major crash - the subject of this post.
It has been determined that the crash happens because SOMETIMES, my replaceScene call results in a messed-up important public variable.
My class:
class Player : public cocos2d::Sprite
{
public:
....
cocos2d::Vec2 desiredPosition;
....
My Layer methods:
Scene* GameLevelLayer::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = GameLevelLayer::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
bool GameLevelLayer::init()
{
// super init first
if ( !Layer::init() )
{
return false;
}
....
player = (Player*) cocos2d::Sprite::create("sprite_idle_right#2x.png");
player->setPosition(Vec2(100, 50));
player->desiredPosition = player->getPosition();
....
this->schedule(schedule_selector(GameLevelLayer::update), 1.0/60.0);
....
return true;
}
void GameLevelLayer::endGame(bool won) {
....
MenuItem* display;
if (currentLevel < lastLevel && won) {
++currentLevel;
display = MenuItemImage::create("next.png" ,"next.png" ,"next.png",
CC_CALLBACK_1(GameLevelLayer::replaceSceneCallback, this));
} else {
// Lost the game
currentLevel = 1;
display = MenuItemImage::create("replay.png", "replay.png", "replay.png",
CC_CALLBACK_1(GameLevelLayer::replaceSceneCallback, this));
}
....
}
void GameLevelLayer::replaceSceneCallback(Ref* sender) {
Director::getInstance()->replaceScene(this->createScene());
}
The member being messed is the desiredPosition. It is changed inside update() method. The problem is that update() gets an already messed-up desired position. It is only messed-up after a scene was being replaced. The problem happens once in 10 runs, or so. It even appears that when update() is called first time after the scene has been replaced, desiredPosition set to some garbage. is I was unable to learn more.
My Player class does not have a separate constructor.
Please advise.
I forgot to initialize another instance variable. That instance variable is used to calculate the desiredPosition.

How to use the CCTimer class in Cocos2d android?

I want to use CCTimer class for the Timer but I can't sort out. After I use to manually create a function for this but it seems not effective .
protected GameLayer(ccColor4B color)
{
super(color);
schedule(new UpdateCallback() {
#Override
public void update(float d) {
countTime(d);
}
},0.99f);
}
public void countTime(float scr) {
if(_label != null){
this.removeChild(_label,true);
}
j=j-(int)scr;
CGSize winSize = CCDirector.sharedDirector().displaySize();
_label = CCLabel.makeLabel("Time Left :" + j, "Verdana", 20);
_label.setColor(ccColor3B.ccGREEN);
_label.setPosition(155f, winSize.height - 15);
addChild(_label);
if(j<=0){
CCDirector.sharedDirector().pause();
}
}
it run from 1 to the the point which i want to stop ... !!!
what should i do to use the CCTimer class to resolve this problem ?
CCTimer is available but I haven't tried this earlier but you can do this thing through Timer class :
Timer timer = new Timer();
timer.scheduleAtFixedRate( new TimerTask(){
public void run() {
updateTimeLabel();
}
public void updateTimeLabel() {
float time += 1;
String string = CCFormatter.format("%02d:%02d", (int)(time /60) , (int)time % 60 );
CCBitmapFontAtlas timerLabel = (CCBitmapFontAtlas) getChildByTag(TIMER_LABEL_TAG) ;
timerLabel.setString(string);
}

OOP Game Menu System Development Conceptualising

I'm trying to write an OO menu system for a game, loosely based on the idea of a Model,View,Controller. In my app so far I've named the views "renderers" and the models are without a suffix. I created a generic menu class which stores the items of a menu, which are menu_item objects, and there is also a menu renderer class which creates renderers for each item and renders them. The problem is I'm not sure where to store the data and logic to do with where on the screen each item should be positioned, and how to check if it is being hovered over, etc. My original idea was to store and set a selected property on each menu item, which could be rendered differently by different views, but even then how to I deal with positioning the graphical elements that make up the button?
Code excerpts so far follow: (more code at https://gist.github.com/3422226)
/**
* Abstract menu model
*
* Menus have many items and have properties such as a title
*/
class menu {
protected:
std::string _title;
std::vector<menu_item*> _items;
public:
std::string get_title();
void set_title(std::string);
std::vector<menu_item*> get_items();
};
class menu_controller: public controller {
private:
menu* _menu;
public:
menu_controller(menu*);
virtual void update();
};
class menu_item {
protected:
std::string _title;
public:
menu_item(std::string title);
virtual ~menu_item();
std::string get_title();
};
class menu_renderer: public renderer {
private:
menu* _menu;
bitmap _background_bitmap;
static font _title_font;
std::map<menu_item*, menu_item_renderer*> _item_renderers;
public:
menu_renderer(menu*);
virtual void render();
};
font menu_renderer::_title_font = NULL;
menu_renderer::menu_renderer(menu* menu) {
_menu = menu;
_background_bitmap = ::load_bitmap("blackjack_menu_bg.jpg");
if (!_title_font)
_title_font = ::load_font("maven_pro_regular.ttf",48);
}
void menu_renderer::render() {
::draw_bitmap(_background_bitmap, 0, 0);
/* Draw the menu title */
const char* title = _menu->get_title().c_str();
int title_width = ::text_width(_title_font, title);
::draw_text(title, color_white, _title_font, screen_width() - title_width - 20, 20);
/* Render each menu item */
std::vector<menu_item*> items = _menu->get_items();
for (std::vector<menu_item*>::iterator it = items.begin(); it != items.end(); ++it) {
menu_item* item = *it;
if (!_item_renderers.count(item))
_item_renderers[item] = new menu_item_renderer(item, it - items.begin());
_item_renderers[item]->render();
}
}
class menu_item_renderer: public renderer {
private:
unsigned _order;
menu_item* _item;
static font _title_font;
public:
menu_item_renderer(menu_item*, unsigned);
virtual ~menu_item_renderer();
virtual void render();
};
font menu_item_renderer::_title_font = NULL;
menu_item_renderer::menu_item_renderer(menu_item* item, unsigned order) {
_item = item;
_order = order;
if (!_title_font)
_title_font = ::load_font("maven_pro_regular.ttf",24);
}
menu_item_renderer::~menu_item_renderer() {
// TODO Auto-generated destructor stub
}
void menu_item_renderer::render() {
const char* title = _item->get_title().c_str();
int title_width = ::text_width(_title_font, title);
unsigned y = 44 * _order + 20;
::fill_rectangle(color_red, 20, y, title_width + 40, 34);
::draw_text(title, color_white, _title_font, 30, y + 5);
}
Your Model class menu needs a add_view(menuview *v) and update() method.
Then you can delegate the update of your widget to the derived View (menu_renderer or a cli_menu_renderer).
The Controller needs to know the Model (as member), when the Controller runs (or executes a Command) and has to update the Model with a Setter (like m_menu_model->set_selected(item, state)) and the Model calls update() on Setters.
Your Controller menu_controller has a update method, there you could also ask for Input, like if (menuview->toggle_select()) m_menu_model->toggle_selected(); (which all menuviews have to implement) and invoke the setter, but thats a inflexible coupling of View and Controller (you could check MVC with the Command Pattern for a more advanced combination).
For the Position you can set member vars like int m_x, m_y, m_w, m_h.
But these members are specific to a View with GUI, so only the derived View needs them.
Then you could use these values to compare against mouse Positions and use a MouseOver Detection Method like this:
// View menu_item
bool menu_item::over()
{
if (::mouse_x > m_x
&& ::mouse_x < m_x + m_w
&& ::mouse_y > m_y
&& ::mouse_y < m_y + m_h) {
return true;
}
return false;
}
// update on gui menu item
bool menu_item::update()
{
if (over()) {
m_over = true;
}
else {
m_over = false;
}
// onclick for the idea
if ((::mouse_b & 1) && m_over) {
// here you could invoke a callback or fire event
m_selected = 1;
} else {
m_selected = 0;
}
return m_selected;
}
// update the command line interface menu item
bool cli_menu_item::update()
{
if ((::enterKeyPressed & 1) && m_selected) {
// here you could invoke a callback or fire event
m_selected = 1;
} else {
m_selected = 0;
}
return m_selected;
}
void menu_item_renderer::render() {
// update widgets
_item->update();
// ...
}
// Model
void menu::add_view(menuview *v) {
m_view=v;
}
void menu::update() {
if (m_view) m_view->update();
}
bool menu::set_selected(int item, int state) {
m_item[index]=state;
update();
}