Created
July 23, 2013 18:33
-
-
Save eleco/6064912 to your computer and use it in GitHub Desktop.
Scala Breakout
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.Some | |
import scala.swing._ | |
import scala.util.Random | |
import java.awt.Color | |
import java.util.Timer | |
import java.util.TimerTask | |
import swing.event._ | |
object Breakout extends SimpleSwingApplication { | |
def top = new MainFrame { | |
title = "BreakOut" | |
contents = new Panel() { | |
focusable = true | |
requestFocus | |
preferredSize = new Dimension(WIDTH, HEIGHT) | |
listenTo(keys) | |
reactions += { | |
case e: KeyPressed if e.key == Key.Right => pallet.move(15) | |
case e: KeyPressed if e.key == Key.Left => pallet.move(-15) | |
} | |
val bricks: List[Drawable] = for (i <- List.range(1, 6)) yield new Brick(i * 30, 20, 20, 15) | |
val borders: List[Drawable] = List(new Border(1, 1, WIDTH, 1), new Border(1, 1, 1, HEIGHT), new Border(WIDTH, 1, 1, HEIGHT), new Border(1, WIDTH, 1, HEIGHT)) | |
val pallet = new Pallet(WIDTH / 2, HEIGHT - 10, 50, 10) | |
val ball = new Ball(120, 50, 5, 5) | |
val world = new World(List(ball, pallet) ::: bricks ::: borders) | |
override def paintComponent(g: Graphics2D) = { | |
super.paintComponent(g) | |
world.draw(g) | |
} | |
new Timer().scheduleAtFixedRate(new Loop(ball, world, this), 10, 10) | |
} | |
} | |
def WIDTH = 200; | |
def HEIGHT = 200; | |
def end(message: String) { | |
println(message) | |
System.exit(0) | |
} | |
} | |
trait Drawable { | |
var x, y: Int | |
val w, h: Int | |
val c: Color | |
def draw(g: Graphics2D) = { | |
g.setColor(c) | |
g.fillRect(x, y, w, h) | |
} | |
} | |
trait Collideable { | |
def collide(b: Ball, world: World) | |
} | |
class Loop(b: Ball, w: World, p: Panel) extends TimerTask { | |
override def run() = { | |
b.move | |
w.lst foreach { | |
case a: Collideable => a.collide(b, w) | |
case _ => Nil | |
} | |
p.repaint() | |
} | |
} | |
class World(var lst: List[Drawable]) { | |
def draw(g: Graphics2D) = lst.foreach(a => { | |
a.draw(g) | |
}) | |
def remainingBricks() = | |
lst flatMap { | |
case x: Brick => Some(x) | |
case _ => None | |
} | |
} | |
class Border(var x: Int, var y: Int, val w: Int, val h: Int, val c: Color = Color.BLUE) extends Drawable with Collideable { | |
override def collide(b: Ball, world: World) = { | |
if (b.x < x && x <= 1) b.rebound(1 + Random.nextDouble() / 5, b.yspeed) | |
if (b.x > x && x >= Breakout.WIDTH) b.rebound(-1 - Random.nextDouble() / 5, b.yspeed) | |
if (b.y < y && y <= 1) b.rebound(1, 1) | |
if (b.y >= Breakout.HEIGHT) Breakout.end("you lose") | |
} | |
} | |
class Pallet(var x: Int, var y: Int, val w: Int, val h: Int, val c: Color = Color.RED) extends Drawable with Collideable { | |
def move(dx: Int) = { | |
x = x + dx | |
if (x + w > Breakout.WIDTH) x = Breakout.WIDTH - w | |
if (x <= 1) x = 1 | |
} | |
override def collide(b: Ball, world: World) = { | |
if (b.y + b.h >= y && b.y <= y + h && b.x + b.w >= x && b.x <= x + w) { | |
b.rebound(if (b.x < (x + w / 2)) -1 else 1, -1) | |
} | |
} | |
} | |
class Brick(var x: Int, var y: Int, val w: Int, val h: Int, val c: Color = Color.BLUE) extends Drawable with Collideable { | |
override def collide(b: Ball, world: World) = { | |
if (b.y + b.h >= y && b.y <= y + h && b.x + b.w >= x && b.x <= x + w) { | |
b.rebound(-b.xspeed, -b.yspeed) | |
world.lst = world.lst.diff(List(this)) | |
if (world.remainingBricks().isEmpty) Breakout.end("you win") | |
} | |
} | |
} | |
class Ball(var x: Int, var y: Int, val w: Int, val h: Int, val c: Color = Color.BLACK, var xspeed: Double = 0, var yspeed: Double = -1) extends Drawable { | |
def rebound(dx: Double = 0, dy: Double = 0) = { | |
yspeed = dy | |
xspeed = dx | |
move | |
} | |
def move = { | |
x = (x + xspeed).toInt | |
y = (y + yspeed).toInt | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment