JS backend: testFiles -> testData

This commit is contained in:
Zalim Bashorov
2014-02-26 15:39:46 +04:00
parent bcd579acdd
commit 442215e829
490 changed files with 0 additions and 0 deletions
@@ -0,0 +1,356 @@
/*
In this example strange creatures are watching the kotlin logo. You can drag'n'drop them as well as the logo.
Doubleclick to add more creatures but be careful. They may be watching you!
*/
package creatures
import js.dom.html5.CanvasContext
import js.jquery.*
import js.dom.html5.CanvasGradient
import js.dom.html5.HTMLCanvasElement
import java.util.ArrayList
import js.dom.html.window
import js.dom.html.HTMLElement
import js.dom.html.HTMLImageElement
fun getImage(path: String): HTMLImageElement {
val image = window.document.createElement("img") as HTMLImageElement
image.src = path
return image
}
val canvas: HTMLCanvasElement
get() {
return window.document.getElementsByTagName("canvas").item(0)!! as HTMLCanvasElement
}
val context: CanvasContext
get() {
return canvas.getContext("2d")!!
}
abstract class Shape() {
abstract fun draw(state: CanvasState)
// these two abstract methods defines that our shapes can be dragged
abstract fun contains(mousePos: Vector): Boolean
abstract var pos: Vector
var selected: Boolean = false
// a couple of helper extension methods we'll be using in the derived classes
fun CanvasContext.shadowed(shadowOffset: Vector, alpha: Double, render: CanvasContext.() -> Unit) {
save()
shadowColor = "rgba(100, 100, 100, $alpha)"
shadowBlur = 5.0
shadowOffsetX = shadowOffset.x
shadowOffsetY = shadowOffset.y
render()
restore()
}
fun CanvasContext.fillPath(constructPath: CanvasContext.() -> Unit) {
beginPath()
constructPath()
closePath()
fill()
}
}
val Kotlin = Logo(v(250.0, 75.0))
class Logo(override var pos: Vector) : Shape() {
val relSize: Double = 0.25
val shadowOffset = v(-3.0, 3.0)
val imageSize = v(377.0, 393.0)
var size: Vector = imageSize * relSize
// get-only properties like this saves you lots of typing and are very expressive
val position: Vector
get() = if (selected) pos - shadowOffset else pos
fun drawLogo(state: CanvasState) {
size = imageSize * (state.size.x / imageSize.x) * relSize
// getKotlinLogo() is a 'magic' function here defined only for purposes of demonstration but in fact it just find an element containing the logo
state.context.drawImage(getImage("http://kotlin-demo.jetbrains.com/static/images/kotlinlogowobackground.png"), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
position.x.toInt(), position.y.toInt(),
size.x.toInt(), size.y.toInt())
}
override fun draw(state: CanvasState) {
val context = state.context
if (selected) {
// using helper we defined in Shape class
context.shadowed(shadowOffset, 0.2) {
drawLogo(state)
}
}
else {
drawLogo(state)
}
}
override fun contains(mousePos: Vector): Boolean = mousePos.isInRect(pos, size)
val centre: Vector
get() = pos + size * 0.5
}
val gradientGenerator: RadialGradientGenerator? = null
get() {
if ($gradientGenerator == null) {
$gradientGenerator = RadialGradientGenerator(context)
}
return $gradientGenerator
}
class Creature(override var pos: Vector, val state: CanvasState) : Shape() {
val shadowOffset = v(-5.0, 5.0)
val colorStops = gradientGenerator!!.getNext()
val relSize = 0.05
// these properties have no backing fields and in java/javascript they could be represented as little helper functions
val radius: Double
get() = state.width * relSize
val position: Vector
get() = if (selected) pos - shadowOffset else pos
val directionToLogo: Vector
get() = (Kotlin.centre - position).normalized
//notice how the infix call can make some expressions extremely expressive
override fun contains(mousePos: Vector) = pos distanceTo mousePos < radius
// defining more nice extension functions
fun CanvasContext.circlePath(position: Vector, rad: Double) {
arc(position.x, position.y, rad, 0.0, 2 * Math.PI, false)
}
//notice we can use an extension function we just defined inside another extension function
fun CanvasContext.fillCircle(position: Vector, rad: Double) {
fillPath {
circlePath(position, rad)
}
}
override fun draw(state: CanvasState) {
val context = state.context
if (!selected) {
drawCreature(context)
}
else {
drawCreatureWithShadow(context)
}
}
fun drawCreature(context: CanvasContext) {
context.fillStyle = getGradient(context)
context.fillPath {
tailPath(context)
circlePath(position, radius)
}
drawEye(context)
}
fun getGradient(context: CanvasContext): CanvasGradient {
val gradientCentre = position + directionToLogo * (radius / 4)
val gradient = context.createRadialGradient(gradientCentre.x, gradientCentre.y, 1.0, gradientCentre.x, gradientCentre.y, 2 * radius)!!
for (colorStop in colorStops) {
gradient.addColorStop(colorStop.first, colorStop.second)
}
return gradient
}
fun tailPath(context: CanvasContext) {
val tailDirection = -directionToLogo
val tailPos = position + tailDirection * radius * 1.0
val tailSize = radius * 1.6
val angle = Math.PI / 6.0
val p1 = tailPos + tailDirection.rotatedBy(angle) * tailSize
val p2 = tailPos + tailDirection.rotatedBy(-angle) * tailSize
val middlePoint = position + tailDirection * radius * 1.0
context.moveTo(tailPos.x.toInt(), tailPos.y.toInt())
context.lineTo(p1.x.toInt(), p1.y.toInt())
context.quadraticCurveTo(middlePoint.x, middlePoint.y, p2.x, p2.y)
context.lineTo(tailPos.x.toInt(), tailPos.y.toInt())
}
fun drawEye(context: CanvasContext) {
val eyePos = directionToLogo * radius * 0.6 + position
val eyeRadius = radius / 3
val eyeLidRadius = eyeRadius / 2
context.fillStyle = "#FFFFFF"
context.fillCircle(eyePos, eyeRadius)
context.fillStyle = "#000000"
context.fillCircle(eyePos, eyeLidRadius)
}
fun drawCreatureWithShadow(context: CanvasContext) {
context.shadowed(shadowOffset, 0.7) {
context.fillStyle = getGradient(context)
fillPath {
tailPath(context)
context.circlePath(position, radius)
}
}
drawEye(context)
}
}
class CanvasState(val canvas: HTMLCanvasElement) {
var width = canvas.width
var height = canvas.height
val size: Vector
get() = v(width, height)
val context = creatures.context
var valid = false
var shapes = ArrayList<Shape>()
var selection: Shape? = null
var dragOff = Vector()
val interval = 1000 / 30
{
jq(canvas).mousedown {
valid = false
selection = null
val mousePos = mousePos(it)
for (shape in shapes) {
if (mousePos in shape) {
dragOff = mousePos - shape.pos
shape.selected = true
selection = shape
break
}
}
}
jq(canvas).mousemove {
if (selection != null) {
selection!!.pos = mousePos(it) - dragOff
valid = false
}
}
jq(canvas).mouseup {
if (selection != null) {
selection!!.selected = false
}
selection = null
valid = false
}
jq(canvas).dblclick {
val newCreature = Creature(mousePos(it), this @CanvasState)
addShape(newCreature)
valid = false
}
window.setInterval({
draw()
}, interval)
}
fun mousePos(e: MouseEvent): Vector {
var offset = Vector()
var element: HTMLElement? = canvas
while (element != null) {
val el: HTMLElement = element!!
offset += Vector(el.offsetLeft, el.offsetTop)
element = el.offsetParent
}
return Vector(e.pageX, e.pageY) - offset
}
fun addShape(shape: Shape) {
shapes.add(shape)
valid = false
}
fun clear() {
context.fillStyle = "#FFFFFF"
context.fillRect(0, 0, width.toInt(), height.toInt())
context.strokeStyle = "#000000"
context.lineWidth = 4.0
context.strokeRect(0, 0, width.toInt(), height.toInt())
}
fun draw() {
if (valid) return
clear()
for (shape in shapes.reversed()) {
shape.draw(this)
}
Kotlin.draw(this)
valid = true
}
}
class RadialGradientGenerator(val context: CanvasContext) {
val gradients = ArrayList<Array<Pair<Double, String>>>()
var current = 0
fun newColorStops(vararg colorStops: Pair<Double, String>) {
gradients.add(colorStops)
}
{
newColorStops(Pair(0.0, "#F59898"), Pair(0.5, "#F57373"), Pair(1.0, "#DB6B6B"))
newColorStops(Pair(0.39, "rgb(140,167,209)"), Pair(0.7, "rgb(104,139,209)"), Pair(0.85, "rgb(67,122,217)"))
newColorStops(Pair(0.0, "rgb(255,222,255)"), Pair(0.5, "rgb(255,185,222)"), Pair(1.0, "rgb(230,154,185)"))
newColorStops(Pair(0.0, "rgb(255,209,114)"), Pair(0.5, "rgb(255,174,81)"), Pair(1.0, "rgb(241,145,54)"))
newColorStops(Pair(0.0, "rgb(132,240,135)"), Pair(0.5, "rgb(91,240,96)"), Pair(1.0, "rgb(27,245,41)"))
newColorStops(Pair(0.0, "rgb(250,147,250)"), Pair(0.5, "rgb(255,80,255)"), Pair(1.0, "rgb(250,0,217)"))
}
fun getNext(): Array<Pair<Double, String>> {
val result = gradients.get(current)
current = (current + 1) % gradients.size()
return result
}
}
fun v(x: Double, y: Double) = Vector(x, y)
class Vector(val x: Double = 0.0, val y: Double = 0.0) {
fun plus(v: Vector) = v(x + v.x, y + v.y)
fun minus() = v(-x, -y)
fun minus(v: Vector) = v(x - v.x, y - v.y)
fun times(koef: Double) = v(x * koef, y * koef)
fun distanceTo(v: Vector) = Math.sqrt((this - v).sqr)
fun rotatedBy(theta: Double): Vector {
val sin = Math.sin(theta)
val cos = Math.cos(theta)
return v(x * cos - y * sin, x * sin + y * cos)
}
fun isInRect(topLeft: Vector, size: Vector) = (x >= topLeft.x) && (x <= topLeft.x + size.x) &&
(y >= topLeft.y) && (y <= topLeft.y + size.y)
val sqr: Double
get() = x * x + y * y
val normalized: Vector
get() = this * (1.0 / Math.sqrt(sqr))
}
fun main(args: Array<String>) {
jq {
val state = CanvasState(canvas)
state.addShape(Kotlin)
state.addShape(Creature(state.size * 0.25, state))
state.addShape(Creature(state.size * 0.75, state))
window.setTimeout({
state.valid = false
}, 1000)
}
}
fun <T> List<T>.reversed(): List<T> {
val result = ArrayList<T>()
var i = size()
while (i > 0) {
result.add(get(--i))
}
return result
}
@@ -0,0 +1,67 @@
/*
This example is based on example from html5 canvas2D docs:
http://www.w3.org/TR/2dcontext/
Note that only a subset of the api is supported for now.
*/
package fancylines
import js.dom.html5.*
import js.dom.html.window
import js.jquery.*
fun main(args: Array<String>) {
jq {
FancyLines().run()
}
}
val canvas: HTMLCanvasElement
get() {
return window.document.getElementsByTagName("canvas").item(0) as HTMLCanvasElement
}
class FancyLines() {
val context = canvas.getContext("2d")!!
val height = canvas.height
val width = canvas.width
var x = width * Math.random()
var y = height * Math.random()
var hue = 0;
fun line() {
context.save();
context.beginPath();
context.lineWidth = 20.0 * Math.random();
context.moveTo(x.toInt(), y.toInt());
x = width * Math.random();
y = height * Math.random();
context.bezierCurveTo(width * Math.random(), height * Math.random(),
width * Math.random(), height * Math.random(), x, y);
hue += Math.random() * 10;
context.strokeStyle = "hsl($hue, 50%, 50%)";
context.shadowColor = "white";
context.shadowBlur = 10.0;
context.stroke();
context.restore();
}
fun blank() {
context.fillStyle = "rgba(255,255,1,0.1)";
context.fillRect(0, 0, width, height);
}
fun run() {
window.setInterval({ line() }, 40);
window.setInterval({ blank() }, 100);
}
}
@@ -0,0 +1,110 @@
/*
This shows simple text floating around.
*/
package hello
import js.dom.html5.*
import js.dom.html.window
import js.jquery.*
val canvas: HTMLCanvasElement
get() {
return window.document.getElementsByTagName("canvas").item(0)!! as HTMLCanvasElement
}
val context: CanvasContext
get() {
return canvas.getContext("2d")!!
}
val width: Double
get() {
return canvas.width
}
val height: Double
get() {
return canvas.height
}
// class representing a floating text
class HelloKotlin() {
var relX = 0.2 + 0.2 * Math.random()
var relY = 0.4 + 0.2 * Math.random()
val absX: Double
get() = (relX * width)
val absY: Double
get() = (relY * height)
var relXVelocity = randomVelocity()
var relYVelocity = randomVelocity()
val message = "Hello, Kotlin!"
val textHeightInPixels = 20
{
context.font = "bold ${textHeightInPixels}px Georgia, serif"
}
val textWidthInPixels = context.measureText(message)!!.width
fun draw() {
context.save()
move()
// if you using chrome chances are good you wont see the shadow
context.shadowColor = "#000000"
context.shadowBlur = 5.0
context.shadowOffsetX = -4.0
context.shadowOffsetY = 4.0
context.fillStyle = "rgb(242,160,110)"
context.fillText(message, absX.toInt(), absY.toInt())
context.restore()
}
fun move() {
val relTextWidth = textWidthInPixels / width
if (relX > (1.0 - relTextWidth - relXVelocity.abs) || relX < relXVelocity.abs) {
relXVelocity *= -1
}
val relTextHeight = textHeightInPixels / height
if (relY > (1.0 - relYVelocity.abs) || relY < relYVelocity.abs + relTextHeight) {
relYVelocity *= -1
}
relX += relXVelocity
relY += relYVelocity
}
fun randomVelocity() = 0.03 * Math.random() * (if (Math.random() < 0.5) 1 else -1)
val Double.abs: Double
get() = if (this > 0) this else -this
}
fun renderBackground() {
context.save()
context.fillStyle = "#5C7EED"
context.fillRect(0, 0, width, height)
context.restore()
}
fun main(args: Array<String>) {
jq {
val interval = 50
// we pass a literal that constructs a new HelloKotlin object
val logos = Array(3) {
HelloKotlin()
}
window.setInterval({
renderBackground()
for (logo in logos) {
logo.draw()
}
}, interval)
}
}
@@ -0,0 +1,508 @@
package traffic
import java.util.ArrayList
import js.dom.html5.CanvasContext
import js.dom.html5.HTMLCanvasElement
import js.dom.html.HTMLImageElement
import js.dom.html.window
import js.jquery.*
import js.dom.html.HTMLElement
fun getImage(path: String): HTMLImageElement {
val image = window.document.createElement("img") as HTMLImageElement
image.src = path
return image
}
val canvas: HTMLCanvasElement
get() {
return window.document.getElementsByTagName("canvas").item(0)!! as HTMLCanvasElement
}
val context: CanvasContext
get() {
return canvas.getContext("2d")!!
}
val PATH_TO_IMAGES = "http://kotlin-demo.jetbrains.com/static/images/canvas/"
var _state: CanvasState? = null
val state: CanvasState
get() {
if (_state == null) {
_state = CanvasState(canvas)
}
return _state!!
}
val colors: Colors
get() {
return Colors()
}
var trafficLightUp = TrafficLight(v(180.0, 181.0), "up", "red")
var trafficLightDown = TrafficLight(v(100.0, 77.0), "down", "red")
var trafficLightLeft = TrafficLight(v(228.0, 109.0), "left", "green")
var trafficLightRight = TrafficLight(v(55.0, 145.0), "right", "green")
fun main(args: Array<String>) {
state.addShape(Map(v(10.0, 10.0)))
state.addShape(trafficLightLeft)
state.addShape(trafficLightUp)
state.addShape(trafficLightDown)
state.addShape(trafficLightRight)
state.addShape(Car(v(178.0, 205.0), "up", "red"))
state.addShape(Car(v(95.0, 4.0), "down", "white"))
state.addShape(Car(v(278.0, 108.0), "left", "blue"))
state.addShape(Car(v(0.0, 142.0), "right", "black"))
state.addShape(Border())
state.addShape(Image(PATH_TO_IMAGES + "controls.png", v(380.0, 10.0), v(190.0, 56.0)))
state.addShape(Button(PATH_TO_IMAGES + "lr.png", v(420.0, 70.0), v(120.0, 50.0)))
state.addShape(Button(PATH_TO_IMAGES + "ud.png", v(455.0, 120.0), v(50.0, 120.0)))
}
fun v(x: Double, y: Double) = Vector(x, y)
class Image(val src: String, override var pos: Vector, var imageSize: Vector) : Shape() {
override fun draw() {
state.context.drawImage(getImage(src), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.x.toInt(), imageSize.y.toInt())
}
fun contains(mousePos: Vector): Boolean = mousePos.isInRect(pos, imageSize)
}
class Button(val src: String, override var pos: Vector, var imageSize: Vector) : Shape() {
var isMouseOver = false
var isMouseDown = false
override fun draw() {
if (isMouseOver) {
state.context.shadowed(v(-3.0, 3.0), 1.2) {
state.context.drawImage(getImage(src), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.x.toInt(), imageSize.y.toInt())
}
}
else if (isMouseDown) {
state.context.shadowed(v(-3.0, 3.0), 0.8) {
state.context.drawImage(getImage(src), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.x.toInt(), imageSize.y.toInt())
}
}
else {
state.context.drawImage(getImage(src), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.x.toInt(), imageSize.y.toInt())
}
}
fun mouseClick() {
isMouseDown = true
window.setTimeout({
isMouseDown = false
}, 1000)
}
fun mouseOver() {
isMouseOver = true
window.setTimeout({
isMouseOver = false
}, 1000)
}
fun contains(mousePos: Vector): Boolean = mousePos.isInRect(pos, imageSize)
}
class Border() : Shape() {
override var pos = Vector(4.0, 4.0);
override fun draw() {
state.context.fillStyle = colors.white
state.context.fillRect(2, 4, 10, 292)
state.context.fillRect(330, 4, 370, 292)
state.context.fillRect(2, 2, 330, 10)
state.context.fillRect(4, 265, 340, 380)
state.context.strokeStyle = colors.black
state.context.lineWidth = 4.0
state.context.strokeRect(0, 0, state.width.toInt(), state.height.toInt())
}
}
class Timer(override var pos: Vector) : Shape() {
var timeLeftForChangeColor: Char = 'c'
var timeStartLastChangeColor = Date().getTime();
var timerLength = 13
override fun draw() {
timeLeftForChangeColor = ("" + (timerLength - (Date().getTime() - timeStartLastChangeColor) / 1000)).get(0)
state.context.font = "bold 9px Arial, serif"
state.context.fillStyle = colors.black
state.context.fillText("" + timeLeftForChangeColor, pos.x.toInt(), pos.y.toInt())
}
fun resetTimer() {
timeStartLastChangeColor = Date().getTime()
timerLength = 10
}
}
//Colors constants
class Colors() {
val black: String = "#000000"
val white = "#FFFFFF"
val grey = "#C0C0C0"
val red = "#EF4137"
val yellow = "#FCE013"
val green = "#0E9648"
}
class TrafficLight(override var pos: Vector, val direction: String, val startColor: String) : Shape() {
val list = ArrayList<TrafficLightItem>()
var size = Vector(27.0, 34.0);
var timer = Timer(Vector(pos.x + 6, pos.y + 12))
var currentColor = startColor;
var isForceColorChange = false
var changeColorForward = (startColor == "red")
{
list.add(TrafficLightItem(v(pos.x, pos.y), PATH_TO_IMAGES + "red_color.png"))
list.add(TrafficLightItem(v(pos.x, pos.y), PATH_TO_IMAGES + "yellow_color.png"))
list.add(TrafficLightItem(v(pos.x, pos.y), PATH_TO_IMAGES + "green_color.png"))
list.add(TrafficLightItem(v(pos.x, pos.y), PATH_TO_IMAGES + "green_color_flash.png"))
}
override fun draw() {
when (currentColor) {
"red" -> list.get(0).draw()
"yellow" -> list.get(1).draw()
"green" -> list.get(2).draw()
"green_flash" -> list.get(3).draw()
else -> {
}
}
timer.draw()
}
fun setRed() {
if (currentColor != "red" && currentColor != "yellow" && currentColor != "green_flash") {
isForceColorChange = true
changeColor()
}
}
fun setGreen() {
if (currentColor != "green" && currentColor != "green_flash" && currentColor != "yellow") {
isForceColorChange = true
changeColor()
}
}
fun changeColor() {
if (changeColorForward) changeColorForward() else changeColorBackward()
}
fun changeColorForward() {
changeColorForward = false
currentColor = "yellow"
window.setTimeout({
if (!isForceColorChange) timer.resetTimer() else isForceColorChange = false
currentColor = "green"
}, 3000)
}
fun changeColorBackward() {
changeColorForward = true
currentColor = "green_flash"
window.setTimeout({
currentColor = "yellow"
window.setTimeout({
if (!isForceColorChange) timer.resetTimer() else isForceColorChange = false
currentColor = "red"
}, 1000)
}, 2000)
}
fun canMove(): Boolean {
return (currentColor != "red" && currentColor != "yellow")
}
}
//One element from Traffic light
class TrafficLightItem(override var pos: Vector, val imageSrc: String) : Shape() {
val relSize: Double = 0.5
val imageSize = v(33.0, 33.0)
var size: Vector = imageSize * relSize
var isFlashing = (imageSrc == PATH_TO_IMAGES + "green_color_flash.png")
var isFlashNow = false
var countOfFlash = 0
override fun draw() {
size = imageSize * relSize
if (isFlashing) {
if (isFlashNow) {
if (countOfFlash > 6) {
isFlashNow = false
countOfFlash = 0
}
else {
countOfFlash++
}
}
else {
state.context.drawImage(getImage(PATH_TO_IMAGES + "green_color.png"), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
size.x.toInt(), size.y.toInt())
if (countOfFlash > 6) {
isFlashNow = true
countOfFlash = 0
}
else {
countOfFlash++
}
}
}
else {
state.context.drawImage(getImage(imageSrc), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
size.x.toInt(), size.y.toInt())
}
}
}
class Car(override var pos: Vector, val direction: String, val color: String) : Shape() {
val imageSize = v(25.0, 59.0)
var speed = getRandomArbitary(2, 10);
override fun draw() {
if (direction == "up" || direction == "down") {
state.context.drawImage(getImage(PATH_TO_IMAGES + color + "_car.png"), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.x.toInt(), imageSize.y.toInt())
if ((!isNearStopLine()) || (trafficLightUp.canMove() && isNearStopLine()) ) {
move()
}
else {
speed = getRandomArbitary(2, 10)
}
}
else {
state.context.drawImage(getImage(PATH_TO_IMAGES + color + "_car.png"), 0, 0,
imageSize.y.toInt(), imageSize.x.toInt(),
pos.x.toInt(), pos.y.toInt(),
imageSize.y.toInt(), imageSize.x.toInt())
if ((!isNearStopLine()) || (trafficLightLeft.canMove() && isNearStopLine()) ) {
move()
}
else {
speed = getRandomArbitary(2, 10)
}
}
}
fun isNearStopLine(): Boolean {
when (direction) {
"up" -> return (pos.y > 198 && pos.y < 208)
"down" -> return (pos.y > 10 && pos.y < 20)
"right" -> return (pos.x > -8 && pos.x < 2)
"left" -> return (pos.x > 243 && pos.x < 253)
else -> return false
}
}
fun move() {
var x = pos.x
var y = pos.y
when (direction) {
"up" -> if (pos.y < -50) y = 250.0 else y = pos.y - speed
"down" -> if (pos.y > 300) y = 0.0 else y = pos.y + speed
"right" -> if (pos.x > 300) x = -10.0 else x = pos.x + speed
"left" -> if (pos.x < -50) x = 340.0 else x = pos.x - speed
else -> {
}
}
pos = v(x, y)
}
}
class Map(override var pos: Vector) : Shape() {
val relSize: Double = 0.8
val imageSize = v(420.0, 323.0)
var size: Vector = imageSize * relSize
override fun draw() {
size = imageSize * relSize
state.context.drawImage(getImage(PATH_TO_IMAGES + "crossroads.jpg"), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(),
size.x.toInt(), size.y.toInt())
}
}
class CanvasState(val canvas: HTMLCanvasElement) {
val context = traffic.context
var shapes = ArrayList<Shape>()
var width = canvas.width
var height = canvas.height
val size: Vector
get() = v(width, height)
fun addShape(shape: Shape) {
shapes.add(shape)
}
{
jq(canvas).click {
val mousePos = mousePos(it)
for (shape in shapes) {
if (shape is Button && mousePos in shape) {
val name = shape.src
shape.mouseClick()
when (name) {
PATH_TO_IMAGES + "lr.png" -> {
trafficLightUp.setRed()
trafficLightDown.setRed()
trafficLightLeft.setGreen()
trafficLightRight.setGreen()
}
PATH_TO_IMAGES + "ud.png" -> {
trafficLightLeft.setRed()
trafficLightRight.setRed()
trafficLightUp.setGreen()
trafficLightDown.setGreen()
}
else -> continue
}
}
}
}
jq(canvas).mousemove {
val mousePos = mousePos(it)
for (shape in shapes) {
if (shape is Button && mousePos in shape) {
val name = shape.src
shape.mouseOver()
}
}
}
window.setInterval({
draw()
}, 1000 / 30)
window.setInterval({
trafficLightUp.changeColor()
trafficLightLeft.changeColor()
trafficLightRight.changeColor()
trafficLightDown.changeColor()
}, 10000)
}
fun mousePos(e: MouseEvent): Vector {
var offset = Vector()
var element: HTMLElement? = canvas
while (element != null) {
val el: HTMLElement = element!!
offset += Vector(el.offsetLeft, el.offsetTop)
element = el.offsetParent
}
return Vector(e.pageX, e.pageY) - offset
}
fun draw() {
clear()
for (shape in shapes) {
shape.draw()
}
}
fun clear() {
context.fillStyle = colors.white
context.fillRect(0, 0, width.toInt(), height.toInt())
}
}
abstract class Shape() {
abstract var pos: Vector
abstract fun draw()
// a couple of helper extension methods we'll be using in the derived classes
fun CanvasContext.shadowed(shadowOffset: Vector, alpha: Double, render: CanvasContext.() -> Unit) {
save()
shadowColor = "rgba(100, 100, 100, $alpha)"
shadowBlur = 5.0
shadowOffsetX = shadowOffset.x
shadowOffsetY = shadowOffset.y
render()
restore()
}
fun CanvasContext.fillPath(constructPath: CanvasContext.() -> Unit) {
beginPath()
constructPath()
closePath()
fill()
}
}
class Vector(val x: Double = 0.0, val y: Double = 0.0) {
fun plus(v: Vector) = v(x + v.x, y + v.y)
fun minus() = v(-x, -y)
fun minus(v: Vector) = v(x - v.x, y - v.y)
fun times(koef: Double) = v(x * koef, y * koef)
fun distanceTo(v: Vector) = Math.sqrt((this - v).sqr)
fun rotatedBy(theta: Double): Vector {
val sin = Math.sin(theta)
val cos = Math.cos(theta)
return v(x * cos - y * sin, x * sin + y * cos)
}
fun isInRect(topLeft: Vector, size: Vector) = (x >= topLeft.x) && (x <= topLeft.x + size.x) &&
(y >= topLeft.y) && (y <= topLeft.y + size.y)
val sqr: Double
get() = x * x + y * y
val normalized: Vector
get() = this * (1.0 / Math.sqrt(sqr))
}
fun getRandomArbitary(min: Int, max: Int): Double {
return Math.random() * (max - min) + min;
}