2014-03-30 4 views
0

학교 프로젝트를 위해 C# XNA에서 매우 간단한 테라 리아와 비슷한 게임을 만들려고합니다. 나는 매우 제한된 시간을 보내고있다. 그렇지 않으면 나 자신을 알아 내기 위해 더 많은 시간을 할애했을 것이다. 나는 타일 맵을 만들었지 만 타일을 "단단한"방법으로 만들 수는 없었습니다.타일 맵 충돌 감지 C# XNA

using System; 
using System.Collections.Generic; 
using System.Linq; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Audio; 
using Microsoft.Xna.Framework.Content; 
using Microsoft.Xna.Framework.GamerServices; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using Microsoft.Xna.Framework.Media; 

namespace TileEngine { 
    public class Game1 : Microsoft.Xna.Framework.Game 
    { 
     GraphicsDeviceManager graphics; 
     SpriteBatch spriteBatch; 

     Texture2D character; 
     Vector2 cPosition; 
     Rectangle cBounds, t1Bounds; 

     List<Texture2D> tileTextures = new List<Texture2D>(); 

     int[,] tileMap = new int[,] 
     { 
      { 0, 1, 1, 0, 2, 1, 1, 1, 0, 1, }, 
      { 0, 1, 1, 0, 2, 1, 1, 1, 0, 1, }, 
      { 0, 1, 1, 0, 2, 1, 1, 1, 0, 1, }, 
      { 0, 1, 1, 0, 2, 1, 1, 1, 0, 1, }, 
     }; 

     int tileWidth = 64; 
     int tileHeight = 36; 

     int cameraPositionX = 0; 
     int cameraPositionY = 0; 

     int vSpeed = 0; 

     public Game1() 
     { 
      graphics = new GraphicsDeviceManager(this); 
      Content.RootDirectory = "Content"; 
     } 

     protected override void Initialize() 
     { 
      IsMouseVisible = true; 

      graphics.IsFullScreen = false; 
      graphics.PreferredBackBufferWidth = 1280; 
      graphics.PreferredBackBufferHeight = 720; 
      graphics.ApplyChanges(); 

      cPosition = new Vector2(graphics.GraphicsDevice.Viewport.Width/2 - 15, graphics.GraphicsDevice.Viewport.Height/2 - 20); 

      cBounds = new Rectangle((int)(cPosition.X), (int)(cPosition.Y), character.Width, character.Height); 

      base.Initialize(); 
     } 
     protected override void LoadContent() 
     { 
      // Create a new SpriteBatch, which can be used to draw textures. 
      spriteBatch = new SpriteBatch(GraphicsDevice); 

      Texture2D texture; 

      character = Content.Load<Texture2D>("Tiles/character"); 

      texture = Content.Load<Texture2D>("Tiles/green"); 
      tileTextures.Add(texture); 

      texture = Content.Load<Texture2D>("Tiles/red"); 
      tileTextures.Add(texture); 

      texture = Content.Load<Texture2D>("Tiles/blue"); 
      tileTextures.Add(texture); 

      cBounds = new Rectangle((int)(cPosition.X), (int)(cPosition.Y), 
character.Width, character.Height); 

      // TODO: use this.Content to load your game content here 
     } 
     protected override void UnloadContent() 
     { 
      // TODO: Unload any non ContentManager content here 
     } 


     protected override void Update(GameTime gameTime) 
     { 

      if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
       this.Exit(); 

      KeyboardState keyState = Keyboard.GetState(); 

      vSpeed += 1; 
      cameraPositionY += vSpeed; 

      if (keyState.IsKeyDown(Keys.Right)) 
       cameraPositionX += 5; 
      if (keyState.IsKeyDown(Keys.Left)) 
       cameraPositionX -= 5; 
      if (keyState.IsKeyDown(Keys.Space)) 
       vSpeed = -15; 

      if (cBounds.Intersects(t1Bounds)) 
      { 
       cameraPositionY = 0; 
       vSpeed = 0; 
      }  

      base.Update(gameTime); 
     } 


     protected override void Draw(GameTime gameTime) 
     { 
      GraphicsDevice.Clear(Color.CornflowerBlue); 

      spriteBatch.Begin(); 

      int tileMapWidth = tileMap.GetLength(1); 
       int tileMapHeight = tileMap.GetLength(0); 

      spriteBatch.Draw(character, cPosition, Color.White); 

      for (int x = 0; x < tileMapWidth; x++) 
      { 
       for (int y = 0; y < tileMapHeight; y++) 
       { 
        int textureIndex = tileMap[y, x]; 
        Texture2D texture = tileTextures[textureIndex]; 

        spriteBatch.Draw(
         texture, t1Bounds = 
         new Rectangle(
          320 + x * tileWidth - cameraPositionX, 
          540 + y * tileHeight - cameraPositionY, 
          tileWidth, 
          tileHeight), 
         Color.White); 
       } 
      } 

      spriteBatch.End(); 

      base.Draw(gameTime); 
     } 
    } } 

당신은 내가 주위의 모든 스프라이트를 사각형을 만들고 서로 교차 할 때 감지하려고 볼 수 있지만 작동하지 않기 때문에. 그리고 Rectangle을 작동 시키더라도 교차하는 경우 어떻게해야할지 모릅니다. 속도를 0으로 설정하면 기본 수직 가속도가 있으므로 블록을 통해 천천히 "떨어집니다".

+2

속도를 '0'으로 설정하여 플레이어를 멈추는 대신 플레이어가 타일에 얼마나 멀리 있는지, 교차 깊이라고도 알려야하며 깊이를 빼서 플레이어를 타일에 다시 놓아야합니다. – Cyral

+0

마지막 타일을 제외하고는 충돌이 확인되는 곳이 없습니다. 아마도 모든 사각형을 가진 배열을 만든 다음 foreach 루프를 만들고 각 타일 사각형이 플레이어 경계를 넘는 지 확인하십시오. @ Cyral이 말한 것을 기억하십시오. – joppiesaus

답변

0

첫째, 당신은이처럼 타일에 대한 간단한 클래스를 작성해야합니다

Class Tile 
{ 
public int type; //Holds the ID to the specific texture. 
public bool collision; //If true you should check for collision if the player is close. 
public int health; //You probably need this since rock is harder to break then dirt. 
} 

그런 다음 타일 배열을 만들 수 있습니다. 이제 플레이어가 충돌 가능한 타일에 가까이 있는지 확인해야합니다. 월드 공간을 타일 공간으로 변환하고 플레이어 좌표를 입력하는 기능이 필요합니다. 각 프레임에서 플레이어 주변의 타일 몇 개를 확인하십시오. 충돌에 대한 전체지도를 확인하면 FPS가 0.001로 떨어지며 모든 타일을 그릴 수 있습니다. (이미 타일 수준에서) 일부 의사 코드 :

for (int y = player.y-4;y <= player.y+4;y++) 
{ //If your player is just the size of a single tile then just -2/+2 will do. 9*9 is already an expensive 81 rectangles to check. 
    for (int x = player.x-4;x <= player.x+4;x++) 
    { 
     if (map[x,y].collision){ 
     if (new Rectangle(x*tilewidth,y*tileheight,tilewidth,tileheight).intersects(player.rectangle)){ 
     //Check farthest valid position and put player there 
     }} 

    } 
} 

newPosition의 속성 및 위치가 유효한지 확인해야이 newPosition 플레이어를 이동하기 전에 추가하시는 것이 가장 좋은 방법입니다.

그 외에는 시간이 없다면 최고의 조언은 게임과 같은 테라 리아를 만들지 않는 것입니다. 게임과 같은 테라 리아 중 가장 단순한 것조차도 시간이 많이 걸릴 것입니다. 당신이 충돌의 기초를 모르기 때문에 나는 우리가 모두 어떻게 시작했는지 거의 알지 못하는 탁구 또는 arkanoid 클론을 만드는 것을 제안합니다.