serpentron
 
(Mikhail Kryshen)
2016-02-18: Do not capture keys when not playing. Esc key now interrupts the

Do not capture keys when not playing. Esc key now interrupts the game in any state.

diff --git a/src/Serpentron.st b/src/Serpentron.st
--- a/src/Serpentron.st
+++ b/src/Serpentron.st
@@ -1,7 +1,7 @@
 Smalltalk createPackage: 'Serpentron'!
 (Smalltalk packageAt: 'Serpentron') imports: {'silk/Silk'}!
 Object subclass: #Serpentron
-	instanceVariableNames: 'field skin players playerColors controllerPrototypes score pointsToWin'
+	instanceVariableNames: 'field skin players playerColors controllerPrototypes score pointsToWin timeoutId startScreenVisible'
 	package: 'Serpentron'!
 !Serpentron commentStamp!
 The game UI.!
@@ -11,13 +11,14 @@
 initialize
 	super initialize.
 	playerColors := #('#377eb8' '#e41a1c' '#4daf4a' '#ff7f00' '#984ea3' '#b3ad78').
+	startScreenVisible := true.
 	skin := TronSkin new.
 	field := TronField new
 		skin: skin;
 		onEndGame: [ self handleEndGame ].
 	self initializePlayers; initializeControllers.
 	(Silk fromElement: document)
-		on: #keydown bind: [ :event | field keyDown: event ].
+		on: #keydown bind: [ :event | self keyDown: event ].
 ! !
 
 !Serpentron methodsFor: 'private'!
@@ -33,16 +34,13 @@
 	(score anySatisfy: [ :each | each >= pointsToWin ])
 		ifFalse: [
 			self status: (self winnerDOM: color) << ' won the round.'.
-			^ self nextRound ].
+			timeoutId := window
+				setTimeout: [ self nextRound ]
+				after: 2000.
+			^ self ].
 	self status: self scoreDOM.
-	window
-		setTimeout: [ 
-			self startScreenVisible: true.
-			self hideMessage.
-			self status: self scoreDOM << '. ' << (self winnerDOM: color) << ' won!!' ]
-		after: 2000.	
-	window
-		setTimeout: [ self showMessage: (self winnerDOM: color) << ' won!!' ]
+	timeoutId := window 
+		setTimeout: [ self showGameWinner: color ]
 		after: 1000.
 !
 
@@ -108,12 +106,22 @@
 	}.
 !
 
+keyDown: event
+	startScreenVisible ifTrue: [ ^ self ].
+	"Handle Esc key."
+	(event keyCode = 27)
+		ifTrue: [
+			event preventDefault.
+			field stopTimer.
+			window clearTimeout: timeoutId.
+			self hideMessage; startScreenVisible: true.
+			^ self ].
+	field keyDown: event.
+!
+
 nextRound
-	window
-		setTimeout: [
-			self status: self scoreDOM.
-			field start: field players ]
-		after: 2000.
+	self status: self scoreDOM.
+	field start: field players.
 !
 
 randomizePlayerColors
@@ -236,6 +244,17 @@
 	^ message.
 !
 
+showGameWinner: color
+	self showMessage: (self winnerDOM: color) << ' won!!'.
+	timeoutId := window
+		setTimeout: [ 
+			self 
+				startScreenVisible: true;
+				hideMessage;
+				status: self scoreDOM << '. ' << (self winnerDOM: color) << ' won!!' ]
+		after: 1000.
+!
+
 showMessage: anObject
 	((Silk at: '#message') resetContents << anObject)
 		element className: 'visible'.
@@ -250,8 +269,9 @@
 !
 
 startScreenVisible: aBoolean
+	startScreenVisible := aBoolean.
 	(Silk at: '#start-screen') element 
-		className: (aBoolean ifTrue: [ 'visible' ] ifFalse: [ 'hidden' ])
+		className: (aBoolean ifTrue: [ 'visible' ] ifFalse: [ 'hidden' ]).
 !
 
 status: anObject
@@ -732,12 +752,6 @@
 !TronField methodsFor: 'event handling'!
 
 keyDown: event
-	"Handle Esc key."
-	livePlayers isEmpty not & (event keyCode = 27)
-		ifTrue: [
-			event preventDefault.
-			self endGame.
-			^ self ].
 	"Check all players rather than livePlayers 
 	so that preventDefault is called for all used keys."
 	(players anySatisfy: [ :each | each keyDown: event keyCode ])
@@ -809,12 +823,6 @@
 	timerId := window setInterval: [ self update ] every: 75.
 !
 
-stopTimer
-	timerId ifNotNil: [
-		window clearInterval: timerId.
-		timerId := nil ]
-!
-
 update
 	| lpCopy |
 	lpCopy := livePlayers copy.
@@ -885,6 +893,14 @@
 	self startIfAllReady.
 ! !
 
+!TronField methodsFor: 'stopping'!
+
+stopTimer
+	timerId ifNotNil: [
+		window clearInterval: timerId.
+		timerId := nil ]
+! !
+
 Object subclass: #TronPlayer
 	instanceVariableNames: 'enabled color name controller segments location moved direction nextDirection onColorChange onEnabledChange onControllerChange'
 	package: 'Serpentron'!