drop interval/timeout funs. Modify traffic light example

This commit is contained in:
pTalanov
2012-05-31 20:10:19 +04:00
parent 44c0baa9e1
commit 5fa3e96e4b
6 changed files with 431 additions and 412 deletions
+1 -10
View File
@@ -27,13 +27,4 @@ open class Exception() : Throwable() {}
library library
open class RuntimeException() : Exception() {} open class RuntimeException() : Exception() {}
library library
class NumberFormatException() : Exception() {} class NumberFormatException() : Exception() {}
native
fun setTimeout(callback : ()-> Unit) {}
native
fun setTimeout(callback : ()-> Unit, ms : Int) {}
native
fun setInterval(callback : ()-> Unit, ms : Int) {}
native
fun setInterval(callback : ()-> Unit) {}
@@ -40,11 +40,11 @@ public final class WebDemoCanvasExamplesTest extends SingleFileTranslationTest {
} }
public void testCreatures() throws Exception { public void testCreatures() throws Exception {
doTest("Creatures.kt", "document"); doTest("Creatures.kt", "$");
} }
public void testHelloKotlin() throws Exception { public void testHelloKotlin() throws Exception {
doTest("Hello, Kotlin.kt", "document"); doTest("Hello, Kotlin.kt", "$");
} }
public void testFancyLines() throws Exception { public void testFancyLines() throws Exception {
@@ -52,7 +52,7 @@ public final class WebDemoCanvasExamplesTest extends SingleFileTranslationTest {
} }
public void testTrafficLight() throws Exception { public void testTrafficLight() throws Exception {
doTest("Traffic light.kt", "document"); doTest("Traffic light.kt", "window");
} }
private void doTest(@NotNull String filename, @NotNull String firstUnknownSymbolEncountered) throws Exception { private void doTest(@NotNull String filename, @NotNull String firstUnknownSymbolEncountered) throws Exception {
@@ -74,6 +74,7 @@ class Logo(override var pos: Vector): Shape()
fun drawLogo(state: CanvasState) { fun drawLogo(state: CanvasState) {
size = imageSize * (state.size.x / imageSize.x) * relSize 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, state.context.drawImage(getImage("http://kotlin-demo.jetbrains.com/static/images/kotlinlogowobackground.png"), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(), imageSize.x.toInt(), imageSize.y.toInt(),
position.x.toInt(), position.y.toInt(), position.x.toInt(), position.y.toInt(),
@@ -245,7 +246,7 @@ class CanvasState(val canvas: HTMLCanvasElement) {
valid = false valid = false
} }
setInterval({ window.setInterval({
draw() draw()
}, interval) }, interval)
} }
@@ -339,9 +340,9 @@ fun main(args: Array<String>) {
state.addShape(Kotlin) state.addShape(Kotlin)
state.addShape(Creature(state.size * 0.25, state)) state.addShape(Creature(state.size * 0.25, state))
state.addShape(Creature(state.size * 0.75, state)) state.addShape(Creature(state.size * 0.75, state))
setTimeout({ window.setTimeout({
state.valid = false state.valid = false
}) }, 1000)
} }
} }
@@ -29,15 +29,15 @@ class FancyLines() {
var hue = 0; var hue = 0;
fun line() { fun line() {
context.save() context.save();
context.beginPath() context.beginPath();
context.lineWidth = 20.0 * Math.random() context.lineWidth = 20.0 * Math.random();
context.moveTo(x.toInt(), y.toInt()); context.moveTo(x.toInt(), y.toInt());
x = width * Math.random(); x = width * Math.random();
y = height * Math.random() y = height * Math.random();
context.bezierCurveTo(width * Math.random(), height * Math.random(), context.bezierCurveTo(width * Math.random(), height * Math.random(),
width * Math.random(), height * Math.random(), x, y); width * Math.random(), height * Math.random(), x, y);
@@ -60,7 +60,7 @@ class FancyLines() {
} }
fun run() { fun run() {
setInterval({line()}, 40); window.setInterval({line()}, 40);
setInterval({blank()}, 100); window.setInterval({blank()}, 100);
} }
} }
@@ -98,7 +98,7 @@ fun main(args: Array<String>) {
HelloKotlin() HelloKotlin()
} }
setInterval({ window.setInterval({
renderBackground() renderBackground()
for (logo in logos) { for (logo in logos) {
logo.draw() logo.draw()
@@ -1,15 +1,42 @@
import jquery.* package traffic
import html5.*
import java.util.ArrayList import java.util.ArrayList
import js.setInterval import js.dom.html5.CanvasContext
import js.DomElement import js.dom.html5.HTMLCanvasElement
import js.setTimeout
import js.*;
val PATH_TO_IMAGES = "/static/images/canvas/" import js.dom.html.HTMLImageElement
import js.dom.html.window
import js.jquery.*
import js.dom.html.HTMLElement
val state = CanvasState(getCanvas()) fun getImage(path: String): HTMLImageElement {
val colors = Colors() 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/"
val state: CanvasState
get() {
return CanvasState(canvas)
}
val colors: Colors
get() {
return Colors()
}
var trafficLightUp = TrafficLight(v(180.0, 181.0), "up", "red") var trafficLightUp = TrafficLight(v(180.0, 181.0), "up", "red")
var trafficLightDown = TrafficLight(v(100.0, 77.0), "down", "red") var trafficLightDown = TrafficLight(v(100.0, 77.0), "down", "red")
@@ -17,450 +44,450 @@ var trafficLightLeft = TrafficLight(v(228.0, 109.0), "left", "green")
var trafficLightRight = TrafficLight(v(55.0, 145.0), "right", "green") var trafficLightRight = TrafficLight(v(55.0, 145.0), "right", "green")
fun main(args : Array<String>) { fun main(args: Array<String>) {
state.addShape(Map(v(10.0, 10.0))) state.addShape(Map(v(10.0, 10.0)))
state.addShape(trafficLightLeft) state.addShape(trafficLightLeft)
state.addShape(trafficLightUp) state.addShape(trafficLightUp)
state.addShape(trafficLightDown) state.addShape(trafficLightDown)
state.addShape(trafficLightRight) state.addShape(trafficLightRight)
state.addShape(Car(v(178.0, 205.0), "up", "red")) state.addShape(Car(v(178.0, 205.0), "up", "red"))
state.addShape(Car(v(95.0, 4.0), "down", "white")) state.addShape(Car(v(95.0, 4.0), "down", "white"))
state.addShape(Car(v(278.0, 108.0), "left", "blue")) state.addShape(Car(v(278.0, 108.0), "left", "blue"))
state.addShape(Car(v(0.0, 142.0), "right", "black")) state.addShape(Car(v(0.0, 142.0), "right", "black"))
state.addShape(Border()) state.addShape(Border())
state.addShape(Image(PATH_TO_IMAGES + "controls.png", v(380.0, 10.0), v(190.0, 56.0))) 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 + "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))) 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) fun v(x: Double, y: Double) = Vector(x, y)
class Image(val src : String, override var pos : Vector, var imageSize : Vector) : Shape() { class Image(val src: String, override var pos: Vector, var imageSize: Vector): Shape() {
override fun draw() { 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, state.context.drawImage(getImage(src), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(), imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(), pos.x.toInt(), pos.y.toInt(),
imageSize.x.toInt(), imageSize.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() { fun contains(mousePos: Vector): Boolean = mousePos.isInRect(pos, imageSize)
isMouseDown = true
setTimeout({
isMouseDown = false
}, 1000)
}
fun mouseOver() {
isMouseOver = true
setTimeout({
isMouseOver = false
}, 1000)
}
fun contains(mousePos : Vector) : Boolean = mousePos.isInRect(pos, imageSize)
} }
class Border() : Shape() { class Button(val src: String, override var pos: Vector, var imageSize: Vector): Shape() {
override var pos = Vector(4.0, 4.0); var isMouseOver = false
var isMouseDown = false
override fun draw() { override fun draw() {
state.context.fillStyle = colors.white if (isMouseOver) {
state.context.fillRect(2, 4, 10, 292) state.context.shadowed(v(- 3.0, 3.0), 1.2) {
state.context.fillRect(330, 4, 370, 292) state.context.drawImage(getImage(src), 0, 0,
state.context.fillRect(2, 2, 330, 10) imageSize.x.toInt(), imageSize.y.toInt(),
state.context.fillRect(4, 265, 340, 380) pos.x.toInt(), pos.y.toInt(),
state.context.strokeStyle = colors.black imageSize.x.toInt(), imageSize.y.toInt())
state.context.lineWidth = 4.0 }
state.context.strokeRect(0, 0, state.width.toInt(), state.height.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() { class Timer(override var pos: Vector): Shape() {
var timeLeftForChangeColor : Char = 'c' var timeLeftForChangeColor: Char = 'c'
var timeStartLastChangeColor = Date().getTime(); var timeStartLastChangeColor = Date().getTime();
var timerLength = 13 var timerLength = 13
override fun draw() { override fun draw() {
timeLeftForChangeColor = ("" + (timerLength - (Date().getTime() - timeStartLastChangeColor) / 1000)).get(0) timeLeftForChangeColor = ("" + (timerLength - (Date().getTime() - timeStartLastChangeColor) / 1000)).get(0)
state.context.font = "bold 9px Arial, serif" state.context.font = "bold 9px Arial, serif"
state.context.fillStyle = colors.black state.context.fillStyle = colors.black
state.context.fillText("" + timeLeftForChangeColor, pos.x.toInt(), pos.y.toInt()) state.context.fillText("" + timeLeftForChangeColor, pos.x.toInt(), pos.y.toInt())
} }
fun resetTimer() { fun resetTimer() {
timeStartLastChangeColor = Date().getTime() timeStartLastChangeColor = Date().getTime()
timerLength = 10 timerLength = 10
} }
} }
//Colors constants //Colors constants
class Colors() { class Colors() {
val black : String = "#000000" val black: String = "#000000"
val white = "#FFFFFF" val white = "#FFFFFF"
val grey = "#C0C0C0" val grey = "#C0C0C0"
val red = "#EF4137" val red = "#EF4137"
val yellow = "#FCE013" val yellow = "#FCE013"
val green = "#0E9648" val green = "#0E9648"
} }
class TrafficLight(override var pos : Vector, val direction : String, val startColor : String) : Shape() { class TrafficLight(override var pos: Vector, val direction: String, val startColor: String): Shape() {
val list = ArrayList<TrafficLightItem>() val list = ArrayList<TrafficLightItem>()
var size = Vector(27.0, 34.0); var size = Vector(27.0, 34.0);
var timer = Timer(Vector(pos.x + 6, pos.y + 12)) var timer = Timer(Vector(pos.x + 6, pos.y + 12))
var currentColor = startColor; var currentColor = startColor;
var isForceColorChange = false var isForceColorChange = false
var changeColorForward = (startColor == "red") 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 + "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 + "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.png"))
list.add(TrafficLightItem(v(pos.x, pos.y), PATH_TO_IMAGES + "green_color_flash.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() { override fun draw() {
if (currentColor != "red" && currentColor != "yellow" && currentColor != "green_flash") { when (currentColor) {
isForceColorChange = true "red" -> list.get(0).draw()
changeColor() "yellow" -> list.get(1).draw()
"green" -> list.get(2).draw()
"green_flash" -> list.get(3).draw()
else -> {
}
}
timer.draw()
} }
}
fun setGreen() { fun setRed() {
if (currentColor != "green" && currentColor != "green_flash" && currentColor != "yellow") { if (currentColor != "red" && currentColor != "yellow" && currentColor != "green_flash") {
isForceColorChange = true isForceColorChange = true
changeColor() changeColor()
}
} }
}
fun changeColor() { fun setGreen() {
if (changeColorForward) changeColorForward() else changeColorBackward() if (currentColor != "green" && currentColor != "green_flash" && currentColor != "yellow") {
} isForceColorChange = true
changeColor()
}
}
fun changeColorForward() { fun changeColor() {
changeColorForward = false if (changeColorForward) changeColorForward() else changeColorBackward()
currentColor = "yellow" }
setTimeout({
if (!isForceColorChange) timer.resetTimer() else isForceColorChange = false fun changeColorForward() {
currentColor = "green" changeColorForward = false
}, 3000) currentColor = "yellow"
} window.setTimeout({
if (!isForceColorChange) timer.resetTimer() else isForceColorChange = false
currentColor = "green"
}, 3000)
}
fun changeColorBackward() { fun changeColorBackward() {
changeColorForward = true changeColorForward = true
currentColor = "green_flash" currentColor = "green_flash"
setTimeout({ window.setTimeout({
currentColor = "yellow" currentColor = "yellow"
setTimeout({ window.setTimeout({
if (!isForceColorChange) timer.resetTimer() else isForceColorChange = false if (!isForceColorChange) timer.resetTimer() else isForceColorChange = false
currentColor = "red" currentColor = "red"
}, 1000) }, 1000)
}, 2000) }, 2000)
} }
fun canMove() : Boolean { fun canMove(): Boolean {
return (currentColor != "red" && currentColor != "yellow") return (currentColor != "red" && currentColor != "yellow")
} }
} }
//One element from Traffic light //One element from Traffic light
class TrafficLightItem(override var pos : Vector, val imageSrc : String) : Shape() { class TrafficLightItem(override var pos: Vector, val imageSrc: String): Shape() {
val relSize : Double = 0.5 val relSize: Double = 0.5
val imageSize = v(33.0, 33.0) val imageSize = v(33.0, 33.0)
var size : Vector = imageSize * relSize var size: Vector = imageSize * relSize
var isFlashing = (imageSrc == PATH_TO_IMAGES + "green_color_flash.png") var isFlashing = (imageSrc == PATH_TO_IMAGES + "green_color_flash.png")
var isFlashNow = false var isFlashNow = false
var countOfFlash = 0 var countOfFlash = 0
override fun draw() { override fun draw() {
size = imageSize * relSize size = imageSize * relSize
if (isFlashing) { if (isFlashing) {
if (isFlashNow) { if (isFlashNow) {
if (countOfFlash > 6) { if (countOfFlash > 6) {
isFlashNow = false isFlashNow = false
countOfFlash = 0 countOfFlash = 0
} else { } else {
countOfFlash++ countOfFlash++
} }
} else { } else {
state.context.drawImage(getImage(PATH_TO_IMAGES + "green_color.png"), 0, 0, state.context.drawImage(getImage(PATH_TO_IMAGES + "green_color.png"), 0, 0,
imageSize.x.toInt(), imageSize.y.toInt(), imageSize.x.toInt(), imageSize.y.toInt(),
pos.x.toInt(), pos.y.toInt(), pos.x.toInt(), pos.y.toInt(),
size.x.toInt(), size.y.toInt()) size.x.toInt(), size.y.toInt())
if (countOfFlash > 6) { if (countOfFlash > 6) {
isFlashNow = true isFlashNow = true
countOfFlash = 0 countOfFlash = 0
} else { } else {
countOfFlash++ 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 : Canvas) {
val context = getContext()
var shapes = ArrayList<Shape>()
var width = canvas.width.toDouble()
var height = canvas.height.toDouble()
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" -> { } 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())
}
}
}
trafficLightLeft.setRed()
trafficLightRight.setRed()
trafficLightUp.setGreen()
trafficLightDown.setGreen()
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)
} }
else -> continue
}
} }
}
} }
jq(canvas).mousemove { fun isNearStopLine(): Boolean {
val mousePos = mousePos(it) when (direction) {
for (shape in shapes) { "up" -> return (pos.y > 198 && pos.y < 208)
if (shape is Button && mousePos in shape) { "down" -> return (pos.y > 10 && pos.y < 20)
val name = shape.src "right" -> return (pos.x > - 8 && pos.x < 2)
shape.mouseOver() "left" -> return (pos.x > 243 && pos.x < 253)
else -> return false
} }
}
} }
setInterval({ fun move() {
draw() var x = pos.x
}, 1000 / 30) var y = pos.y
setInterval({ when (direction) {
trafficLightUp.changeColor() "up" -> if (pos.y < - 50) y = 250.0 else y = pos.y - speed
trafficLightLeft.changeColor() "down" -> if (pos.y > 300) y = 0.0 else y = pos.y + speed
trafficLightRight.changeColor() "right" -> if (pos.x > 300) x = - 10.0 else x = pos.x + speed
trafficLightDown.changeColor() "left" -> if (pos.x < - 50) x = 340.0 else x = pos.x - speed
}, 10000) else -> {
}
}
pos = v(x, y)
}
fun mousePos(e : MouseEvent) : Vector {
var offset = Vector()
var element : DomElement? = canvas
while (element != null) {
val el : DomElement = element.sure()
offset += Vector(el.offsetLeft, el.offsetTop)
element = el.offsetParent
} }
return v(e.pageX, e.pageY) - offset }
}
fun draw() { class Map(override var pos: Vector): Shape() {
clear() val relSize: Double = 0.8
for (shape in shapes) { val imageSize = v(420.0, 323.0)
shape.draw() 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())
} }
} }
fun clear() {
context.fillStyle = colors.white class CanvasState(val canvas: HTMLCanvasElement) {
context.fillRect(0, 0, width.toInt(), height.toInt()) 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.sure()
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 class Shape() {
abstract var pos : Vector abstract var pos: Vector
abstract fun draw() abstract fun draw()
// a couple of helper extension methods we'll be using in the derived classes // a couple of helper extension methods we'll be using in the derived classes
fun Context.shadowed(shadowOffset : Vector, alpha : Double, render : Context.() -> Unit) { fun CanvasContext.shadowed(shadowOffset: Vector, alpha: Double, render: CanvasContext.() -> Unit) {
save() save()
shadowColor = "rgba(100, 100, 100, $alpha)" shadowColor = "rgba(100, 100, 100, $alpha)"
shadowBlur = 5.0 shadowBlur = 5.0
shadowOffsetX = shadowOffset.x shadowOffsetX = shadowOffset.x
shadowOffsetY = shadowOffset.y shadowOffsetY = shadowOffset.y
render() render()
restore() restore()
} }
fun Context.fillPath(constructPath : Context.() -> Unit) { fun CanvasContext.fillPath(constructPath: CanvasContext.() -> Unit) {
beginPath() beginPath()
constructPath() constructPath()
closePath() closePath()
fill() fill()
} }
} }
class Vector(val x : Double = 0.0, val y : Double = 0.0) { class Vector(val x: Double = 0.0, val y: Double = 0.0) {
fun plus(v : Vector) = v(x + v.x, y + v.y) fun plus(v: Vector) = v(x + v.x, y + v.y)
fun minus() = v(- x, - y) fun minus() = v(- x, - y)
fun minus(v : Vector) = v(x - v.x, y - v.y) fun minus(v: Vector) = v(x - v.x, y - v.y)
fun times(koef : Double) = v(x * koef, y * koef) fun times(koef: Double) = v(x * koef, y * koef)
fun distanceTo(v : Vector) = Math.sqrt((this - v).sqr) fun distanceTo(v: Vector) = Math.sqrt((this - v).sqr)
fun rotatedBy(theta : Double) : Vector { fun rotatedBy(theta: Double): Vector {
val sin = Math.sin(theta) val sin = Math.sin(theta)
val cos = Math.cos(theta) val cos = Math.cos(theta)
return v(x * cos - y * sin, x * sin + y * cos) return v(x * cos - y * sin, x * sin + y * cos)
} }
fun isInRect(topLeft : Vector, size : Vector) = (x >= topLeft.x) && (x <= topLeft.x + size.x) && fun isInRect(topLeft: Vector, size: Vector) = (x >= topLeft.x) && (x <= topLeft.x + size.x) &&
(y >= topLeft.y) && (y <= topLeft.y + size.y) (y >= topLeft.y) && (y <= topLeft.y + size.y)
val sqr : Double val sqr: Double
get() = x * x + y * y get() = x * x + y * y
val normalized : Vector val normalized: Vector
get() = this * (1.0 / Math.sqrt(sqr)) get() = this * (1.0 / Math.sqrt(sqr))
} }
fun getRandomArbitary(val min : Int, val max : Int) : Double { fun getRandomArbitary(val min: Int, val max: Int): Double {
return Math.random() * (max - min) + min; return Math.random() * (max - min) + min;
} }