1 //  SuperTuxKart - a fun racing game with go-kart
2 //
3 //  Copyright (C) 2012-2015  SuperTuxKart-Team
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 #include "graphics/stars.hpp"
20 
21 #include "graphics/irr_driver.hpp"
22 #include "karts/abstract_kart.hpp"
23 #include "karts/kart_model.hpp"
24 #include "utils/constants.hpp"
25 
26 #include <ISceneNode.h>
27 #include <IBillboardSceneNode.h>
28 
29 #include <cmath>
30 
31 const int STAR_AMOUNT = 7;
32 const float RADIUS = 0.7f;
33 const float STAR_SIZE = 0.4f;
34 
Stars(AbstractKart * kart)35 Stars::Stars(AbstractKart *kart)
36 {
37     m_parent_kart_node = kart->getNode();
38     m_enabled = false;
39     m_center = core::vector3df(0.0f,
40                                kart->getKartModel()->getModel()
41                                    ->getBoundingBox().MaxEdge.Y,
42                                0.0f                             );
43 
44     for (int n=0; n<STAR_AMOUNT; n++)
45     {
46         scene::ISceneNode* billboard =
47             irr_driver->addBillboard(core::dimension2df(STAR_SIZE, STAR_SIZE),
48                                      "starparticle.png", kart->getNode());
49 #ifdef DEBUG
50         billboard->setName("star");
51 #endif
52 
53         billboard->setVisible(false);
54 
55         m_nodes.push_back(billboard);
56     }
57 }   // Stars
58 
59 // ----------------------------------------------------------------------------
60 
~Stars()61 Stars::~Stars()
62 {
63     const int nodeAmount = (int) m_nodes.size();
64     for (int n=0; n<nodeAmount; n++)
65     {
66         m_parent_kart_node->removeChild(m_nodes[n]);
67     }
68 }   // ~Stars
69 
70 // ----------------------------------------------------------------------------
71 
showFor(float time)72 void Stars::showFor(float time)
73 {
74     m_enabled        = true;
75     m_remaining_time = time;
76     m_fade_in_time   = 1.0f;
77 
78     const int node_amount = (int)m_nodes.size();
79     for (int n=0; n<node_amount; n++)
80     {
81         m_nodes[n]->setVisible(true);
82         ((scene::IBillboardSceneNode*)m_nodes[n])
83                ->setSize( core::dimension2df(0.01f, 0.01f) );
84     }
85 
86     // set stars initial position
87     update(0);
88 }   // showFor
89 
90 // ----------------------------------------------------------------------------
91 /** Resets the stars, esp. disabling them at a restart.
92  */
reset()93 void Stars::reset()
94 {
95     // This will make the stars invisible and disable them
96     m_remaining_time = -1;
97 }   // reset
98 
99 // ----------------------------------------------------------------------------
100 
update(float delta_t)101 void Stars::update(float delta_t)
102 {
103     if (!m_enabled) return;
104 
105     m_remaining_time -= delta_t;
106     if (m_remaining_time < 0)
107     {
108         m_enabled = false;
109 
110         const int node_amount = (int)m_nodes.size();
111         for (int n=0; n<node_amount; n++)
112         {
113             m_nodes[n]->setVisible(false);
114         }
115         return;
116     }
117 
118     const int node_amount = (int)m_nodes.size();
119     for (int n=0; n<node_amount; n++)
120     {
121         // do one full rotation every 4 seconds (this "ranges" ranges
122         // from 0 to 1)
123         float angle = (m_remaining_time / 4.0f) - (int)(m_remaining_time / 4);
124 
125         // each star must be at a different angle
126         angle += n * (1.0f / STAR_AMOUNT);
127 
128         // keep angle in range [0, 1[
129         angle -= (int)angle;
130 
131         float radius = RADIUS;
132 
133 
134         // manage "fade-in"
135         if (m_fade_in_time > 0.0f)
136         {
137             float fade = (1.0f - m_fade_in_time);
138 
139             ((scene::IBillboardSceneNode*)m_nodes[n])->setSize(
140                     core::dimension2d< f32 >(fade*STAR_SIZE, fade*STAR_SIZE) );
141 
142             radius *= fade;
143         }
144         // manage "fade-out"
145         else if (m_remaining_time < 1.0f)
146         {
147             radius *= m_remaining_time;
148 
149             ((scene::IBillboardSceneNode*)m_nodes[n])
150                 ->setSize( core::dimension2df(m_remaining_time*STAR_SIZE,
151                                               m_remaining_time*STAR_SIZE) );
152         }
153 
154         // Set position: X and Z are the position in the cirlce,
155         // the Y components shakes the stars up and down like falling coin
156         core::vector3df offset(std::cos(angle*M_PI*2.0f)*radius,
157                                std::cos(angle*M_PI*2.0f+m_remaining_time*4.0f)
158                                *radius*0.25f,
159                                std::sin(angle*M_PI*2.0f)*radius              );
160         m_nodes[n]->setPosition(m_center + offset);
161     } // end for
162 
163     if (m_fade_in_time > 0.0f) m_fade_in_time -= delta_t;
164 }   // update
165 
166