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

Revision 2639, 9.5 KB checked in by hniemi, 8 years ago (diff)

Lisätty siirtojen laskeminen

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