Exemple #1
0
Being *BeingManager::findNearestLivingBeing(int x, int y,
                                            int maxTileDist,
                                            Being::Type type) const
{
    Being *closestBeing = 0;
    int dist = 0;

    const int maxDist = maxTileDist * 32;

    Beings::const_iterator itr = mBeings.begin();
    Beings::const_iterator itr_end = mBeings.end();

    for (; itr != itr_end; ++itr)
    {
        Being *being = (*itr);
        const Vector &pos = being->getPosition();
        int d = abs(((int) pos.x) - x) + abs(((int) pos.y) - y);

        if ((being->getType() == type || type == Being::UNKNOWN)
                && (d < dist || !closestBeing)          // it is closer
                && being->isAlive())       // no dead beings
        {
            dist = d;
            closestBeing = being;
        }
    }

    return (maxDist >= dist) ? closestBeing : 0;
}
Exemple #2
0
void MapComposite::update()
{
    // Update object status
    const std::vector< Entity * > &entities = getEverything();
    for (std::vector< Entity * >::const_iterator it = entities.begin(),
         it_end = entities.end(); it != it_end; ++it)
    {
        (*it)->update();
    }

    if (mUpdateCallback.isValid())
    {
        Script *s = ScriptManager::currentState();
        s->setMap(this);
        s->prepare(mUpdateCallback);
        s->push(mID);
        s->execute();
    }

    // Move objects around and update zones.
    for (BeingIterator it(getWholeMapIterator()); it; ++it)
    {
        (*it)->move();
    }

    for (int i = 0; i < mContent->mapHeight * mContent->mapWidth; ++i)
    {
        mContent->zones[i].destinations.clear();
    }

    // Cannot use a WholeMap iterator as objects will change zones under its feet.
    for (std::vector< Entity * >::iterator i = mContent->entities.begin(),
         i_end = mContent->entities.end(); i != i_end; ++i)
    {
        if (!(*i)->canMove())
            continue;

        Being *obj = static_cast< Being * >(*i);

        const Point &pos1 = obj->getOldPosition(),
                    &pos2 = obj->getPosition();

        MapZone &src = mContent->getZone(pos1),
                &dst = mContent->getZone(pos2);
        if (&src != &dst)
        {
            addZone(src.destinations, &dst - mContent->zones);
            src.remove(obj);
            dst.insert(obj);
        }
    }
}
Exemple #3
0
static Being *findBeingNear(Actor *p, int id)
{
    MapComposite *map = p->getMap();
    const Point &ppos = p->getPosition();
    // See map.h for tiles constants
    const int pixelDist = DEFAULT_TILE_LENGTH * TILES_TO_BE_NEAR;
    for (BeingIterator i(map->getAroundPointIterator(ppos, pixelDist)); i; ++i)
    {
        Being *b = *i;
        if (b->getPublicID() != id)
            continue;
        return ppos.inRangeOf(b->getPosition(), pixelDist) ? b : 0;
    }
    return 0;
}
Exemple #4
0
        bool operator() (ActorSprite *actor)
        {
            if (actor->getType() == ActorSprite::FLOOR_ITEM)
                return false;
            Game *game = Game::instance();
            if (!game)
                return false;

            Being* b = static_cast<Being*>(actor);

            uint16_t other_y = y + ((b->getType() == ActorSprite::NPC) ? 1 : 0);
            const Vector &pos = b->getPosition();
            return ((int) pos.x / game->getCurrentTileWidth() == x &&
                    ((int) pos.y / game->getCurrentTileHeight() == y
                    || (int) pos.y / game->getCurrentTileHeight() == other_y) &&
                    b->isAlive() &&
                    (type == ActorSprite::UNKNOWN || b->getType() == type));
        }
Exemple #5
0
/**
 * Informs a player of what happened around the character.
 */
static void informPlayer(MapComposite *map, Character *p)
{
    MessageOut moveMsg(GPMSG_BEINGS_MOVE);
    MessageOut damageMsg(GPMSG_BEINGS_DAMAGE);
    const Point &pold = p->getOldPosition(), ppos = p->getPosition();
    int pid = p->getPublicID(), pflags = p->getUpdateFlags();
    int visualRange = Configuration::getValue("game_visualRange", 448);

    // Inform client about activities of other beings near its character
    for (BeingIterator it(map->getAroundBeingIterator(p, visualRange));
         it; ++it)
    {
        Being *o = *it;

        const Point &oold = o->getOldPosition(), opos = o->getPosition();
        int otype = o->getType();
        int oid = o->getPublicID(), oflags = o->getUpdateFlags();
        int flags = 0;

        // Check if the character p and the moving object o are around.
        bool wereInRange = pold.inRangeOf(oold, visualRange) &&
                           !((pflags | oflags) & UPDATEFLAG_NEW_ON_MAP);
        bool willBeInRange = ppos.inRangeOf(opos, visualRange);

        if (!wereInRange && !willBeInRange)
        {
            // Nothing to report: o and p are far away from each other.
            continue;
        }


        if (wereInRange && willBeInRange)
        {
            // Send attack messages.
            if ((oflags & UPDATEFLAG_ATTACK) && oid != pid)
            {
                MessageOut AttackMsg(GPMSG_BEING_ATTACK);
                AttackMsg.writeInt16(oid);
                AttackMsg.writeInt8(o->getDirection());
                AttackMsg.writeInt8(static_cast< Being * >(o)->getAttackId());
                gameHandler->sendTo(p, AttackMsg);
            }

            // Send action change messages.
            if ((oflags & UPDATEFLAG_ACTIONCHANGE))
            {
                MessageOut ActionMsg(GPMSG_BEING_ACTION_CHANGE);
                ActionMsg.writeInt16(oid);
                ActionMsg.writeInt8(static_cast< Being * >(o)->getAction());
                gameHandler->sendTo(p, ActionMsg);
            }

            // Send looks change messages.
            if (oflags & UPDATEFLAG_LOOKSCHANGE)
            {
                MessageOut LooksMsg(GPMSG_BEING_LOOKS_CHANGE);
                LooksMsg.writeInt16(oid);
                Character * c = static_cast<Character * >(o);
                serializeLooks(c, LooksMsg);
                LooksMsg.writeInt16(c->getHairStyle());
                LooksMsg.writeInt16(c->getHairColor());
                LooksMsg.writeInt16(c->getGender());
                gameHandler->sendTo(p, LooksMsg);
            }

            // Send emote messages.
            if (oflags & UPDATEFLAG_EMOTE)
            {
                int emoteId = o->getLastEmote();
                if (emoteId > -1)
                {
                    MessageOut EmoteMsg(GPMSG_BEING_EMOTE);
                    EmoteMsg.writeInt16(oid);
                    EmoteMsg.writeInt16(emoteId);
                    gameHandler->sendTo(p, EmoteMsg);
                }
            }

            // Send direction change messages.
            if (oflags & UPDATEFLAG_DIRCHANGE)
            {
                MessageOut DirMsg(GPMSG_BEING_DIR_CHANGE);
                DirMsg.writeInt16(oid);
                DirMsg.writeInt8(o->getDirection());
                gameHandler->sendTo(p, DirMsg);
            }

            // Send damage messages.
            if (o->canFight())
            {
                Being *victim = static_cast< Being * >(o);
                const Hits &hits = victim->getHitsTaken();
                for (Hits::const_iterator j = hits.begin(),
                     j_end = hits.end(); j != j_end; ++j)
                {
                    damageMsg.writeInt16(oid);
                    damageMsg.writeInt16(*j);
                }
            }

            if (oold == opos)
            {
                // o does not move, nothing more to report.
                continue;
            }
        }

        if (!willBeInRange)
        {
            // o is no longer visible from p. Send leave message.
            MessageOut leaveMsg(GPMSG_BEING_LEAVE);
            leaveMsg.writeInt16(oid);
            gameHandler->sendTo(p, leaveMsg);
            continue;
        }

        if (!wereInRange)
        {
            // o is now visible by p. Send enter message.
            MessageOut enterMsg(GPMSG_BEING_ENTER);
            enterMsg.writeInt8(otype);
            enterMsg.writeInt16(oid);
            enterMsg.writeInt8(static_cast< Being *>(o)->getAction());
            enterMsg.writeInt16(opos.x);
            enterMsg.writeInt16(opos.y);
            enterMsg.writeInt8(o->getDirection());
            enterMsg.writeInt8(o->getGender());
            switch (otype)
            {
                case OBJECT_CHARACTER:
                {
                    Character *q = static_cast< Character * >(o);
                    enterMsg.writeString(q->getName());
                    enterMsg.writeInt8(q->getHairStyle());
                    enterMsg.writeInt8(q->getHairColor());
                    serializeLooks(q, enterMsg);
                } break;

                case OBJECT_MONSTER:
                {
                    Monster *q = static_cast< Monster * >(o);
                    enterMsg.writeInt16(q->getSpecy()->getId());
                    enterMsg.writeString(q->getName());
                } break;

                case OBJECT_NPC:
                {
                    NpcComponent *npcComponent = o->getComponent<NpcComponent>();
                    enterMsg.writeInt16(npcComponent->getNpcId());
                    enterMsg.writeString(o->getName());
                } break;

                default:
                    assert(false); // TODO
                    break;
            }
            gameHandler->sendTo(p, enterMsg);
        }

        if (opos != oold)
        {
            // Add position check coords every 5 seconds.
            if (currentTick % 50 == 0)
                flags |= MOVING_POSITION;

            flags |= MOVING_DESTINATION;
        }

        // Send move messages.
        moveMsg.writeInt16(oid);
        moveMsg.writeInt8(flags);
        if (flags & MOVING_POSITION)
        {
            moveMsg.writeInt16(oold.x);
            moveMsg.writeInt16(oold.y);
        }

        if (flags & MOVING_DESTINATION)
        {
            moveMsg.writeInt16(opos.x);
            moveMsg.writeInt16(opos.y);
            // We multiply the sent speed (in tiles per second) by ten
            // to get it within a byte with decimal precision.
            // For instance, a value of 4.5 will be sent as 45.
            moveMsg.writeInt8((unsigned short)
                (o->getModifiedAttribute(ATTR_MOVE_SPEED_TPS) * 10));
        }
    }

    // Do not send a packet if nothing happened in p's range.
    if (moveMsg.getLength() > 2)
        gameHandler->sendTo(p, moveMsg);

    if (damageMsg.getLength() > 2)
        gameHandler->sendTo(p, damageMsg);

    // Inform client about status change.
    p->sendStatus();

    // Inform client about health change of party members
    for (CharacterIterator i(map->getWholeMapIterator()); i; ++i)
    {
        Character *c = *i;

        // Make sure its not the same character
        if (c == p)
            continue;

        // make sure they are in the same party
        if (c->getParty() == p->getParty())
        {
            int cflags = c->getUpdateFlags();
            if (cflags & UPDATEFLAG_HEALTHCHANGE)
            {
                MessageOut healthMsg(GPMSG_BEING_HEALTH_CHANGE);
                healthMsg.writeInt16(c->getPublicID());
                healthMsg.writeInt16(c->getModifiedAttribute(ATTR_HP));
                healthMsg.writeInt16(c->getModifiedAttribute(ATTR_MAX_HP));
                gameHandler->sendTo(p, healthMsg);
            }
        }
    }

    // Inform client about items on the ground around its character
    MessageOut itemMsg(GPMSG_ITEMS);
    for (FixedActorIterator it(map->getAroundBeingIterator(p, visualRange));
         it; ++it)
    {
        Actor *o = *it;

        assert(o->getType() == OBJECT_ITEM ||
               o->getType() == OBJECT_EFFECT);

        Point opos = o->getPosition();
        int oflags = o->getUpdateFlags();
        bool willBeInRange = ppos.inRangeOf(opos, visualRange);
        bool wereInRange = pold.inRangeOf(opos, visualRange) &&
                           !((pflags | oflags) & UPDATEFLAG_NEW_ON_MAP);

        if (willBeInRange ^ wereInRange)
        {
            switch (o->getType())
            {
                case OBJECT_ITEM:
                {
                    ItemComponent *item = o->getComponent<ItemComponent>();
                    ItemClass *itemClass = item->getItemClass();

                    if (oflags & UPDATEFLAG_NEW_ON_MAP)
                    {
                        /* Send a specific message to the client when an item appears
                           out of nowhere, so that a sound/animation can be performed. */
                        MessageOut appearMsg(GPMSG_ITEM_APPEAR);
                        appearMsg.writeInt16(itemClass->getDatabaseID());
                        appearMsg.writeInt16(opos.x);
                        appearMsg.writeInt16(opos.y);
                        gameHandler->sendTo(p, appearMsg);
                    }
                    else
                    {
                        itemMsg.writeInt16(willBeInRange ? itemClass->getDatabaseID() : 0);
                        itemMsg.writeInt16(opos.x);
                        itemMsg.writeInt16(opos.y);
                    }
                }
                break;
                case OBJECT_EFFECT:
                {
                    EffectComponent *e = o->getComponent<EffectComponent>();
                    e->setShown();
                    // Don't show old effects
                    if (!(oflags & UPDATEFLAG_NEW_ON_MAP))
                        break;

                    if (Being *b = e->getBeing())
                    {
                        MessageOut effectMsg(GPMSG_CREATE_EFFECT_BEING);
                        effectMsg.writeInt16(e->getEffectId());
                        effectMsg.writeInt16(b->getPublicID());
                        gameHandler->sendTo(p, effectMsg);
                    } else {
                        MessageOut effectMsg(GPMSG_CREATE_EFFECT_POS);
                        effectMsg.writeInt16(e->getEffectId());
                        effectMsg.writeInt16(opos.x);
                        effectMsg.writeInt16(opos.y);
                        gameHandler->sendTo(p, effectMsg);
                    }
                }
                break;
                default: break;
            } // Switch
        }
    }

    // Do not send a packet if nothing happened in p's range.
    if (itemMsg.getLength() > 2)
        gameHandler->sendTo(p, itemMsg);
}
Exemple #6
0
void Monster::refreshTarget()
{
    // Check potential attack positions
    Being *bestAttackTarget = mTarget = NULL;
    int bestTargetPriority = 0;
    Point bestAttackPosition;
    BeingDirection bestAttackDirection = DOWN;

    // Iterate through objects nearby
    int aroundArea = Configuration::getValue("game_visualRange", 448);
    for (BeingIterator i(getMap()->getAroundBeingIterator(this, aroundArea));
         i; ++i)
    {
        // We only want to attack player characters
        if ((*i)->getType() != OBJECT_CHARACTER)
            continue;

        Being *target = static_cast<Being *>(*i);

        // Dead characters are ignored
        if (target->getAction() == DEAD)
            continue;

        // Determine how much we hate the target
        int targetPriority = 0;
        std::map<Being *, int, std::greater<Being *> >::iterator angerIterator;
        angerIterator = mAnger.find(target);
        if (angerIterator != mAnger.end())
        {
            targetPriority = angerIterator->second;
        }
        else if (mSpecy->isAggressive())
        {
            targetPriority = 1;
        }
        else
        {
            continue;
        }

        // Check all attack positions
        for (std::list<AttackPosition>::iterator j = mAttackPositions.begin();
             j != mAttackPositions.end(); j++)
        {
            Point attackPosition = target->getPosition();
            attackPosition.x += j->x;
            attackPosition.y += j->y;

            int posPriority = calculatePositionPriority(attackPosition,
                                                        targetPriority);
            if (posPriority > bestTargetPriority)
            {
                bestAttackTarget = mTarget = target;
                bestTargetPriority = posPriority;
                bestAttackPosition = attackPosition;
                bestAttackDirection = j->direction;
            }
        }
    }

    // Check if an enemy has been found
    if (bestAttackTarget)
    {
        // Check which attacks have a chance to hit the target
        MonsterAttacks allAttacks = mSpecy->getAttacks();
        std::map<int, MonsterAttack *> workingAttacks;
        int prioritySum = 0;

        const int distX = getPosition().x - bestAttackTarget->getPosition().x;
        const int distY = getPosition().y - bestAttackTarget->getPosition().y;
        const int distSquare = (distX * distX + distY * distY);

        for (MonsterAttacks::iterator i = allAttacks.begin();
             i != allAttacks.end();
             i++)
        {
            int maxDist = (*i)->range + bestAttackTarget->getSize();

            if (maxDist * maxDist >= distSquare)
            {
                prioritySum += (*i)->priority;
                workingAttacks[prioritySum] = (*i);
            }
        }

        if (workingAttacks.empty() || !prioritySum)
        {   //when no attack can hit move closer to attack position
            setDestination(bestAttackPosition);
        }
        else
        {
            // Prepare for using a random attack which can hit the enemy
            // Stop movement
            setDestination(getPosition());
            // Turn into direction of enemy
            setDirection(bestAttackDirection);
            // Perform a random attack based on priority
            mCurrentAttack =
                         workingAttacks.upper_bound(rand()%prioritySum)->second;
            setAction(ATTACK);
            raiseUpdateFlags(UPDATEFLAG_ATTACK);
        }
    }
}
Exemple #7
0
    void handle_mouse(Event *evt)
    {
        if (!mapEngine->mapLoaded())
            return;

        Point camPos = graphicsEngine->getCamera()->getPosition();
        Point pos;
        pos.x = evt->x + camPos.x;
        pos.y = evt->y + camPos.y + mapEngine->getTileHeight();

        // left mouse button has finished being pressed
        if (evt->button == SDL_BUTTON_LEFT && evt->type == 1)
        {
            // check user clicked on map
            Node *node = graphicsEngine->getNode(pos.x, pos.y);
            if (node)
            {
                // show name if player/NPC is clicked
                Being *being = beingManager->findBeing(node->getName());
                if (being)
                {
                    // toggle being name
                    being->toggleName();
                    if (being->isNPC() && withinReach(being->getPosition(), player->getSelectedCharacter()->getPosition()) && !being->isTalking())
                    {
                        Packet *p = new Packet(PGMSG_NPC_START_TALK);
                        p->setInteger(being->getId());
                        networkManager->sendPacket(p);
                    }
                    return;
                }

                Point pt = mapEngine->convertPixelToTile(pos.x, pos.y);

                if (mapEngine->blocked(pt))
                    return;

                // send move message
                Packet *p = new Packet(PGMSG_PLAYER_MOVE);
                p->setInteger(pt.x);
                p->setInteger(pt.y);
                networkManager->sendPacket(p);
                //logger->logDebug("Sending move request");

                // save destination for later
                player->getSelectedCharacter()->saveDestination(pt);
            }
        }

		if (evt->button == 0)
		{
		    if (!interfaceManager->getMouse()->cursor)
                return;

//            pos.x += mapEngine->getTileWidth() >> 1;

		    int mapWidth = mapEngine->getWidth() * mapEngine->getTileWidth();
		    int mapHeight = mapEngine->getHeight() * mapEngine->getTileHeight();

		    if (pos.x > mapWidth || -pos.x > mapWidth)
		        return;
		    if (pos.y > mapHeight || pos.y < 0)
		        return;

            Point tilePos = mapEngine->convertPixelToTile(pos.x, pos.y);

		    if (tilePos.x < 0 || tilePos.y < 0)
                return;

		    if (tilePos.x == interfaceManager->getMouse()->cursorPos.x && tilePos.y == interfaceManager->getMouse()->cursorPos.y)
                return;

            interfaceManager->getMouse()->cursorPos = tilePos;

		    Point screenPos;
		    screenPos.x = 0.5 * (tilePos.x - tilePos.y) * mapEngine->getTileWidth();
            screenPos.y = 0.5 * (tilePos.x + tilePos.y) * mapEngine->getTileHeight();
			interfaceManager->getMouse()->cursor->moveNode(&screenPos);
		}
    }
Exemple #8
0
void BeingHandler::handleBeingsMoveMessage(Net::MessageIn &msg)
{
    while (msg.getUnreadLength())
    {
        int id = msg.readInt16();
        int flags = msg.readInt8();
        Being *being = actorSpriteManager->findBeing(id);
        int sx = 0, sy = 0, dx = 0, dy = 0, speed = 0;

        if ((!flags & (MOVING_POSITION | MOVING_DESTINATION)))
            continue;

        if (flags & MOVING_POSITION)
        {
            sx = msg.readInt16();
            sy = msg.readInt16();
        }

        if (flags & MOVING_DESTINATION)
        {
            dx = msg.readInt16();
            dy = msg.readInt16();
            speed = msg.readInt8();
        }

        if (!being)
            continue;

        if (speed)
        {
           /*
            * The being's speed is transfered in tiles per second * 10
            * to keep it transferable in a Byte.
            * We set it back to tiles per second and in a float.
            */
            float speedTilesSeconds = (float) speed / 10;
            being->setMoveSpeed(Vector(speedTilesSeconds, speedTilesSeconds,
                                       0));
        }

        // Ignore messages from the server for the local player
        if (being == player_node)
            continue;

        // If the position differs too much from the actual one, we resync
        // the being position
        if (flags & MOVING_POSITION)
        {
            if (!being->getMap()->containsPixel(sx, sy))
            {
                logger->log("Warning: Received GPMSG_BEINGS_MOVE for being id "
                            "%i with position outside the map boundaries "
                            "(x = %i, y = %i)", id, sx, sy);
                continue;
            }

            Vector serverPos(sx, sy);
            if (serverPos.length()
                - being->getPosition().length() > POSITION_DIFF_TOLERANCE)
                being->setPosition(serverPos);
        }

        if (flags & MOVING_DESTINATION)
        {
            if (!being->getMap()->containsPixel(dx, dy))
            {
                logger->log("Warning: Received GPMSG_BEINGS_MOVE for being id "
                            "%i with destination outside the map boundaries "
                            "(x = %i, y = %i)", id, dx, dy);
                continue;
            }

            being->setDestination(dx, dy);
        }
    }
}
Exemple #9
0
void Viewport::_drawDebugPath(Graphics *graphics)
{
    if (mDebugFlags & Map::MAP_MOUSE_PATH)
    {
        // Get the current mouse position
        SDL_GetMouseState(&mMouseX, &mMouseY);

        // Prepare the walkmask corresponding to the protocol
        unsigned char walkMask;
        switch (Net::getNetworkType())
        {
          case ServerInfo::TMWATHENA:
            walkMask = Map::BLOCKMASK_WALL | Map::BLOCKMASK_CHARACTER;
            break;
          case ServerInfo::MANASERV:
          default:
            walkMask = Map::BLOCKMASK_WALL;
            break;
        }

        static Path debugPath;
        static Vector lastMouseDestination = Vector(0.0f, 0.0f);
        Vector mouseDestination(mMouseX + (int) mPixelViewX,
                                mMouseY + (int) mPixelViewY);

        if (mouseDestination.x != lastMouseDestination.x
            || mouseDestination.y != lastMouseDestination.y)
        {
            const Vector &playerPos = player_node->getPosition();

            // Adapt the path finding to the precision requested
            if (Net::getPlayerHandler()->usePixelPrecision())
            {
                debugPath = mMap->findPixelPath((int) playerPos.x,
                                                (int) playerPos.y,
                                                mouseDestination.x,
                                                mouseDestination.y,
                                                player_node->getCollisionRadius(),
                                                walkMask);
            }
            else
            {
                debugPath = mMap->findTilePath((int) playerPos.x,
                                               (int) playerPos.y,
                                               mouseDestination.x,
                                               mouseDestination.y,
                                               walkMask);
            }

            lastMouseDestination = mouseDestination;
        }

        _drawPath(graphics, debugPath, gcn::Color(128, 0, 128, 150));
    }

    // Draw the path debug information for every beings.
    ActorSpritesConstIterator it, it_end;
    const ActorSprites &actors = actorSpriteManager->getAll();
    for (it = actors.begin(), it_end = actors.end() ; it != it_end; it++)
    {
        Being *being = dynamic_cast<Being*>(*it);
        if (!being)
            continue;

        const Vector &beingPos = being->getPosition();
        graphics->setColor(gcn::Color(128, 128, 0, 150));

        if (mDebugFlags & Map::MAP_BEING_COLLISION_RADIUS)
        {
            const int radius = being->getCollisionRadius();
            graphics->fillRectangle(gcn::Rectangle(
                                        (int) beingPos.x
                                        - (int) mPixelViewX - radius,
                                        (int) beingPos.y - (int) mPixelViewY
                                        - radius,
                                        radius * 2, radius * 2));
        }

        if (mDebugFlags & Map::MAP_BEING_PATH)
            _drawPath(graphics, being->getPath(), gcn::Color(0, 0, 255, 150));

        if (mDebugFlags & Map::MAP_BEING_POSITION)
        {
            // Draw the absolute x, y position using a cross.
            graphics->setColor(gcn::Color(0, 0, 255, 255));
            graphics->drawLine((int) beingPos.x - (int) mPixelViewX - 4,
                               (int) beingPos.y - (int) mPixelViewY - 4,
                               (int) beingPos.x - (int) mPixelViewX + 4,
                               (int) beingPos.y - (int) mPixelViewY + 4);
            graphics->drawLine((int) beingPos.x - (int) mPixelViewX + 4,
                               (int) beingPos.y - (int) mPixelViewY - 4,
                               (int) beingPos.x - (int) mPixelViewX - 4,
                               (int) beingPos.y - (int) mPixelViewY + 4);
        }
    }
}