我需要修复 XNA 中的这个 Tile 错误
I need to fix this Tile bug in XNA
我目前正在制作 space 射击游戏。对于这个游戏,我想要一个带有星星的背景,它会永远循环播放。
为了创建这个,我制作了一个基于图块的系统,它为每个纹理简单地创建了一个矩形。我已经能够使所说的纹理有点循环,但是当它们这样做时,我遇到了一个非常奇怪的错误。
如您所见,我的瓷砖有时会在彼此之间产生一个小间隙,我不确定为什么。
问题可能出在我的 Background.cs 文件中,但我不确定在哪里。
另外,我想要一个更好的名字 "Background.cs"。你认为像 "Tile.cs" 这样的东西更好吗?
Background.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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 SpaceShooter
{
class Background
{
public Texture2D texture;
public List<Rectangle> tiles = new List<Rectangle>();
public Color color;
public int tileSize;
public int speed;
GraphicsDevice graphicsDevice;
public Background(Texture2D texture, GraphicsDevice graphicsDevice, int tileSize)
{
this.texture = texture;
this.graphicsDevice = graphicsDevice;
this.tileSize = tileSize;
speed = 3;
this.color = Color.White;
CalculateTiles();
}
public void Update()
{
for (int i = 0; i < tiles.Count(); i++)
{
tiles[i] = new Rectangle(tiles[i].X, tiles[i].Y + speed, tiles[i].Width, tiles[i].Height);
if (tiles[i].Y >= graphicsDevice.Viewport.Height)
{
tiles[i] = new Rectangle(tiles[i].X, 0 - tiles[i].Height, tiles[i].Width, tiles[i].Height);
}
}
}
public void CalculateTiles()
{
if (tiles.Count() > 0)
{
for (int i = 0; i < tiles.Count(); i++)
{
tiles.Remove(tiles[i]);
}
}
int XT = (int)(graphicsDevice.Viewport.Width / (tileSize / 1.5f));
int YT = (int)(graphicsDevice.Viewport.Height / (tileSize / 1.5f));
for (int i = 0; i < XT; i++)
{
tiles.Add(new Rectangle(tileSize * i, 0, tileSize, tileSize));
for (int j = 0; j < YT; j++)
{
tiles.Add(new Rectangle(tileSize * i, tileSize * j, tileSize, tileSize));
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
for (int i = 0; i < tiles.Count(); i++)
{
spriteBatch.Draw(texture, tiles[i], color);
}
}
}
}
Game.cs
public class Game1 : Microsoft.Xna.Framework.Game
{
Background background;
protected override void LoadContent()
{
// Assign Background
background = new Background(Content.Load<Texture2D>("Stars"),GraphicsDevice, 128);
}
protected override void Update(GameTime gameTime)
{
if(Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Escape))
this.Exit();
background.Update();
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(bgc);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
// Call all drawing functions here
background.Draw(spriteBatch);
player1.Draw(spriteBatch);
player2.Draw(spriteBatch);
//
spriteBatch.End();
base.Draw(gameTime);
}
我认为使用 LinearWrap
可以轻松解决您的问题
如果您在 Game1.draw.
中执行以下操作
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap);
background.Draw(spriteBatch);
spriteBatch.End();
要获得比例,只需进行以下计算:
float scale = 128 / 512; // Where 128 is your desired size. and 512 your actual texture size.
并在您的 Background.cs 绘图方法中。
spriteBatch.Draw(texture, new Vector2(0,0), new Rectangle(pos.X, pos.Y, graphicsDevice.Viewport.Width / scale, graphicsDevice.Viewport.Height / scale), Color.White, 0, Vector2.Zero, scale, SpriteEffects.None, 0);
这应该会在整个屏幕上重复您的纹理。
编辑:
要使图像动态化,您可以使用相机。但是使用您拥有的系统,您只需在更新时执行此操作:
pos += new Vector2(movementX, movementY);
请注意 spriteBatch.Draw 有一个参数 "Source Rectangle"。如果您更改此矩形的位置,您的纹理将会移动。
问题已解决
我现在将磁贴相对于屏幕高度向上放置,而不是将其原始编程为 0。
if (tiles[i].Y >= graphicsDevice.Viewport.Height)
{
tiles[i] = new Rectangle(tiles[i].X, tiles[i].Y - graphicsDevice.Viewport.Height - tiles[i].Height, tiles[i].Width, tiles[i].Height);
}
我目前正在制作 space 射击游戏。对于这个游戏,我想要一个带有星星的背景,它会永远循环播放。
为了创建这个,我制作了一个基于图块的系统,它为每个纹理简单地创建了一个矩形。我已经能够使所说的纹理有点循环,但是当它们这样做时,我遇到了一个非常奇怪的错误。
如您所见,我的瓷砖有时会在彼此之间产生一个小间隙,我不确定为什么。
问题可能出在我的 Background.cs 文件中,但我不确定在哪里。
另外,我想要一个更好的名字 "Background.cs"。你认为像 "Tile.cs" 这样的东西更好吗?
Background.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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 SpaceShooter
{
class Background
{
public Texture2D texture;
public List<Rectangle> tiles = new List<Rectangle>();
public Color color;
public int tileSize;
public int speed;
GraphicsDevice graphicsDevice;
public Background(Texture2D texture, GraphicsDevice graphicsDevice, int tileSize)
{
this.texture = texture;
this.graphicsDevice = graphicsDevice;
this.tileSize = tileSize;
speed = 3;
this.color = Color.White;
CalculateTiles();
}
public void Update()
{
for (int i = 0; i < tiles.Count(); i++)
{
tiles[i] = new Rectangle(tiles[i].X, tiles[i].Y + speed, tiles[i].Width, tiles[i].Height);
if (tiles[i].Y >= graphicsDevice.Viewport.Height)
{
tiles[i] = new Rectangle(tiles[i].X, 0 - tiles[i].Height, tiles[i].Width, tiles[i].Height);
}
}
}
public void CalculateTiles()
{
if (tiles.Count() > 0)
{
for (int i = 0; i < tiles.Count(); i++)
{
tiles.Remove(tiles[i]);
}
}
int XT = (int)(graphicsDevice.Viewport.Width / (tileSize / 1.5f));
int YT = (int)(graphicsDevice.Viewport.Height / (tileSize / 1.5f));
for (int i = 0; i < XT; i++)
{
tiles.Add(new Rectangle(tileSize * i, 0, tileSize, tileSize));
for (int j = 0; j < YT; j++)
{
tiles.Add(new Rectangle(tileSize * i, tileSize * j, tileSize, tileSize));
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
for (int i = 0; i < tiles.Count(); i++)
{
spriteBatch.Draw(texture, tiles[i], color);
}
}
}
}
Game.cs
public class Game1 : Microsoft.Xna.Framework.Game
{
Background background;
protected override void LoadContent()
{
// Assign Background
background = new Background(Content.Load<Texture2D>("Stars"),GraphicsDevice, 128);
}
protected override void Update(GameTime gameTime)
{
if(Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Escape))
this.Exit();
background.Update();
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(bgc);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
// Call all drawing functions here
background.Draw(spriteBatch);
player1.Draw(spriteBatch);
player2.Draw(spriteBatch);
//
spriteBatch.End();
base.Draw(gameTime);
}
我认为使用 LinearWrap
可以轻松解决您的问题如果您在 Game1.draw.
中执行以下操作spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap);
background.Draw(spriteBatch);
spriteBatch.End();
要获得比例,只需进行以下计算:
float scale = 128 / 512; // Where 128 is your desired size. and 512 your actual texture size.
并在您的 Background.cs 绘图方法中。
spriteBatch.Draw(texture, new Vector2(0,0), new Rectangle(pos.X, pos.Y, graphicsDevice.Viewport.Width / scale, graphicsDevice.Viewport.Height / scale), Color.White, 0, Vector2.Zero, scale, SpriteEffects.None, 0);
这应该会在整个屏幕上重复您的纹理。
编辑:
要使图像动态化,您可以使用相机。但是使用您拥有的系统,您只需在更新时执行此操作:
pos += new Vector2(movementX, movementY);
请注意 spriteBatch.Draw 有一个参数 "Source Rectangle"。如果您更改此矩形的位置,您的纹理将会移动。
问题已解决
我现在将磁贴相对于屏幕高度向上放置,而不是将其原始编程为 0。
if (tiles[i].Y >= graphicsDevice.Viewport.Height)
{
tiles[i] = new Rectangle(tiles[i].X, tiles[i].Y - graphicsDevice.Viewport.Height - tiles[i].Height, tiles[i].Width, tiles[i].Height);
}