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