ฉันได้สร้างเอ็นจิ้นเกมคล้ายกับTerrariaซึ่งส่วนใหญ่เป็นสิ่งที่ท้าทายและในขณะที่ฉันคิดว่าส่วนใหญ่แล้วฉันไม่สามารถคาดเดาได้ว่าพวกเขาจัดการกับกระเบื้องที่สามารถโต้ตอบ / เก็บเกี่ยวได้นับล้าน เกมมีในครั้งเดียว การสร้างไทล์ประมาณ 500,000 แผ่นนั่นคือ 1 ใน 20 ของสิ่งที่เป็นไปได้ในTerrariaในเครื่องยนต์ของฉันทำให้อัตราเฟรมลดลงจาก 60 เหลือประมาณ 20 ถึงแม้ว่าฉันจะยังคงแสดงเฉพาะไพ่ในมุมมองเท่านั้น ใจคุณฉันไม่ได้ทำอะไรกับกระเบื้องเพียงแค่ทำให้พวกเขาอยู่ในความทรงจำ
อัปเดต : รหัสถูกเพิ่มเพื่อแสดงว่าฉันทำสิ่งต่าง ๆ อย่างไร
นี่เป็นส่วนหนึ่งของชั้นเรียนที่จัดการกับกระเบื้องและดึงพวกเขา ฉันเดาว่าผู้ร้ายคือส่วน "foreach" ซึ่งวนซ้ำทุกอย่างแม้แต่ดัชนีที่ว่างเปล่า
...
public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{
foreach (Tile tile in this.Tiles)
{
if (tile != null)
{
if (tile.Position.X < -this.Offset.X + 32)
continue;
if (tile.Position.X > -this.Offset.X + 1024 - 48)
continue;
if (tile.Position.Y < -this.Offset.Y + 32)
continue;
if (tile.Position.Y > -this.Offset.Y + 768 - 48)
continue;
tile.Draw(spriteBatch, gameTime);
}
}
}
...
นอกจากนี้นี่คือวิธี Tile.Draw ซึ่งสามารถทำได้ด้วยการอัปเดตเนื่องจากไทล์แต่ละอันใช้การเรียกสี่ครั้งไปยังเมธอด SpriteBatch.Draw นี่เป็นส่วนหนึ่งของระบบการหมุนอัตโนมัติของฉันซึ่งหมายถึงการวาดแต่ละมุมขึ้นอยู่กับกระเบื้องข้างเคียง texture_ * เป็นรูปสี่เหลี่ยมตั้งครั้งเดียวที่การสร้างระดับไม่ใช่การอัปเดตแต่ละครั้ง
...
public virtual void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{
if (this.type == TileType.TileSet)
{
spriteBatch.Draw(this.texture, this.realm.Offset + this.Position, texture_tl, this.BlendColor);
spriteBatch.Draw(this.texture, this.realm.Offset + this.Position + new Vector2(8, 0), texture_tr, this.BlendColor);
spriteBatch.Draw(this.texture, this.realm.Offset + this.Position + new Vector2(0, 8), texture_bl, this.BlendColor);
spriteBatch.Draw(this.texture, this.realm.Offset + this.Position + new Vector2(8, 8), texture_br, this.BlendColor);
}
}
...
คำติชมหรือคำแนะนำเกี่ยวกับรหัสของฉันยินดีต้อนรับ
อัปเดต : เพิ่มโซลูชันแล้ว
นี่คือวิธี Level.Draw สุดท้าย กระบวนการ Level.TileAt วิธีการตรวจสอบค่าอินพุตเพื่อหลีกเลี่ยงข้อยกเว้น OutOfRange
...
public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
{
Int32 startx = (Int32)Math.Floor((-this.Offset.X - 32) / 16);
Int32 endx = (Int32)Math.Ceiling((-this.Offset.X + 1024 + 32) / 16);
Int32 starty = (Int32)Math.Floor((-this.Offset.Y - 32) / 16);
Int32 endy = (Int32)Math.Ceiling((-this.Offset.Y + 768 + 32) / 16);
for (Int32 x = startx; x < endx; x += 1)
{
for (Int32 y = starty; y < endy; y += 1)
{
Tile tile = this.TileAt(x, y);
if (tile != null)
tile.Draw(spriteBatch, gameTime);
}
}
}
...