source: trunk/orbital/snake.h @ 1433

Last change on this file since 1433 was 1433, checked in by sam, 11 years ago

orbital: use hexadecimal colour commands everywhere.

File size: 6.0 KB
Line 
1//
2// Orbital
3//
4// Copyright: (c) 2009-2012 Cédric Lecacheur <jordx@free.fr>
5//            (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com>
6//            (c) 2012 Sam Hocevar <sam@hocevar.net>
7//
8
9/* FIXME: this file is pure crap; it's only a test. */
10
11#if !defined __SNAKE_H__
12#define __SNAKE_H__
13
14class Snake : public WorldEntity
15{
16public:
17    Snake(int nodes)
18      : m_steer(0.f),
19        m_stick(0),
20        m_ready(false)
21    {
22        m_head.SendCommand("sc#d91,"
23                           "afcb30,3,3,.8,fl,"
24                           "sc#cca,"
25                           "afcb10,10,10,1,fl,"
26                           "afcb.4,.4,12,.4,tz3,tx8,mx,fl,"
27                           "afcb.4,.4,12,.4,tz3,tx12,mx,fl,"
28                           "sc#69c9,"
29                           "afcb5,8,8,1,ty3,tz3,fl");
30
31        m_body.SendCommand("sc#d91,"
32                           "afcb3,20,3,.8,afcb20,3,3,.8,fl,"
33                           "sc#cca,"
34                           "afcb6,6,12,1,fl,"
35                           "afcb.4,.4,7,.4,ty8,my,fl,"
36                           "afcb.4,.4,7,.4,tx8,mx,fl");
37
38        m_tail.SendCommand("sc#cca,"
39                           "afcb6,6,10,1,tz-1,fl,"
40                           "afcb.4,.4,8,.4,tz-1,ty8,fl,"
41                           "afcb.4,.4,8,.4,tz-1,ty12,fl,"
42                           "afcb.4,.4,8,.4,tz-1,tx8,fl,"
43                           "afcb.4,.4,8,.4,tz-1,tx12,fl,"
44                           "sc#d91,"
45                           "afcb3,15,3,.8,ty8,fl,"
46                           "afcb15,3,3,.8,tx8,fl");
47
48        m_position = vec3(RandF(0.f, 100.f), 20.f, RandF(150.f, 250.f));
49        m_rotation = quat::rotate(RandF(30.f, 70.f), 0.f, 1.f, 0.f);;
50
51        /* The last node is actually the tail */
52        for (int i = 0; i < nodes; i++)
53            m_nodes.Push(m_rotation.transform(vec3(-12.f, 0.f, 0.f)),
54                         0.f, 100.f, 0.f);
55        m_nodes.Push(vec3(0.f, 0.f, 0.f), 45.f, 100.f, 0.f);
56    }
57
58    ~Snake()
59    {
60        if (m_stick)
61            Input::UntrackStick(m_stick);
62    }
63
64    char const *GetName() { return "<snake>"; }
65
66    vec3 GetBarycenter()
67    {
68        vec3 new_camera_pos = m_position;
69        for (int i = 0; i < m_nodes.Count(); i++)
70            new_camera_pos += m_nodes[i].m1;
71        new_camera_pos /= (float)(m_nodes.Count() + 1);
72
73        return new_camera_pos;
74    }
75
76protected:
77    virtual void TickGame(float seconds)
78    {
79        WorldEntity::TickGame(seconds);
80
81        m_steer += 2.f * seconds;
82
83        /* Destruction test */
84        if (!m_stick)
85            m_stick = Input::TrackStick();
86        bool fire = m_stick && m_stick->GetButtonCount() >= 4
87                            && m_stick->GetButton(12);
88        fire = fire || Input::GetButtonState(305 /* Right Ctrl */);
89        if (fire && (int)m_steer != (int)(m_steer - 2.f * seconds))
90        {
91            int tohit = (int)RandF(m_nodes.Count() - 2);
92            m_nodes[tohit].m4 += 150.f;
93            m_nodes[tohit + 1].m4 += 150.f;
94        }
95
96        float test = sinf(m_steer) * 100.f + 30.f;
97        m_rotation *= quat::rotate(seconds * test, vec3(0, 1, 0));
98
99        m_velocity = 60.f * m_rotation.transform(vec3(0, 0, 1));
100        vec3 deltapos = seconds * m_velocity;
101        m_position += deltapos;
102
103        /* Remove dead nodes */
104        for (int i = m_nodes.Count(); i--; )
105        {
106            if (m_nodes[i].m3 < 0.f)
107            {
108                m_nodes[i + 1].m1 += m_nodes[i].m1;
109                m_nodes.Remove(i);
110            }
111        }
112
113        /* Regrow! FIXME: just a test */
114        if (m_nodes.Count() < 5)
115        {
116            m_nodes.Empty();
117            for (int i = 0; i < 35; i++)
118                m_nodes.Push(m_rotation.transform(vec3(-12.f, 0.f, 0.f)),
119                             0.f, 100.f, 0.f);
120            m_nodes.Push(vec3(0.f, 0.f, 0.f), 45.f, 100.f, 0.f);
121        }
122
123        for (int i = 0; i < m_nodes.Count(); i++)
124        {
125            /* The current node is dragged by the previous one */
126            vec3 new_delta = m_nodes[i].m1 - deltapos;
127            float new_distance = length(new_delta);
128            if (new_distance > 12.f)
129            {
130                new_delta /= new_distance;
131                new_distance = std::max(12.f, new_distance - seconds * 80.f);
132                new_delta *= new_distance;
133            }
134            deltapos = new_delta + deltapos - m_nodes[i].m1;
135            m_nodes[i].m1 = new_delta;
136
137            /* If the current node is not the tail, rotate */
138            if (i != m_nodes.Count() - 1)
139                m_nodes[i].m2 += seconds * ((i & 1) ? 200.f : -200.f);
140
141            /* Apply damage */
142            float damage = std::min(m_nodes[i].m4, 80.f * seconds);
143            m_nodes[i].m3 -= damage;
144            m_nodes[i].m4 -= damage;
145        }
146    }
147
148    virtual void TickDraw(float seconds)
149    {
150        WorldEntity::TickDraw(seconds);
151
152        if (!m_ready)
153        {
154            m_head.SendCommand("irb");
155            m_body.SendCommand("irb");
156            m_tail.SendCommand("irb");
157            m_ready = true;
158        }
159
160        vec3 pos = m_position;
161        quat rot = m_rotation;
162        float y_angle = 0.f;
163        mat4 model = mat4::translate(pos) * mat4(rot);
164        m_head.Render(model);
165
166        for (int i = 0; i < m_nodes.Count(); i++)
167        {
168            pos += m_nodes[i].m1;
169            y_angle = (180.f / M_PI) * atan2(m_nodes[i].m1.x, m_nodes[i].m1.z);
170            rot = quat::rotate(y_angle, 0.f, 1.f, 0.f)
171                * quat::rotate(m_nodes[i].m2, 0.f, 0.f, 1.f);
172            model = mat4::translate(pos) * mat4(rot);
173            if (i != m_nodes.Count() - 1 && m_nodes[i].m4)
174                m_body.Render(model, sin(2.f * m_nodes[i].m3) * .5f + .5f);
175            else if (i != m_nodes.Count() - 1)
176                m_body.Render(model);
177            else
178                m_tail.Render(model);
179        }
180    }
181
182private:
183    Mesh m_head, m_body, m_tail;
184    float m_steer;
185    /* List of nodes (position, self-rotation angle, life, damage) */
186    Array<vec3, float, float, float> m_nodes;
187    /* Test */
188    Stick *m_stick;
189    bool m_ready;
190};
191
192#endif /* __SNAKE_H__ */
193
Note: See TracBrowser for help on using the repository browser.