00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "NPC.hpp"
00019 #include "Enemy.hpp"
00020 #include "MathFuncs.hpp"
00021
00022 #include <cmath>
00023
00024 bool ANPC::init(global_data_pointers Data, strength* tStrength)
00025 {
00026 m_Ship->Init(m_shipfile);
00027 m_Ship->SetPosition(m_posx, m_posy);
00028
00029
00030 desired_distance = m_parameter->des_dist_base + frnd(-m_parameter->des_dist_var, m_parameter->des_dist_var);
00031 desired_center = SCREEN_X_SIZE/2 + frnd(-m_parameter->des_x_var, m_parameter->des_x_var);
00032
00033 m_firedist = tStrength->firedist;
00034
00035 if (tStrength->boni.size() > 0)
00036 {
00037 std::list<bonus*>::iterator IT = tStrength->boni.begin();
00038 while (IT != tStrength->boni.end())
00039 {
00040 for (int i = 0; i < (*IT)->number; i++)
00041 m_Ship->EquipWeapon((*IT)->id);
00042 ++IT;
00043 }
00044 }
00045
00046 return true;
00047 }
00048
00049 ANPC::ANPC(unsigned int starttime, int posx, int posy, Strength theStrength, std::string shipfile, AI_parameter* parameter)
00050 : m_Ship(new CShip()),
00051 m_shipfile(shipfile),
00052 m_posx(posx),
00053 m_posy(posy),
00054 m_strength(theStrength),
00055 m_starttime(starttime),
00056 m_parameter(parameter),
00057 des_x(0),
00058 des_y(0)
00059 {}
00060
00061 void ANPC::update(const std::bitset<SCREEN_X_SIZE - HUD_SIZE_X>& owned)
00062 {
00063 static float last_frame(sgl::get_clock().GetElapsedTime());
00064
00065 float movement =
00066 (sgl::get_clock().GetElapsedTime() - static_cast<float>(last_frame))
00067 * 100;
00068
00069 last_frame = sgl::get_clock().GetElapsedTime();
00070
00071 m_Ship->MoveX(des_x * movement);
00072 m_Ship->MoveY(des_y * movement);
00073
00074 int start, ende;
00075
00076 start = ((m_Ship->GetXPosition() - m_firedist) + m_weapon_offset > 0)
00077 ? ((m_Ship->GetXPosition() - m_firedist) + m_weapon_offset)
00078 : 0;
00079
00080 ende = (m_Ship->GetXPosition() + m_firedist + m_weapon_offset <= SCREEN_X_SIZE - HUD_SIZE_X)
00081 ? (m_Ship->GetXPosition() + m_firedist + m_weapon_offset)
00082 : (SCREEN_X_SIZE - HUD_SIZE_X);
00083
00084 for(; start < ende; start++)
00085 {
00086 if (owned.test(start))
00087 {
00088 m_Ship->Shoot();
00089 break;
00090 }
00091 }
00092 }
00093
00094 void ANPC::calculate(float* fancy, std::list<projectileData>& r_Projectiles, std::list<ANPC*>& r_myEnemys, std::list<ANPC*>& r_myAllys)
00095 {
00096 rest_x++;
00097 rest_y++;
00098
00099 float xseparate[2];
00100 float yseparate[2];
00101
00102 m_weapon_offset = m_Ship->GetProjectileTarget(SCREEN_Y_SIZE/4);
00103
00104 xseparate[0] = 0;
00105 yseparate[0] = 0;
00106 xseparate[1] = 0;
00107 yseparate[1] = 0;
00108
00109 float fancydir[3];
00110
00111 fancydir[0] = 0;
00112 fancydir[1] = 0;
00113 fancydir[2] = 0;
00114
00115
00116 bool skip_Y = !calculate_y(yseparate);
00117 bool skip_X = !calculate_x(fancy, fancydir, r_Projectiles, r_myEnemys);
00118
00119
00120 if (skip_X && skip_Y)
00121 return;
00122
00123 separation(r_myAllys, xseparate, yseparate);
00124
00125 if (!skip_X)
00126 {
00127 fancydir[0] += xseparate[0];
00128 fancydir[2] += xseparate[1];
00129
00130 if ((fancydir[2] > fancydir[1] + 5) && (fancydir[2] > fancydir[0]))
00131 {
00132 steer_x(1);
00133 }
00134 else if (fancydir[0] > fancydir[1] + 5)
00135 {
00136 steer_x(-1);
00137 }
00138 else
00139 {
00140 steer_x(0);
00141 }
00142 }
00143
00144 if(!skip_Y)
00145 {
00146 if (yseparate[0] > 0 && yseparate[0] > yseparate[1])
00147 {
00148 steer_y(1);
00149 }
00150 else if (yseparate[1] > 0)
00151 {
00152 steer_y(-1);
00153 }
00154 else
00155 {
00156 steer_y(0);
00157 }
00158 }
00159 }
00160
00161 void ANPC::separation(std::list<ANPC*>& r_activeEnemys, float* xseparate, float* yseparate)
00162 {
00163 float tmp;
00164 float des_man = m_parameter->des_man / std::sqrt(r_activeEnemys.size());
00165
00166 std::list<ANPC*>::iterator it = r_activeEnemys.begin();
00167
00168 while (it != r_activeEnemys.end())
00169 {
00170 if (*it != this && (tmp = des_man - manhattan(m_Ship->GetXPosition(), m_Ship->GetYPosition(), (*it)->getShip()->GetXPosition(), (*it)->getShip()->GetYPosition()) > 0))
00171 {
00172 int i;
00173 i = sgn(m_Ship->GetXPosition() - (*it)->getShip()->GetXPosition());
00174 xseparate[1] += i * tmp * m_parameter->sep_x_mult;
00175 xseparate[0] += i * tmp * m_parameter->sep_x_mult;
00176 i = sgn(m_Ship->GetYPosition() - (*it)->getShip()->GetYPosition());
00177 yseparate[1] += (i * tmp/des_man) * m_parameter->sep_y_mult;
00178 yseparate[0] += (i * tmp/des_man) * m_parameter->sep_y_mult;
00179 }
00180 it++;
00181 }
00182 }
00183
00184 bool ANPC::calculate_x(float* fancy, float* fancy_dir, std::list<projectileData>& r_Projectiles, std::list<ANPC*>& r_activeEnemys)
00185 {
00186
00187 int left_border = m_Ship->GetXPosition() - m_Ship->GetCollisionSystemWidth()/2;
00188 int right_border = m_Ship->GetXPosition() + m_Ship->GetCollisionSystemWidth()/2;
00189
00190 if (left_border + static_cast<int>(m_Ship->GetCollisionSystemWidth()/3) < 0)
00191 {
00192 des_x = 1;
00193 return false;
00194 }
00195 if (right_border - static_cast<int>(m_Ship->GetCollisionSystemWidth()/3)
00196 > static_cast<int>(SCREEN_X_SIZE - HUD_SIZE_X))
00197 {
00198 des_x = -1;
00199 return false;
00200 }
00201
00202 update_array(fancy, r_Projectiles);
00203
00204 int numbers[3];
00205
00206 numbers[0] = 0;
00207 numbers[1] = 0;
00208 numbers[2] = 0;
00209
00210 number_enemys(numbers, r_activeEnemys);
00211
00212
00213
00214 if (numbers[0] > numbers[1] && numbers[0] > numbers[2])
00215 fancy_dir[0] += m_parameter->player_weight;
00216 else if (numbers[2] > numbers[1])
00217 fancy_dir[2] += m_parameter->player_weight;
00218 else
00219 fancy_dir[1] += m_parameter->player_weight;
00220
00221
00222 fancy_dir[1] += get_fancy(fancy, left_border, right_border);
00223
00224 fancy_dir[0] += get_fancy(fancy, left_border - m_parameter->searchdepth, right_border - m_parameter->searchdepth);
00225
00226 fancy_dir[2] += get_fancy(fancy, left_border + m_parameter->searchdepth, right_border + m_parameter->searchdepth);
00227
00228 return true;
00229 }
00230
00231
00232 void ANPC::update_array(float* fancy, std::list<projectileData>& r_Projectiles)
00233 {
00234 const int randbreite = (m_Ship->GetCollisionSystemWidth()/4)*4;
00235 static const int width = SCREEN_X_SIZE - HUD_SIZE_X;
00236
00237 std::list<projectileData>::iterator tmp = r_Projectiles.begin();
00238 float ftmp;
00239 int i;
00240
00241 for (i = 0; i < width; i++)
00242 {
00243 fancy[i] = 0;
00244 }
00245
00246
00247
00248 while (tmp != r_Projectiles.end())
00249 {
00250
00251 if (tmp->posy > (m_Ship->GetYPosition() - m_Ship->GetCollisionSystemWidth()/2))
00252 {
00253 ftmp = ((tmp->posy - m_Ship->GetYPosition()) < 400) ? (1 / ((tmp->posy - m_Ship->GetYPosition())/m_parameter->dist_divisor) * tmp->damage) : 0;
00254 for (i = (tmp->posx - tmp->width/2) ; i < (tmp->posx + tmp->width/2); i++)
00255 {
00256 if (i >= 0 && i < width)
00257 {
00258
00259 if (fancy[i] >= -ftmp)
00260 fancy[i] = -ftmp;
00261 }
00262 }
00263 }
00264 tmp++;
00265 }
00266
00267 ftmp = 0;
00268 for (i = randbreite; i >= 0; i--)
00269 {
00270 ftmp = fancy[i] += ftmp;
00271 }
00272 ftmp = 0;
00273 for (i = (width - randbreite); i < width; i++)
00274 {
00275 ftmp = fancy[i] += ftmp;
00276 }
00277 }
00278
00279 void ANPC::steer_x(int direction)
00280 {
00281 if(direction == des_x) return;
00282 if(direction == 0)
00283 {
00284 des_x = 0;
00285 return;
00286 }
00287 if (des_x == 0)
00288 {
00289 if (rest_x >= m_parameter->pause)
00290 {
00291 des_x = direction;
00292 }
00293 }
00294 else
00295 {
00296 des_x = 0;
00297 }
00298 }
00299
00300 void ANPC::steer_y(int direction)
00301 {
00302 if(direction == des_y) return;
00303 if(direction == 0)
00304 {
00305 des_y = 0;
00306 return;
00307 }
00308 if (des_y == 0)
00309 {
00310 if (rest_y >= m_parameter->pause)
00311 {
00312 des_y = direction;
00313 }
00314 }
00315 else
00316 {
00317 des_y = 0;
00318 }
00319 }
00320
00321 float ANPC::get_fancy(float* fancy, std::size_t start, std::size_t end)
00322 {
00324 float result = 0;
00325
00326 for (std::size_t i = start; i < end; i++)
00327 {
00328 if (i < 0)
00329 {
00330 result += fancy[0];
00331 }
00332 else if (i >= SCREEN_X_SIZE - HUD_SIZE_X)
00333 {
00334 result += fancy[(SCREEN_X_SIZE - HUD_SIZE_X) - 1];
00335 }
00336 else
00337 {
00338 result += fancy[i];
00339 }
00340 }
00341 return result;
00342 }