public Game() : base(640, 480, new OpenTK.Graphics.GraphicsMode(32, 24, 0, 8)) { Title = ""; slevel = "menu"; WindowBorder = WindowBorder.Fixed; if (SoundManager.volume == -1) { SoundManager.volume = 0.1f; } DialogBox.cd = intro[0].color; DialogBox.LoadString(intro[0].msg); GL.Enable(EnableCap.Texture2D); GL.Enable(EnableCap.Blend); //Set how the alpha blending function works GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); ObjectHandler.Load(); Input.Initialize(this); view = new View(Vector2.Zero, 1f, 0.0); } //Window initializer
public Level(string filePath) { this.filePath = filePath; try { if (Path.GetExtension(filePath).ToLower() == ".xml" || Path.GetExtension(filePath).ToLower() == ".tmx") { #region Loading XML using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { XmlDocument doc = new XmlDocument(); doc.Load(stream); int width = int.Parse(doc.DocumentElement.GetAttribute("width")); int height = int.Parse(doc.DocumentElement.GetAttribute("height")); this.grid = new Block[width, height]; this.filePath = filePath; this.playerStartPos = new Point(1, 1); XmlNode tileLayer = doc.DocumentElement.SelectSingleNode("layer[@name='Tile Layer 1']"); XmlNode data = tileLayer.SelectSingleNode("data"); XmlNodeList tiles = data.SelectNodes("tile"); int x = 0, y = 0; for (int i = 0; i < tiles.Count; i++) { int gid = int.Parse(tiles[i].Attributes["gid"].Value); switch (gid) { case 0: //Empty space grid[x, y] = new Block(BlockType.Empty, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 26: //Torch grid[x, y] = new Block(BlockType.Empty, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 44: //WaterBody grid[x, y] = new Block(BlockType.Empty, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 103: //WaterHead grid[x, y] = new Block(BlockType.Empty, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 8: //LavaBody grid[x, y] = new Block(BlockType.Empty, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 151: //LavaLadder grid[x, y] = new Block(BlockType.Ladder, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 139: //LavaHead grid[x, y] = new Block(BlockType.Empty, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 25: //FireflowerBlock grid[x, y] = new Block(BlockType.FlowerBlock, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 20: //LadderTop grid[x, y] = new Block(BlockType.Ladder, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 32: //LadderMid grid[x, y] = new Block(BlockType.Ladder, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 34: //LadderwithPlatform grid[x, y] = new Block(BlockType.LadderPlatform, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 121: //CoinBlock grid[x, y] = new Block(BlockType.CoinBlock, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 125: //Bridge grid[x, y] = new Block(BlockType.Platform, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; case 41: //Sign grid[x, y] = new Block(BlockType.Empty, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; default: //Everything else not defined here is solid grid[x, y] = new Block(BlockType.Block1, x, y, (((gid - 1) % 12) * 72), (int)Math.Floor((float)(gid - 1) / 12) * 72); break; } x++; if (x >= width) { x = 0; y++; } } XmlNode objectsLayer = doc.DocumentElement.SelectSingleNode("objectgroup[@name='Objects']"); XmlNodeList objects = objectsLayer.SelectNodes("object"); for (int i = 0; i < objects.Count; i++) { switch (objects[i].Attributes["name"].Value) { case "playerStartPos": int posX = int.Parse(objects[i].Attributes["x"].Value); int posY = int.Parse(objects[i].Attributes["y"].Value); this.playerStartPos = new Point((int)(posX / 70), (int)(posY / 70)); break; case "slime": int xx = int.Parse(objects[i].Attributes["x"].Value); int yy = int.Parse(objects[i].Attributes["y"].Value); Game.enemies.Add(new Enemy(new Slime(new Vector2(xx / 70 + 0.5f, yy / 70 + 0.5f) * 48, new Vector2(0, 0.5f)), 0)); break; case "snail": int xxx = int.Parse(objects[i].Attributes["x"].Value); int yyy = int.Parse(objects[i].Attributes["y"].Value); Game.enemies.Add(new Enemy(new Snail(new Vector2(xxx / 70 + 0.5f, yyy / 70 + 0.5f) * 48, new Vector2(0, 0.5f)), 1)); break; case "ghost": int x2 = int.Parse(objects[i].Attributes["x"].Value); int y2 = int.Parse(objects[i].Attributes["y"].Value); Game.enemies.Add(new Enemy(new Ghost(new Vector2(x2 / 70 + 0.5f, y2 / 70 + 0.5f) * 48, new Vector2(0, 0.5f)), 3)); break; case "eventghost": int x3 = int.Parse(objects[i].Attributes["x"].Value); int y3 = int.Parse(objects[i].Attributes["y"].Value); Game.enemies.Add(new Enemy(new EventGhost(new Vector2(x3 / 70 + 0.5f, y3 / 70 + 0.5f) * 48, new Vector2(0, 0.5f)), 4)); break; case "coin": int xxxx = int.Parse(objects[i].Attributes["x"].Value); int yyyy = int.Parse(objects[i].Attributes["y"].Value); Vector2 po = new Vector2(xxxx / 70, yyyy / 70) * 48; ObjectHandler.AddObject(ObjectHandler.ObjectType.StandingCoin, po); break; case "grass": int xxxxx = int.Parse(objects[i].Attributes["x"].Value); int yyyyy = int.Parse(objects[i].Attributes["y"].Value); Game.enemies.Add(new Enemy(new GrassBlock(new Vector2(xxxxx / 70 + 0.5f, yyyyy / 70 + 0.5f) * 48, new Vector2(0, 0.5f)), 2)); break; case "piranha": int x5 = int.Parse(objects[i].Attributes["x"].Value); int y5 = int.Parse(objects[i].Attributes["y"].Value); Game.enemies.Add(new Enemy(new Piranha(new Vector2(x5 / 70 + 0.5f, y5 / 70 + 0.5f) * 48, new Vector2(0, 0.5f)), 5)); break; case "door": int x1 = int.Parse(objects[i].Attributes["x"].Value); int y1 = int.Parse(objects[i].Attributes["y"].Value); Vector2 p1 = new Vector2(x1 / 70, y1 / 70) * 48; ObjectHandler.AddObject(ObjectHandler.ObjectType.Door, p1); break; case "init_ghostevent": int x4 = int.Parse(objects[i].Attributes["x"].Value); int y4 = int.Parse(objects[i].Attributes["y"].Value); for (int t = 0; t < 13; t++) { Game.enemies.Add(new Enemy(new EventGhost(new Vector2(x4 / 70 + 0.5f, y4 / 70 + 0.5f) * 48, new Vector2(0, 0.5f)), 4)); } break; case "logo": int xy1 = int.Parse(objects[i].Attributes["x"].Value); int yy1 = int.Parse(objects[i].Attributes["y"].Value); Vector2 py1 = new Vector2((new Vector2(xy1 / 70, yy1 / 70) * 48).X - 15, (new Vector2(xy1 / 70, yy1 / 70) * 48).Y); ObjectHandler.AddObject(ObjectHandler.ObjectType.Logo, py1); break; case "cursor": ObjectHandler.AddObject(ObjectHandler.ObjectType.Cursor, new Vector2(300, 460)); break; case "play": ObjectHandler.AddObject(ObjectHandler.ObjectType.Play, new Vector2(336, 460)); break; case "options": ObjectHandler.AddObject(ObjectHandler.ObjectType.Options, new Vector2(336, 508)); break; case "spongesad": ObjectHandler.AddObject(ObjectHandler.ObjectType.SadSponge, new Vector2(350, 706)); break; case "thebones": ObjectHandler.AddObject(ObjectHandler.ObjectType.TheBones, new Vector2(513, 741)); break; case "man_of_mystery": ObjectHandler.AddObject(ObjectHandler.ObjectType.RedBrother, new Vector2(550, 600)); break; case "shadow": ObjectHandler.AddObject(ObjectHandler.ObjectType.Shadow, new Vector2(72, 380)); break; default: Console.WriteLine("Unknown object: {0}", objects[i].Attributes["name"].Value); break; } } } #endregion } else { #region Loading Level using (StreamReader reader = new StreamReader(filePath)) { string line = reader.ReadLine(); int width = int.Parse(line.Substring(0, line.IndexOf(','))); int height = int.Parse(line.Substring(line.IndexOf(',') + 1, line.Length - 1 - line.IndexOf(','))); playerStartPos = new Point(1, 1); grid = new Block[width, height]; line = reader.ReadLine(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { char current = line[x]; switch (current) { case '@': grid[x, y] = new Block(BlockType.Block1, x, y, x, y); break; case '-': grid[x, y] = new Block(BlockType.Platform, x, y, x, y); break; case '#': grid[x, y] = new Block(BlockType.Ladder, x, y, x, y); break; case '=': grid[x, y] = new Block(BlockType.LadderPlatform, x, y, x, y); break; case '&': grid[x, y] = new Block(BlockType.Empty, x, y, x, y); playerStartPos = new Point(x, y); break; default: grid[x, y] = new Block(BlockType.Empty, x, y, x, y); break; } } line = reader.ReadLine(); } } #endregion } } catch (Exception e) { Console.WriteLine("Something went wrong while loading '{0}'.", filePath); Console.WriteLine("Exception was: '{0}'", e); #region Create Empty Room //We'll create an empty level with size 20,20 this.grid = new Block[20, 20]; playerStartPos = new Point(10, 18); for (int x = 0; x < 20; x++) { for (int y = 0; y < 20; y++) { if (x == 0 || y == 0 || x == 19 || y == 19) { this.grid[x, y] = new Block(BlockType.Block1, x, y, x, y); } else { this.grid[x, y] = new Block(BlockType.Empty, x, y, x, y); } } } #endregion } }
private void ResolveCollisions(ref Level level) { int minX = (int)Math.Floor((this.position.X - this.size.X / 2f) / Game.GRIDSIZE); int minY = (int)Math.Floor((this.position.Y - this.size.Y / 2f) / Game.GRIDSIZE); int maxX = (int)Math.Ceiling((this.position.X + this.size.X / 2f) / Game.GRIDSIZE); int maxY = (int)Math.Ceiling((this.position.Y + this.size.Y / 2f) / Game.GRIDSIZE); this.grounded = false; this.onLadder = false; for (int x = minX; x <= maxX; x++) { for (int y = minY; y <= maxY; y++) { RectangleF blockRec = new RectangleF(x * Game.GRIDSIZE, y * Game.GRIDSIZE, Game.GRIDSIZE, Game.GRIDSIZE); if (level[x, y].IsSolid && this.ColRec.IntersectsWith(blockRec)) { if ((level[x, y].posY + 1) * 48 < this.position.Y && !grounded && this.position.X >= 48 * level[x, y].posX && this.position.X < 48 * (level[x, y].posX + 1)) { if (level[x, y].IsCoin) { ObjectHandler.AddObject(ObjectHandler.ObjectType.Coin, new Vector2(level[x, y].posX * 48, (level[x, y].posY - 1) * 48)); Block b = new Block(BlockType.Block1, level[x, y].posX, level[x, y].posY, 0, 648); level[x, y] = b; SoundManager.sounds[2].Play(); View.Coins += 1; } else if (level[x, y].IsFlower) { ObjectHandler.AddObject(ObjectHandler.ObjectType.Fireflower, new Vector2(level[x, y].posX * 48, (level[x, y].posY - 1) * 48)); Block b = new Block(BlockType.Block1, level[x, y].posX, level[x, y].posY, 0, 72); level[x, y] = b; } else if (level[x, y].tileX == 0) { SoundManager.sounds[1].Play(); } } #region Resolve float[] depths = new float[4] { blockRec.Right - ColRec.Left, //PosX blockRec.Bottom - ColRec.Top, //PosY ColRec.Right - blockRec.Left, //NegX ColRec.Bottom - blockRec.Top //NegY }; if (level[x + 1, y].IsSolid) { depths[0] = -1; } if (level[x, y + 1].IsSolid || level[x, y].IsPlatform) { depths[1] = -1; } if (level[x - 1, y].IsSolid) { depths[2] = -1; } if (level[x, y - 1].IsSolid) { depths[3] = -1; } float min = float.MaxValue; Vector2 minDirection = Vector2.Zero; for (int i = 0; i < 4; i++) { if (depths[i] >= 0 && depths[i] < min) { min = depths[i]; switch (i) { case 0: minDirection = new Vector2(1, 0); break; case 1: minDirection = new Vector2(0, 1); break; case 2: minDirection = new Vector2(-1, 0); break; default: minDirection = new Vector2(0, -1); break; } } } if (minDirection == Vector2.Zero) { //Console.WriteLine("This shouldn't really happen..."); } else { this.position += minDirection * min; if (this.velocity.X * minDirection.X < 0) { this.velocity.X = 0; } if (this.velocity.Y * minDirection.Y < 0) { this.velocity.Y = 0; } if (minDirection == new Vector2(0, -1)) { grounded = true; } } #endregion } if (this.velocity.Y > 0 && (!Input.KeyDown(OpenTK.Input.Key.Down) && !Input.down) && level[x, y].IsPlatform && this.ColRec.IntersectsWith(blockRec)) { if (this.position.Y - this.velocity.Y + this.size.Y / 2f <= blockRec.Top) //if we were above last frame { this.velocity.Y = 0; this.position.Y = blockRec.Top - this.size.Y / 2f; grounded = true; } } if (level[x, y].Isladder && this.ColRec.IntersectsWith(blockRec)) { this.onLadder = true; } } } }
private void HandleInput() { if (!onLadder) { climbing = false; } else if (Input.KeyDown(OpenTK.Input.Key.Up) || Input.up) { climbing = true; } if (grounded) { this.velocity.X *= 0.9f; } else if (climbing) { this.velocity.X *= 0.5f; this.velocity.Y = 0f; if (Input.KeyDown(OpenTK.Input.Key.Up) || Input.up) { this.velocity.Y -= 5f; } if (Input.KeyDown(OpenTK.Input.Key.Down) || Input.down) { this.velocity.Y += 5f; } } if (grounded && !Input.KeyDown(OpenTK.Input.Key.Up) && !Input.up) { climbing = false; } if (Input.KeyDown(OpenTK.Input.Key.Right) || Input.right) { int run = 1; if (Input.KeyDown(OpenTK.Input.Key.X) || Input.B) { run = 2; } if (climbing) { this.velocity.X = 2f; } else if (grounded) { this.velocity.X += 0.5f * run; } else { this.velocity.X += 0.4f * run; } index += 1; if (index == 4) { index = 0; } facingRight = true; if (!fireflower) { sprite = walkAnimation[index]; } else { sprite = firewalkAnimation[index]; } } else if (Input.KeyDown(OpenTK.Input.Key.Left) || Input.left) { int run = 1; if (Input.KeyDown(OpenTK.Input.Key.X) || Input.B) { run = 2; } if (climbing) { this.velocity.X = -2f; } else if (grounded) { this.velocity.X -= 0.5f * run; } else { this.velocity.X -= 0.4f * run; } index += 1; if (index == 4) { index = 0; } facingRight = false; if (!fireflower) { sprite = walkAnimation[index]; } else { sprite = firewalkAnimation[index]; } } else { if (!fireflower) { sprite = walkAnimation[0]; } else { sprite = firewalkAnimation[0]; } } if ((Input.KeyDown(OpenTK.Input.Key.Z) || Input.A) && (grounded || climbing)) { SoundManager.sounds[0].Play(); this.velocity.Y = -16; this.climbing = false; } if ((Input.KeyPress(OpenTK.Input.Key.X) || (Input.B && !Input.lastB)) && fireflower) { sprite = firespriteShoot; if (facingRight) { ObjectHandler.AddObject(ObjectHandler.ObjectType.Fireball, new Vector2(position.X + size.X / 2, position.Y + 5)); } else { ObjectHandler.AddObject(ObjectHandler.ObjectType.Fireball, new Vector2(position.X, position.Y + 5), true); } } }