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 Answer 1

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\$
3
  • \$\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, 2019 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\$ Nov 16, 2019 at 15:26
  • \$\begingroup\$ ok sir ty for your time i am waiting for result \$\endgroup\$
    – younlok
    Nov 16, 2019 at 20:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .