随机飘动的泡泡

  • 2019 年 10 月 6 日
  • 筆記
import javafx.geometry.Pos  import javafx.scene.canvas.Canvas  import javafx.scene.canvas.GraphicsContext  import javafx.scene.paint.Color  import javafx.scene.paint.Paint  import javafx.scene.shape.Circle  import javafx.scene.text.FontWeight  import tornadofx.*  import java.util.*  import kotlin.system.exitProcess    class AlgoApp : App(AlgoFrame::class, Styles::class) {      override fun stop() {          super.stop()          // 退出进程,runAsync也一并退出          exitProcess(0)      }  }    class AlgoFrame : View("随机飘动的泡泡") {      lateinit var cv: Canvas      val R = 50.0      var circles = mutableListOf<MyCircle>()      override val root = borderpane {          center = canvas(700.0, 300.0) {              cv = this              with(cv.graphicsContext2D) {                  strokeRect(0.0,0.0,cv.width,cv.height)              }          }      }        private fun runn(){       runAsync {              while (true) {                  render()                  AlgoVisHelper.pause(20)                  circles.forEach {                      it.move(0,0,cv.width.toInt(),cv.height.toInt())                  }              }          }      }        private fun render() {          repaint()      }        private fun repaint() {          cv.graphicsContext2D.clearRect(0.0, 0.0, cv.width, cv.height)          cv.graphicsContext2D.strokeRect(0.0,0.0,cv.width,cv.height)          paintComponent(cv.graphicsContext2D)      }        private fun paintComponent(g: GraphicsContext) {          g.fill = Color.RED          g.stroke= Paint.valueOf("red")          circles.forEach {              g.strokeOval(it.centerX, it.centerY, it.radius, it.radius)          }      }        init {          circles = genCircles()          paintComponent(cv.graphicsContext2D)          runn()      }        private fun genCircles(): MutableList<MyCircle> {          return (0..10).map {              val x = Random().nextDouble() * (700 - 2 * R) + R              val y = Random().nextDouble() * (300 - 2 * R) + R              val vx = Random().nextDouble() * 11 - 5              val vy = Random().nextDouble() * 11 - 5              MyCircle(x, y, R, vx, vy)          }.toMutableList()      }    }    class MyCircle(var x: Double, var y: Double, var r: Double, var vx: Double, var vy: Double) : Circle(x, y, r) {      fun move(minx: Int, miny: Int, maxx: Int, maxy: Int) {          this.centerX += vx          this.centerY += vy          this.x += vx          this.y += vy          checkCollision(minx,miny,maxx,maxy)      }        private fun checkCollision(minx: Int, miny: Int, maxx: Int, maxy: Int) {          if (x - r < minx) {              x = r              vx = -vx          }          if (x + r >= maxx) {              x = maxx - r              vx = -vx          }          if (y - r < miny) {              y = r              vy = -vy          }          if (y + r >= maxy) {              y = maxy - r              vy = -vy          }      }  }    class Styles : Stylesheet() {      init {          button {              padding = box(10.px)              alignment = Pos.CENTER              backgroundColor += c("#DD7549")              fontWeight = FontWeight.EXTRA_BOLD              fontSize = 14.px                and(hover) {                  backgroundColor += c("#A05434")                  textFill = Color.WHITE              }          }          label {              fontSize = 14.px              textFill = Color.RED          }      }  }