source: 2013/30/DenisZ/CastleMaster/CastleMaster/CastleMaster/World/Level.cs @ 4535

Revision 4535, 8.2 KB checked in by dezhidki, 6 years ago (diff)

Uusi versio:

  • Tason luonti valmis
  • Piirtojärjestys toimii
  • Palikoiden lisääminen ja muokkaus toimii
  • Esivalmistelut liikkumista varten
Line 
1using CastleMaster.Entities;
2using CastleMaster.Entities.TileEntities;
3using CastleMaster.Graphics;
4using CastleMaster.Physics;
5using CastleMaster.World.Tiles;
6using Microsoft.Xna.Framework;
7using Microsoft.Xna.Framework.Graphics;
8using System.Collections.Generic;
9using Viewport = CastleMaster.Graphics.Viewport;
10
11namespace CastleMaster.World
12{
13
14    public class EntityComprarer : Comparer<Entity>
15    {
16        /// <summary>
17        /// Compares entities between them.
18        /// </summary>
19        /// <param name="e1">Entity 1.</param>
20        /// <param name="e2">Entity 2.</param>
21        /// <returns>-1 = e1 render before e2 (e1 -> e2). +1 = e1 render after e2 (e2 -> e1).</returns>
22        public override int Compare(Entity e1, Entity e2)
23        {
24            BoundingRectangle br1 = e1.BoundingRectangle;
25            BoundingRectangle br2 = e2.BoundingRectangle;
26
27            if (br1.ZFar >= br2.ZNear)
28            {
29                if ((e1.Z + e1.X - e1.RenderOffset.Y) - e1.RenderOffset.Y < (e2.Z + e2.X - e2.RenderOffset.Y) - e2.RenderOffset.Y) return -1;
30                return +1;
31            }
32            if (br1.ZNear <= br2.ZFar)
33                return -1;
34            if (br1.XRight <= br2.XLeft)
35                return -1;
36            if (br1.XLeft >= br2.XRight)
37                return +1;
38
39            return 0;
40        }
41    }
42
43    public class Level
44    {
45        public const int TILE_VOID = 0;
46        public const int UPDATES_IN_TICK = 50;
47        protected List<Tile> registeredTiles;
48        protected int[] tiles;
49        protected byte[] data;
50
51        private List<Entity> entities;
52        private List<TileEntity> tileEntities;
53        private List<Entity>[] entitiesInTiles;
54        private SortedSet<Entity> entitesToRender;
55        private int width, height;
56        protected Texture2D tileMap;
57        private EntityComprarer comparer = new EntityComprarer();
58        private AnimationHelper waterAnimation = new AnimationHelper(10, 2);
59
60        public Level(Texture2D tileMap)
61        {
62            this.tileMap = tileMap;
63            width = tileMap.Width;
64            height = tileMap.Height;
65
66            tiles = new int[width * height];
67            data = new byte[width * height];
68            registeredTiles = new List<Tile>();
69
70            new Tile(this);
71            InitTiles();
72
73            entities = new List<Entity>();
74            tileEntities = new List<TileEntity>();
75            entitiesInTiles = new List<Entity>[width * height];
76            for (int i = 0; i < width * height; i++)
77                entitiesInTiles[i] = new List<Entity>();
78            entitesToRender = new SortedSet<Entity>(comparer);
79
80            InitLevel();
81        }
82
83        public int Width { get { return width; } }
84
85        public int Height { get { return height; } }
86
87        public List<Tile> RegisteredTiles { get { return registeredTiles; } }
88
89        public int WaterTimer { get { return waterAnimation.CurrentFrame; } }
90
91        protected virtual void InitTiles() { }
92
93        protected virtual void InitLevel() { }
94
95        public void RenderBackground(Camera camera, RenderHelper renderer)
96        {
97            float w = (Game.WIDTH / Viewport.FLOOR_TILE_WIDTH) / Viewport.ZOOM;
98            float h = (Game.HEIGHT / Viewport.Y_STEP) / Viewport.ZOOM;
99
100            int x0 = (int)((camera.XLeft / Viewport.FLOOR_TILE_WIDTH) / Viewport.ZOOM) - 3;
101            int y0 = (int)((camera.YTop / Viewport.Y_STEP) / Viewport.ZOOM) - 5;
102            int x1 = (int)(x0 + w) + 5;
103            int y1 = (int)(y0 + h) + 7;
104
105            renderer.SetOffset(camera);
106            int tp;
107            for (int y = y0; y < y1; y++)
108            {
109                for (int x = x0; x < x1; x++)
110                {
111                    int xTile = x + (y >> 1) + (y & 1);
112                    int zTile = (y >> 1) - x;
113
114                    if (xTile >= 0 && zTile >= 0 && xTile < width && zTile < height)
115                    {
116                        tp = xTile + zTile * width;
117                        Tile t = registeredTiles[tiles[tp]];
118                        if (t.ID != TILE_VOID)
119                            t.Render(renderer, this, new Vector2((x * Viewport.FLOOR_TILE_WIDTH + (y & 1) * Viewport.X_STEP) * Viewport.ZOOM, (y * Viewport.Y_STEP + Viewport.Y_STEP) * Viewport.ZOOM), xTile, zTile, data[tp]);
120                        entitiesInTiles[tp].ForEach(ent => entitesToRender.Add(ent));
121                    }
122                }
123            }
124
125            renderer.SetOffset();
126        }
127
128        public void RenderEntities(Camera camera, RenderHelper renderer)
129        {
130            if (entitesToRender.Count > 0)
131            {
132                renderer.SetOffset(camera);
133
134                foreach (Entity ent in entitesToRender)
135                    ent.Render(renderer);
136
137                renderer.SetOffset();
138
139                entitesToRender.Clear();
140            }
141        }
142
143        public void Update()
144        {
145            waterAnimation.UpdateStep();
146
147            for (int i = 0; i < UPDATES_IN_TICK; i++)
148            {
149                int xTile = Game.Random.Next(width);
150                int zTile = Game.Random.Next(height);
151
152                registeredTiles[tiles[xTile + zTile * width]].Update(this, xTile, zTile);
153
154                if (tileEntities.Count > 0)
155                    tileEntities[Game.Random.Next(tileEntities.Count)].Update();
156            }
157
158            foreach (Entity ent in entities)
159            {
160                int xTile_old = (int)(ent.X / Viewport.TILESIZE);
161                int zTile_old = (int)(ent.Z / Viewport.TILESIZE);
162
163                ent.Update();
164
165                if (ent.Removed)
166                {
167                    RemoveEntity(ent);
168                    TakeEntity(ent, xTile_old, zTile_old);
169                    continue;
170                }
171
172                int xTile = (int)(ent.X / Viewport.TILESIZE);
173                int zTile = (int)(ent.Z / Viewport.TILESIZE);
174
175                if (xTile != xTile_old || zTile != zTile_old)
176                {
177                    TakeEntity(ent, xTile_old, zTile_old);
178                    InsertEntity(ent, xTile, zTile);
179                }
180            }
181        }
182
183        public void SetTile(int tileX, int tileZ, int tileID)
184        {
185            if (IsValidPos(tileX, tileZ))
186                tiles[tileX + tileZ * width] = tileID;
187        }
188
189        public void SetData(int tileX, int tileZ, byte dataVal)
190        {
191            if (IsValidPos(tileX, tileZ))
192                data[tileX + tileZ * width] = dataVal;
193        }
194
195        public Tile GetTile(int tileX, int tileZ)
196        {
197            return IsValidPos(tileX, tileZ) ? registeredTiles[tiles[tileX + tileZ * width]] : registeredTiles[TILE_VOID];
198        }
199
200        public byte GetData(int tileX, int tileZ)
201        {
202            return IsValidPos(tileX, tileZ) ? data[tileX + tileZ * width] : (byte)0;
203        }
204
205        public void AddEntity(Entity ent, float xPos, float zPos)
206        {
207            int xTile = (int)(xPos / Viewport.TILESIZE);
208            int zTile = (int)(zPos / Viewport.TILESIZE);
209
210            if (!IsValidPos(xTile, zTile)) return;
211
212            ent.X = xPos;
213            ent.Z = zPos;
214
215            ent.Init();
216
217            if (typeof(TileEntity).IsAssignableFrom(ent.GetType()))
218                tileEntities.Add((TileEntity)ent);
219            else
220                entities.Add(ent);
221
222            InsertEntity(ent, xTile, zTile);
223        }
224
225        private void InsertEntity(Entity ent, int xTile, int zTile)
226        {
227            entitiesInTiles[xTile + zTile * width].Add(ent);
228        }
229
230        private void TakeEntity(Entity ent, int xTile, int zTile)
231        {
232            entitiesInTiles[xTile + zTile * width].Remove(ent);
233        }
234
235        private void RemoveEntity(Entity ent)
236        {
237            ent.OnRemoved();
238
239            entities.Remove(ent);
240
241            TakeEntity(ent, (int)(ent.X / Viewport.TILESIZE), (int)(ent.Z / Viewport.TILESIZE));
242        }
243
244        private bool IsValidPos(int tileX, int tileZ)
245        {
246            return (tileX >= 0 && tileZ >= 0 && tileX < width && tileZ < height);
247        }
248    }
249}
Note: See TracBrowser for help on using the repository browser.