Example #1
0
// tessellates the stroke of the line from a_ to b_ with the given width and a flat cap
void QTessellator::tessellateRect(const QPointF &a_, const QPointF &b_, qreal width)
{
    Vertex a = { FloatToQ27Dot5(a_.x()), FloatToQ27Dot5(a_.y()) };
    Vertex b = { FloatToQ27Dot5(b_.x()), FloatToQ27Dot5(b_.y()) };

    QPointF pa = a_, pb = b_;

    if (a.y > b.y) {
        qSwap(a, b);
        qSwap(pa, pb);
    }

    Vertex delta = { b.x - a.x, b.y - a.y };

    if (delta.x == 0 && delta.y == 0)
        return;

    qreal hw = 0.5 * width;

    if (delta.x == 0) {
        Q27Dot5 halfWidth = FloatToQ27Dot5(hw);

        if (halfWidth == 0)
            return;

        Vertex topLeft = { a.x - halfWidth, a.y };
        Vertex topRight = { a.x + halfWidth, a.y };
        Vertex bottomLeft = { a.x - halfWidth, b.y };
        Vertex bottomRight = { a.x + halfWidth, b.y };

        QTessellator::Trapezoid trap = { topLeft.y, bottomLeft.y, &topLeft, &bottomLeft, &topRight, &bottomRight };
        addTrap(trap);
    } else if (delta.y == 0) {
        Q27Dot5 halfWidth = FloatToQ27Dot5(hw);

        if (halfWidth == 0)
            return;

        if (a.x > b.x)
            qSwap(a.x, b.x);

        Vertex topLeft = { a.x, a.y - halfWidth };
        Vertex topRight = { b.x, a.y - halfWidth };
        Vertex bottomLeft = { a.x, a.y + halfWidth };
        Vertex bottomRight = { b.x, a.y + halfWidth };

        QTessellator::Trapezoid trap = { topLeft.y, bottomLeft.y, &topLeft, &bottomLeft, &topRight, &bottomRight };
        addTrap(trap);
    } else {
        QPointF perp(pb.y() - pa.y(), pa.x() - pb.x());
        qreal length = qSqrt(perp.x() * perp.x() + perp.y() * perp.y());

        if (qFuzzyIsNull(length))
            return;

        // need the half of the width
        perp *= hw / length;

        QPointF pta = pa + perp;
        QPointF ptb = pa - perp;
        QPointF ptc = pb - perp;
        QPointF ptd = pb + perp;

        Vertex ta = { FloatToQ27Dot5(pta.x()), FloatToQ27Dot5(pta.y()) };
        Vertex tb = { FloatToQ27Dot5(ptb.x()), FloatToQ27Dot5(ptb.y()) };
        Vertex tc = { FloatToQ27Dot5(ptc.x()), FloatToQ27Dot5(ptc.y()) };
        Vertex td = { FloatToQ27Dot5(ptd.x()), FloatToQ27Dot5(ptd.y()) };

        if (ta.y < tb.y) {
            if (tb.y < td.y) {
                QTessellator::Trapezoid top = { ta.y, tb.y, &ta, &tb, &ta, &td };
                QTessellator::Trapezoid bottom = { td.y, tc.y, &tb, &tc, &td, &tc };
                addTrap(top);
                addTrap(bottom);

                QTessellator::Trapezoid middle = { tb.y, td.y, &tb, &tc, &ta, &td };
                addTrap(middle);
            } else {
                QTessellator::Trapezoid top = { ta.y, td.y, &ta, &tb, &ta, &td };
                QTessellator::Trapezoid bottom = { tb.y, tc.y, &tb, &tc, &td, &tc };
                addTrap(top);
                addTrap(bottom);

                if (tb.y != td.y) {
                    QTessellator::Trapezoid middle = { td.y, tb.y, &ta, &tb, &td, &tc };
                    addTrap(middle);
                }
            }
        } else {
            if (ta.y < tc.y) {
                QTessellator::Trapezoid top = { tb.y, ta.y, &tb, &tc, &tb, &ta };
                QTessellator::Trapezoid bottom = { tc.y, td.y, &tc, &td, &ta, &td };
                addTrap(top);
                addTrap(bottom);

                QTessellator::Trapezoid middle = { ta.y, tc.y, &tb, &tc, &ta, &td };
                addTrap(middle);
            } else {
                QTessellator::Trapezoid top = { tb.y, tc.y, &tb, &tc, &tb, &ta };
                QTessellator::Trapezoid bottom = { ta.y, td.y, &tc, &td, &ta, &td };
                addTrap(top);
                addTrap(bottom);

                if (ta.y != tc.y) {
                    QTessellator::Trapezoid middle = { tc.y, ta.y, &tc, &td, &tb, &ta };
                    addTrap(middle);
                }
            }
        }
    }
}
Example #2
0
int
shMapLevel::buildSewer ()
{
    int x, y, i, n;
    int lighting = RNG (2) ? -1 : 1;
    SewerRoom nodes[NODECOLS][NODEROWS];

    mMapType = kSewer;

    x = RNG (NODECOLS);
    y = RNG (NODEROWS);

    //first pass
    buildSewerHelper (nodes, x, y, 0);

    //second pass, make more tightly connected
    for (n = 10; n; n--) {
        if (RNG(3)) {
            x = RNG (NODECOLS-1);
            y = RNG (NODEROWS);
            nodes[x][y].mWalls[1] = 0;
            nodes[x+1][y].mWalls[2] = 0;
        } else {
            x = RNG (NODECOLS);
            y = RNG (NODEROWS-1);
            nodes[x][y].mWalls[3] = 0;
            nodes[x][y+1].mWalls[0] = 0;
        }
    }

    for (x = 0; x < NODECOLS; x++) {
        for (y = 0; y < NODEROWS; y++) {
            if (nodes[x][y].mDeadEnd or !RNG(7)) {
                nodes[x][y].mBulbous = 1;
            }
        }
    }

    // force 2 bulbous rooms
    x = RNG (NODECOLS/3); y = RNG (NODEROWS);
    nodes[x][y].mBulbous = 1;
    x = NODECOLS - 1 - RNG (NODECOLS/3); y = RNG (NODEROWS);
    nodes[x][y].mBulbous = 1;

    // don't have adjacent bulbous rooms (looks bad)
    for (x = 0; x < NODECOLS-1; x++) {
        for (y = 0; y < NODEROWS; y++) {
            if (nodes[x][y].mBulbous and nodes[x+1][y].mBulbous and
                nodes[x][y].mWalls[1])
            {
                if (RNG(2))
                    nodes[x][y].mBulbous = 0;
                else
                    nodes[x+1][y].mBulbous = 0;
            }
        }
    }

    for (x = 0; x < NODECOLS; x++) {
        for (y = 0; y < NODEROWS-1; y++) {
            if (nodes[x][y].mBulbous and nodes[x][y+1].mBulbous and
                nodes[x][y].mWalls[3])
            {
                if (RNG(2))
                    nodes[x][y].mBulbous = 0;
                else
                    nodes[x][y+1].mBulbous = 0;
            }
        }
    }

    for (x = 0; x < NODECOLS; x++) {
        for (y = 0; y < NODEROWS; y++) {
            buildSewerRoom (nodes, x, y);
        }
    }

    for (n = NDX(2,4); n; n--) {
        floodMuck (RNG(NODECOLS)*6+5, RNG(NODEROWS)*4+2, kSewage, NDX(8,20));
    }

    for (i = NDX (2, 3); i; --i) {
        findUnoccupiedSquare (&x, &y);
        switch (RNG (4)) {
        case 0:
            addTrap (x, y, shFeature::kPit); break;
        case 1:
            addTrap (x, y, shFeature::kHole); break;
        case 2:
            addTrap (x, y, shFeature::kTrapDoor); break;
        case 3:
            addTrap (x, y, shFeature::kRadTrap); break;
        }
    }

    for (i = 0; i < 8; i++) {
        findUnoccupiedSquare (&x, &y);
        putObject (generateObject (mDLevel), x, y);
    }

    for (x = 0; x < mColumns; x++)
        for (y = 0; y < mRows; y++)
            setLit (x, y, lighting, lighting, lighting, lighting);



    return 1;
}
Example #3
0
// tessellates the given convex polygon
void QTessellator::tessellateConvex(const QPointF *points, int nPoints)
{
    Q_ASSERT(points[0] == points[nPoints-1]);
    --nPoints;

    d->vertices.nPoints = nPoints;
    d->vertices.init(nPoints);

    for (int i = 0; i < nPoints; ++i) {
        d->vertices[i]->x = FloatToQ27Dot5(points[i].x());
        d->vertices[i]->y = FloatToQ27Dot5(points[i].y());
    }

    int left = 0, right = 0;

    int top = 0;
    for (int i = 1; i < nPoints; ++i) {
        if (d->vertices[i]->y < d->vertices[top]->y)
            top = i;
    }

    left = (top + nPoints - 1) % nPoints;
    right = (top + 1) % nPoints;

    while (d->vertices[left]->x == d->vertices[top]->x && d->vertices[left]->y == d->vertices[top]->y && left != right)
        left = (left + nPoints - 1) % nPoints;

    while (d->vertices[right]->x == d->vertices[top]->x && d->vertices[right]->y == d->vertices[top]->y && left != right)
        right = (right + 1) % nPoints;

    if (left == right)
        return;

    int dir = 1;

    Vertex dLeft = { d->vertices[top]->x - d->vertices[left]->x,
                     d->vertices[top]->y - d->vertices[left]->y };

    Vertex dRight = { d->vertices[right]->x - d->vertices[top]->x,
                      d->vertices[right]->y - d->vertices[top]->y };

    Q27Dot5 cross = dLeft.x * dRight.y - dLeft.y * dRight.x;

    // flip direction if polygon is clockwise
    if (cross < 0 || (cross == 0 && dLeft.x > 0)) {
        qSwap(left, right);
        dir = -1;
    }

    Vertex *lastLeft = d->vertices[top];
    Vertex *lastRight = d->vertices[top];

    QTessellator::Trapezoid trap;

    while (lastLeft->y == d->vertices[left]->y && left != right) {
        lastLeft = d->vertices[left];
        left = (left + nPoints - dir) % nPoints;
    }

    while (lastRight->y == d->vertices[right]->y && left != right) {
        lastRight = d->vertices[right];
        right = (right + nPoints + dir) % nPoints;
    }

    while (true) {
        trap.top = qMax(lastRight->y, lastLeft->y);
        trap.bottom = qMin(d->vertices[left]->y, d->vertices[right]->y);
        trap.topLeft = lastLeft;
        trap.topRight = lastRight;
        trap.bottomLeft = d->vertices[left];
        trap.bottomRight = d->vertices[right];

        if (trap.bottom > trap.top)
            addTrap(trap);

        if (left == right)
            break;

        if (d->vertices[right]->y < d->vertices[left]->y) {
            do {
                lastRight = d->vertices[right];
                right = (right + nPoints + dir) % nPoints;
            }
            while (lastRight->y == d->vertices[right]->y && left != right);
        } else {
            do {
                lastLeft = d->vertices[left];
                left = (left + nPoints - dir) % nPoints;
            }
            while (lastLeft->y == d->vertices[left]->y && left != right);
        }
    }
}
Example #4
0
void
shMapLevel::mundaneRoom (int sx, int sy, int ex, int ey)
{
    int i, npiles, n;
    int x, y;

    if (mDLevel != TOWNLEVEL) {
        if (RNG (mDLevel + 6) > 9) {
            darkRoom (sx, sy, ex, ey);
        }

        if (!RNG (30)) {
            /* Radioactive room. */
            for (x = sx + 1; x < ex; x++) {
                for (y = sy + 1; y < ey; y++) {
                    mSquares[x][y].mFlags |= shSquare::kRadioactive;
                }
            }
        }
    }

    /* treasure expectation per room:
       version 0.3:
         0.375 piles x 1.1875 obj per pile +
         (~) 0.125 niches x 0.8 obj per niche
         ~ .5453125 objs per room

       version 0.2.9:
         0.375 piles x 1.375 obj per pile
         = .515625 obj per room
   */

    npiles = RNG (4) ? 0 : RNG (2) + RNG (2) + RNG (2);

    while (npiles--) {
        x = RNG (sx + 1, ex - 1);
        y = RNG (sy + 1, ey - 1);
        if (TESTSQ (x, y, kFloor)  and !isObstacle (x, y)) {
            n = RNG (10) ? 1 : RNG (2, 3);
            for (i = 0; i < n; i++) {
                putObject (generateObject (mDLevel), x, y);
            }
        }
    }

    if (0 == RNG (9)) {
        x = RNG (sx + 1, ex - 1);
        y = RNG (sy + 1, ey - 1);
        if (TESTSQ (x, y, kFloor) and !isObstacle (x, y) and
            0 == countObjects (x, y))
        {
            addVat (x, y);
        }
    }

    /* Reticulans of PRIME are weak enough to get instakilled in a pit.
       Do not place traps at all on first level. */
    while (!RNG (12) and mDLevel > 1) {
        x = RNG (sx + 1, ex - 1);
        y = RNG (sy + 1, ey - 1);
        if (TESTSQ (x, y, kFloor) and !isObstacle (x, y) and
            !getFeature (x, y))
        {
            shFeature::Type ttype;
        retrap:
            /* I'm using this retrap label because putting a for or while
               loop here uncovers a bug in g++! */
            /* FIXME: Probably the bug is long gone.  Get rid of goto. */
                ttype = (shFeature::Type) RNG (shFeature::kPit,
                                              shFeature::kPortal);
                switch (ttype) {
                case shFeature::kPit:
                case shFeature::kTrapDoor:
                    break;
                case shFeature::kAcidPit:
                    if (mDLevel < 7) goto retrap;
                    break;
                case shFeature::kHole:
                    if (RNG (5)) goto retrap;
                    break;
                case shFeature::kWeb:
                    goto retrap;
                case shFeature::kRadTrap:
                    if (mDLevel < 5) goto retrap;
                    break;
                case shFeature::kPortal:
                default: /* these traps are unimplemented */
                    goto retrap;
                }

            addTrap (x, y, ttype);
        }
    }
}