Probabilmente otterrò la candidatura come "Worst Arkanoid Ever" e "Worst F# Code Ever" con discrete possibilità di vittoria.
In ogni caso ho mosso da pochi giorni i primi passi con F# e mi premeva capire come poterlo integrare con XNA 4 e come ereditare e fare overriding di metodi di classi .NET.
Con la poca sintassi che ho imparato questo è il risultato.
Il progetto è scaricabile da qui.
open System open Microsoft.Xna.Framework open Microsoft.Xna.Framework.Graphics open Microsoft.Xna.Framework.Input module Farkanoid = type GameState = { mutable running: bool } type PlayerBrick = { mutable texture : Texture2D mutable position : Vector2 lives : int } type Ball = { mutable texture : Texture2D mutable position : Vector2 mutable direction: Vector2 velocity : int } type CollisionSide = None | Left | Right | Top | Bottom let initTexture(graphics : GraphicsDevice, width : int, height : int) = let mutable colorList = [] let texture = new Texture2D(graphics, width, height) for i = 1 to height do for j = 1 to width do if (j = 1) || (i = 1) || (j = width) || (i = height) || (j = 2) || (i = 2) || (j = width - 1) || (i = height - 1) then colorList <- Color.DarkGray :: colorList else colorList <- Color.White :: colorList let colorArray = List.toArray(colorList) texture.SetData(colorArray) texture let initBrickList(texture : Texture2D) = let mutable brickList : Brick list = [] for i = 0 to 5 do for j = 0 to i do let (c : float),(k : float) = (float)i,(float)j let offsetX : float = (float)texture.Width * (k - (0.5 * c) - 0.5) let offsetY : float = ((float)texture.Height * 0.5) - (c * (float)texture.Height) let brickPosition = new Vector2(320.0 + offsetX |> float32 , 120.0 + offsetY |> float32) let brick = { position = brickPosition live = 2 } brickList <- brick :: brickList brickList type FarkanoidGame() as this = inherit Game() let mutable spriteBatch = null let graphicsDeviceManager = new GraphicsDeviceManager(this) let mutable brickTexture = null let mutable brickList : Brick list = [] let mutable state = { running = false } let mutable playerBrick = { texture = null position = new Vector2(260.0 |> float32, 450 |> float32) lives = 3 } let mutable ball = { texture = null position = new Vector2(playerBrick.position.X + (float32)50, playerBrick.position.Y - (float32)10) direction = Vector2.Zero velocity = 5 } let newDirection() = let rand = new Random() let angle = 0.6 + rand.NextDouble() * 0.3 new Vector2(Math.Cos(angle) |> float32, Math.Sin(angle) |> float32) * (float32)ball.velocity let rec checkBrickCollision () : CollisionSide = let collision = ref CollisionSide.None if ball.position.Y < (float32)300 then let rec updateBrickList(brickList) = match brickList with | [] -> [] | brick::list -> if (ball.position.X + (float32)10 >= brick.position.X) && (ball.position.X <= brick.position.X + (float32)100) then if (ball.position.Y + (float32)10 >= brick.position.Y) && (ball.position.Y <= brick.position.Y + (float32)20) then if (ball.position.X <= brick.position.X) then collision := CollisionSide.Left elif (ball.position.X + (float32)10 >= brick.position.X + (float32)100) then collision := CollisionSide.Right elif (ball.position.Y + (float32)10 <= brick.position.Y + (float32)20) then collision := CollisionSide.Top else collision := CollisionSide.Bottom if brick.live > 1 then brick.live <- 1 brick::updateBrickList(list) else list else brick::updateBrickList(list) else brick::updateBrickList(list) brickList <- updateBrickList(brickList) collision.Value member private this.updateInput : bool = let keyboardState = Keyboard.GetState() let mutable pressedKey = false if keyboardState.IsKeyDown(Keys.Left) then playerBrick.position.X <- (playerBrick.position.X - (float32)5) pressedKey <- true elif keyboardState.IsKeyDown(Keys.Right) then playerBrick.position.X <- (playerBrick.position.X + (float32)5) pressedKey <- true playerBrick.position.X <- MathHelper.Clamp(playerBrick.position.X, (float32)10, (float32)510) pressedKey member private this.updateBall : bool = let mutable gameOver = false let mutable xChanger = (float32)1 let mutable yChanger = (float32)1 let mutable change = false let collisionSide = checkBrickCollision() (*bottom Collision (top of the brick) *) if collisionSide = CollisionSide.Top then if ball.direction.X < (float32)0.0 then xChanger <- float32(-1) yChanger <- float32(-1) change <- true if ball.position.Y >= (playerBrick.position.Y - (float32)10) then if (ball.position.X >= playerBrick.position.X) && (ball.position.X <= (playerBrick.position.X + (float32)120)) then if ball.direction.X < (float32)0.0 then xChanger <- float32(-1) yChanger <- float32(-1) change <- true else state.running <- false brickList <- initBrickList(brickTexture) playerBrick.position <- new Vector2(260.0 |> float32, 450 |> float32) ball.position <- new Vector2(playerBrick.position.X + (float32)50, playerBrick.position.Y - (float32)10) ball.direction <- Vector2.Zero (*right Collision (left of the brick)*) if ball.position.X >= (float32)620 || collisionSide = CollisionSide.Left then if ball.direction.Y < (float32)0.0 then yChanger <- float32(-1) xChanger <- float32(-1) change <- true (*left Collision (right of the brick)*) if ball.position.X <= (float32)10 || collisionSide = CollisionSide.Right then if ball.direction.Y < (float32)0.0 then yChanger <- float32(-1) change <- true (*top Collision (bottom of the brick)*) if ball.position.Y <= (float32)10 || collisionSide = CollisionSide.Bottom then if ball.direction.X < (float32)0.0 then xChanger <- float32(-1) change <- true if change then let newDirection = newDirection() ball.direction.X <-newDirection.X * xChanger ball.direction.Y <- newDirection.Y * yChanger ball.position <- ball.position + ball.direction gameOver override Super.Initialize() = graphicsDeviceManager.PreferredBackBufferHeight <- 480 graphicsDeviceManager.PreferredBackBufferWidth <- 640 graphicsDeviceManager.ApplyChanges() base.Initialize() override Super.LoadContent() = playerBrick.texture <- initTexture(this.GraphicsDevice, 120, 20) ball.texture <- initTexture(this.GraphicsDevice, 11,11) brickTexture <- initTexture(this.GraphicsDevice, 100, 20) brickList <- initBrickList(brickTexture) spriteBatch <- new SpriteBatch(this.GraphicsDevice) override Super.Update(time : GameTime) = match state.running with | false -> if this.updateInput then state.running <- true | true -> ignore(this.updateInput) ignore(this.updateBall) base.Update(time) override Super.Draw(time : GameTime) = this.GraphicsDevice.Clear(Color.Black) spriteBatch.Begin() spriteBatch.Draw(playerBrick.texture, playerBrick.position, Color.CornflowerBlue) spriteBatch.Draw(ball.texture, ball.position, Color.Red) for brick in brickList do if brick.live > 1 then spriteBatch.Draw(brickTexture, brick.position, Color.White) else spriteBatch.Draw(brickTexture, brick.position, Color.Gray) spriteBatch.End() base.Draw(time) let farkanoidGame = new FarkanoidGame() farkanoidGame.Run() farkanoidGame.Dispose()
Nessun commento:
Posta un commento