func Bounce(int xdir, int ydir) { var angle = Angle(0, 0, xdir, ydir); var surface = GetSurfaceVector(0, 0); var surface_angle = Angle(0, 0, surface[0], surface[1]); var angle_diff = GetTurnDirection(angle - 180, surface_angle); var new_angle = surface_angle + angle_diff; SetXDir(Sin(new_angle, Speed*10), 100); SetYDir(-Cos(new_angle, Speed*10), 100); }
AIAction PlayerAI::Tick(float _timespan, std::vector<Core*>& /*_allies*/, std::vector<Core*>& _enemies, Core* _self) { if(core_id_ == -1) { core_id_ = _self->GetSectionID(); if(core_id_ != -1) { core_ids_.push_back(core_id_); } else Logger::ErrorOut() << "Player ID of -1 encountered\n"; } if(core_ids_.size() == 1) { Radar::SetPlayerPosition(_self->GetGlobalPosition()); } AIAction action; Uint8* keystates = SDL_GetKeyState(0); int mx, my; int mb = SDL_GetMouseState(&mx, &my); Vector3f point_to_face; Vector3f peer_factor; bool lock_movement = false; bool lock_angle = false; bool look_backwards = false; if(SDL_NumJoysticks()) SDL_JoystickUpdate(); point_to_face = _self->GetGlobalPosition(); std::vector<InputConfig>& binds = bindings[player_id_]; for(std::vector<InputConfig>::iterator it = binds.begin(); it != binds.end(); ++it) { switch(it->type) { case BindingType::MouseAxisBinding: { float axis_value = 0; float ltv_axis_value = 0; switch(it->binding.mouse_axis) { case MouseAxis::MouseX: axis_value = static_cast<float>(mx); ltv_axis_value = ltv_mouse_position_.x; break; case MouseAxis::MouseY: axis_value = static_cast<float>(my); ltv_axis_value = ltv_mouse_position_.y; break; } switch(it->action) { case Action::LookXAxis: point_to_face.x = Camera::Instance().ScreenToWorld(Vector3f(axis_value, 0, 0)).x; peer_factor.x = (axis_value - (Camera::Instance().GetWindowWidth() / 2.0f)) * 2.0f / Camera::Instance().GetWindowWidth(); break; case Action::LookYAxis: point_to_face.y = Camera::Instance().ScreenToWorld(Vector3f(0, axis_value, 0)).y; peer_factor.y = -(axis_value - (Camera::Instance().GetWindowHeight() / 2.0f)) * 2.0f / Camera::Instance().GetWindowHeight(); break; case Action::XMovement: movement_integrator_.x *= (1.0f - 0.2f * _timespan); movement_integrator_.x += axis_value - ltv_axis_value; action.dx_ += movement_integrator_.x / (fabs(movement_integrator_.x) > 1.0f ? fabs(movement_integrator_.x) : 1.0f); break; case Action::YMovement: movement_integrator_.y *= (1.0f - 0.2f * _timespan); movement_integrator_.y += axis_value - ltv_axis_value; action.dx_ += movement_integrator_.y / (fabs(movement_integrator_.y) > 1.0f ? fabs(movement_integrator_.y) : 1.0f); break; } } break; case BindingType::JoystickAxisBinding: { float axis_value = 0; if(it->binding.joystick_axis.joystick) { Sint16 js_axis_val = SDL_JoystickGetAxis(it->binding.joystick_axis.joystick, it->binding.joystick_axis.axis_index); if(abs(js_axis_val) < MAXSHORT * 0.2f) js_axis_val = 0; axis_value = (float)js_axis_val / (float)MAXSHORT; } switch(it->action) { case Action::LookXAxis: point_to_face.x += axis_value; peer_factor.x = axis_value; break; case Action::LookYAxis: point_to_face.y -= axis_value; peer_factor.y = -axis_value; break; case Action::XMovement: action.dx_ += axis_value; break; case Action::YMovement: action.dy_ -= axis_value; break; } break; } case BindingType::KeyboardBinding: case BindingType::MouseButtonBinding: case BindingType::JoystickButtonBinding: if((it->type == BindingType::KeyboardBinding && keystates[it->binding.key]) || (it->type == BindingType::MouseButtonBinding && (mb & SDL_BUTTON(GetSDLCode(it->binding.mouse_button)))) || (it->type == BindingType::JoystickButtonBinding && it->binding.joystick_button.joystick && SDL_JoystickGetButton(it->binding.joystick_button.joystick, it->binding.joystick_button.button_index))) { switch(it->action) { case Action::Fire: action.firing_ = true; break; case Action::Boost: action.thrust_ = true; break; case Action::Target: break; case Action::MoveLeft: action.dx_--; break; case Action::MoveRight: action.dx_++; break; case Action::MoveUp: action.dy_++; break; case Action::MoveDown: action.dy_--; break; case Action::LockMovement: lock_movement = true; break; case Action::LockAngle: lock_angle = true; break; case Action::LookBackwards: look_backwards = true; break; } } break; } } if(look_backwards) { point_to_face *= -1; } if(lock_angle_) { point_to_face = lock_vector_ + _self->GetGlobalPosition();//+ _self->GetAngle(); } Vector3f point_to_face_relative = point_to_face - _self->GetGlobalPosition(); if(point_to_face_relative.lengthSq()!=0) { TurnData turn_data = GetTurnDirection(_self->GetAngle(), point_to_face_relative); float dotprod = turn_data.turn_factor; action.dtheta_ = ClampTurnDirection(dotprod, 0.4f); if(peer_factor.lengthSq() > 1) peer_factor.normalize(); Vector3f camera_centre = _self->GetGlobalPosition(); Camera::Instance().SetCentreTarget(camera_centre.x, camera_centre.y, peer_factor.x, peer_factor.y, CameraLevel::Human); Camera::Instance().SetFocus(_self->GetPosition().x, _self->GetPosition().y, CameraLevel::Human); } else { Camera::Instance().SetCentreTarget(_self->GetPosition().x, _self->GetPosition().y, 0, 0, CameraLevel::Human); Camera::Instance().SetFocus(_self->GetPosition().x, _self->GetPosition().y, CameraLevel::Human); } ltv_mouse_position_.x = static_cast<float>(mx); ltv_mouse_position_.y = static_cast<float>(my); if(lock_movement) { action.dx_ = 0; action.dy_ = 0; } if(lock_angle && !lock_angle_) { lock_vector_ = Vector3f(sinf(_self->GetAngle() * M_PI / 180.0f), cosf(_self->GetAngle() * M_PI / 180.0f), 0); } lock_angle_ = lock_angle; return action; }
void ThrusterTrail::Tick(float _timespan, Matrix4f _transform, std::vector<Decoration_ptr>& _decoration_spawn) { Decoration::Tick(_timespan, _transform, _decoration_spawn); if(source_!=NULL && _timespan > 0) { //Get updated position and angle for the root segment, Speed is calculated purely by change in position Vector3f np = source_->GetTransform() * offset_; Vector3f dp = np - ltv_source_position_; float angle = source_->GetGlobalAngle() + angular_offset_; //if(!angular_corrected_) //angle += angular_offset_; Vector3f forward = Vector3f(sin(angle * M_PI / 180.0f), cos(angle * M_PI / 180.0f), 0); float speed = dp.length() / _timespan; float target_length = speed * 0.02f * length_scale_; if(dp.lengthSq() > 0.0f) { //Calculate the dot product of section movement with section angle. This is used to turn the plume towards the back of the segment dp.normalize(); float alignment_scale = dp.dotProduct(forward); /* k(x+1)^2 + P = y. Fit points (-1,P) and (1, 1) -> k = (1-P)/4 valid for -1 to 1.*/ alignment_scale = ((alignment_scale+1) * (alignment_scale+1) * (1.0f - antiparallel_factor_) / 4.0f) + antiparallel_factor_; target_length *= alignment_scale; if(angular_corrected_) { TurnData td = GetTurnDirection(angle, dp); angle += td.turn_factor * 30; } } //Calculate the weighting to give the new calculated length, so that length changes smoothly regardless of framerate. float new_weight = 1.0f - expf(-_timespan * 7.0f); float rotation_rate = (400 + speed) * 1; if(section_length_ < 0) section_length_ = 0; section_length_ = (1.0f - new_weight) * section_length_ + new_weight * target_length; float section_length_sqr = sqrt(section_length_); //Calculate worldspace coordinates of plume polygons points_[0] = angle; cartesian_points_[0] = np; for(int i = 1; i < points_.size(); i++) { TurnData td = GetTurnDirection(points_[i], points_[i-1]); cartesian_points_[i] = cartesian_points_[i-1] + Vector3f(-sin(points_[i] * M_PI / 180.0f), -cos(points_[i] * M_PI / 180.0f), 0) * section_length_; points_[i] = points_[i] + td.turn_factor * _timespan * rotation_rate; Vector3f perp = cartesian_points_[i] - cartesian_points_[i-1]; perp.z = perp.x; perp.x = -perp.y; perp.y = perp.z; perp.z = 0; if(perp.lengthSq() > 0) perp.normalize(); perp *= (1.0f + 3.0f * section_length_sqr * sin(((float)i / (float)points_.size()) * M_PI)); perp *= width_scale_; int base = (i - 2) * 6 + 3; if(i==1) { fill_points_[0] = cartesian_points_[0]; fill_points_[1] = cartesian_points_[1] + perp; fill_points_[2] = cartesian_points_[1] - perp; } else if(i < points_.size() - 1) { fill_points_[base + 0] = fill_points_[base - 1]; fill_points_[base + 1] = fill_points_[base - 2]; fill_points_[base + 2] = cartesian_points_[i] + perp; fill_points_[base + 3] = fill_points_[base - 1]; fill_points_[base + 4] = cartesian_points_[i] + perp; fill_points_[base + 5] = cartesian_points_[i] - perp; } else { cartesian_points_[i] = cartesian_points_[i-1] + Vector3f(-sin(points_[i] * M_PI / 180.0f), -cos(points_[i] * M_PI / 180.0f), 0) * section_length_ * 2; fill_points_[base + 0] = fill_points_[base - 1]; fill_points_[base + 1] = fill_points_[base - 2]; fill_points_[base + 2] = cartesian_points_[i]; } } lifetime_ = 1.0f; // should live as long as source exists ltv_source_position_ = source_->GetGlobalPosition(); const float minimum_length = 0.4f; const float fade_length = 1.0f; if(section_length_ < minimum_length) { fill_.GetFillColor().a = 0; } else if(section_length_ < fade_length + minimum_length) { float alpha = 255.0f * ((section_length_ - minimum_length) / fade_length) ; fill_.GetFillColor().a = alpha; } else { fill_.GetFillColor().a = 255; } } else { fill_.GetFillColor().a = 255.0f * lifetime_; } }
AIAction SimpleAI::Tick(float _timespan, std::vector<Core_ptr>& /*_allies*/, std::vector<Core_ptr>& _enemies, Core_ptr _self) { AIAction a = AIAction(0, 0, 0, false, false); sum_time_ += _timespan; focus_time_ += _timespan; strafe_time_ += _timespan; if(strafe_time_ > SimpleAIStrafeTime) { strafe_time_ = 0; if(Random::RandomChance(0.4f)) strafe_clockwise_ = !strafe_clockwise_; if(Random::RandomChance(0.8f)) preferred_minimum_range_ = SimpleAIMinimumRange * 1.5f; else preferred_minimum_range_ = SimpleAIMinimumRange * 1.0f; } if(focus_time_ > max_focus_time_ || target_ == NULL) { focus_time_ = 0; //Pick a new target if(_enemies.size() > 0) { if(target_ != NULL) target_->RemoveSubscriber(this); int index = Random::RandomIndex(static_cast<int>(_enemies.size())); target_ = _enemies[index]; target_->AddSubscriber(this); } } if(target_ != NULL) { Vector3f relative_position = (target_->GetPosition() - _self->GetPosition()); float range = relative_position.length(); float angle = atan2f(relative_position.x, relative_position.y); if(relative_position.lengthSq() > 0) relative_position.normalize(); if(range > preferred_minimum_range_ * 2) //Close on target { a.dx_ = sinf(angle); a.dy_ = cosf(angle); }else if(range < preferred_minimum_range_) //Back off target { a.dx_ = -sinf(angle); a.dy_ = -cosf(angle); } else //Circle strafe { //Add sideways movement if(strafe_clockwise_) { a.dx_ = -cosf(angle) * 0.2f; a.dy_ = sinf(angle) * 0.2f; } else { a.dx_ = cosf(angle) * 0.2f; a.dy_ = -sinf(angle) * 0.2f; } //Reduce range movement float movement_in_range_dimension; Vector3f self_velocity = _self->GetVelocity(); if(self_velocity.lengthSq() > 0) { self_velocity.normalize(); movement_in_range_dimension = self_velocity.dotProduct(relative_position); a.dx_ -= 0.8f * sinf(angle) * movement_in_range_dimension; a.dy_ -= 0.8f * cosf(angle) * movement_in_range_dimension; } } TurnData td = GetTurnDirection(_self->GetAngle(), relative_position); td.turn_factor = ClampTurnDirection(td.turn_factor, 0.1f); //td.turn_factor *= 0.2f; a.dtheta_ = td.turn_factor; a.firing_ = true; a.target_ = target_; } return a; }