Code Search for Developers
 
 
  

maptileclient.cpp from FreePop at Krugle


Show maptileclient.cpp syntax highlighted

/***************************************************************************
                          maptile.cpp  -  description
                             -------------------
    begin                : Mon Aug 5 2002
    copyright            : (C) 2002 by Brendon Higgins
    email                : freepop-devel@lists.sourceforge.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <client.h>
#include <corner.h>
#include <mappos.h>
#include <maptileclient.h>
#include <maptilepos.h>
#include <misc.h>
#include <rules.h>
#include <worldpos.h>

#include <ClanLib/display.h>

#include <cassert>

const int MapTileClient::PICWIDTH = 128;
const int MapTileClient::PICHEIGHT = 64;
CL_Sprite** MapTileClient::sprites = 0;


MapTileClient::MapTileClient() {
}

MapTileClient::MapTileClient(const MapTileClient& t): MapTile(t) {
}

MapTileClient::~MapTileClient() {
}

MapTileClient& MapTileClient::operator=(const MapTileClient& copy) {
    z = copy.z;
    s = copy.s;
    return *this;
}

MapTileClient& MapTileClient::operator*=(const Rotation& r) {
    MapTile::operator*=(r);
    return *this;
}

CL_Point MapTileClient::getOffset() const {
    return offset;
}

CL_Point MapTileClient::calcOffset(const MapPos& p) {
    offset = CL_Point(picWidth() * (p.getX() - p.getY()) / 2,
                      picHeight() * (p.getX() + p.getY() - int(z)) / 2);
    return offset;
}

Corner MapTileClient::calcNearestScreenCorner(const CL_Point& p) const {
    CL_Point a = findPosSlope(Corner::NORTH) - p;
    CL_Point b = findPosSlope(Corner::EAST) - p;
    CL_Point c = findPosSlope(Corner::SOUTH) - p;
    CL_Point d = findPosSlope(Corner::WEST) - p;
    int ad = a.x * a.x + a.y * a.y;
    int bd = b.x * b.x + b.y * b.y;
    int cd = c.x * c.x + c.y * c.y;
    int dd = d.x * d.x + d.y * d.y;
    int m = min(ad, bd, cd, dd);
    if (m == ad) return Corner::NORTH;
    else if (m == bd) return Corner::EAST;
    else if (m == cd) return Corner::SOUTH;
    else return Corner::WEST;
}

MapTilePos MapTileClient::findPos(const CL_Point& gp) const {
    return findPosSlope(gp - getOffset());
}

CL_Point MapTileClient::findPosSlope(const MapTilePos& p) const {
    switch (getSlope().getRaw()) {
    case 0:
        return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
            int((p.getX() + p.getY() - 1.0f) * picHeight()) / 2);

    case 1:
        if (p.getX() + p.getY() >= 1.0f) {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() + p.getY() - 1.0f) * picHeight()) / 2);
        } else {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() + p.getY() - 1.0f) * picHeight()));
        }

    case 2:
        if (p.getX() <= p.getY()) {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() + p.getY() - 1.0f) * picHeight()) / 2);
        } else {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getY() - 0.5f) * picHeight()));
        }

    case 3:
        return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
            int((p.getX() + 2.0f * p.getY() - 2.0f) * picHeight()) / 2);

    case 4:
        if (p.getX() + p.getY() >= 1.0f) {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2, 0);
        } else {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() + p.getY() - 1.0f) * picHeight()) / 2);
        }

    case 5:
        if (p.getX() + p.getY() >= 1.0f) {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2, 0);
        } else {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() + p.getY() - 1.0f) * picHeight()));
        }

    case 6:
        return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
            int((p.getY() - 1.0f) * picHeight()) / 2);

    case 7:
        if (p.getX() >= p.getY()) {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() + p.getY() - 2.0f) * picHeight()) / 2);
        } else {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getY() - 1.0f) * picHeight()));
        }

        case 8:
            // HACK, A little bit of a
        if (p.getX() >= p.getY()) {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() + p.getY() - 1.0f) * picHeight()) / 2);
        } else {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() - 0.5f) * picHeight()));
        }

    case 9:
        return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
            int((p.getY() + 2.0f * p.getX() - 2.0f) * picHeight()) / 2);

    case 10:
        if (p.getX() >= p.getY()) {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getY() - 0.5f) * picHeight()));
        } else {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() - 0.5f) * picHeight()));
        }

    case 11:
        if (p.getX() + p.getY() <= 1.0f) {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() + p.getY() - 2.0f) * picHeight()) / 2);
        } else {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() + p.getY() - 1.5f) * picHeight()));
        }

    case 12:
        return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
            int((p.getX() - 1.0f) * picHeight()) / 2);

    case 13:
        if (p.getX() <= p.getY()) {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() + p.getY() - 2.0f) * picHeight()) / 2);
        } else {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() - 1.0f) * picHeight()));
        }

    case 14:
        if (p.getX() + p.getY() >= 1.0f) {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                int((p.getX() + p.getY() - 2.0f) * picHeight()) / 2);
        } else {
            return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
                picHeight() / -2);    // Any position produces this y.
        }

    //case 15: There is no 15th slope.

    case 16:
        return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
            int((p.getX() + p.getY() - 1.5f) * picHeight()));

    case 17:
        return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
            int((p.getY() - 1.0f) * picHeight()));

    case 18:
        return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
            picHeight() / -2);      // Any position produces this y.

    case 19:
        return CL_Point(int((p.getX() - p.getY()) * picWidth()) / 2,
            int((p.getX() - 1.0f) * picHeight()));

    default:
        // This should never happen.
        assert(0 && "Bad slope state in switch.");
        return CL_Point(0, 0);
    }
}

CL_Point MapTileClient::findPosSlope(const Corner& c) const {
    switch (getSlope().getRaw()) {
    case 0:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, picHeightOnNeg2());
        case 1: return CL_Point(picWidthOn2(), 0);
        case 2: return CL_Point(0, picHeightOn2());
        case 3: return CL_Point(picWidthOnNeg2(), 0);
        }

    case 1:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, -picHeight());
        case 1: return CL_Point(picWidthOn2(), 0);
        case 2: return CL_Point(0, picHeightOn2());
        case 3: return CL_Point(picWidthOnNeg2(), 0);
        }

    case 2:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, picHeightOnNeg2());
        case 1: return CL_Point(picWidthOn2(), picHeightOnNeg2());
        case 2: return CL_Point(0, picHeightOn2());
        case 3: return CL_Point(picWidthOnNeg2(), 0);
        }

    case 3:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, -picHeight());
        case 1: return CL_Point(picWidthOn2(), -picHeightOn2());
        case 2: return CL_Point(0, picHeightOn2());
        case 3: return CL_Point(picWidthOnNeg2(), 0);
        }

    case 4:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, picHeightOnNeg2());
        case 1: return CL_Point(picWidthOn2(), 0);
        case 2: return CL_Point(0, 0);
        case 3: return CL_Point(picWidthOnNeg2(), 0);
        }

    case 5:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, -picHeight());
        case 1: return CL_Point(picWidthOn2(), 0);
        case 2: return CL_Point(0, 0);
        case 3: return CL_Point(picWidthOnNeg2(), 0);
        }

    case 6:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, picHeightOnNeg2());
        case 1: return CL_Point(picWidthOn2(), picHeightOnNeg2());
        case 2: return CL_Point(0, 0);
        case 3: return CL_Point(picWidthOnNeg2(), 0);
        }

    case 7:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, -picHeight());
        case 1: return CL_Point(picWidthOn2(),  picHeightOnNeg2());
        case 2: return CL_Point(0, 0);
        case 3: return CL_Point(picWidthOnNeg2(), 0);
        }

    case 8:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, picHeightOnNeg2());
        case 1: return CL_Point(picWidthOn2(), 0);
        case 2: return CL_Point(0, picHeightOn2());
        case 3: return CL_Point(picWidthOnNeg2(), picHeightOnNeg2());
        }

    case 9:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, -picHeight());
        case 1: return CL_Point(picWidthOn2(), 0);
        case 2: return CL_Point(0, picHeightOn2());
        case 3: return CL_Point(picWidthOnNeg2(), picHeightOnNeg2());
        }

    case 10:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, picHeightOnNeg2());
        case 1: return CL_Point(picWidthOn2(), picHeightOnNeg2());
        case 2: return CL_Point(0, picHeightOn2());
        case 3: return CL_Point(picWidthOnNeg2(), picHeightOnNeg2());
        }

    case 11:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, -picHeight());
        case 1: return CL_Point(picWidthOn2(), picHeightOnNeg2());
        case 2: return CL_Point(0, picHeightOn2());
        case 3: return CL_Point(picWidthOnNeg2(), picHeightOnNeg2());
        }

    case 12:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, picHeightOnNeg2());
        case 1: return CL_Point(picWidthOn2(), 0);
        case 2: return CL_Point(0, 0);
        case 3: return CL_Point(picWidthOnNeg2(), picHeightOnNeg2());
        }

    case 13:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, -picHeight());
        case 1: return CL_Point(picWidthOn2(), 0);
        case 2: return CL_Point(0, 0);
        case 3: return CL_Point(picWidthOnNeg2(), picHeightOnNeg2());
        }

    case 14:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, picHeightOnNeg2());
        case 1: return CL_Point(picWidthOn2(), picHeightOnNeg2());
        case 2: return CL_Point(0, 0);
        case 3: return CL_Point(picWidthOnNeg2(), picHeightOnNeg2());
        }

    //case 15: There is no 15th slope.

    case 16:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, 3 * picHeightOnNeg2());
        case 1: return CL_Point(picWidthOn2(), picHeightOnNeg2());
        case 2: return CL_Point(0, picHeightOn2());
        case 3: return CL_Point(picWidthOnNeg2(), picHeightOnNeg2());
        }

    case 17:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, -picHeight());
        case 1: return CL_Point(picWidthOn2(), -picHeight());
        case 2: return CL_Point(0, 0);
        case 3: return CL_Point(picWidthOnNeg2(), 0);
        }

    case 18:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, picHeightOnNeg2());
        case 1: return CL_Point(picWidthOn2(), picHeightOnNeg2());
        case 2: return CL_Point(0, picHeightOnNeg2());
        case 3: return CL_Point(picWidthOnNeg2(), picHeightOnNeg2());
        }

    case 19:
        switch (c.getCornerNum()) {
        case 0: return CL_Point(0, -picHeight());
        case 1: return CL_Point(picWidthOn2(), 0);
        case 2: return CL_Point(0, 0);
        case 3: return CL_Point(picWidthOnNeg2(), -picHeight());
        }

    default:
        // This should never happen.
        assert(0 && "Bad slope state in switch.");
        return CL_Point(0, 0);
    }
}

MapTilePos MapTileClient::findPosSlope(const CL_Point& p) const {
    // Must be careful to return an invalid pos when the position is outside.
    const float xow = float(p.x) / picWidth();
    const float yoh = float(p.y) / picHeight();
    switch (getSlope().getRaw()) {
    case 0:
        return MapTilePos(xow + yoh + 0.5f, yoh - xow + 0.5f);

    case 1:
        if (p.y >= 0) {
            return MapTilePos(xow + yoh + 0.5f, yoh - xow + 0.5f);
        } else {
            return MapTilePos(xow + yoh / 2.0f + 0.5f, yoh / 2.0f - xow + 0.5f);
        }

    case 2:
        if (p.x <= 0) {
            return MapTilePos(xow + yoh + 0.5f, yoh - xow + 0.5f);
        } else {
            return MapTilePos(xow * 2.0f + yoh + 0.5f, yoh + 0.5f);
        }

    case 3: {
            const float twoThirds = 2.0f / 3.0f;
            return MapTilePos((xow * 2.0f + yoh + 1.0f) * twoThirds,
                (yoh - xow + 1.0f) * twoThirds);
        }

    case 4:
        if (p.y <= 0) {
            return MapTilePos(xow + yoh + 0.5f, yoh - xow + 0.5f);
        } else {
            return MapTilePos(-1.0f, -1.0f);
        }

    case 5:
        if (p.y <= 0) {
            return MapTilePos(xow + yoh / 2.0f + 0.5f, yoh / 2.0f - xow + 0.5f);
        } else {
            return MapTilePos(-1.0f, -1.0f);
        }

    case 6:
        return MapTilePos(xow * 2.0f + yoh * 2.0f + 1.0f, yoh * 2.0f + 1.0f);

    case 7:
        if (p.x >= 0) {
            return MapTilePos(xow + yoh + 1.0f, yoh - xow + 1.0f);
        } else {
            return MapTilePos(xow * 2.0f + yoh + 1.0f, yoh + 1.0f);
        }

    case 8:
        if (p.x >= 0) {
            return MapTilePos(xow + yoh + 0.5f, yoh - xow + 0.5f);
        } else {
            return MapTilePos(yoh + 0.5f, yoh - xow * 2.0f + 0.5f);
        }

    case 9:
        return MapTilePos((2.0f * xow + 2.0f * yoh + 2.0f) / 3.0f,
            (2.0f * yoh - 4.0f * xow + 2.0f) / 3.0f);

    case 10:
        if (p.x >= 0) {
            return MapTilePos(2.0f * xow + yoh + 0.5f, yoh + 0.5f);
        } else {
            return MapTilePos(yoh + 0.5f, yoh - 2.0f * xow + 0.5f);
        }

    case 11:
        if (yoh <= -0.5f) {
            return MapTilePos(xow + yoh + 1.0f, 1.0f - xow + yoh);
        } else {
            return MapTilePos(xow + yoh / 2.0f + 0.75f,
                              yoh / 2.0f - xow + 0.75f);
        }

    case 12:
        return MapTilePos(2.0f * yoh + 1.0f, 2.0f * yoh - 2.0f * xow + 1.0f);

    case 13:
        if (p.x <= 0) {
            return MapTilePos(yoh + xow + 1.0f, yoh - xow + 1.0f);
        } else {
            return MapTilePos(yoh + 1.0f, yoh - 2.0f * xow + 1.0f);
        }

    case 14:
        if (yoh >= -0.5f) {
            return MapTilePos(yoh + xow + 1.0f, yoh - xow + 1.0f);
        } else {
            return MapTilePos(-1.0f, -1.0f);
        }

    //case 15: There is no 15th slope... so don't make one.

    case 16:
        return MapTilePos(xow + yoh / 2.0f + 0.75f, yoh / 2.0f - xow + 0.75f);

    case 17:
        return MapTilePos(xow * 2.0f + yoh + 1.0f, yoh + 1.0f);

    case 18:
        // This slope produces a line of possible positions,
        // so just default to [-1, -1], ie invalid. (You can't even SELECT
        // a slope like this!)
        return MapTilePos(-1.0f, -1.0f);

    case 19:
        return MapTilePos(yoh + 1.0f, yoh - xow * 2.0f + 1.0f);

    default:
        // This should never happen.
        assert(0 && "Bad slope state in switch.");
        break;
    }
}

void MapTileClient::draw() const {
    CL_Point p = getOffset();
    sprites[getSpriteNum()]->draw(p.x, p.y);
}

int MapTileClient::picWidth() {
    return PICWIDTH;
}

int MapTileClient::picHeight() {
    return PICHEIGHT;
}

int MapTileClient::picWidthOn2() {
    static int ret = picWidth() / 2;
    return ret;
}

int MapTileClient::picHeightOn2() {
    static int ret = picHeight() / 2;
    return ret;
}

int MapTileClient::picWidthOnNeg2() {
    static int ret = -picWidthOn2();
    return ret;
}

int MapTileClient::picHeightOnNeg2() {
    static int ret = -picHeightOn2();
    return ret;
}

std::string MapTileClient::getSpriteName(Rules* r, int n, bool s) {
    std::string ret;
    switch (n) {
    case 0: ret = "00"; break;
    case 1: ret = "01"; break;
    case 2: ret = "02"; break;
    case 3: ret = "03"; break;
    case 4: ret = "04"; break;
    case 5: ret = "05"; break;
    case 6: ret = "06"; break;
    case 7: ret = "07"; break;
    case 8: ret = "08"; break;
    case 9: ret = "09"; break;
    case 10: ret = "10"; break;
    case 11: ret = "11"; break;
    case 12: ret = "12"; break;
    case 13: ret = "13"; break;
    case 14: ret = "14"; break;
    case 16: ret = "16"; break;
    case 17: ret = "17"; break;
    case 18: ret = "18"; break;
    case 19: ret = "19"; break;
    default:
        // This should never happen.
        assert(0 && "Bad slope state in switch.");
        break;
    }

    if (s) return "tiles/" + r->theater + "/sea/" + ret;
    else return "tiles/" + r->theater + "/land/" + ret;
}

int MapTileClient::getSpriteNum() const {
    if (isAtSeaLevel()) {
        return getSlope().getRaw() + 20;
    } else {
        return getSlope().getRaw();
    }
}

void MapTileClient::loadSprites(Rules* r) {
    sprites = new CL_Sprite*[40];
    for (int i = 0; i < 20; ++i) {
        if (i != 15) {
            sprites[i] = new CL_Sprite(getSpriteName(r, i, false),
                                       app.getResources());
        }
    }
    for (int i = 0; i < 20; ++i) {
        if (i != 15) {
            sprites[i + 20] = new CL_Sprite(getSpriteName(r, i, true),
                                            app.getResources());
        }
    }
}

void MapTileClient::freeSprites() {
    for (int i = 0; i < 40; ++i) {
        if (i != 15 && i != 35) {
            delete sprites[i];
        }
    }
    delete [] sprites;
}




See more files for this project here

FreePop

FreePop is a multi-platform tile-based game based on the great old game Populous 2 by Bullfrog Productions Ltd., but much improved.

Project homepage: http://sourceforge.net/projects/freepop
Programming language(s): C++
License: other

  Makefile.am
  client.cpp
  client.h
  clientmisc.cpp
  clientmisc.h
  clientstate.cpp
  clientstate.h
  connectstate.cpp
  connectstate.h
  cropsclient.cpp
  cropsclient.h
  entityclient.cpp
  entityclient.h
  entityclientfactory.cpp
  entityclientfactory.h
  firecolumnclient.cpp
  firecolumnclient.h
  gamestate.cpp
  gamestate.h
  loadstate.cpp
  loadstate.h
  mapclient.cpp
  mapclient.h
  maptileclient.cpp
  maptileclient.h
  messagebox.cpp
  messagebox.h
  oversprite.cpp
  oversprite.h
  paintable.cpp
  paintable.h
  pausefader.cpp
  pausefader.h
  peepclient.cpp
  peepclient.h
  peepmagnetclient.cpp
  peepmagnetclient.h
  playerclient.cpp
  playerclient.h
  playeroptionsdialog.cpp
  playeroptionsdialog.h
  rockclient.cpp
  rockclient.h
  swampclient.cpp
  swampclient.h
  townclient.cpp
  townclient.h
  treeclient.cpp
  treeclient.h
  worldclient.cpp
  worldclient.h