1
\$\begingroup\$

I am working on 2D tile based game. I want to render the tilemap from a file but every tile has its own behavior for example: magmablock : poorlava(); slimeblock : knockback();

I have this files Tile, (magmablock;slimeblock;iceblock)(just examples and they inherit from tile ) ,handler

This is what I did I loaded the map in class with an array in every character i create a tile object in an array and give it an ID in the tile constructori do a switch statement if the ID is 1 for example create magmablock and i call the deconstruct so the tiles array will be empty

in the magmablock class i add magmablock object(this) to a handler class which update them and render them this is the codes so u can understand more

levels.h


#ifndef LEVELS_H
#define LEVELS_H
#include <iostream>
#include <fstream>
#include <vector>
#include "tile.h"
using namespace std;

vector< vector<tile> > tiles;

class levels
{
public:

    static void loadworld(string levelfile)
    {
        int mw = 0,mh = 0;
        string tempNum;
        ifstream readLevel(levelfile);
        string mapCode;

        //i read from file i get the width and height (mw,mh) and the array
        //here i loop in the array

                for (int j = 0 ; j <= mh ; j++)
                {
                    for (int i = 0 ; i <= mw; i++)
                    {                   
                                tile t(stoi(tempNum),i,j); 
    //tempnum is the ID 
    //it's not important here
    //so i deleted it so the code will not be complicated

                                tiles[j][i] = t; //j - i
    // i create tile object in the array
                    }
                }
    }
};

#endif // LEVELS_H


tile.cpp


#include "tile.h"
#include "magma.h"
#include "slimeblock.h"
#include "wall.h"

tile::tile(int id,int x,int y)
{
        switch (id)
        {
            case 001:
        {
                tile *wallBlock = new wall(x,y); //create new objects
        }
            case 002:
        {
                tile *magmaBlock = new magma(x,y);
        }
            case 003:
        {
                tile *slime = new slimeblock(x,y);
        }
            default:
                break;
        }

        this->~tile(); // here i destroy it
}


magmablock.cpp

#include "magma.h"
#include "game.h"

magma::magma(int x,int y)
{
    this->id = magmaID;
    this->tileID = tile::tileID;
    tile::tileID++;
    this->tex = game::textures[0]; //this just load the texture

    this->crop.x = 32; //its texture from the spritesheet
    this->crop.y = 0;

    this->pos.x = x*32; // its position 
    this->pos.y = y*32;

    game::hand->addTile(this); // hand is the handler
}

void wall::init(){}

void wall::tick(){}

void wall::render(SDL_Renderer *ren)
{
    SDL_RenderCopy(ren,tex,&crop,&pos);
}

handler.h


#ifndef HANDLER_H
#define HANDLER_H

#include "tile.h"
#include <vector>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

using namespace std;

class handler
{
    public:

    handler(SDL_Renderer* ren){this->rend = ren;}

    SDL_Renderer* rend;

    vector<tile> tiles;

    /// Insert The  Tile ///

    void addTile(tile t)
    {
        tiles.push_back(t);
    }

    /// Destroy  The Tile ///

    void removeTile(tile t)
    {
        for(int i = 0;i < tiles.size();i++)
        {
                if(tiles[i].tileID = t.tileID)
                {
                    tiles.erase(tiles.begin() + i);
                    tiles[i].destroy();
                }
        }
    }

    void init()
    {

    }

    void tick()
    {
        /// Tile Tick

        for(int i = 0;i < tiles.size();i++)
        {
            tiles[i].tick();
        }

        /// Tile Tick

        for(int i = 0;i < objects.size();i++)
        {
            objects[i].tick();
        }
    }

    void render()
    {
          for(int i = 0;i < tiles.size();i++)
        {

            tiles[i].render(rend);
        }
    }
};

#endif // HANDLER_H


Hope you understand me i know that this is too much but I didn't find another way to describe it.

is this a good way? how to do it?

\$\endgroup\$
1
\$\begingroup\$

I think this is more an opinion-based question but here are my thought (I'm not a C++ expert):

  • Create a base class Tile that will handle generic stuff like rendering, animations if any, behavior of the tile...
  • For each of your special tiles, create a new class that inherits from your base class Tile and override the behavior if your new tile has a custom behavior, or override the animation/render if it is a special case.
  • Read the level file, and based on these informations, create your level and handle special cases like you did it.

To store the level you can either store it in a text file with special characters or if you need more data (i.e. a magma block can have different levels of damage done) I would take a shot at JSON or XML serialization. That way you can encode full objects to a file and read them directly as an array of tiles, it would make your method loadworld obsolete and you will have to just deserialize your JSON/XML file into a map.

This is what your level could looks like as a JSON file :

{
    "levelName" : "Level 1",
    "tiles" : [
        [{"type": "magma", "damages": 2}, {"type": "wall","color": "blue"}],
        [{"type": "floor"}, {"type": "floor"}]
    ]
}

This would translate to :

MW
FF

But you are able to pass in data into your tile objects.

I invite you to read a little bit more about Inheritance and Polymorphism in C++ if you are not so familiar with it.

I also think that the most used JSON library out there is this one.

\$\endgroup\$
  • \$\begingroup\$ but how i can add the special tiles to the level u mean like this cplusplus for (int j = 0 ; j <= mh ; j++) { for (int i = 0 ; i <= mw; i++) { switch (id) { case 001: { tile *wallBlock = new wall(x,y); //create new objects } case 002: . \$\endgroup\$ – younlok Nov 16 '19 at 10:55
  • \$\begingroup\$ So, using JSON or XML files you can take advantage of what we call deserialization (extracting a data structure from a series of bytes). You encode your special tiles in the JSON file and when you deserialize it, you will have your tilemap with the special tiles. I'll install a c++ compiler now and try to give you a more visual exemple of that process :) \$\endgroup\$ – Antoine Thiry Nov 16 '19 at 15:26
  • \$\begingroup\$ ok sir ty for your time i am waiting for result \$\endgroup\$ – younlok Nov 16 '19 at 20:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.