[英]If statement hack, is there is better way to write this?
我正在嘗試編寫一個簡單的橫向卷軸游戲,這是實驗性的第一步。 如果播放器在某個方向上移得太遠,我有這段代碼可以重新居中屏幕。
有更好的書寫方式嗎? 我覺得我在濫用這種語言,但是效果很好,我認為可能還不錯。
public void adjustFrameIfNecessary()
{
int dx, dy;
if ((dx = (GAME_WIDTH - GAME_WIDTH / 3) - player.x) < 0 || (dx = GAME_WIDTH / 3 - player.x) > 0 || (dx = 0) == 0);
if ((dy = (GAME_HEIGHT - GAME_HEIGHT / 3) - player.y) < 0 || (dy = GAME_HEIGHT / 3 - player.y) > 0 || (dy = 0) == 0);
if(dx != 0 || dy != 0)
{
for (Drawable shiftMe : drawables)
{
shiftMe.unconditionalShift(dx, dy);
}
}
}
編輯
關於每個人的輸入,為了使其更具可讀性,我將其更改為
public void adjustFrameIfNecessary()
{
int dx, dy;
assignX:
{
dx = (GAME_WIDTH - GAME_WIDTH / 3) - player.x;
if(dx < 0) break assignX;
dx = GAME_WIDTH / 3 - player.x;
if(dx > 0) break assignX;
dx = 0;
}
assignY:
{
dy = (GAME_HEIGHT - GAME_HEIGHT / 3) - player.y;
if(dy < 0) break assignY;
dy = GAME_HEIGHT / 3 - player.y;
if(dy > 0) break assignY;
dy = 0;
}
if (dx != 0 || dy != 0)
{
for (Drawable shiftMe : drawables)
{
shiftMe.unconditionalShift(dx, dy);
}
}
}
這是否更好?
編輯2
public void adjustFrameIfNecessary()
{
int dx = calculateShift(GAME_WIDTH, frameReference.x);
int dy = calculateShift(GAME_HEIGHT, frameReference.y);
if (dx != 0 || dy != 0)
{
for (Drawable shiftMe : drawables)
{
shiftMe.unconditionalShift(dx, dy);
}
}
}
我認為現在很清楚。 感謝大家。
我不確定我為什么會在頂部使用if
語句。 初始化變量時,只需分配變量即可。
dx = (GAME_WIDTH - GAME_WIDTH / 3) - player.x)
dy = (GAME_HEIGHT - GAME_HEIGHT / 3) - player.y)
無論您在if
語句中如何,它們都將被分配給該對象。 如果rearches第三個條件,那么它已經是零,因此沒有理由為它分配。 丟棄兩個if
語句,而只堅持直接變量分配。 將條件保持在for
循環之上,這是您需要進行的唯一檢查。
您的if語句難以讀取。 如果您(或其他任何人)以后需要進行更改,則可能會非常困難且容易出錯。
編寫不僅有效而且可維護的代碼是一個好習慣。 既然您可以使用它,則應使其更易於維護。
將if語句分成有意義的變量並使用多行。 你不是在寫高爾夫比賽嗎?
待會兒你會謝謝你的。
這個怎么樣?
/* calculate offset to center */
dx = X_current_center - player.x;
dy = Y_current_center - player.y;
if (abs(dx) > MARGIN || abs(dy) > MARGIN)
/* recenter */
不可讀,但我明白你的意思。 但是,有一件事:為什么不對x和y重用相同的檢查? 通過使用三元運算符,您可以減少一分駭客。
static int toBounds(int max, int curr) {
int ret;
return ((ret = (max - max/3) - curr) < 0 || (ret = max/3 - curr) > 0)? ret : 0;
}
改進此類代碼的想法通常是使用數學:)
首先,對於冗長的帖子,我們深表歉意。 如果您親自遇到我,不要問我這個話題,我將不會停止講話。
做這個:
/**
* Computes the distance from a point x to an interval [a,b]
*/
public static int distanceToInterval( int x, int a, int b ){
return x<a? (a-x): ( x>b? (b-x):0 );
// alternative:
// return Math.max( a - x, 0 ) + Math.min( b - x, 0 );
}
// then use as
int dx = distanceToInterval( player.x, GAME_WIDTH/3, GAME_WIDTH*2/3 );
int dy = distanceToInterval( player.y, GAME_HEIGHT/3, GAME_HEIGHT*2/3 );
您的初始聲明
if ((dx = (GAME_WIDTH - GAME_WIDTH / 3) - player.x) < 0 ||
(dx = GAME_WIDTH / 3 - player.x) > 0 ||
(dx = 0) == 0);
可以通過將它變成...來清理一點
...更長的版本
dx1 = GAME_WIDTH*2/3 - player.x;
dx2 = GAME_WIDTH*1/3 - player.x;
dx3 = 0;
if( dx1 < 0 ) dx = dx1;
else if( dx2 > 0 ) dx = dx2;
else dx = dx3;
恕我直言,這很清楚。 現在,我可以看到您要執行的操作,並用簡潔的句子表達出來: 如果播放器不在屏幕中間三分之一處,我們想移動屏幕
使其更加清晰
if( player.x < GAME_WIDTH/3 ) dx = GAME_WIDTH/3 - player.x; // positive num
else if( player.x > GAME_WIDTH*2/3 ) dx = GAME_WIDTH*2/3 - player.x; // negative num
else dx = 0; // no shift
您可以看到我對您的陳述進行了重新排序,我先檢查了左邊界,然后是右邊界。 如果您是一個從右到左閱讀的國家,您可能會發現另一個方向更加直觀:)
這是我會選擇的解決方案。 它很短,很可讀,很完美:)
但是,如果您想要更簡潔,則可以更進一步
做數學技巧
您需要了解這三種情況是完全排斥的,它們不可能同時發生。 讓我們回到使用更多的變量:
// on the left side we shift a positive number, or not at all
dx1 = Math.max( GAME_WIDTH/3 - player.x, 0 );
// on the right side we shift a negative amount, or not at all
dx2 = Math.min( GAME_WIDTH*2/3 - player.x, 0 );
現在來看一下這個美麗:
GAME_WIDTH/3-player.x > 0
,則GAME_WIDTH*2/3 - player.x > 0
因此Math.min(...,0) = 0
GAME_WIDTH*2/3 - player.x < 0
,則GAME_WIDTH*1/3 - player.x < 0
因此Math.max(...,0) = 0
這意味着您可以簡單地將兩者相加來計算總位移。 這是您的代碼將如下所示:
int dx =
Math.max( GAME_WIDTH/3 - player.x, 0 ) + // too far to the left?
Math.min( GAME_WIDTH*2/3 - player.x, 0 ); // or too far to the right?
多一點抽象
無論您選擇哪種變體,現在都可以輕松地將其放入方法中。 但是讓我們使其比這種特殊情況更有意義。 我會建議
/**
* Computes the distance from a point x to an interval [a,b]
*/
public static int distanceToInterval( int x, int a, int b ){
return
Math.max( a - x, 0 ) + // too far to the left?
Math.min( b - x, 0 ); // or too far to the right?
}
// now use as
int dx = distanceToInterval( player.x, GAME_WIDTH/3, GAME_WIDTH*2/3 );
int dy = distanceToInterval( player.y, GAME_HEIGHT/3, GAME_HEIGHT*2/3 );
ps,請注意,在GAME_WIDTH - GAME_WIDTH/3
,我已將GAME_WIDTH - GAME_WIDTH/3
替換為GAME_WIDTH*2/3
。 這兩個整數運算的結果略有不同,但是我更喜歡短版本,因為我發現它更直觀(“三分之二的屏幕”與“整個屏幕,然后三分之一的屏幕”)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.