Skip to content

Instantly share code, notes, and snippets.

@eleco
Created July 23, 2013 18:33
Show Gist options
  • Save eleco/6064912 to your computer and use it in GitHub Desktop.
Save eleco/6064912 to your computer and use it in GitHub Desktop.
Scala Breakout
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