2011-01-30 6 views
2

C#/XNA 클래스 용 XNA 3.1 응용 프로그램을 작성하고 있습니다. 사용자가 단순히 화면의 색상을 변경하고 키보드의 R, G 또는 B 버튼을 눌러 색상 채널을 선택한 다음 위아래 화살표를 눌러 해당 채널의 값을 높이거나 낮추는 간단한 소개입니다. . 내가 감소하는의는 다시 0에 랩 255 과거 바이트, 그 반대를 증가하면 그들에 연산을 수행 할 때255가 넘어갈 때 바이트가 0으로 되돌아 가지 않도록 방지

는 C#을 실제로 intbyte 변환 아마도 때문이다. 그러나 교수는 특별히 채널이 최대 값이나 최소값에 도달하면 사용자가이 범위를 벗어나려고하면 채널에 머물러있게됩니다. 나는이 문제를 해결하기위한 방법을 혼자서 찾았지만, 여기 또는 Google에서 이런 종류의 문제에 대한 해결책을 찾았을 때 아무것도 찾지 못했습니다.

/// <summary> 
/// This is the main type for your game 
/// </summary> 
public class Game1 : Microsoft.Xna.Framework.Game 
{ 
    // ... 

    Color color; 

    private int Red 
    { 
     set { color.R = NoWrapIntToByte(value); } 
     get { return (int)color.R; } 
    } 

    private int Green 
    { 
     set { color.G = NoWrapIntToByte(value); } 
     get { return (int)color.G; } 
    } 

    private int Blue 
    { 
     set {color.B = NoWrapIntToByte(value); } 
     get { return (int)color.B; } 
    } 

    /// <summary> 
    /// Converts an integer to a byte but doesn't wrap. 
    /// </summary> 
    /// <param name="x"></param> 
    /// <returns></returns> 
    static byte NoWrapIntToByte(int x) 
    { 
     if (x < Byte.MinValue) 
      return Byte.MinValue; 
     else if (x > Byte.MaxValue) 
      return Byte.MaxValue; 
     else 
      return (byte)x; 
    } 
} 

Draw() 메서드를 호출 할 때마다 color에 저장된 색상이 화면의 색상으로 설정이 내가 여기에 문제를 해결 한 방법이다.

그냥 명확하게, 나는 컴파일러가 불평

byte x = 256; // compiler error 

처럼 뭔가를 할 수 없습니다 알고 있습니다. 그러나 사용자가 위쪽 또는 아래쪽 화살표를 누르면 해당 색상 채널이 증가 또는 감소되고 채널이 0보다 작아 지거나 255보다 커지면 줄 바꿈됩니다. Red -= 1 또는 Red += 1과 같은 것을 사용하고 있다면 범위를 벗어날 경우 다른 기대치가 발생하기 때문에 채널 속성의 유형으로 int을 사용했습니다. 추가하는 경우 결과 값이 원래 값보다 작을 것으로 예상하고 반대의 경우는 감소시킬 것입니다. int을 사용하고 있습니다. 속성에서이를 감지하고 이에 따라 처리 할 수 ​​있기 때문입니다.

내 솔루션은 괜찮다고 생각하지만 뭔가를 간과한다면 궁금합니다. 나는이 문제를 해결하려고 노력한 유일한 사람이 될 수 없으므로이 문제를 해결하기 위해 관용적이거나 모범 사례가 될 수있는 것이 궁금합니다. 나는 이미 해결책이 있기 때문에 숙제 문제에 대한 답을 요구하지는 않습니다. 그러나, 나는 C#을 잘 모른다. 그래서 똑같은 일을하는 훨씬 간단한 방법이 있거나 여기에있는 코드보다 적은 코드가 있다면 나는 궁금하다. 나는 C#에서 Overflow 예외를 던지게 할 수 있다는 것을 알고 있지만, 프로젝트 설정을 변경해야하고 또한 어떤 종류인지 구체적으로 알려주지 않는다.

감사합니다!

+1

바이트 x = 256이 한 바이트에 비해 너무 큰 경우 255가 가장 큰 값이므로 컴파일러가 정확합니다. 나는 당신의 해결책이 좋다고 생각합니다. 나는 그것을 확장으로 써야 하겠지만, 그것은 나 뿐이다. –

+0

예, 저는 컴파일러가 불평 할 것이라고 언급했습니다. 어쩌면 나는 명확성을 위해 코멘트를 추가 할 것이다 ... –

+0

왜 처음에'int'를 사용하고 있습니까? 항상 '바이트'를 사용하지 않는 이유는 무엇입니까? 그것은 많은 캐스팅을 피할 것입니다. – DonkeyMaster

답변

2

XNA 프레임 워크에 내장 된 "클램프 (Clamp)"방법을 사용해야한다는 생각이 들었습니다.

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.mathhelper.clamp.aspx

는 기본적으로 0에서 255 다음 방금 다음처럼 작성할 내에서 값이 말하고 싶은 경우.

static byte NoWrapIntToByte(int x) 
{ 
    return (byte)MathHelper.Clamp(x, 0, 255); 
} 

당신이 찾고있는 것처럼 들리겠습니까?

+0

완벽한! 이것은 내가 찾고 있었던 바로 그 것이다. –

-1

나는 포장에서 멈출 수 없다고 생각합니다. int16 또는 int32를 사용해야합니다. 그러나 if 문을 사용하여 결과가 255보다 큰지 확인한 다음 변환 할 수 있습니다.

+0

그게 내가 이미하고있는거야. 'Color'는 XNA의 클래스이고'R','G','B'는 그 클래스의 속성이고 그 타입은'byte'입니다. 나는 그것을 바꿀 수 없다. 그래서 나는이 세 가지 특성을 내 자신의 수업에 넣는다. –

4

당신의 대답은 당신이 원하는대로해야 할 것처럼 보이지만, 거기에 도달하는 데는 많은 코드가 있다고 느낍니다. 그것을 해결하기 위해 내 문제가 있다면, 나는 아마 이런 짓을 할 것이다 :

static byte NoWrapIntToByte(int x) 
{ 
    int tmp; 
    tmp = Math.Max(x, 0); 
    tmp = Math.Min(255, tmp); 
    return (byte)tmp; 
} 

감사 @Marlon을 Math.Max/Min 수정을 위해.

주연 수정을 위해 @Andrew Noyes에게 감사드립니다.

희망이 도움이됩니다. :)

+1

당신은 C#을 모르거나 전문가입니다! : P Math.Max ​​및 Math.Min은 사용자가 찾고있는 것입니다 – Marlon

+1

예, 함수가 내 것보다 약간 간단하지만 같은 결과를 얻습니다. 내 진짜 문제는이 기능이 필요한지 아닌지하는 것입니다. 기능이 없어도이를 수행 할 수있는 언어의 일부가있는 것처럼 말입니다. 또한 함수의 반환 값은 C#의 바이트로 실제로 캐스팅되어야합니다. :) –

2

귀하의 솔루션은 작동하지만 근본적으로 잘못된 접근 방법입니다.이처럼 속성을 작성해야 :

자신을 포함하여 클래스를 사용하는 사람을 할 수
private int Red 
{ 
    get { return (int)color.R; } 
    set { 
     if (value < 0 || value > 255) throw new ArgumentOutOfRangeException(); 
     color.R = (byte)value; 
    } 
} 

은 성공의 구덩이에 속합니다.

private void IncrementRed_Click(object sender, EventArgs e) { 
    if (this.Color.Red < 255) this.Color.Red += 1; 
} 

당신은 다음 더 속성 setter는하여 PropertyChanged 이벤트를 발생함으로써이 문제를 개선 할 수있는 후에는 다음과 유사한 적절한 솔루션, 뭔가를 발견 한 것입니다. 사용자가 UI에서 구독하여 버튼의 Enabled 속성을 false로 설정하여 버튼을 클릭하면 더 이상 유용하지 않다는 것을 즉시 알 수있는 이벤트입니다.

+0

이 방법을 완전히 이해하지만 XNA 워크 플로가 다릅니다. 버튼 누름이나 그와 비슷한 이벤트 처리기가 없기 때문에 단순히 키보드 상태를 반복적으로 폴링하므로 무언가를하는 것이 어려울 것입니다 (적어도 코드 현명한 경우, 하루가 끝날 때와 똑같습니다).) 특정 게임 상태에 도달하면 버튼을 "아무 것도하지 않음"과 같이 설정합니다. 사용자가 이해할 수없는 뭔가를하려고 할 때 올바른 대답이 무엇인지 항상 분명하게 알 수 있도록 API를 만드는 것에 대한 귀하의 요지를 이해합니다. 좋은 대답입니다! –

+0

난 그냥 왜 이런 솔루션을 사용하고 싶지 않아 언급하고 싶습니다 : 사용자가 현재 채널의 값을 위아래로 증가시킬 수 있으므로 위 또는 아래 키를 누르면 'enum' ('1') 또는 아래로 ('-1') 중 하나가 전달됩니다. 증분 연산자는 항상 사용되지만 값은 방향에 따라 양수 또는 음수입니다. 솔루션을 사용하려면 채널 당 두 가지 기능이 필요합니다. 하나는 아래로, 다른 하나는 아래로, 나머지는 조건부 논리 검사로 사용됩니다. –

+0

꽤 자주 발생해야하는 이벤트에 대한 예외가 발생하기 때문에 Downvoted. – DonkeyMaster

1

오버로드 된 연산자와 캐스터 집합에서 바이트를 래핑하는 새로운 구조를 정의 할 수 있습니다.

struct NoWrapByte 
{ 
    private byte _data; 

    public NoWrapByte(byte data) 
    { 
     this._data = data; 
    } 

    public static NoWrapByte operator +(NoWrapByte a, NoWrapByte b) 
    { 
     if (a._data + b._data > 255) 
      return new NoWrapByte((byte)255); 
     else if (a._data + b._data < 0) 
      return new NoWrapByte((byte)0); 
     else 
     return new NoWrapByte((byte)(a._data + b._data)); 
    } 

    public static NoWrapByte operator -(NoWrapByte a, NoWrapByte b) 
    { 
     if (a._data - b._data > 255) 
      return new NoWrapByte((byte)255); 
     else if (a._data - b._data < 0) 
      return new NoWrapByte((byte)0); 
     else 
      return new NoWrapByte((byte)(a._data - b._data)); 
    } 

    public static implicit operator byte(NoWrapByte op) 
    { 
     return op._data; 
    } 
} 
관련 문제