2014-04-14 3 views
0

이동중인 플랫폼이 타일을 치면 다른 방향으로 이동해야하는 타일 맵을 사용하고 있습니다. 타일 ​​맵과 플랫폼 모두에 대한 목록을 사용하고 있습니다.이동 플랫폼을 타일 맵으로

아래 이미지는 플랫폼을 보여 주며 지속적으로 움직이며 검은 색 원 중 하나와 충돌하면 방향을 바꾸고 가고있는 것과 반대 방향으로 향해야합니다. 나는 그것이 다른 방향으로 갈 수 있도록 올바른 플랫폼을 찾을 필요로하는 곳에

Image of Platform and colliding tile

는 불행하게도 나는 문제가 있습니다. 나는 메인 클래스에서리스트를 만들었고 메인 클래스 외에 다른 클래스 안에리스트를 호출하는 방법을 모른다.

질문 : 플랫폼이 경우 내가 아는 수 있도록, 내가 다른 위치에서 다른 방향으로가는 여러 개체를 들고 목록을 부르는 것이고, 메인 클래스에서 생성되는 방법

타일과 충돌하는거야?

간단히 말해, 플랫폼을 타일과 충돌 시키려면 어떻게해야합니까?

두 개의 클래스가 사용되는 타일 맵, 블록 클래스와 GAME1 클래스 (기본 클래스)를 만들려면 : 여기

은 타일지도를 사용하고 호출 할 거쳐야하는 과정입니다. 블록 클래스 텍스처, 위치 내부

및 BlockState (그것이 무엇을 할 것 인 것을 결정하는)
public Block(Texture2D Texture, Vector2 Position, int BlockState) 
    { 
     this.Texture = Texture; 
     this.Position = Position; 
     this.BlockState = BlockState; 
    } 

다음 블록 클래스는 플레이어 클래스를 사용하는 방법을 사용합니다.

public Player BlockCollision(Player player) 
    { 
     Rectangle top = new Rectangle((int)Position.X + 5, (int)Position.Y - 10, Texture.Width - 10, 10); 
     Rectangle bottom = new Rectangle((int)Position.X + 5, (int)Position.Y + Texture.Height, Texture.Width - 10, 10); 
     Rectangle left = new Rectangle((int)Position.X - 10, (int)Position.Y + 5, 10, Texture.Height - 10); 
     Rectangle right = new Rectangle((int)Position.X + Texture.Width, (int)Position.Y + 5, 10, Texture.Height - 10); 

     if (BlockState == 1 || (BlockState == 2 && !player.goingUp)) 
     { 
      if (top.Intersects(new Rectangle((int)player.Position.X, (int)player.Position.Y, player.Texture.Width, player.Texture.Height))) 
      { 
       if (player.Position.Y + player.Texture.Height > Position.Y && player.Position.Y + player.Texture.Height < Position.Y + Texture.Height/2) 
       { 
        player.Position.Y = player.ground = Position.Y - player.Texture.Height; 
        player.Velocity.Y = 0; 
        player.isJumping = false; 
        player.Time = 0; 
        player.botCollision = true; 
       } 
      } 
     } 

     return player; 
    } 

다음으로 그리기 방법.

public void Draw(SpriteBatch spriteBatch) 
    { 
     spriteBatch.Draw(Texture, new Rectangle((int)Position.X, (int)Position.Y, Texture.Width, Texture.Height), Color.White); 
    } 

다음 주 클래스 Game1로 이동합니다.

저는 블록과 플랫폼 모두에 대한 목록을 만듭니다.

숯 시스템을 사용하여지도를 만듭니다.

List<char[,]> Levels = new List<char[,]>(); 
    public int tileWidth, tileHeight; 

그런 다음 Initialize 메서드에서 List를 호출하고지도를 만듭니다.

protected override void Initialize() 
    { 
     Blocks = new List<Block>(); 
     Platforms = new List<MovingPlatform>(); 

     char[,] Level1 = {{'.','.','#'}, 
          {'.','.','#'}, 
          {'.','.','#'}}; 

     Levels.Add(Level1); 

     base.Initialize(); 
    } 

그러면 void LoadLevel이 on으로 설정됩니다.

void LoadLevel(int level) 
    { 
     Blocks.Clear(); 
     Platforms.Clear(); 

     player.Position = Vector2.Zero; 

     tileWidth = Levels[level].GetLength(1); 
     tileHeight = Levels[level].GetLength(0); 

     Texture2D blockSpriteA = Content.Load<Texture2D>("blockA2"); 

     for (int x = 0; x < tileWidth; x++) 
     { 
      for (int y = 0; y < tileHeight; y++) 
      { 

       //Background 
       Blocks.Add(new Block(background, new Vector2(x * 50, y * 50), 0)); 

       //Impassable Blocks 
       if (Levels[level][y, x] == '#') 
       { 
        Blocks.Add(new Block(blockSpriteA, new Vector2(x * 50, y * 50), 1)); 
       } 

       //Vertical Moving Platform 
       if (Levels[level][y, x] == '=') 
       { 
        Platforms.Add(new MovingPlatform(platform, new Vector2(x * 50, y * 50), 3.0f, true)); 
       } 

다음 목록에서 업데이트를 호출합니다.

 foreach (Block b in Blocks) 
     { 
      player = b.BlockCollision(player); 
     } 

     foreach (MovingPlatform m in Platforms) 
     { 
      player = m.BlockCollision(player); 
      m.Update(gameTime); 
     } 

마지막으로 Draw 메서드가이를 호출합니다.

 foreach (Block b in Blocks) 
     { 
      b.Draw(spriteBatch); 
     } 

     foreach (MovingPlatform m in Platforms) 
     { 
      m.Draw(spriteBatch); 
     } 

답변

1

나는 귀하의 질문을 이해한다고 생각하지만, 확실하지는 않습니다. 그러나 어쨌든 답을 내릴 것입니다.

당신이해야 할 일은 게임 클래스에서 물건을 옮기는 것입니다. 당신은지도의 개념과지도에 (플랫폼, 블록)에 속하는 물건을 잔뜩 가지고 그래서 자신의 수업 시간에이를 캡슐화하는 것이 좋습니다 예입니다 : 이제

class Map 
{ 
    public List<Block> Blocks; 
    public List<MovingPlatform> Platforms; 

    void LoadLevel(int level) 
    { 
     /// 
    } 
} 

는 코드 청소기를 만드는 , 이제 전달할 수있는 Map 객체가 생겼습니다.

예를 들어 MovingPlatform에서지도의 모든 항목에 액세스 할 수있게하려면지도에 대한 참조를 MovingPlatform 생성자의 매개 변수로 전달하면됩니다.이 매개 변수는 개인 필드에 저장합니다. 예 :

class Map 
{ 
    void LoadLevel(int level) 
    { 
     //Vertical Moving Platform 
     if (Levels[level][y, x] == '=') 
     { 
      Platforms.Add(new MovingPlatform(this, ...)); 
     } 
    } 
} 

당신은 다른 맵의 특정 일을 추가 할 수 있습니다 (:

class MovingPlatform 
{ 
    Map _map; 
    public MovingPlatform(Map map, Vector2 position, ...) 
    { 
     _map = map; 
    } 

    public void Update(GameTime gameTime) 
    { 
     //move platform 
     //detect collision 
     //have access to all the blocks and other platforms on map 
     //_map.Blocks; 
     //_map.Platforms; 
    } 
} 

그래서지도 클래스 LoadLevel() 메소드에 당신이 MovingPlatform 생성자의 첫 번째 매개 변수로 '이'를 전달할 것

심지어 플레이어에 대한 참조?)를 Map 클래스에 추가하면 MovingPlatform이 자동으로 액세스 할 수 있습니다.

이것을 종속성 주입이라고합니다. MovingPlatform 클래스는 맵에 대한 종속성이 있으며 생성자를 통해 해당 종속성을 주입하고 있습니다.

편집 :

충돌 당신은 타일과 MovingPlatform 클래스에 경계 속성을 추가 할 수 있습니다. 이렇게하면 현재 직사각형 경계를 쉽게 얻을 수 있습니다. 또한 플랫폼이 지정된 타일과 교차하는 경우 true를 반환하는 MovingPlatform의 IntersectsTile 메서드입니다. 운동 후, 충돌이있을 경우

class Tile 
{ 
    Rectangle Bounds 
    { 
     get 
     { 
      return new Rectangle((int)Position.X, (int)Position.Y, tileWidth, tileHeight); 
     } 
    } 
} 

class MovingPlatform 
{ 
    Rectangle Bounds 
    { 
     get 
     { 
      return new Rectangle((int)Position.X, (int)Position.Y, platformWidth, platformHeight); 
     } 
    } 

    //returns true if this platform intersects the specified tile 
    bool IntersectsTile(Tile tile) 
    { 
     return Bounds.Intersects(tile.Bounds); 
    } 
} 

그런 다음 플랫폼은 각각의 프레임을 이동하는 업데이트 방법에서 MovingPlatfom 클래스 확인. 충돌이있는 경우 이동을 취소하고 플랫폼 방향을 반대로 전환하면 다음 프레임이 반대 방향으로 이동합니다.

class MovingPlatform 
{ 
    void Update(Tile[] collidableTiles) 
    { 
     Position += direction; 

     //test collision 
     bool isCollision = CollisionTest(collidableTiles); 
     if (isCollision) 
     { 
      //undo the movement and change direction 
      Position -= direction; 
      direction = newDirection; 
     } 
    } 

    //returns true if this platform intersects with any of the specified tiles 
    bool CollisionTest(Tile[] tiles) 
    { 
     foreach (Tile tile in tiles) 
      if (IntersectsTile(tile)) 
       return true; 
     return false; 
    } 
} 

위의 작업을 수행하려면 맵의 충돌 가능한 타일 목록을 MovingPlatform 업데이트로 전달해야합니다. 매핑 클래스의 각 MovingPlatform을 호출하여 충돌 가능한 타일 목록을 전달합니다.

class Map 
{ 
    List<Tile> _collidableTiles; 

    void Update(GameTime gameTime) 
    { 
     foreach (MovingPlatform platform in MovingPlatforms) 
     { 
      platform.Update(_collidableTiles); 
     } 
    } 
} 

그 방법 중 하나입니다. 더 좋은 방법은 충돌 가능한 타일을 전달하는 대신에 MovingPlatform이 주변의 타일을 잡고 테스트하는 것입니다.

class MovingPlatform 
{ 
    void Update() 
    { 
     Position += direction; 

     //test collision 
     Tile[] tiles = _map.GetNearbyTiles(Position); 
     foreach (Tile tile in tiles) 
      if (tile.IsSolid) 
       if (IntersectsTile(tile)) 
       { 
        //undo the movement and change direction 
        Position -= direction; 
        direction = newDirection; 
        break; 
       } 
    } 
} 

그런 식으로 모든 타일에는 IsSolid 속성이 있고 true로 설정된 모든 타일은 이동하는 플랫폼과 충돌합니다.

class Tile 
{ 
    bool IsSolid; 
} 
+0

지저분한 코드로 도와 주셔서 감사합니다. 나는이 일을하려고 노력할 것이고, 나는 나의 질문에 분명하지 않다는 점에 유감이다. 나는 당신이 약간 혼란스럽게 만들었을지도 모르는 것을 알고 있습니다. 클래스에서 코드를 따로 따로 추가하는 것이 가장 좋은 생각은 아니 었습니다. 나는 코드를 보여주는 더 쉬운 방법을 보지 못했다. 왜냐하면 누군가가 훑어보기에는 싫은 큰 덩어리 였기 때문이다. –

+0

아니오 나는 당신의 게시물을 잘 이해했다. 나는 실제 충돌 탐지를하기위한 대답에 코드를 게시하기로되어 있었는지 확실하지 않았다. (나는 블록으로 그렇게하는 법을 모르겠다.) –

+0

자, 이것에 대해서, 우리는 단지 쳐다 본다. 플랫폼 오브젝트를 포함한리스트 이제 for 루프를 만들고 타일의 위치가 겹치는 지 확인하기 위해 모두의 위치를 ​​찾는 방법은 무엇입니까? 타일을 할 수있는 플랫폼을 찾는 방법을 말해줘. –