00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "camera.h"
00023 #include "map.h"
00024 #include "maps_list.h"
00025 #include "wind.h"
00026 #include "../include/app.h"
00027 #include "../interface/mouse.h"
00028 #include "../team/teams_list.h"
00029 #include "../tool/debug.h"
00030 #include "../tool/rectangle.h"
00031 #include "../tool/math_tools.h"
00032
00033 const Point2i CAMERA_MARGIN(200, 200);
00034 const Point2i CAMERA_SPEED(20, 20);
00035
00036 Camera camera;
00037
00038 Camera::Camera(){
00039 throw_camera = false;
00040 auto_crop = true;
00041 followed_object = NULL;
00042 }
00043
00044 bool Camera::HasFixedX() const{
00045 return (int)world.GetWidth() <= GetSizeX();
00046 }
00047
00048 bool Camera::HasFixedY() const{
00049 return (int)world.GetHeight() <= GetSizeY();
00050 }
00051
00052 Point2i Camera::FreeDegrees() const{
00053 return Point2i(HasFixedX()? 0 : 1,
00054 HasFixedY()? 0 : 1);
00055 }
00056
00057 Point2i Camera::NonFreeDegrees() const{
00058 return Point2i(1, 1) - FreeDegrees();
00059 }
00060
00061 void Camera::SetXYabs(int x, int y){
00062 AppWormux * app = AppWormux::GetInstance();
00063
00064 if( !HasFixedX() )
00065 position.x = BorneLong(x, 0, world.GetWidth() - GetSizeX());
00066 else
00067 position.x = - (app->video.window.GetWidth() - world.GetWidth())/2;
00068
00069 if( !HasFixedY() )
00070 position.y = BorneLong(y, 0, world.GetHeight()-GetSizeY());
00071 else
00072 position.y = - (app->video.window.GetHeight() - world.GetHeight())/2;
00073
00074 throw_camera = true;
00075 }
00076
00077 void Camera::SetXYabs(const Point2i &pos){
00078 SetXYabs(pos.x, pos.y);
00079 }
00080
00081 void Camera::SetXY(Point2i pos){
00082 pos = pos * FreeDegrees();
00083 if( pos.IsNull() )
00084 return;
00085
00086 SetXYabs(position + pos);
00087 }
00088
00089 void Camera::CenterOnFollowedObject(){
00090 CenterOn(*followed_object);
00091 }
00092
00093
00094 void Camera::CenterOn(const PhysicalObj &obj){
00095 if (obj.IsGhost())
00096 return;
00097
00098 MSG_DEBUG( "camera.scroll", "centering on %s", obj.GetName().c_str() );
00099
00100 Point2i pos(0, 0);
00101
00102 pos += FreeDegrees() * obj.GetPosition() - ( GetSize() - obj.GetSize() )/2;
00103 pos += NonFreeDegrees() * ( world.GetSize() - GetSize() )/2;
00104
00105 SetXYabs( pos );
00106 }
00107
00108 void Camera::AutoCrop(){
00109 if( !followed_object || followed_object->IsGhost() )
00110 return;
00111
00112 if( !IsVisible(*followed_object) )
00113 {
00114 MSG_DEBUG("camera.scroll", "The object is not visible.");
00115 CenterOnFollowedObject();
00116 return;
00117 }
00118
00119 if(follow_closely)
00120 {
00121 CenterOn(*followed_object);
00122 return;
00123 }
00124 Point2i pos = followed_object->GetPosition();
00125 Point2i size = followed_object->GetSize();
00126
00127 if( pos.y < 0 )
00128 pos.y = 0;
00129
00130 Point2i dstMax = GetSize()/2 - CAMERA_MARGIN;
00131 Point2i cameraBR = GetSize() + position;
00132 Point2i objectBRmargin = pos + size + CAMERA_MARGIN;
00133 Point2i dst(0, 0);
00134
00135 dst += cameraBR.inf(objectBRmargin) * (objectBRmargin - cameraBR);
00136 dst += (pos - CAMERA_MARGIN).inf(position) * (pos - CAMERA_MARGIN - position);
00137
00138 SetXY( dst * CAMERA_SPEED / dstMax );
00139 }
00140
00141 void Camera::SetAutoCrop(bool crop)
00142 {
00143 auto_crop = crop;
00144 }
00145
00146 bool Camera::IsAutoCrop() const
00147 {
00148 return auto_crop;
00149 }
00150
00151 void Camera::SetCloseFollowing(bool close)
00152 {
00153 follow_closely = close;
00154 }
00155
00156 void Camera::Refresh(){
00157 throw_camera = false;
00158
00159
00160 Mouse::GetInstance()->TestCamera();
00161 if (throw_camera) return;
00162
00163 #ifdef TODO_KEYBOARD // ???
00164
00165 clavier.TestCamera();
00166 if (throw_camera)
00167 return;
00168 #endif
00169
00170 if (auto_crop)
00171 AutoCrop();
00172 }
00173
00174 void Camera::FollowObject(PhysicalObj *obj, bool follow, bool center_on, bool force_center_on_object){
00175 MSG_DEBUG( "camera.tracking", "Following object %s, center_on=%d, follow=%d", obj->GetName().c_str(), center_on, follow);
00176 if ((center_on) && ((followed_object != obj) || !IsVisible(*obj) || force_center_on_object))
00177 {
00178 bool visible = IsVisible(*obj);
00179 CenterOn(*obj);
00180 auto_crop = follow;
00181 if(!visible)
00182 wind.RandomizeParticlesPos();
00183 }
00184 followed_object = obj;
00185 }
00186
00187 void Camera::StopFollowingObj(PhysicalObj* obj){
00188 if(followed_object == obj)
00189 FollowObject((PhysicalObj*)&ActiveCharacter(), true, true, true);
00190 }
00191
00192 bool Camera::IsVisible(const PhysicalObj &obj){
00193 return Intersect( obj.GetRect() );
00194 }
00195