1+ /*
2+ Example file for olcUTIL_Camera2D.h
3+
4+ License (OLC-3)
5+ ~~~~~~~~~~~~~~~
6+
7+ Copyright 2018 - 2022 OneLoneCoder.com
8+
9+ Redistribution and use in source and binary forms, with or without
10+ modification, are permitted provided that the following conditions
11+ are met:
12+
13+ 1. Redistributions or derivations of source code must retain the above
14+ copyright notice, this list of conditions and the following disclaimer.
15+
16+ 2. Redistributions or derivative works in binary form must reproduce
17+ the above copyright notice. This list of conditions and the following
18+ disclaimer must be reproduced in the documentation and/or other
19+ materials provided with the distribution.
20+
21+ 3. Neither the name of the copyright holder nor the names of its
22+ contributors may be used to endorse or promote products derived
23+ from this software without specific prior written permission.
24+
25+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36+
37+ Links
38+ ~~~~~
39+ YouTube: https://www.youtube.com/javidx9
40+ Discord: https://discord.gg/WhwHUMV
41+ Twitter: https://www.twitter.com/javidx9
42+ Twitch: https://www.twitch.tv/javidx9
43+ GitHub: https://www.github.com/onelonecoder
44+ Homepage: https://www.onelonecoder.com
45+
46+ Author
47+ ~~~~~~
48+ David Barr, aka javidx9, ©OneLoneCoder 2019, 2020, 2021, 2022
49+
50+ */
51+
52+ #define OLC_PGE_APPLICATION
53+ #include " olcPixelGameEngine.h"
54+
55+ #define OLC_PGEX_TRANSFORMEDVIEW
56+ #include " extensions/olcPGEX_TransformedView.h"
57+
58+ #include " utilities/olcUTIL_Camera2D.h"
59+
60+ /*
61+ To demonstrate the camera, we need a world. In this case its a simle tile
62+ world of 80x75 tiles, and each tile is 32x32 screen pixels.
63+
64+ A transformed view is used to navigate the world manually via the middle
65+ mouse button in "free roam" mode, or controlled by the camera.
66+
67+ Specifically a Tile Transformed View is used, which means all units for
68+ drawing and for the camera are specified in tile space, i.e. 1 tile is
69+ 1x1 units (regardless of pixel size)
70+
71+ No assets are used for this application, so the world is constructed
72+ out of coloured squares so you can see you are moving through it.
73+
74+ Pressing "TAB" key will swap between "free roam" and "play" modes. In
75+ free roam mode, you can use middle mouse button to pan and zoom around
76+ the world. The camera's visible area to the player is highlighted in red.
77+ In play mode, the camera behaves as it would in a 2D game, depending upon
78+ the selected mode.
79+ */
80+
81+ class TEST_Camera2D : public olc ::PixelGameEngine
82+ {
83+ public:
84+ TEST_Camera2D ()
85+ {
86+ sAppName = " Camera2D Utility Test" ;
87+ }
88+
89+ // Transformed view object to make world offsetting simple
90+ olc::TileTransformedView tv;
91+
92+ // Conveninet constants to define tile map world
93+ olc::vi2d m_vWorldSize = { 80 , 75 };
94+ olc::vi2d m_vTileSize = { 32 , 32 };
95+
96+ // The camera!
97+ olc::utils::Camera2D camera;
98+
99+ // The point that represents the player, it is "tracked"
100+ // by the camera
101+ olc::vf2d vTrackedPoint;
102+
103+ // Flag whether we are in "free roam" or "play" mode
104+ bool bFreeRoam = false ;
105+
106+ // The world map, stored as a 1D array
107+ std::vector<uint8_t > vWorldMap;
108+
109+ public:
110+ bool OnUserCreate () override
111+ {
112+ // Construct transform view
113+ tv = olc::TileTransformedView (GetScreenSize (), m_vTileSize);
114+
115+ // Construct Camera
116+ vTrackedPoint = { 20 .0f , 20 .0f };
117+ camera = olc::utils::Camera2D (GetScreenSize () / m_vTileSize, vTrackedPoint);
118+
119+ // Configure Camera
120+ camera.SetTarget (vTrackedPoint);
121+ camera.SetMode (olc::utils::Camera2D::Mode::Simple);
122+ camera.SetWorldBoundary ({ 0 .0f , 0 .0f }, m_vWorldSize);
123+ camera.EnableWorldBoundary (true );
124+
125+ // Create "tile map" world with just two tiles
126+ vWorldMap.resize (m_vWorldSize.x * m_vWorldSize.y );
127+ for (int i = 0 ; i < vWorldMap.size (); i++)
128+ vWorldMap[i] = ((rand () % 20 ) == 1 ) ? 1 : 0 ;
129+
130+ // Set background colour
131+ Clear (olc::CYAN );
132+ return true ;
133+ }
134+
135+ bool OnUserUpdate (float fElapsedTime ) override
136+ {
137+ // In free roam, middle mouse button pans & zooms
138+ if (bFreeRoam)
139+ tv.HandlePanAndZoom ();
140+
141+ // Handle player "physics" in response to key presses
142+ olc::vf2d vVel = { 0 .0f , 0 .0f };
143+ if (GetKey (olc::Key::W).bHeld ) vVel += {0 , -1 };
144+ if (GetKey (olc::Key::S).bHeld ) vVel += {0 , +1 };
145+ if (GetKey (olc::Key::A).bHeld ) vVel += {-1 , 0 };
146+ if (GetKey (olc::Key::D).bHeld ) vVel += {+1 , 0 };
147+ vTrackedPoint += vVel * 8 .0f * fElapsedTime ;
148+
149+ // Switch between "free roam" and "play" mode with TAB key
150+ if (GetKey (olc::Key::TAB ).bPressed )
151+ {
152+ // Always setup camera to play mode when tab key pressed
153+ tv.SetWorldOffset (camera.GetViewPosition ());
154+ tv.SetWorldScale (m_vTileSize);
155+ bFreeRoam = !bFreeRoam;
156+ }
157+
158+ // Switch camera mode in operation
159+ if (GetKey (olc::Key::K1 ).bPressed )
160+ camera.SetMode (olc::utils::Camera2D::Mode::Simple);
161+ if (GetKey (olc::Key::K2 ).bPressed )
162+ camera.SetMode (olc::utils::Camera2D::Mode::EdgeMove);
163+ if (GetKey (olc::Key::K3 ).bPressed )
164+ camera.SetMode (olc::utils::Camera2D::Mode::LazyFollow);
165+ if (GetKey (olc::Key::K4 ).bPressed )
166+ camera.SetMode (olc::utils::Camera2D::Mode::FixedScreens);
167+
168+ // Update the camera, if teh tracked object remains visible,
169+ // true is returned
170+ bool bOnScreen = camera.Update (fElapsedTime );
171+
172+ // In "play" mode, set the transformed view to that required by
173+ // the camera
174+ if (!bFreeRoam)
175+ tv.SetWorldOffset (camera.GetViewPosition ());
176+
177+ // Render "tile map", by getting visible tiles
178+ olc::vi2d vTileTL = tv.GetTopLeftTile ().max ({ 0 ,0 });
179+ olc::vi2d vTileBR = tv.GetBottomRightTile ().min (m_vWorldSize);
180+ olc::vi2d vTile;
181+ // Then looping through them and drawing them
182+ for (vTile.y = vTileTL.y ; vTile.y < vTileBR.y ; vTile.y ++)
183+ for (vTile.x = vTileTL.x ; vTile.x < vTileBR.x ; vTile.x ++)
184+ {
185+ int idx = vTile.y * m_vWorldSize.x + vTile.x ;
186+
187+ if (vWorldMap[idx] == 0 )
188+ tv.FillRectDecal (vTile, { 1 .0f , 1 .0f }, olc::Pixel (40 , 40 , 40 ));
189+
190+ if (vWorldMap[idx] == 1 )
191+ tv.FillRectDecal (vTile, { 1 .0f , 1 .0f }, olc::Pixel (60 , 60 , 60 ));
192+ }
193+
194+ // Draw the "player" as a 1x1 cell
195+ tv.FillRectDecal (vTrackedPoint - olc::vf2d (0 .5f , 0 .5f ), {1 .0f , 1 .0f }, olc::BLUE );
196+
197+ // Overlay with information
198+ if (bFreeRoam)
199+ {
200+ tv.FillRectDecal (camera.GetViewPosition (), camera.GetViewSize (), olc::PixelF (1 .0f , 0 .0f , 0 .0f , 0 .5f ));
201+ DrawStringPropDecal ({ 2 , 2 }, " TAB: Free Mode, M-Btn to Pan & Zoom" , olc::YELLOW );
202+ }
203+ else
204+ DrawStringPropDecal ({ 2 ,2 }, " TAB: Play Mode" , olc::YELLOW );
205+
206+ DrawStringPropDecal ({ 2 ,12 }, " WASD : Move" , olc::YELLOW );
207+ DrawStringPropDecal ({ 2 ,22 }, " CAMERA: 1) Simple 2) EdgeMove 3) LazyFollow 4) Screens" , olc::YELLOW );
208+ DrawStringPropDecal ({ 2 ,42 }, vTrackedPoint.str (), olc::YELLOW );
209+ return true ;
210+ }
211+ };
212+
213+ int main ()
214+ {
215+ TEST_Camera2D demo;
216+ if (demo.Construct (512 , 480 , 2 , 2 ))
217+ demo.Start ();
218+ return 0 ;
219+ }
0 commit comments