1
/****************************************************************************
2
3
This file is part of the wolfenqt project on http://qt.gitorious.org.
4
5
Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).*
6
All rights reserved.
7
8
Contact:  Nokia Corporation (qt-info@nokia.com)**
9
10
You may use this file under the terms of the BSD license as follows:
11
12
"Redistribution and use in source and binary forms, with or without
13
modification, are permitted provided that the following conditions are met:
14
* Redistributions of source code must retain the above copyright notice,
15
* this list of conditions and the following disclaimer.
16
* Redistributions in binary form must reproduce the above copyright notice,
17
* this list of conditions and the following disclaimer in the documentation
18
* and/or other materials provided with the distribution.
19
* Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
20
* names of its contributors may be used to endorse or promote products
21
* derived from this software without specific prior written permission.
22
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
POSSIBILITY OF SUCH DAMAGE."
33
34
****************************************************************************/
35
#include "entity.h"
36
37
const QImage toAlpha(const QImage &image)
38
{
39
    if (image.isNull())
40
        return image;
41
    QRgb alpha = image.pixel(0, 0);
42
    QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
43
    QRgb *data = reinterpret_cast<QRgb *>(result.bits());
44
    int size = image.width() * image.height();
45
    for (int i = 0; i < size; ++i)
46
        if (data[i] == alpha)
47
            data[i] = 0;
48
    return result;
49
}
50
51
Entity::Entity(const QPointF &pos)
52
    : ProjectedItem(QRectF(-0.3, -0.4, 0.6, 0.9), false, false)
53
    , m_pos(pos)
54
    , m_angle(180)
55
    , m_walking(false)
56
    , m_walked(false)
57
    , m_turnVelocity(0)
58
    , m_useTurnTarget(false)
59
    , m_animationIndex(0)
60
    , m_angleIndex(0)
61
{
62
    startTimer(300);
63
}
64
65
void Entity::walk()
66
{
67
    m_walking = true;
68
}
69
70
void Entity::stop()
71
{
72
    m_walking = false;
73
    m_useTurnTarget = false;
74
    m_turnVelocity = 0;
75
}
76
77
void Entity::turnTowards(qreal x, qreal y)
78
{
79
    m_turnTarget = QPointF(x, y);
80
    m_useTurnTarget = true;
81
}
82
83
void Entity::turnLeft()
84
{
85
    m_useTurnTarget = false;
86
    m_turnVelocity = -0.5;
87
}
88
89
void Entity::turnRight()
90
{
91
    m_useTurnTarget = false;
92
    m_turnVelocity = 0.5;
93
}
94
95
static QVector<QImage> loadSoldierImages()
96
{
97
    QVector<QImage> images;
98
    for (int i = 1; i <= 40; ++i) {
99
        QImage image(QString("soldier/O%0.png").arg(i, 2, 10, QLatin1Char('0')));
100
        images << toAlpha(image.convertToFormat(QImage::Format_RGB32));
101
    }
102
    return images;
103
}
104
105
static inline int mod(int x, int y)
106
{
107
    return ((x % y) + y) % y;
108
}
109
110
void Entity::updateTransform(const Camera &camera)
111
{
112
    qreal angleToCamera = QLineF(m_pos, camera.pos()).angle();
113
    int cameraAngleIndex = mod(qRound(angleToCamera + 22.5), 360) / 45;
114
115
    m_angleIndex = mod(qRound(cameraAngleIndex * 45 - m_angle + 22.5), 360) / 45;
116
117
    QPointF delta = QLineF::fromPolar(1, 270.1 + 45 * cameraAngleIndex).p2();
118
    setPosition(m_pos - delta, m_pos + delta);
119
120
    updateImage();
121
    ProjectedItem::updateTransform(camera);
122
}
123
124
bool Entity::move(MazeScene *scene)
125
{
126
    bool moved = false;
127
    if (m_useTurnTarget) {
128
        qreal angleToTarget = QLineF::fromPolar(1, m_angle)
129
            .angleTo(QLineF(m_pos, m_turnTarget));
130
131
        if (angleToTarget != 0) {
132
            if (angleToTarget >= 180)
133
                angleToTarget -= 360;
134
135
            if (angleToTarget < 0)
136
                m_angle -= qMin(-angleToTarget, qreal(0.5));
137
            else
138
                m_angle += qMin(angleToTarget, qreal(0.5));
139
            moved = true;
140
        }
141
    } else if (m_turnVelocity != 0) {
142
        m_angle += m_turnVelocity;
143
        moved = true;
144
    }
145
146
    m_walked = false;
147
    if (m_walking) {
148
        QPointF walkingDelta = QLineF::fromPolar(0.006, m_angle).p2();
149
        if (scene->tryMove(m_pos, walkingDelta, this)) {
150
            moved = true;
151
            m_walked = true;
152
        }
153
    }
154
155
    return moved;
156
}
157
158
void Entity::timerEvent(QTimerEvent *)
159
{
160
    ++m_animationIndex;
161
    updateImage();
162
}
163
164
void Entity::updateImage()
165
{
166
    static QVector<QImage> images = loadSoldierImages();
167
    if (m_walked)
168
        setImage(images.at(8 + 8 * (m_animationIndex % 4) + m_angleIndex));
169
    else
170
        setImage(images.at(m_angleIndex));
171
}