Giter VIP home page Giter VIP logo

kingdom's Introduction

Kingdom

Created using C++ and SFML, this is a game where the world is viewed from a top down perspective.

The earliest screenshot of the game is this, showing grass tiles and random water tiles. It was created during the testing of tile collisons.

The tile collisions were somewhat awkward to do as unlike other tile games, the player is not restricted to be in the square, meaning they can go in any direction they like and move anywhere in a square.

alt text

#Building Building can be done on linux with the makefile. In order to reduce compilation time, you should use multiple make jobs. This is done with the -jX argument, with X being the amount of processing cores you have. An example for 4 cores:

make -j4

#Prerequisites In order to build the game you need the sfml library, sfml's dependancies and OpenGL headers.

On ubuntu:

sudo apt-get install libpthread-stubs0-dev libgl1-mesa-dev libx11-dev libxrandr-dev libfreetype6-dev libglew1.5-dev libjpeg8-dev libsndfile1-dev libopenal-dev libsfml-dev libglu1-mesa-dev mesa-common-dev freeglut3-dev

#Entities

All entities (exluding tiles) are based of a component system. This means that entities must inherit from "Mob" (or Enemy_Mob). The "Mob" class has an std::vector of components, of which get cycled through every frame in the update method of the mob, after doing any unique logic of a derived mob class first.

Components are in the "Component" folder, and inherit from the "Component::Component_Base" class, and implement the logic method from the base.

It is then very easy to add logic to the Entities as you can simply do it in a header include and a couple lines of code in the Entities constructor. For example, to make an derived mob collide with tiles:

addComponent( std::make_unique<Component::Tile_Collidable>
            ( this, m_tileMap ) );

#Tiles

Tiles are bit odd, as I decided to only have 3 varients of tile textures and then colour them in the code. That texture looks like this:

alt text

The jigsaw style edges allows for the tiles to easily interlock with eachother and sort of "blend" with tiles of not the same type without looking too square.

All tiles must inherit from the base "Tiles::Tile" class, and pass along some basic information such as location and colour.

Each tile type also has a respective .tile (custom file type) in Res/Data/Tiles/ which allows much easier changes for tile types, eg their friction or viscosity values. The format is as follows, as shown by the Grass.tile file as an example:

...........

Viscosity

0

Friction

0.76

Swimmable

false

Walkable

true

Colour

0 255 50

..................

The information can go in any order, except the RGBA colour values must go at the bottom due to a possible alpha value at the end, and the current way of detection for that is checking for the EOF.

Thanks to the "Component::Steps_On_Tiles" class and the "steppedOn()" method of tiles, it is also possible to trigger events when walking on tiles. For example, here a screenshot of water turning into ice when stepped on, simply by adding that logic to the Tiles::Water_Tile class, and then adding the "Steps_On_Tiles" component to the Player class.

alt text

#Level generation

Much room for improvement.

As of now, the whole map is filled with water and then randomly place islands are "genertated". Here is a couple of zoomed out views of that:

alt text alt text

Rendering

Only tiles within the view are updated and drawn, allowing for 1 million tiles and still run at 120 FPS. The tile map has a vector of tiles, and then selects which ones to draw

void
Tile_Map :: draw ( sf::RenderWindow& window, const sf::Vector2i& playerTilePos )
{
    const int tilesX = (Win_Info::WIDTH / Tiles::Info::SIZE) + 3; //Width of the screen in tiles
    const int tilesY = (Win_Info::WIDTH / Tiles::Info::SIZE) + 3;

    int xStart = playerTilePos.x - tilesX; //Start of the render bounds
    int xEnd = playerTilePos.x + tilesX;  //End of the render bounds

    if ( xStart < 0 ) xStart = 0; //Make sure the tile range is actually within the maps bounds
    if ( xEnd > Tiles::Info::MAP_SIZE - 1 ) xEnd = Tiles::Info::MAP_SIZE - 1;

    int yStart = playerTilePos.y - tilesY;
    int yEnd = playerTilePos.y + tilesY;

    if ( yStart < 0 ) yStart = 0;
    if ( yEnd > Tiles::Info::MAP_SIZE - 1 ) yEnd = Tiles::Info::MAP_SIZE - 1;

    //Only drawing those tiles
    for ( int y = yStart ; y < yEnd ; y++ )
    {
        for ( int x = xStart ; x < xEnd ; x++ )
        {
            this->at( x, y )->draw ( window );
        }
    }
}

Lighting

Lighting is as simple as each tile checking lights and multiplying colours together.

void
Tile :: updateLight ( const std::vector<Light>& lights )
{
    //Start the lights as being dark
    m_light = { 0, 0, 0 };

    for ( const Light& light : lights)
    {
        if ( m_light.r < 255 &&
             m_light.g < 255 &&
             m_light.b < 255 )
        {
            //Increase the light of the tile based on distance from the light
            m_light += light.getLightFromIntensity ( m_tilePos );
        }
    }
    applyLight(); //aka "M_sprite.setColor( m_info.colour * m_light );"
}

Unfournatly, this caused the game's performance to suffer. Luckily, I made a few optimisations.

One optimisations to add a static booleon into the light class that says whether or not there has been a "light update". If there has, then the light is recalculated.

The boolean is set to true if

  1. A light is moved.
  2. A light is added.
  3. A light is removed.

Mobs are lit up by adding the "Effected_By_Light" component to them, which simply checks the light value of the tile below them, and then applies the light colours to the mob.

The lights look like this:

alt text alt text

Compared to no lights, it is a huge improvement:

alt text

kingdom's People

Contributors

hopson97 avatar cwfitzgerald avatar

Watchers

James Cloos avatar Jason Yang avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.