source: 2010/23/hniemi/BlockPusher/Blockpusher/Blockpusher/BlockLevel.cs @ 2640

Revision 2640, 10.4 KB checked in by hniemi, 7 years ago (diff)

Tiedostoformaattia muutettu, ja korjatut bugi, että palikoita voi oikeasti työntää...

Kentät myös siirretty hakemistoihin ja hakemisto lisätty projektiin

Line 
1using System;
2using System.IO;
3using System.Collections.Generic;
4using System.Linq;
5using System.Text;
6using Jypeli;
7
8/// <summary>
9/// Class that holds information of level and players location
10/// Also handles movement of player.
11/// </summary>
12public class BlockLevel
13{
14    private static readonly string tagPar = "par: ";
15    private static readonly string tagName = "name: ";
16    private static readonly string tagAuthor = "author: ";
17    private static readonly int levelStartRow = 3;
18
19
20    private Block[,] playfield;
21    private Blockpusher game;
22    private List<Tuple<char, BlockType>> charcolors = new List<Tuple<char, BlockType>>();
23    private List<Block> goals = new List<Block>();
24
25    private int playerX;
26    private int playerY;
27
28    public delegate void GameEvent();
29    public event GameEvent Victory;
30
31    /// <summary>
32    /// Height of the playfield
33    /// </summary>
34    public int PlayfieldHeight { get { return playfield.GetLength(1); } }
35    /// <summary>
36    /// Width of the playfield
37    /// </summary>
38    public int PlayfieldWidth { get { return playfield.GetLength(0); } }
39
40    /// <summary>
41    /// Name of the level
42    /// </summary>
43    public string Name { get; set; }
44
45    /// <summary>
46    /// Author of level
47    /// </summary>
48    public string Author { get;set; }
49
50    /// <summary>
51    /// Movecount
52    /// </summary>
53    public int Moves { get; set; }
54
55    /// <summary>
56    /// How many moves to par score
57    /// </summary>
58    public int ParMoves { get; set; }
59
60    /// <summary>
61    /// Constructor from game
62    /// </summary>
63    /// <param name="game">Game that level is used in</param>
64    public BlockLevel(Blockpusher game)
65    {
66        this.game = game;
67        InitCharColors();
68    }
69
70    /// <summary>
71    /// Adds blocks to game
72    /// </summary>
73    public void AddToGame()
74    {
75        game.Level.Size = new Vector(playfield.GetLength(0) * (Blockpusher.BlockSize + 1), playfield.GetLength(1) * (Blockpusher.BlockSize + 1));
76        game.Level.CreateBorders();
77        for (int i = 0; i < playfield.GetLength(0); i++)
78        {
79            for (int j = 0; j < playfield.GetLength(1); j++)
80            {
81
82                playfield[i, j].X = i * (Blockpusher.BlockSize + 1) + game.Level.Left + (Blockpusher.BlockSize / 2);
83                playfield[i, j].Y = -(j * (Blockpusher.BlockSize + 1) + game.Level.Bottom + (Blockpusher.BlockSize / 2));
84                game.Add(playfield[i,j]);
85            }
86        }
87    }
88
89    /// <summary>
90    /// Moves player x and y steps
91    /// </summary>
92    /// <param name="x">X Movement</param>
93    /// <param name="y">Y Movement</param>
94    public void MovePlayer(int x, int y)
95    {
96        switch (Type(playerX + x, playerY + y))
97        {
98            case BlockType.SatisfiedGoalZone:
99            case BlockType.Movable:
100                int nextX = playerX + x;
101                if (x != 0) { nextX += (x / Math.Abs(x)); }
102                int nextY = playerY + y;
103                if (y != 0) { nextY += (y / Math.Abs(y)); }
104                BlockType t = Type(nextX, nextY);
105                if (t == BlockType.Empty || t == BlockType.GoalZone || t == BlockType.SatisfiedGoalZone)
106                {
107                    Move(playerX + x, playerY + y, nextX, nextY);
108                    Move(playerX, playerY, playerX + x, playerY + y);
109                    playerX += x;
110                    playerY += y;
111                    Moves++;
112                }
113
114                break;
115            case BlockType.GoalZone:
116            case BlockType.Empty:
117                Move(playerX, playerY, playerX + x, playerY + y);
118                playerX += x;
119                playerY += y;
120                Moves++;
121                break;
122            default:
123                break;
124        }
125       
126        VictoryCheck();
127    }
128
129    /// <summary>
130    /// Moves block from place a to place b
131    ///
132    /// Don't move walls!
133    /// </summary>
134    /// <param name="startx">Source X coordinate</param>
135    /// <param name="starty">Source Y coordinate</param>
136    /// <param name="endx">Destination X coordinate</param>
137    /// <param name="endy">Destination Y coordinate</param>
138    public void Move(int startx, int starty, int endx, int endy)
139    {
140        //TODO Works, but fugly.
141        BlockType destType = playfield[endx, endy].Type;
142        BlockType sourType = playfield[startx, starty].Type;
143        bool destGoal = playfield[endx, endy].IsGoalZone;
144        bool sourGoal = playfield[startx, starty].IsGoalZone;
145
146        if (sourGoal)
147        {
148            playfield[startx, starty].Type = BlockType.GoalZone;
149        }
150        else
151        {
152            playfield[startx, starty].Type = BlockType.Empty;
153        }
154
155        if (destGoal)
156        {
157            if (sourType == BlockType.Player) { playfield[endx, endy].Type = BlockType.Player; }
158            if (sourType == BlockType.SatisfiedGoalZone) { playfield[endx, endy].Type = BlockType.SatisfiedGoalZone; }
159            if (sourType == BlockType.Movable) { playfield[endx, endy].Type = BlockType.SatisfiedGoalZone; }
160        }
161        else
162        {
163            if (sourType == BlockType.Player) { playfield[endx, endy].Type = BlockType.Player; }
164            if (sourType == BlockType.SatisfiedGoalZone) { playfield[endx, endy].Type = BlockType.Movable; }
165            if (sourType == BlockType.Movable) { playfield[endx, endy].Type = BlockType.Movable; }
166        }
167    }
168
169    /// <summary>
170    /// Checks if level is completed.
171    /// </summary>
172    /// <returns></returns>
173    public bool VictoryCheck()
174    {
175        foreach (var item in goals)
176        {
177            if (!(item.Type == BlockType.SatisfiedGoalZone)) return false;
178        }
179        if (Victory != null) Victory();
180        return true;
181    }
182
183    /// <summary>
184    /// Initialaizes char->Color-dict.
185    /// </summary>
186    public void InitCharColors()
187    {
188        charcolors.Add(new Tuple<char, BlockType>('x', BlockType.UnMovable));
189        charcolors.Add(new Tuple<char, BlockType>('b', BlockType.Movable));
190        charcolors.Add(new Tuple<char, BlockType>(' ', BlockType.Empty));
191        charcolors.Add(new Tuple<char, BlockType>('m', BlockType.GoalZone));
192        charcolors.Add(new Tuple<char, BlockType>('p', BlockType.Player));
193        charcolors.Add(new Tuple<char, BlockType>('s', BlockType.SatisfiedGoalZone));
194    }
195
196    /// <summary>
197    /// Finds char matching type.
198    /// If not found, return ' '
199    /// </summary>
200    /// <param name="type">Type you want to find</param>
201    /// <returns>Matching char</returns>
202    public char FindChar(BlockType type) 
203    {
204        foreach (var item in charcolors)
205        {
206            if (item.Item2 == type) return item.Item1;
207        }
208        return ' ';
209    }
210
211    /// <summary>
212    /// Finds Blocktype matching char.
213    /// If not found, BlockType.Empty is returned.
214    /// </summary>
215    /// <param name="c">Char you want to find</param>
216    /// <returns>Matching type</returns>
217    public BlockType FindBlockType(char c)
218    {
219        foreach (var item in charcolors)
220        {
221            if (item.Item1 == c) return item.Item2;
222        }
223        return BlockType.Empty;
224    }
225
226    /// <summary>
227    /// Creates playfield from given list of strings
228    /// </summary>
229    /// <param name="level"></param>
230    public void CreateField(IList<string> level)
231    {
232        int playfieldWidth = level[levelStartRow].Length;
233        int playfieldHeight = level.Count - levelStartRow;
234
235        Name = level[0].Substring(tagName.Length);
236        Author = level[1].Substring(tagAuthor.Length);
237        ParMoves = int.Parse(level[2].Substring(tagPar.Length));
238       
239
240        playfield = new Block[playfieldWidth, playfieldHeight];
241
242        for (int i = 0; i < playfield.GetLength(0); i++)
243        {
244            for (int j = 0; j < playfield.GetLength(1); j++)
245            {
246                Block block = new Block(Blockpusher.BlockSize, Blockpusher.BlockSize);
247                block.X = i * (Blockpusher.BlockSize + 1) + game.Level.Left + (Blockpusher.BlockSize / 2);
248                block.Y = -(j * (Blockpusher.BlockSize + 1) + game.Level.Bottom + (Blockpusher.BlockSize / 2));
249
250                block.Type = FindBlockType(level[j+levelStartRow][i]);
251                if (block.Type == BlockType.Player)
252                {
253                    playerX = i;
254                    playerY = j;
255                }
256                if (block.IsGoalZone)
257                {
258                    goals.Add(block);
259                }
260                playfield[i, j] = block;
261            }
262        }
263        UpdatePlayer(BlockType.Player);
264    }
265
266    /// <summary>
267    /// Checks if given coordinates are empty and can be moved to.
268    ///
269    /// If coordinates are not in playfield, UnMovable is returned.
270    /// </summary>
271    /// <param name="x">X-coordinate</param>
272    /// <param name="y">Y-coordinate</param>
273    /// <returns>State of block at given coordinates</returns>
274    public BlockType Type(int x, int y)
275    {
276        if (x < 0) return BlockType.UnMovable;
277        if (y < 0) return BlockType.UnMovable;
278        if (x >= PlayfieldWidth) return BlockType.UnMovable;
279        if (y >= PlayfieldHeight) return BlockType.UnMovable;
280
281        return playfield[x, y].Type;
282    }
283
284    /// <summary>
285    /// Returns the current state of level.
286    /// </summary>
287    /// <returns></returns>
288    public IList<string> CurrentState() 
289    {
290        List<string> list = new List<string>();
291
292        list.Add(tagName + Name);
293        list.Add(tagAuthor + Author);
294        list.Add(tagPar + ParMoves);
295
296        for (int i = 0; i < playfield.GetLength(1); i++)
297        {
298            StringBuilder line = new StringBuilder();
299            for (int j = 0; j < playfield.GetLength(0); j++)
300            {
301               
302                line.Append(FindChar(playfield[j,i].Type));
303            }
304            list.Add(line.ToString());
305        }
306
307        return list;
308    }
309
310    /// <summary>
311    /// Changes color of players coordinates
312    /// </summary>
313    /// <param name="color">Color</param>
314    public void UpdatePlayer(BlockType type)
315    {
316        playfield[playerX, playerY].Type = type;
317    }
318
319    public BlockLevel Clone() 
320    {
321        BlockLevel clone = new BlockLevel(game);
322        clone.CreateField(this.CurrentState());
323
324        return clone;
325    }
326}
327
Note: See TracBrowser for help on using the repository browser.