Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: 2D Puzzle game  (Read 8978 times)

0 Members and 1 Guest are viewing this topic.

Godsend72

  • Newbie
  • *
  • Posts: 20
    • View Profile
2D Puzzle game
« on: January 12, 2016, 03:10:52 am »
Greetings,

I am creating a 2d puzzle game inspired by Talos Principle, I don't have much to show but still here it is...

-Doors are working perfectly
-Jammer needs fixing
-The box has no purpose
-The sphere(enemy) is half done, it detects the player and reacts to it. In the future it will start to warm up for 2 seconds and if the player is still in the range it will shoot him. The range is currently drawn around it for testing purposes.

Currently I am working on the jammer ray collision with walls, I was planing on asking for an advice but I just got an idea.

Here is the video https://www.youtube.com/watch?v=iKMoJ_W-C40



All placeholders are drawn by me, except the jammer, and if you want to use them just ask, I'll upload them  ;)
The jammer is a mushroom from Super Mario, on which I redraw that ugly thing.


I don't have much experience with inheritance, and if anybody can give me some tips on this, it would be great.

I have a base class  BaseObject and all object derive from it.
I have a vector of unique_ptr to BaseObject containing all objects except the player and walls.
When i try to access a function from derived class I get an error, to solve this I cast it to desired type.

The question is: how would look the correct usage of std::vector<unique_ptr<BaseObject> > so that I can access the derived class functions without casting them? Or is this acceptable design?

My code looks like this:
std::vector<std::unique_ptr<BaseObject>> m_objects;
m_objectContainer.emplace_back(new Jammer("jammer.png", sf::Vector2f(0, 0)));


for(int i=0; i<m_objects[i];++i)
{

       m_object[i]->derivedClassFunction();
       //Error base class doesn't have derivedClassFunction()

       if(m_objects[i]->type() == objectType::Jammer)
       {
             Jammer* tempJammer = dynamic_cast<Jammer*>(m_object[i].get());
             if(tempJammer != nullptr)
             {
                    tempJammer->derivedClassFunction();
                    //OK
             }
        }
}
 


Mortal

  • Sr. Member
  • ****
  • Posts: 284
    • View Profile
Re: 2D Puzzle game
« Reply #1 on: January 12, 2016, 03:51:58 am »
it looks nice

i haven't done any tile-base game yet, probably i will catch up soon. :)

The question is: how would look the correct usage of std::vector<unique_ptr<BaseObject> > so that I can access the derived class functions without casting them? Or is this acceptable design?
i think you need to make the base class functions a virtual, and let the derived class override it.
« Last Edit: January 13, 2016, 12:54:45 am by MORTAL »

Godsend72

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: 2D Puzzle game
« Reply #2 on: January 12, 2016, 10:23:14 am »
For example if I have two classes that derive from base, and in each derived class I add 2 new different functions, I need to make 4 virtual functions in base object?
Then I would need to implement that functions in classes that do not use them.

dwarfman78

  • Full Member
  • ***
  • Posts: 228
  • I'm bietzsche, Nietzsche !
    • MSN Messenger - cd4c@hotmail.com
    • View Profile
    • Email
Re: 2D Puzzle game
« Reply #3 on: January 12, 2016, 03:14:23 pm »
For example if I have two classes that derive from base, and in each derived class I add 2 new different functions, I need to make 4 virtual functions in base object?
Then I would need to implement that functions in classes that do not use them.

it often means that you have a problem in your design.

Base and Derived class are means of abstractions, if you store a vector of Base classes, then you must be sure that, where you use that vector, you only need the functions declared in the Base class.

Can you be more specific regarding those functions in derived and base classes ?
@dwarfman78
github.com/dwarfman78

Mortal

  • Sr. Member
  • ****
  • Posts: 284
    • View Profile
Re: 2D Puzzle game
« Reply #4 on: January 12, 2016, 03:24:53 pm »
For example if I have two classes that derive from base, and in each derived class I add 2 new different functions, I need to make 4 virtual functions in base object?
Then I would need to implement that functions in classes that do not use them.

no need to override all virtual functions in base class, just override what the derived class need. the only case, you must override a virtual function from base class is when base class is abstract. you may read more about it here https://en.wikibooks.org/wiki/C%2B%2B_Programming/Classes/Abstract_Classes.
it is better if you showed your code otherwise we going to guess what you might need to solve your inherit classes problems.

for if you may need access member functions of derived class. it is better to make traceable pointer of which derived class you need to access its member functions, here minimal-example of game structure if it is rely on inheriting by using smart pointers like you did:

code:
(click to show/hide)
« Last Edit: January 13, 2016, 10:48:23 pm by MORTAL »

Ungod

  • Newbie
  • *
  • Posts: 44
    • View Profile
Re: 2D Puzzle game
« Reply #5 on: January 12, 2016, 06:38:56 pm »
Virtual methods, as already explained, should fit your needs. If you can solve your problem using virtuals, never try to cast someting.

Anyway, if you decide to use casts at some point consider carefully. If you check the type of an object through some enums and you are, by you own logic, sure that the object must be of type jammer, you can use static_cast, with does no runtime type-check and is more efficient in this case.

On the other hand, if you use dynamic_cast, you dont need your own enum to check. Just cast and check for nullptr afterwarts.

This:

Code: [Select]
if(m_objects[i]->type() == objectType::Jammer)
       {
             Jammer* tempJammer = static_cast<Jammer*>(m_object[i].get());
             tempJammer->derivedClassFunction();
        }

Or this:

Code: [Select]
Jammer* tempJammer = dynamic_cast<Jammer*>(m_object[i].get());
if(tempJammer != nullptr)
{
       tempJammer->derivedClassFunction();
}

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: 2D Puzzle game
« Reply #6 on: January 12, 2016, 08:20:51 pm »
In in 99% of the cases, explicit case differentiations for the type can be replaced with dynamic polymorphism, i.e. virtual functions. Don't use enums or RTTI when the language provides a simple and clean mechanism. I know virtual functions have been suggested already, but some posts here still sound like the manual alternatives are equivalent -- which they aren't. Avoid RTTI wherever possible (and no, re-inventing it with manual enums/integers isn't better).

See also this post for a more detailed expanation.

Emplacing dynamically allocated objects is dangerous, use std::make_unique().
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Godsend72

  • Newbie
  • *
  • Posts: 20
    • View Profile
Re: 2D Puzzle game
« Reply #7 on: January 12, 2016, 10:10:21 pm »
Thank you all so much for the responses.

I will remove the casting, rework the classes, move the functions to the base class and make virtual.
I'll try to avoid RTTI, but I like to live a dangerous life and can't promise anything 8)

MORTAL, in your example, what happens when you need to trace multiple derived objects, would you need to create multiple trace pointers, or vector of trace pointers? Or can you point another existing object from baseClass vector to it?

Quote from: MORTAL
you may read more about it here C++ Programming/Classes/Abstract Classes.
The link is not working but I searched the term and read about it.


This is kinda how my code looks
(click to show/hide)

This topic looks more like it should belong in the help section, From now on I'll try to add more content instead of questions to it.

I know the game looks like rubbish right now, but i have a vision.

Feel free to comment something about the game too. :D

Mortal

  • Sr. Member
  • ****
  • Posts: 284
    • View Profile
Re: 2D Puzzle game
« Reply #8 on: January 13, 2016, 12:18:05 am »
Quote from: MORTAL
you may read more about it here C++ Programming/Classes/Abstract Classes.
The link is not working but I searched the term and read about it.
sorry about that i didn't notice, i'm glad that you found same the topic else where  :)


MORTAL, in your example, what happens when you need to trace multiple derived objects, would you need to create multiple trace pointers, or vector of trace pointers? Or can you point another existing object from baseClass vector to it?
yes ofcourse, you can use std::vector for objects whose types are same. like std::vector<Door*> and std::vector<Enemy*> ...etc

from the sample of your code, it seems that you used multiple inheritance which may lead to diamond problem. in case you encounter such problem here link about how to fix it. http://www.cprogramming.com/tutorial/virtual_inheritance.html

lastly, let m_objectContainer only care about update and render. and for handling the reaction between player and the game entities, you may need to create trace pointers like std::vector<Door*>,std::vector<Enemy*> and Player*