source: trunk/orbital/snake.h @ 1510

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

easymesh: move the Mesh builder into the engine core.

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.Compile("sc#d91"
23                           "[afcb30 3 3 .8]"
24                           "sc#cca"
25                           "[afcb10 10 10 1]"
26                           "[afcb.4 .4 12 .4 tz3 tx8 mx]"
27                           "[afcb.4 .4 12 .4 tz3 tx12 mx]"
28                           "sc#69c9"
29                           "[afcb5 8 8 1 ty3 tz3]");
30
31        m_body.Compile("sc#d91"
32                           "[afcb3 20 3 .8 afcb20 3 3 .8]"
33                           "sc#cca"
34                           "[afcb6 6 12 1]"
35                           "[afcb.4 .4 7 .4 ty8 my]"
36                           "[afcb.4 .4 7 .4 tx8 mx]");
37
38        m_tail.Compile("sc#cca"
39                           "[afcb6 6 10 1 tz-1]"
40                           "[afcb.4 .4 8 .4 tz-1 ty8]"
41                           "[afcb.4 .4 8 .4 tz-1 ty12]"
42                           "[afcb.4 .4 8 .4 tz-1 tx8]"
43                           "[afcb.4 .4 8 .4 tz-1 tx12]"
44                           "sc#d91"
45                           "[afcb3 15 3 .8 ty8]"
46                           "[afcb15 3 3 .8 tx8]");
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 += 4.f * seconds;
82
83        /* Destruction test */
84        if (!m_stick)
85            m_stick = Input::TrackStick();
86        bool fire = m_stick && m_stick->GetButtonCount() >= 12
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((float)m_nodes.Count() - 2.0f);
92            m_nodes[tohit].m4 += 150.f;
93            m_nodes[tohit + 1].m4 += 150.f;
94        }
95
96        float test = sinf(m_steer) * 200.f + 60.f;
97        m_rotation *= quat::rotate(seconds * test, vec3(0, 1, 0));
98
99        m_velocity = 120.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 = (float)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 * 160.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.MeshConvert();
155            m_body.MeshConvert();
156            m_tail.MeshConvert();
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 / (float)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    EasyMesh 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.