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

Revision 2641, 10.7 KB checked in by hniemi, 7 years ago (diff)

Nyt pelitilanteen jatkaminen säilyttää myös liikutusten määrän ja kestää pelin sammuttamisen.

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