Browse Source

Perfectly align all resolutions

pull/872/head
Anders Jenbo 6 years ago
parent
commit
32778cdbb9
  1. 3
      CMakeLists.txt
  2. 32
      Source/cursor.cpp
  3. 2
      Source/diablo.cpp
  4. 84
      Source/scrollrt.cpp
  5. 6
      Source/scrollrt.h
  6. 161
      SourceT/scrollrt_test.cpp

3
CMakeLists.txt

@ -338,7 +338,8 @@ if(RUN_TESTS)
SourceT/drlg_l3_test.cpp
SourceT/drlg_l4_test.cpp
SourceT/effects_test.cpp
SourceT/file_util_test.cpp)
SourceT/file_util_test.cpp
SourceT/scrollrt_test.cpp)
endif()
add_executable(${BIN_TARGET} WIN32 MACOSX_BUNDLE ${devilutionx_SRCS})

32
Source/cursor.cpp

@ -244,26 +244,32 @@ void CheckCursMove()
sy -= fy;
}
// Convert to tile grid
mx = ViewX;
my = ViewY;
TilesInView(&columns, &rows);
int lrow = rows - RowsCoveredByPanel();
// When both columns and rows are even or odd vertical alignment must be done using a screen offset
if (zoomflag && (columns & 1) == (rows & 1)) {
sy -= TILE_HEIGHT / 2;
// Center player tile on screen
ShiftGrid(&mx, &my, -columns / 2, -lrow / 2);
// Align grid
if ((columns & 1) == 0 && (lrow & 1) == 0) {
sy += TILE_HEIGHT / 2;
} else if (columns & 1 && lrow & 1) {
sx -= TILE_WIDTH / 2;
} else if (columns & 1 && (lrow & 1) == 0) {
my++;
}
if (!zoomflag) {
sy -= TILE_HEIGHT / 4;
}
// Convert to tile grid
mx = ViewX;
my = ViewY;
tx = sx / TILE_WIDTH;
ty = sy / TILE_HEIGHT;
ShiftGrid(&mx, &my, tx, ty);
// Shift player row to one that can be centered with out pixel offset
if ((columns & 1) != 0) {
my++;
}
// Center player tile on screen
ShiftGrid(&mx, &my, -columns / 2, -(rows - RowsCoveredByPanel()) / 4);
// Shift position to match diamond grid aligment
px = sx % TILE_WIDTH;

2
Source/diablo.cpp

@ -237,6 +237,7 @@ void run_game_loop(unsigned int uMsg)
void start_game(unsigned int uMsg)
{
zoomflag = TRUE;
CalcViewportGeometry();
cineflag = FALSE;
InitCursor();
InitLightTable();
@ -1179,6 +1180,7 @@ void PressChar(int vkey)
case 'Z':
case 'z':
zoomflag = !zoomflag;
CalcViewportGeometry();
return;
case 'S':
case 's':

84
Source/scrollrt.cpp

@ -930,7 +930,7 @@ int RowsCoveredByPanel()
return 0;
}
int rows = PANEL_HEIGHT / TILE_HEIGHT * 2;
int rows = PANEL_HEIGHT / TILE_HEIGHT;
if (!zoomflag) {
rows /= 2;
}
@ -952,7 +952,7 @@ void CalcTileOffset(int *offsetX, int *offsetY)
y = VIEWPORT_HEIGHT % TILE_HEIGHT;
} else {
x = (SCREEN_WIDTH / 2) % TILE_WIDTH;
y = (VIEWPORT_HEIGHT / 2 + TILE_HEIGHT / 2) % TILE_HEIGHT;
y = (VIEWPORT_HEIGHT / 2) % TILE_HEIGHT;
}
if (x)
@ -975,8 +975,8 @@ void TilesInView(int *rcolumns, int *rrows)
if (SCREEN_WIDTH % TILE_WIDTH) {
columns++;
}
int rows = VIEWPORT_HEIGHT / (TILE_HEIGHT / 2);
if (VIEWPORT_HEIGHT % (TILE_HEIGHT / 2)) {
int rows = VIEWPORT_HEIGHT / TILE_HEIGHT;
if (VIEWPORT_HEIGHT % TILE_HEIGHT) {
rows++;
}
@ -991,12 +991,62 @@ void TilesInView(int *rcolumns, int *rrows)
}
rows /= 2;
}
rows++; // Cover lower edge saw tooth, right edge accounted for in scrollrt_draw()
*rcolumns = columns;
*rrows = rows;
}
int tileOffsetX;
int tileOffsetY;
int tileShiftX;
int tileShiftY;
int tileColums;
int tileRows;
void CalcViewportGeometry()
{
int xo, yo;
tileShiftX = 0;
tileShiftY = 0;
// Adjust by player offset and tile grid alignment
CalcTileOffset(&xo, &yo);
tileOffsetX = 0 - xo;
tileOffsetY = 0 - yo - 1 + TILE_HEIGHT / 2;
TilesInView(&tileColums, &tileRows);
int lrow = tileRows - RowsCoveredByPanel();
// Center player tile on screen
ShiftGrid(&tileShiftX, &tileShiftY, -tileColums / 2, -lrow / 2);
tileRows *= 2;
// Align grid
if ((tileColums & 1) == 0) {
tileShiftY--; // Shift player row to one that can be centered with out pixel offset
if ((lrow & 1) == 0) {
// Offset tile to vertically align the player when both rows and colums are even
tileRows++;
tileOffsetY -= TILE_HEIGHT / 2;
}
} else if (tileColums & 1 && lrow & 1) {
// Offset tile to vertically align the player when both rows and colums are odd
ShiftGrid(&tileShiftX, &tileShiftY, 0, -1);
tileRows++;
tileOffsetY -= TILE_HEIGHT / 2;
}
// Slightly lower the zoomed view
if (!zoomflag) {
tileOffsetY += TILE_HEIGHT / 4;
if (yo < TILE_HEIGHT / 4)
tileRows++;
}
tileRows++; // Cover lower edge saw tooth, right edge accounted for in scrollrt_draw()
}
/**
* @brief Configure render and process screen rows
* @param x Center of view in dPiece coordinate
@ -1004,7 +1054,7 @@ void TilesInView(int *rcolumns, int *rrows)
*/
static void DrawGame(int x, int y)
{
int i, sx, sy, columns, rows, xo, yo;
int sx, sy, columns, rows;
// Limit rendering to the view area
if (zoomflag)
@ -1013,24 +1063,14 @@ static void DrawGame(int x, int y)
gpBufEnd = &gpBuffer[BUFFER_WIDTH * (VIEWPORT_HEIGHT / 2 + SCREEN_Y)];
// Adjust by player offset and tile grid alignment
CalcTileOffset(&xo, &yo);
sx = ScrollInfo._sxoff - xo + SCREEN_X;
sy = ScrollInfo._syoff - yo + SCREEN_Y + (TILE_HEIGHT / 2 - 1);
sx = ScrollInfo._sxoff + tileOffsetX + SCREEN_X;
sy = ScrollInfo._syoff + tileOffsetY + SCREEN_Y;
// Center player tile on screen
TilesInView(&columns, &rows);
// Shift player row to one that can be centered with out pixel offset
if ((columns & 1) == 0) {
y--;
}
ShiftGrid(&x, &y, -columns / 2, -(rows - RowsCoveredByPanel()) / 4);
columns = tileColums;
rows = tileRows;
// When both columns and rows are even or odd vertical alignment must be done using a screen offset
if (zoomflag && (columns & 1) == (rows & 1)) {
ShiftGrid(&x, &y, 0, -1);
rows += 2;
sy -= TILE_HEIGHT / 2;
}
x += tileShiftX;
y += tileShiftY;
// Skip rendering parts covered by the panels
if (PANELS_COVER) {

6
Source/scrollrt.h

@ -23,6 +23,11 @@ extern int cel_foliage_active;
extern int level_piece_id;
extern void (*DrawPlrProc)(int, int, int, int, int, BYTE *, int, int, int, int);
extern int tileOffsetX;
extern int tileOffsetY;
extern int tileShiftX;
extern int tileShiftY;
void ClearCursor();
void DrawMissile(int x, int y, int sx, int sy, BOOL pre);
void DrawDeadPlayer(int x, int y, int sx, int sy);
@ -30,6 +35,7 @@ void ShiftGrid(int *x, int *y, int horizontal, int vertical);
int RowsCoveredByPanel();
void CalcTileOffset(int *offsetX, int *offsetY);
void TilesInView(int *columns, int *rows);
void CalcViewportGeometry();
void DrawView(int StartX, int StartY);
void ClearScreenBuffer();
#ifdef _DEBUG

161
SourceT/scrollrt_test.cpp

@ -0,0 +1,161 @@
#include <gtest/gtest.h>
#include "all.h"
#include "ui_fwd.h"
// TilesInView
TEST(Scrool_rt, calc_tiles_in_view_original)
{
dvl::screenWidth = 640;
dvl::screenHeight = 480;
dvl::viewportHeight = dvl::screenHeight - 128;
dvl::zoomflag = true;
int columns = 0;
int rows = 0;
dvl::TilesInView(&columns, &rows);
EXPECT_EQ(columns, 10);
EXPECT_EQ(rows, 11);
}
TEST(Scrool_rt, calc_tiles_in_view_original_zoom)
{
dvl::screenWidth = 640;
dvl::screenHeight = 480;
dvl::viewportHeight = dvl::screenHeight - 128;
dvl::zoomflag = false;
int columns = 0;
int rows = 0;
dvl::TilesInView(&columns, &rows);
EXPECT_EQ(columns, 5);
EXPECT_EQ(rows, 6);
}
TEST(Scrool_rt, calc_tiles_in_view_960_540)
{
dvl::screenWidth = 960;
dvl::screenHeight = 540;
dvl::viewportHeight = dvl::screenHeight;
dvl::zoomflag = true;
int columns = 0;
int rows = 0;
dvl::TilesInView(&columns, &rows);
EXPECT_EQ(columns, 15);
EXPECT_EQ(rows, 17);
}
TEST(Scrool_rt, calc_tiles_in_view_640_512)
{
dvl::screenWidth = 640;
dvl::screenHeight = 512;
dvl::viewportHeight = dvl::screenHeight - 128;
dvl::zoomflag = true;
int columns = 0;
int rows = 0;
dvl::TilesInView(&columns, &rows);
EXPECT_EQ(columns, 10);
EXPECT_EQ(rows, 12);
}
TEST(Scrool_rt, calc_tiles_in_view_768_480_zoom)
{
dvl::screenWidth = 768;
dvl::screenHeight = 480;
dvl::viewportHeight = dvl::screenHeight;
dvl::zoomflag = false;
int columns = 0;
int rows = 0;
dvl::TilesInView(&columns, &rows);
EXPECT_EQ(columns, 6);
EXPECT_EQ(rows, 8);
}
// CalcTileOffset
TEST(Scrool_rt, calc_tile_offset_original)
{
dvl::screenWidth = 640;
dvl::screenHeight = 480;
dvl::viewportHeight = dvl::screenHeight - 128;
dvl::zoomflag = true;
int x = 0;
int y = 0;
dvl::CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 0);
}
TEST(Scrool_rt, calc_tile_offset_original_zoom)
{
dvl::screenWidth = 640;
dvl::screenHeight = 480;
dvl::viewportHeight = dvl::screenHeight - 128;
dvl::zoomflag = false;
int x = 0;
int y = 0;
dvl::CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 8);
}
TEST(Scrool_rt, calc_tile_offset_960_540)
{
dvl::screenWidth = 960;
dvl::screenHeight = 540;
dvl::viewportHeight = dvl::screenHeight;
dvl::zoomflag = true;
int x = 0;
int y = 0;
dvl::CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 2);
}
TEST(Scrool_rt, calc_tile_offset_853_480)
{
dvl::screenWidth = 853;
dvl::screenHeight = 480;
dvl::viewportHeight = dvl::screenHeight;
dvl::zoomflag = true;
int x = 0;
int y = 0;
dvl::CalcTileOffset(&x, &y);
EXPECT_EQ(x, 21);
EXPECT_EQ(y, 0);
}
TEST(Scrool_rt, calc_tile_offset_768_480_zoom)
{
dvl::screenWidth = 768;
dvl::screenHeight = 480;
dvl::viewportHeight = dvl::screenHeight;
dvl::zoomflag = false;
int x = 0;
int y = 0;
dvl::CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 8);
}
// RowsCoveredByPanel
TEST(Scrool_rt, calc_tiles_covered_by_panel_original)
{
dvl::screenWidth = 640;
dvl::zoomflag = true;
EXPECT_EQ(dvl::RowsCoveredByPanel(), 0);
}
TEST(Scrool_rt, calc_tiles_covered_by_panel_960)
{
dvl::screenWidth = 960;
dvl::zoomflag = true;
EXPECT_EQ(dvl::RowsCoveredByPanel(), 4);
}
TEST(Scrool_rt, calc_tiles_covered_by_panel_960_zoom)
{
dvl::screenWidth = 960;
dvl::zoomflag = false;
EXPECT_EQ(dvl::RowsCoveredByPanel(), 2);
}
Loading…
Cancel
Save