Implemented zoom in/out with the scroll wheel
The focus of the zooming is the top left of the screen, but that is fine for now.
This commit is contained in:
@@ -86,6 +86,10 @@ void BaseScene::ProcessEvents() {
|
|||||||
MouseButtonUp(event.button);
|
MouseButtonUp(event.button);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SDL_MOUSEWHEEL:
|
||||||
|
MouseWheel(event.wheel);
|
||||||
|
break;
|
||||||
|
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
KeyDown(event.key);
|
KeyDown(event.key);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+32
-8
@@ -65,6 +65,7 @@ void ExampleScene::FrameEnd() {
|
|||||||
|
|
||||||
void ExampleScene::RenderFrame(SDL_Renderer* renderer) {
|
void ExampleScene::RenderFrame(SDL_Renderer* renderer) {
|
||||||
for (std::list<Region>::iterator it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
|
for (std::list<Region>::iterator it = regionPager.GetContainer()->begin(); it != regionPager.GetContainer()->end(); it++) {
|
||||||
|
//NOTE: Graphical scaling is done internally
|
||||||
tileSheet.DrawRegionTo(renderer, &(*it), camera.x, camera.y, camera.scale, camera.scale);
|
tileSheet.DrawRegionTo(renderer, &(*it), camera.x, camera.y, camera.scale, camera.scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,8 +77,8 @@ void ExampleScene::RenderFrame(SDL_Renderer* renderer) {
|
|||||||
void ExampleScene::MouseMotion(SDL_MouseMotionEvent const& event) {
|
void ExampleScene::MouseMotion(SDL_MouseMotionEvent const& event) {
|
||||||
//right mouse button moves the camera
|
//right mouse button moves the camera
|
||||||
if (event.state & SDL_BUTTON_RMASK) {
|
if (event.state & SDL_BUTTON_RMASK) {
|
||||||
camera.x -= event.xrel;
|
camera.x -= event.xrel / camera.scale;
|
||||||
camera.y -= event.yrel;
|
camera.y -= event.yrel / camera.scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,14 +86,15 @@ void ExampleScene::MouseButtonDown(SDL_MouseButtonEvent const& event) {
|
|||||||
switch(event.button) {
|
switch(event.button) {
|
||||||
case SDL_BUTTON_LEFT: {
|
case SDL_BUTTON_LEFT: {
|
||||||
//DOCS: broke this down into several lines for clarity
|
//DOCS: broke this down into several lines for clarity
|
||||||
//these are the "real" click positions, relative to the map (can be scaled)
|
//these are the "real" click positions, relative to the map
|
||||||
int fieldX = event.x + camera.x;
|
//(scaled input is transformed into unscaled tile selection)
|
||||||
int fieldY = event.y + camera.y;
|
int fieldX = event.x / camera.scale + camera.x;
|
||||||
|
int fieldY = event.y / camera.scale + camera.y;
|
||||||
|
|
||||||
//these are the x & y indexes of the selected tile
|
//these are the x & y indexes of the selected tile
|
||||||
//NOTE: the terniary operator is used to circumvent an error with integer devision
|
//NOTE: the terniary operator is used to circumvent an error with integer devision
|
||||||
int tileX = (fieldX >= 0 ? fieldX : fieldX - 32) / 32;
|
int tileX = (fieldX >= 0 ? fieldX : fieldX - tileSheet.GetTileW()) / tileSheet.GetTileW();
|
||||||
int tileY = (fieldY >= 0 ? fieldY : fieldY - 32) / 32;
|
int tileY = (fieldY >= 0 ? fieldY : fieldY - tileSheet.GetTileH()) / tileSheet.GetTileH();
|
||||||
|
|
||||||
//finally, call the method
|
//finally, call the method
|
||||||
regionPager.SetTile(tileX, tileY, layer, selection);
|
regionPager.SetTile(tileX, tileY, layer, selection);
|
||||||
@@ -106,7 +108,29 @@ void ExampleScene::MouseButtonUp(SDL_MouseButtonEvent const& event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ExampleScene::MouseWheel(SDL_MouseWheelEvent const& event) {
|
void ExampleScene::MouseWheel(SDL_MouseWheelEvent const& event) {
|
||||||
//
|
constexpr double scaleMod = 1.2;
|
||||||
|
constexpr double scaleUpperBound = 3.0;
|
||||||
|
constexpr double scaleLowerBound = 0.5;
|
||||||
|
|
||||||
|
//zoom out
|
||||||
|
if (event.y < 0) { //downscroll
|
||||||
|
if (camera.scale / scaleMod <= scaleLowerBound) {
|
||||||
|
camera.scale = scaleLowerBound;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
camera.scale /= scaleMod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//zoom in
|
||||||
|
if (event.y > 0) { //upscroll
|
||||||
|
if (camera.scale * scaleMod >= scaleUpperBound) {
|
||||||
|
camera.scale = scaleUpperBound;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
camera.scale *= scaleMod;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExampleScene::KeyDown(SDL_KeyboardEvent const& event) {
|
void ExampleScene::KeyDown(SDL_KeyboardEvent const& event) {
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ public:
|
|||||||
|
|
||||||
std::bitset<REGION_WIDTH*REGION_HEIGHT>* GetSolidBitset();
|
std::bitset<REGION_WIDTH*REGION_HEIGHT>* GetSolidBitset();
|
||||||
private:
|
private:
|
||||||
|
friend class TileSheet;
|
||||||
|
|
||||||
const int x;
|
const int x;
|
||||||
const int y;
|
const int y;
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
*/
|
*/
|
||||||
#include "tile_sheet.hpp"
|
#include "tile_sheet.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
TileSheet& TileSheet::operator=(TileSheet const& rhs) {
|
TileSheet& TileSheet::operator=(TileSheet const& rhs) {
|
||||||
//don't screw yourself
|
//don't screw yourself
|
||||||
if (this == &rhs) {
|
if (this == &rhs) {
|
||||||
@@ -85,21 +87,37 @@ void TileSheet::DrawLayerTo(SDL_Renderer* const renderer, Region* const region,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TileSheet::DrawRegionTo(SDL_Renderer* const renderer, Region* const region, int camX, int camY, double scaleX, double scaleY) {
|
void TileSheet::DrawRegionTo(SDL_Renderer* const renderer, Region* const region, int camX, int camY, double scaleX, double scaleY) {
|
||||||
//TODO: (2) make TileSheet a friend class of Region
|
//NOTE: TileSheet is a friend class of Region
|
||||||
|
//reimplementing DrawTo() to improve performance (less indirection)
|
||||||
|
if (!texture) {
|
||||||
|
throw(std::logic_error("No image texture to draw"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//the local variables
|
||||||
|
SDL_Rect sclip = {0, 0, clip.w, clip.h};
|
||||||
|
SDL_Rect dclip = {0, 0, Uint16(clip.w * scaleX), Uint16(clip.h * scaleY)};
|
||||||
Region::type_t tile = 0;
|
Region::type_t tile = 0;
|
||||||
|
|
||||||
|
//for each tile
|
||||||
for (register int i = 0; i < REGION_WIDTH; ++i) {
|
for (register int i = 0; i < REGION_WIDTH; ++i) {
|
||||||
for (register int j = 0; j < REGION_HEIGHT; ++j) {
|
for (register int j = 0; j < REGION_HEIGHT; ++j) {
|
||||||
for (register int k = 0; k < REGION_DEPTH; ++k) {
|
for (register int k = 0; k < REGION_DEPTH; ++k) {
|
||||||
tile = region->GetTile(i, j, k);
|
//get the value to skip expensive lookups
|
||||||
|
tile = region->tiles[i][j][k];
|
||||||
|
|
||||||
//0 is invisible
|
//0 is invisible
|
||||||
if (tile == 0) continue;
|
if (tile == 0) continue;
|
||||||
clip.x = (tile-1) % countX * clip.h;
|
|
||||||
clip.y = (tile-1) / countX * clip.w;
|
//set the sclip
|
||||||
//TODO: (2) raw rendering; improve preformance
|
sclip.x = (tile-1) % countX * clip.h;
|
||||||
Image::DrawTo(renderer,
|
sclip.x = (tile-1) / countX * clip.w;
|
||||||
(region->GetX() + i) * clip.w - camX,
|
|
||||||
(region->GetY() + j) * clip.h - camY,
|
//set the dclip
|
||||||
scaleX, scaleY);
|
dclip.x = ((region->x + i) * clip.w - camX) * scaleX;
|
||||||
|
dclip.y = ((region->y + j) * clip.h - camY) * scaleY;
|
||||||
|
|
||||||
|
//draw
|
||||||
|
SDL_RenderCopy(renderer, texture, &sclip, &dclip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user