From 118da03ec7fcd353b29358bb78686fa242ff1254 Mon Sep 17 00:00:00 2001 From: Julia Tonne Date: Mon, 24 Jun 2024 00:25:17 +0200 Subject: [PATCH] Added GameWindow --- .squot-materialize | 48 ++- assets/Kara-FacingRight.png | Bin 969 -> 253 bytes src/SqueakKara-Core/SKEnvironment.class.st | 119 +++++- .../SKExecuteControls.class.st | 6 +- src/SqueakKara/SKCloverleaf.class.st | 23 ++ src/SqueakKara/SKDirection.class.st | 50 +++ src/SqueakKara/SKEnvironment.class.st | 358 ++++++++++++++++++ src/SqueakKara/SKEnvironmentTest.class.st | 158 ++++++++ src/SqueakKara/SKExecuteContext.class.st | 39 ++ src/SqueakKara/SKExecuteControls.class.st | 286 ++++++++++++++ src/SqueakKara/SKExecuter.class.st | 227 +++++++++++ src/SqueakKara/SKGrid.class.st | 326 ++++++++++++++++ src/SqueakKara/SKGridCoordinator.class.st | 152 ++++++++ src/SqueakKara/SKGridCoordinatorTest.class.st | 170 +++++++++ src/SqueakKara/SKGridNullTile.class.st | 14 + src/SqueakKara/SKGridObject.class.st | 309 +++++++++++++++ src/SqueakKara/SKGridObjectTest.class.st | 184 +++++++++ src/SqueakKara/SKGridTile.class.st | 5 + src/SqueakKara/SKKara.class.st | 142 +++++++ src/SqueakKara/SKKaraDecorator.class.st | 86 +++++ src/SqueakKara/SKKaraDecoratorTest.class.st | 141 +++++++ src/SqueakKara/SKKaraTest.class.st | 263 +++++++++++++ src/SqueakKara/SKLandingPage.class.st | 192 ++++++++++ src/SqueakKara/SKTextureLoader.class.st | 57 +++ src/SqueakKara/SKTrunk.class.st | 23 ++ src/SqueakKara/SKWorkspace.class.st | 104 +++++ src/SqueakKara/package.st | 4 + 27 files changed, 3458 insertions(+), 28 deletions(-) create mode 100644 src/SqueakKara/SKCloverleaf.class.st create mode 100644 src/SqueakKara/SKDirection.class.st create mode 100644 src/SqueakKara/SKEnvironment.class.st create mode 100644 src/SqueakKara/SKEnvironmentTest.class.st create mode 100644 src/SqueakKara/SKExecuteContext.class.st create mode 100644 src/SqueakKara/SKExecuteControls.class.st create mode 100644 src/SqueakKara/SKExecuter.class.st create mode 100644 src/SqueakKara/SKGrid.class.st create mode 100644 src/SqueakKara/SKGridCoordinator.class.st create mode 100644 src/SqueakKara/SKGridCoordinatorTest.class.st create mode 100644 src/SqueakKara/SKGridNullTile.class.st create mode 100644 src/SqueakKara/SKGridObject.class.st create mode 100644 src/SqueakKara/SKGridObjectTest.class.st create mode 100644 src/SqueakKara/SKGridTile.class.st create mode 100644 src/SqueakKara/SKKara.class.st create mode 100644 src/SqueakKara/SKKaraDecorator.class.st create mode 100644 src/SqueakKara/SKKaraDecoratorTest.class.st create mode 100644 src/SqueakKara/SKKaraTest.class.st create mode 100644 src/SqueakKara/SKLandingPage.class.st create mode 100644 src/SqueakKara/SKTextureLoader.class.st create mode 100644 src/SqueakKara/SKTrunk.class.st create mode 100644 src/SqueakKara/SKWorkspace.class.st create mode 100644 src/SqueakKara/package.st diff --git a/.squot-materialize b/.squot-materialize index af24640..e23e555 100644 --- a/.squot-materialize +++ b/.squot-materialize @@ -2,56 +2,50 @@ SquotImageMapper { #path : FSAbsolutePath [ 'assets', - 'Cloverleaf.png' + 'stop.png' ], #encoding : Class [ #PNGReadWriter ] }, SquotImageMapper { #path : FSAbsolutePath [ 'assets', - 'play.png' + 'Kara-FacingDown.png' ], #encoding : @4 }, - SquotTonelMapper { - #package : MCPackage { - #name : 'SqueakKara-Tests' - }, - #path : FSAbsolutePath [ - 'src' - ] - }, SquotImageMapper { #path : FSAbsolutePath [ 'assets', - 'stop.png' + 'Trunk.png' ], #encoding : @4 }, SquotImageMapper { #path : FSAbsolutePath [ 'assets', - 'Kara-FacingUp.png' + 'pause.png' ], #encoding : @4 }, SquotTonelMapper { #package : MCPackage { - #name : 'SqueakKara-Core' + #name : 'SqueakKara' }, - #path : @9 + #path : FSAbsolutePath [ + 'src' + ] }, SquotImageMapper { #path : FSAbsolutePath [ 'assets', - 'pause.png' + 'Kara-FacingRight.png' ], #encoding : @4 }, SquotImageMapper { #path : FSAbsolutePath [ 'assets', - 'Trunk.png' + 'play.png' ], #encoding : @4 }, @@ -64,22 +58,36 @@ }, SquotTonelMapper { #package : MCPackage { - #name : 'BaselineOfSqueakKara' + #name : 'SqueakKara-Tests' }, - #path : @9 + #path : FSAbsolutePath [ + 'src' + ] }, SquotImageMapper { #path : FSAbsolutePath [ 'assets', - 'Kara-FacingRight.png' + 'Kara-FacingUp.png' ], #encoding : @4 }, + SquotTonelMapper { + #package : MCPackage { + #name : 'SqueakKara-Core' + }, + #path : @22 + }, SquotImageMapper { #path : FSAbsolutePath [ 'assets', - 'Kara-FacingDown.png' + 'Cloverleaf.png' ], #encoding : @4 + }, + SquotTonelMapper { + #package : MCPackage { + #name : 'BaselineOfSqueakKara' + }, + #path : @22 } ] \ No newline at end of file diff --git a/assets/Kara-FacingRight.png b/assets/Kara-FacingRight.png index 2ef4bf851eb6abbbf115b7e53e50fb219959350f..f8945c2142196b2a9d76aef73b8c6fa2bc1f6d46 100644 GIT binary patch delta 225 zcmV<703QFz2mJw%B!9$7L_t(|Ugekl3VDZ{5Cwg@yW6y&!Tw3MT&nCfSVXCoT`BRVOlzeK+gf>XgY#A0CF^e zV~9c23QcVuS%{1V@Je#16btvi2cY$u3Pjp<{Dp?()t1bJ=Cesx%)nWX2gOnt_3N0V6_o0TWzSVF5FO4N|x-+UG6MkjTuC zh>{3jAFJg2T)o7U{G?R9irfN_0tTB3D*7iAWdWaj57fXq!y$}cUk zRZ;?31P2gzmSmF$O!EW36A34{o?VbNd@~crzRJG^o<4LJZCj#G}5Yg&> zqH;;<)*9t~mze*3IqB!X>L}nkwd6{0jHEl0XuRG1cvF4P3qOAR>WguI~H+nWdspy_7`Ox=8Si;6eW8uD+?+%=q7%X$lluvqQWocU>v+*OxCpv3=N=nTI zZmzofa$~m4^X+?txh1N7ziGdVJF4z7C;a)fuj}^e?Dk_`rI@`$-63$@Is=Xn83T^| zM;?kb0`AJD4aY;lRqJM?$ILsxFVt6QI?JTz2Pk8By85}S Ib4q9e0CzfFvH$=8 diff --git a/src/SqueakKara-Core/SKEnvironment.class.st b/src/SqueakKara-Core/SKEnvironment.class.st index 322b19b..28b2a81 100644 --- a/src/SqueakKara-Core/SKEnvironment.class.st +++ b/src/SqueakKara-Core/SKEnvironment.class.st @@ -6,7 +6,9 @@ Class { 'workspace', 'executer', 'kara', - 'executeControls' + 'executeControls', + 'gameWidth', + 'gameHeight' ], #category : #'SqueakKara-Core' } @@ -84,6 +86,42 @@ SKEnvironment >> executionSpeed: aSpeed [ self executer speed: aSpeed. ] +{ + #category : #accessing, + #'squeak_changestamp' : 'jt 6/24/2024 00:14' +} +SKEnvironment >> gameHeight [ + + ^ gameHeight ifNil: [gameHeight := self grid height + (self grid pixelPerBlock * 4)] +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'jt 6/24/2024 00:16' +} +SKEnvironment >> gameHeight: aNumber [ + + gameHeight := aNumber +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'jt 6/24/2024 00:15' +} +SKEnvironment >> gameWidth [ + + ^ gameWidth ifNil: [gameWidth := self grid width + (self grid pixelPerBlock * 2)] +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'jt 6/24/2024 00:15' +} +SKEnvironment >> gameWidth: aNumber [ + + gameWidth := aNumber +] + { #category : #accessing, #'squeak_changestamp' : 'JJG 6/17/2024 16:40' @@ -113,10 +151,11 @@ SKEnvironment >> initialize [ { #category : #initialization, - #'squeak_changestamp' : 'KD 6/23/2024 20:56' + #'squeak_changestamp' : 'jt 6/24/2024 00:17' } SKEnvironment >> initializeWithChallenge1 [ + | gameWindow startPoint | self grid: (SKGrid newWithExtent: 7 @ 7). self kara: self grid challenge1. @@ -125,14 +164,32 @@ SKEnvironment >> initializeWithChallenge1 [ (self executer kara) kara: self kara. self executeControls: SKExecuteControls new. executeControls environment: self. + + gameWindow := SystemWindow new. + gameWindow setLabel: 'Kara'. + gameWindow extent: self gameWidth @ self gameHeight. + gameWindow setWindowColor: self grid backgroundColor. + + gameWindow addMorph: self executeControls. + gameWindow addMorph: self grid. + + startPoint := self grid pixelPerBlock @ (3 * self grid pixelPerBlock). + self grid position: gameWindow position + startPoint. + + startPoint := ((self gameWidth / 2) - (executeControls width / 2)) @ ( 1.5 * self grid pixelPerBlock). + self executeControls position: gameWindow position + startPoint. + + gameWindow openInHand. + ] { #category : #initialization, - #'squeak_changestamp' : 'KD 6/23/2024 20:56' + #'squeak_changestamp' : 'jt 6/24/2024 00:23' } SKEnvironment >> initializeWithChallenge2 [ + | gameWindow startPoint | self grid: (SKGrid newWithExtent: 9 @ 2). self kara: self grid challenge2. @@ -141,14 +198,31 @@ SKEnvironment >> initializeWithChallenge2 [ (self executer kara) kara: self kara. self executeControls: SKExecuteControls new. executeControls environment: self. + + gameWindow := SystemWindow new. + gameWindow setLabel: 'Kara'. + gameWindow extent: self gameWidth @ self gameHeight. + gameWindow setWindowColor: self grid backgroundColor. + + gameWindow addMorph: self executeControls. + gameWindow addMorph: self grid. + + startPoint := self grid pixelPerBlock @ (3 * self grid pixelPerBlock). + self grid position: gameWindow position + startPoint. + + startPoint := ((self gameWidth / 2) - (executeControls width / 2)) @ ( 1.5 * self grid pixelPerBlock). + self executeControls position: gameWindow position + startPoint. + + gameWindow openInHand. ] { #category : #initialization, - #'squeak_changestamp' : 'KD 6/23/2024 20:57' + #'squeak_changestamp' : 'jt 6/24/2024 00:23' } SKEnvironment >> initializeWithChallenge3 [ + | gameWindow startPoint | self grid: (SKGrid newWithExtent: 9 @ 3). self kara: self grid challenge3. @@ -157,15 +231,32 @@ SKEnvironment >> initializeWithChallenge3 [ (self executer kara) kara: self kara. self executeControls: SKExecuteControls new. executeControls environment: self. + + gameWindow := SystemWindow new. + gameWindow setLabel: 'Kara'. + gameWindow extent: self gameWidth @ self gameHeight. + gameWindow setWindowColor: self grid backgroundColor. + + gameWindow addMorph: self executeControls. + gameWindow addMorph: self grid. + + startPoint := self grid pixelPerBlock @ (3 * self grid pixelPerBlock). + self grid position: gameWindow position + startPoint. + + startPoint := ((self gameWidth / 2) - (executeControls width / 2)) @ ( 1.5 * self grid pixelPerBlock). + self executeControls position: gameWindow position + startPoint. + + gameWindow openInHand. ] { #category : #initialization, - #'squeak_changestamp' : 'EB 6/22/2024 14:11' + #'squeak_changestamp' : 'jt 6/24/2024 00:23' } SKEnvironment >> initializeWithKaraAt: aPoint [ - + | gameWindow startPoint | + self grid: (SKGrid newWithExtent: 7 @ 7). self kara: (SKKara newInGrid: self grid at: aPoint). self workspace: (SKWorkspace newWithKara: self kara). @@ -173,6 +264,22 @@ SKEnvironment >> initializeWithKaraAt: aPoint [ (self executer kara) kara: self kara. self executeControls: SKExecuteControls new. executeControls environment: self. + + gameWindow := SystemWindow new. + gameWindow setLabel: 'Kara'. + gameWindow extent: self gameWidth @ self gameHeight. + gameWindow setWindowColor: self grid backgroundColor. + + gameWindow addMorph: self executeControls. + gameWindow addMorph: self grid. + + startPoint := self grid pixelPerBlock @ (3 * self grid pixelPerBlock). + self grid position: gameWindow position + startPoint. + + startPoint := ((self gameWidth / 2) - (executeControls width / 2)) @ ( 1.5 * self grid pixelPerBlock). + self executeControls position: gameWindow position + startPoint. + + gameWindow openInHand. ] { diff --git a/src/SqueakKara-Core/SKExecuteControls.class.st b/src/SqueakKara-Core/SKExecuteControls.class.st index 524424a..699726a 100644 --- a/src/SqueakKara-Core/SKExecuteControls.class.st +++ b/src/SqueakKara-Core/SKExecuteControls.class.st @@ -202,13 +202,15 @@ SKExecuteControls >> getTexture: aFilename [ { #category : #widgets, - #'squeak_changestamp' : 'EB 6/22/2024 14:03' + #'squeak_changestamp' : 'jt 6/23/2024 23:59' } SKExecuteControls >> initialize [ super initialize. self bounds: self defaultBounds. - self color: Color white. + self color: Color lightGreen lighter. + self borderWidth: 1 px. + self borderColor: Color lightGray. self addAllWidgets. self openInWorld. ] diff --git a/src/SqueakKara/SKCloverleaf.class.st b/src/SqueakKara/SKCloverleaf.class.st new file mode 100644 index 0000000..dda911a --- /dev/null +++ b/src/SqueakKara/SKCloverleaf.class.st @@ -0,0 +1,23 @@ +Class { + #name : #SKCloverleaf, + #superclass : #SKGridObject, + #category : #'SqueakKara-Core' +} + +{ + #category : #type, + #'squeak_changestamp' : 'jt 6/11/2024 13:02' +} +SKCloverleaf >> isCloverleaf [ + + ^ true +] + +{ + #category : #appearance, + #'squeak_changestamp' : 'jt 6/11/2024 19:55' +} +SKCloverleaf >> textureFilename [ + + ^ 'Cloverleaf.png' +] diff --git a/src/SqueakKara/SKDirection.class.st b/src/SqueakKara/SKDirection.class.st new file mode 100644 index 0000000..65a5e3b --- /dev/null +++ b/src/SqueakKara/SKDirection.class.st @@ -0,0 +1,50 @@ +Class { + #name : #SKDirection, + #superclass : #Object, + #category : #'SqueakKara-Core' +} + +{ + #category : #directions, + #'squeak_changestamp' : 'LK 5/24/2024 11:28' +} +SKDirection class >> above [ + + ^ 0 @ -1 +] + +{ + #category : #directions, + #'squeak_changestamp' : 'LK 5/24/2024 11:28' +} +SKDirection class >> below [ + + ^ 0 @ 1 +] + +{ + #category : #directions, + #'squeak_changestamp' : 'LK 5/24/2024 11:28' +} +SKDirection class >> here [ + + ^ 0 @ 0 +] + +{ + #category : #directions, + #'squeak_changestamp' : 'LK 5/24/2024 11:28' +} +SKDirection class >> left [ + + ^ -1 @ 0 +] + +{ + #category : #directions, + #'squeak_changestamp' : 'LK 5/24/2024 11:28' +} +SKDirection class >> right [ + + ^ 1 @ 0 +] diff --git a/src/SqueakKara/SKEnvironment.class.st b/src/SqueakKara/SKEnvironment.class.st new file mode 100644 index 0000000..28b2a81 --- /dev/null +++ b/src/SqueakKara/SKEnvironment.class.st @@ -0,0 +1,358 @@ +Class { + #name : #SKEnvironment, + #superclass : #Object, + #instVars : [ + 'grid', + 'workspace', + 'executer', + 'kara', + 'executeControls', + 'gameWidth', + 'gameHeight' + ], + #category : #'SqueakKara-Core' +} + +{ + #category : #'instance creation', + #'squeak_changestamp' : 'JJG 6/18/2024 11:38' +} +SKEnvironment class >> newWithKaraAt: aPoint [ + + ^ self basicNew initializeWithKaraAt: aPoint +] + +{ + #category : #commands, + #'squeak_changestamp' : 'JJG 6/18/2024 18:43' +} +SKEnvironment >> close [ + + self workspace close. + self grid abandon. + + +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 14:11' +} +SKEnvironment >> executeControls [ + ^ executeControls +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 14:11' +} +SKEnvironment >> executeControls: anObject [ + executeControls := anObject +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:40' +} +SKEnvironment >> executer [ + + ^ executer +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:40' +} +SKEnvironment >> executer: anObject [ + + executer := anObject +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 14:16' +} +SKEnvironment >> executerState [ + + ^ self executer state. +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'KD 6/12/2024 12:16' +} +SKEnvironment >> executionSpeed: aSpeed [ + + self executer speed: aSpeed. +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'jt 6/24/2024 00:14' +} +SKEnvironment >> gameHeight [ + + ^ gameHeight ifNil: [gameHeight := self grid height + (self grid pixelPerBlock * 4)] +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'jt 6/24/2024 00:16' +} +SKEnvironment >> gameHeight: aNumber [ + + gameHeight := aNumber +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'jt 6/24/2024 00:15' +} +SKEnvironment >> gameWidth [ + + ^ gameWidth ifNil: [gameWidth := self grid width + (self grid pixelPerBlock * 2)] +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'jt 6/24/2024 00:15' +} +SKEnvironment >> gameWidth: aNumber [ + + gameWidth := aNumber +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:40' +} +SKEnvironment >> grid [ + + ^ grid +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:40' +} +SKEnvironment >> grid: anObject [ + + grid := anObject +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'JJG 6/18/2024 11:32' +} +SKEnvironment >> initialize [ + + "self initializeWithChallenge1" +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'jt 6/24/2024 00:17' +} +SKEnvironment >> initializeWithChallenge1 [ + + | gameWindow startPoint | + + self grid: (SKGrid newWithExtent: 7 @ 7). + self kara: self grid challenge1. + self workspace: (SKWorkspace newWithKara: self kara). + self executer: (SKExecuter new). + (self executer kara) kara: self kara. + self executeControls: SKExecuteControls new. + executeControls environment: self. + + gameWindow := SystemWindow new. + gameWindow setLabel: 'Kara'. + gameWindow extent: self gameWidth @ self gameHeight. + gameWindow setWindowColor: self grid backgroundColor. + + gameWindow addMorph: self executeControls. + gameWindow addMorph: self grid. + + startPoint := self grid pixelPerBlock @ (3 * self grid pixelPerBlock). + self grid position: gameWindow position + startPoint. + + startPoint := ((self gameWidth / 2) - (executeControls width / 2)) @ ( 1.5 * self grid pixelPerBlock). + self executeControls position: gameWindow position + startPoint. + + gameWindow openInHand. + +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'jt 6/24/2024 00:23' +} +SKEnvironment >> initializeWithChallenge2 [ + + | gameWindow startPoint | + + self grid: (SKGrid newWithExtent: 9 @ 2). + self kara: self grid challenge2. + self workspace: (SKWorkspace newWithKara: self kara). + self executer: (SKExecuter new). + (self executer kara) kara: self kara. + self executeControls: SKExecuteControls new. + executeControls environment: self. + + gameWindow := SystemWindow new. + gameWindow setLabel: 'Kara'. + gameWindow extent: self gameWidth @ self gameHeight. + gameWindow setWindowColor: self grid backgroundColor. + + gameWindow addMorph: self executeControls. + gameWindow addMorph: self grid. + + startPoint := self grid pixelPerBlock @ (3 * self grid pixelPerBlock). + self grid position: gameWindow position + startPoint. + + startPoint := ((self gameWidth / 2) - (executeControls width / 2)) @ ( 1.5 * self grid pixelPerBlock). + self executeControls position: gameWindow position + startPoint. + + gameWindow openInHand. +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'jt 6/24/2024 00:23' +} +SKEnvironment >> initializeWithChallenge3 [ + + | gameWindow startPoint | + + self grid: (SKGrid newWithExtent: 9 @ 3). + self kara: self grid challenge3. + self workspace: (SKWorkspace newWithKara: self kara). + self executer: (SKExecuter new). + (self executer kara) kara: self kara. + self executeControls: SKExecuteControls new. + executeControls environment: self. + + gameWindow := SystemWindow new. + gameWindow setLabel: 'Kara'. + gameWindow extent: self gameWidth @ self gameHeight. + gameWindow setWindowColor: self grid backgroundColor. + + gameWindow addMorph: self executeControls. + gameWindow addMorph: self grid. + + startPoint := self grid pixelPerBlock @ (3 * self grid pixelPerBlock). + self grid position: gameWindow position + startPoint. + + startPoint := ((self gameWidth / 2) - (executeControls width / 2)) @ ( 1.5 * self grid pixelPerBlock). + self executeControls position: gameWindow position + startPoint. + + gameWindow openInHand. +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'jt 6/24/2024 00:23' +} +SKEnvironment >> initializeWithKaraAt: aPoint [ + + | gameWindow startPoint | + + self grid: (SKGrid newWithExtent: 7 @ 7). + self kara: (SKKara newInGrid: self grid at: aPoint). + self workspace: (SKWorkspace newWithKara: self kara). + self executer: (SKExecuter new). + (self executer kara) kara: self kara. + self executeControls: SKExecuteControls new. + executeControls environment: self. + + gameWindow := SystemWindow new. + gameWindow setLabel: 'Kara'. + gameWindow extent: self gameWidth @ self gameHeight. + gameWindow setWindowColor: self grid backgroundColor. + + gameWindow addMorph: self executeControls. + gameWindow addMorph: self grid. + + startPoint := self grid pixelPerBlock @ (3 * self grid pixelPerBlock). + self grid position: gameWindow position + startPoint. + + startPoint := ((self gameWidth / 2) - (executeControls width / 2)) @ ( 1.5 * self grid pixelPerBlock). + self executeControls position: gameWindow position + startPoint. + + gameWindow openInHand. +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:41' +} +SKEnvironment >> kara [ + + ^ kara +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:41' +} +SKEnvironment >> kara: anObject [ + + kara := anObject +] + +{ + #category : #commands, + #'squeak_changestamp' : 'KD 6/12/2024 13:29' +} +SKEnvironment >> pause [ + + executer suspendExecution. +] + +{ + #category : #commands, + #'squeak_changestamp' : 'KD 6/12/2024 13:29' +} +SKEnvironment >> resume [ + + executer resumeExecution. +] + +{ + #category : #commands, + #'squeak_changestamp' : 'JJG 6/17/2024 16:41' +} +SKEnvironment >> run [ + + |code| + + code := self workspace userCode. + self executer execute: code +] + +{ + #category : #commands, + #'squeak_changestamp' : 'EB 6/22/2024 14:30' +} +SKEnvironment >> stop [ + + self executer terminate. +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:41' +} +SKEnvironment >> workspace [ + + ^ workspace +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:41' +} +SKEnvironment >> workspace: anObject [ + + workspace := anObject +] diff --git a/src/SqueakKara/SKEnvironmentTest.class.st b/src/SqueakKara/SKEnvironmentTest.class.st new file mode 100644 index 0000000..6ed11dd --- /dev/null +++ b/src/SqueakKara/SKEnvironmentTest.class.st @@ -0,0 +1,158 @@ +Class { + #name : #SKEnvironmentTest, + #superclass : #TestCase, + #instVars : [ + 'environment' + ], + #category : #'SqueakKara-Tests' +} + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/18/2024 11:14' +} +SKEnvironmentTest >> environment [ + + ^ environment +] + +{ + #category : #setup, + #'squeak_changestamp' : 'JJG 6/18/2024 11:33' +} +SKEnvironmentTest >> setUp [ + + environment := (SKEnvironment newWithKaraAt: 1 @ 1) +] + +{ + #category : #setup, + #'squeak_changestamp' : 'JJG 6/18/2024 18:44' +} +SKEnvironmentTest >> tearDown [ + + self environment close + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 11:40' +} +SKEnvironmentTest >> testCreation [ + + self assert: self environment kara coordinates = (1 @ 1) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:19' +} +SKEnvironmentTest >> testDetectCloverleaf [ + + self environment workspace userCode: 'kara onCloverleaf ifTrue: [kara move]'. + SKCloverleaf newInGrid: self environment grid at: 1 @ 1. + self environment run. + self environment executer step. + self environment executer step. + self environment executer step. + self assert: self environment kara coordinates = (2 @ 1) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:18' +} +SKEnvironmentTest >> testDetectNoCloverleaf [ + + self environment workspace userCode: 'kara onCloverleaf ifTrue: [kara move]'. + self environment run. + self environment executer step. + self environment executer step. + self environment executer step. + self assert: self environment kara coordinates = (1 @ 1) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:21' +} +SKEnvironmentTest >> testDetectNoTrunk [ + + self environment workspace userCode: 'kara trunkAhead ifTrue: [kara turn: right. kara move]'. + self environment run. + self environment executer step. + self environment executer step. + self environment executer step. + self assert: self environment kara coordinates = (1 @ 1) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 19:04' +} +SKEnvironmentTest >> testDetectTrunk [ + + self environment workspace userCode: 'kara trunkAhead ifTrue: [kara turn: right. kara move]'. + SKTrunk newInGrid: self environment grid at: 2 @ 1. + self environment run. + self environment executer step. + self environment executer step. + self environment executer step. + self environment executer step. + self assert: self environment kara coordinates = (1 @ 2) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 12:17' +} +SKEnvironmentTest >> testMove [ + + self environment workspace userCode: 'kara move'. + self environment run. + self environment executer step. + self assert: self environment kara coordinates = (2 @ 1) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 19:06' +} +SKEnvironmentTest >> testMoveTwice [ + + self environment workspace userCode: 'kara move. kara move'. + self environment run. + self environment executer step. + self environment executer step. + self environment executer step. + self assert: self environment kara coordinates = (3 @ 1) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 19:07' +} +SKEnvironmentTest >> testTurnLeftMove [ + + self environment kara coordinates: (2 @ 2). + self environment workspace userCode: 'kara turn: left. kara move'. + self environment run. + self environment executer step. + self environment executer step. + self environment executer step. + self assert: self environment kara coordinates = (2 @ 1) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 12:20' +} +SKEnvironmentTest >> testTurnRightMove [ + + self environment workspace userCode: 'kara turn: right. kara move'. + self environment run. + self environment executer step. + self environment executer step. + self assert: self environment kara coordinates = (1 @ 2) +] diff --git a/src/SqueakKara/SKExecuteContext.class.st b/src/SqueakKara/SKExecuteContext.class.st new file mode 100644 index 0000000..a53bc5d --- /dev/null +++ b/src/SqueakKara/SKExecuteContext.class.st @@ -0,0 +1,39 @@ +Class { + #name : #SKExecuteContext, + #superclass : #Object, + #instVars : [ + 'kara', + 'right', + 'left' + ], + #category : #'SqueakKara-Core' +} + +{ + #category : #'as yet unclassified', + #'squeak_changestamp' : 'KD 6/12/2024 12:26' +} +SKExecuteContext class >> create: aKara [ + + self basicNew. + self kara: aKara. +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'KD 6/12/2024 12:35' +} +SKExecuteContext >> initialize [ + + left := 'left'. + right := 'right' +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:40' +} +SKExecuteContext >> kara: anObject [ + + kara := anObject +] diff --git a/src/SqueakKara/SKExecuteControls.class.st b/src/SqueakKara/SKExecuteControls.class.st new file mode 100644 index 0000000..699726a --- /dev/null +++ b/src/SqueakKara/SKExecuteControls.class.st @@ -0,0 +1,286 @@ +Class { + #name : #SKExecuteControls, + #superclass : #Morph, + #instVars : [ + 'environment', + 'buttonRun', + 'sliderSpeed', + 'buttonStop' + ], + #category : #'SqueakKara-Core' +} + +{ + #category : #widgets, + #'squeak_changestamp' : 'EB 6/23/2024 19:42' +} +SKExecuteControls >> actionRun [ + |dict texture| + dict := Dictionary new. + dict at: #terminated put:[self environment run. texture := self pauseTextureFilename]. + dict at: #suspended put:[self environment resume. texture := self pauseTextureFilename]. + dict at: #running put:[self environment pause. texture := self runTextureFilename]. + (dict at: self environment executerState) value. + self buttonRunSetTexture: texture. +] + +{ + #category : #widgets, + #'squeak_changestamp' : 'EB 6/22/2024 15:06' +} +SKExecuteControls >> actionStop [ + + self environment stop. + self buttonRunSetTexture: self runTextureFilename +] + +{ + #category : #widgets, + #'squeak_changestamp' : 'EB 6/22/2024 15:00' +} +SKExecuteControls >> addAllWidgets [ + + | verticalSpace| + + self buttonRun: self buildButtonRun. + self sliderSpeed: self buildSliderSpeed. + self buttonStop: self buildButtonStop. + self buttonRunSetTexture: self runTextureFilename. + self buttonStopSetTexture. + verticalSpace := self addWidgetCentered: self buttonRun atXPosition: self widgetMargin. + verticalSpace := self addWidgetCentered: self sliderSpeed atXPosition: verticalSpace + self widgetMargin. + verticalSpace := self addWidgetCentered: self buttonStop atXPosition: verticalSpace + self widgetMargin. +] + +{ + #category : #widgets, + #'squeak_changestamp' : 'EB 6/22/2024 13:59' +} +SKExecuteControls >> addWidgetCentered: aWidget atXPosition: aXValue [ + + |verticalCenter widgetCenter| + + self addMorph: aWidget. + verticalCenter := (self extent y)/2. + widgetCenter := (aWidget extent y)/2. + aWidget position: (aXValue @ (verticalCenter-widgetCenter)). + ^ aXValue + aWidget extent x. +] + +{ + #category : #widgets, + #'squeak_changestamp' : 'EB 6/23/2024 19:41' +} +SKExecuteControls >> buildButtonRun [ + + ^IconicButton new + target: self; + actionSelector: #actionRun; + color: Color lightGray. +] + +{ + #category : #widgets, + #'squeak_changestamp' : 'EB 6/23/2024 19:42' +} +SKExecuteControls >> buildButtonStop [ + + ^ IconicButton new + target: self; + actionSelector: #actionStop; + color: Color lightGray +] + +{ + #category : #widgets, + #'squeak_changestamp' : 'EB 6/22/2024 14:41' +} +SKExecuteControls >> buildSliderSpeed [ + + ^ SimpleSliderMorph new + bounds: (0@0 extent: 100@20); + minVal: 0; + maxVal: 50; + setNumericValue: 25; + orientation: #horizontal; + target: self; + actionSelector: #sliderSpeedValueChanged:. +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 13:53' +} +SKExecuteControls >> buttonRun [ + ^ buttonRun +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 13:53' +} +SKExecuteControls >> buttonRun: anObject [ + buttonRun := anObject +] + +{ + #category : #texture, + #'squeak_changestamp' : 'EB 6/22/2024 14:58' +} +SKExecuteControls >> buttonRunSetTexture: aFilename [ + + self buttonRun labelGraphic: (self getTexture: aFilename). +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 13:53' +} +SKExecuteControls >> buttonStop [ + ^ buttonStop +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 13:53' +} +SKExecuteControls >> buttonStop: anObject [ + buttonStop := anObject +] + +{ + #category : #texture, + #'squeak_changestamp' : 'EB 6/22/2024 15:04' +} +SKExecuteControls >> buttonStopSetTexture [ + + self buttonStop labelGraphic: (self getTexture: self stopTextureFilename). +] + +{ + #category : #widgets, + #'squeak_changestamp' : 'EB 6/22/2024 14:06' +} +SKExecuteControls >> defaultBounds [ + + ^0@0 extent: 250@50 +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 13:53' +} +SKExecuteControls >> environment [ + ^ environment +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 13:53' +} +SKExecuteControls >> environment: anObject [ + environment := anObject +] + +{ + #category : #texture, + #'squeak_changestamp' : 'EB 6/22/2024 14:50' +} +SKExecuteControls >> getTexture [ + + ^ SKTextureLoader new getTexture: self textureFilename. +] + +{ + #category : #texture, + #'squeak_changestamp' : 'EB 6/22/2024 14:57' +} +SKExecuteControls >> getTexture: aFilename [ + + ^ SKTextureLoader new getTexture: aFilename. +] + +{ + #category : #widgets, + #'squeak_changestamp' : 'jt 6/23/2024 23:59' +} +SKExecuteControls >> initialize [ + + super initialize. + self bounds: self defaultBounds. + self color: Color lightGreen lighter. + self borderWidth: 1 px. + self borderColor: Color lightGray. + self addAllWidgets. + self openInWorld. +] + +{ + #category : #texture, + #'squeak_changestamp' : 'EB 6/23/2024 19:40' +} +SKExecuteControls >> pauseTextureFilename [ + + ^'pause.png' +] + +{ + #category : #texture, + #'squeak_changestamp' : 'EB 6/23/2024 19:40' +} +SKExecuteControls >> runTextureFilename [ + + ^'play.png' +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 13:53' +} +SKExecuteControls >> sliderSpeed [ + ^ sliderSpeed +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 13:53' +} +SKExecuteControls >> sliderSpeed: anObject [ + sliderSpeed := anObject +] + +{ + #category : #widgets, + #'squeak_changestamp' : 'EB 6/22/2024 14:41' +} +SKExecuteControls >> sliderSpeedValueChanged: aValue [ + + self environment executionSpeed: aValue. + Transcript showln: aValue. +] + +{ + #category : #texture, + #'squeak_changestamp' : 'EB 6/23/2024 19:40' +} +SKExecuteControls >> stopTextureFilename [ + + ^'stop.png' +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 14:47' +} +SKExecuteControls >> textureFilename [ + + ^'Trunk.png' +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 14:06' +} +SKExecuteControls >> widgetMargin [ + ^20 +] diff --git a/src/SqueakKara/SKExecuter.class.st b/src/SqueakKara/SKExecuter.class.st new file mode 100644 index 0000000..5c0296b --- /dev/null +++ b/src/SqueakKara/SKExecuter.class.st @@ -0,0 +1,227 @@ +Class { + #name : #SKExecuter, + #superclass : #Object, + #instVars : [ + 'kara', + 'codeString', + 'compiler', + 'process', + 'speed', + 'state' + ], + #category : #'SqueakKara-Core' +} + +{ + #category : #execution, + #'squeak_changestamp' : 'JJG 6/17/2024 16:36' +} +SKExecuter >> codeContext [ + + ^ (SKExecuteContext new kara: self kara) +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:37' +} +SKExecuter >> codeString [ + + ^ codeString +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:37' +} +SKExecuter >> codeString: anObject [ + + codeString := anObject +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:37' +} +SKExecuter >> compiler [ + + ^ compiler +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:37' +} +SKExecuter >> compiler: anObject [ + + compiler := anObject +] + +{ + #category : #execution, + #'squeak_changestamp' : 'EB 6/22/2024 14:28' +} +SKExecuter >> execute: aCode [ + + self codeString: aCode. + "self suspendExecution. geht gerade nicht aber wär schon wenn der aktuelle Prozess beendet würde bevor ein neuer ausgeführt wird" + self state: #running. + self process: [self executeBlock: aCode] fork + +] + +{ + #category : #execution, + #'squeak_changestamp' : 'JJG 6/17/2024 16:37' +} +SKExecuter >> executeBlock: aBlock [ + + ^ compiler evaluate: aBlock for: (self codeContext) +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'EB 6/22/2024 14:13' +} +SKExecuter >> initialize [ + + self kara: SKKaraDecorator new. + self kara executer: self. + self compiler: Compiler new. + self speed: 5. + self state: #terminated. + ^self +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:37' +} +SKExecuter >> kara [ + + ^ kara +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:38' +} +SKExecuter >> kara: anObject [ + + kara := anObject +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:38' +} +SKExecuter >> process [ + + ^ process +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:38' +} +SKExecuter >> process: anObject [ + + process := anObject +] + +{ + #category : #execution, + #'squeak_changestamp' : 'EB 6/22/2024 14:10' +} +SKExecuter >> resumeExecution [ + + (self process isTerminated not) ifTrue: [ + self state: #running. + self process resume. + ] +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'KD 6/12/2024 12:05' +} +SKExecuter >> speed [ + + ^ speed +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'KD 6/12/2024 12:05' +} +SKExecuter >> speed: aSpeed [ + + speed := aSpeed +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 14:08' +} +SKExecuter >> state [ + + (self process isNil) ifTrue: [ + self state: #terminated + ] + ifFalse: [ + (self process isTerminated) ifTrue: [ + self state: #terminated + ] + ]. + ^ state +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 14:07' +} +SKExecuter >> state: anObject [ + state := anObject +] + +{ + #category : #execution, + #'squeak_changestamp' : 'JJG 6/17/2024 16:37' +} +SKExecuter >> step [ + + self stepTime > 0 + ifTrue: [(Delay forMilliseconds: self stepTime) wait] + +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'EB 6/22/2024 14:42' +} +SKExecuter >> stepTime [ + + (self speed = 0) ifTrue: [ ^ 5000]. + ^ 5000 / self speed +] + +{ + #category : #execution, + #'squeak_changestamp' : 'EB 6/22/2024 14:09' +} +SKExecuter >> suspendExecution [ + + ((self process isTerminated not) and: (self process isSuspended not)) ifTrue: [ + self state: #suspended. + process suspend. + ]. +] + +{ + #category : #execution, + #'squeak_changestamp' : 'EB 6/22/2024 14:34' +} +SKExecuter >> terminate [ + + (self state = #terminated) ifFalse: [self process terminate. self state: #terminated] +] diff --git a/src/SqueakKara/SKGrid.class.st b/src/SqueakKara/SKGrid.class.st new file mode 100644 index 0000000..88787f1 --- /dev/null +++ b/src/SqueakKara/SKGrid.class.st @@ -0,0 +1,326 @@ +Class { + #name : #SKGrid, + #superclass : #Morph, + #instVars : [ + 'gridWidth', + 'gridHeight', + 'gridCoordinator', + 'scaleFactor' + ], + #category : #'SqueakKara-Core' +} + +{ + #category : #'instance creation', + #'squeak_changestamp' : 'JJG 6/5/2024 17:29' +} +SKGrid class >> newWithExtent: aPoint [ + + ^ self newWithExtent: aPoint andScale: 1 +] + +{ + #category : #'instance creation', + #'squeak_changestamp' : 'JJG 6/5/2024 17:28' +} +SKGrid class >> newWithExtent: aPoint andScale: aFloat [ + + ^ SKGrid basicNew initializeWithExtent: aPoint andScale: aFloat +] + +{ + #category : #texture, + #'squeak_changestamp' : 'JJG 6/12/2024 16:41' +} +SKGrid >> addHorizontalLineAt: aCoordinate [ + + | aMorph | + + aMorph := Morph new. + + self addMorph: aMorph. + + aMorph color: self lineColor; + width: self width; + height: self lineWidth; + position: self position x @ (self position y + (aCoordinate * self pixelPerBlock)). + + + +] + +{ + #category : #texture, + #'squeak_changestamp' : 'KD 6/23/2024 20:58' +} +SKGrid >> addTexture [ + + 1 to: self gridHeight - 1 do: [:anInteger | + self addHorizontalLineAt: anInteger]. + 1 to: self gridWidth - 1 do: [:anInteger | + self addVerticalLineAt: anInteger]. +] + +{ + #category : #texture, + #'squeak_changestamp' : 'JJG 6/12/2024 16:37' +} +SKGrid >> addVerticalLineAt: aCoordinate [ + + | aMorph | + + aMorph := Morph new. + + self addMorph: aMorph. + + aMorph color: self lineColor; + width: self lineWidth; + height: self height; + position: (self position x + (aCoordinate * self pixelPerBlock)) @ self position y. + + +] + +{ + #category : #texture, + #'squeak_changestamp' : 'JJG 6/12/2024 16:45' +} +SKGrid >> backgroundColor [ + + ^ Color lightGreen lighter +] + +{ + #category : #challenges, + #'squeak_changestamp' : 'JJG 6/18/2024 11:19' +} +SKGrid >> challenge1 [ + + SKTrunk newInGrid: self at: 1 @ 1. + SKTrunk newInGrid: self at: 2 @ 1. + SKTrunk newInGrid: self at: 3 @ 1. + SKTrunk newInGrid: self at: 4 @ 1. + SKTrunk newInGrid: self at: 5 @ 1. + SKTrunk newInGrid: self at: 6 @ 1. + SKTrunk newInGrid: self at: 7 @ 1. + + SKTrunk newInGrid: self at: 7 @ 2. + SKTrunk newInGrid: self at: 7 @ 3. + SKTrunk newInGrid: self at: 7 @ 4. + SKTrunk newInGrid: self at: 7 @ 5. + SKTrunk newInGrid: self at: 7 @ 6. + SKTrunk newInGrid: self at: 7 @ 7. + + SKTrunk newInGrid: self at: 6 @ 7. + SKTrunk newInGrid: self at: 5 @ 7. + SKTrunk newInGrid: self at: 4 @ 7. + SKTrunk newInGrid: self at: 3 @ 7. + SKTrunk newInGrid: self at: 2 @ 7. + SKTrunk newInGrid: self at: 1 @ 7. + + SKTrunk newInGrid: self at: 1 @ 6. + SKTrunk newInGrid: self at: 1 @ 5. + SKTrunk newInGrid: self at: 1 @ 4. + SKTrunk newInGrid: self at: 1 @ 3. + + SKTrunk newInGrid: self at: 2 @ 3. + SKTrunk newInGrid: self at: 3 @ 3. + SKTrunk newInGrid: self at: 4 @ 3. + SKTrunk newInGrid: self at: 5 @ 3. + + SKTrunk newInGrid: self at: 5 @ 3. + SKTrunk newInGrid: self at: 5 @ 4. + SKTrunk newInGrid: self at: 5 @ 5. + + SKTrunk newInGrid: self at: 4 @ 5. + SKTrunk newInGrid: self at: 3 @ 5. + + SKCloverleaf newInGrid: self at: 4 @ 4. + ^SKKara newInGrid: self at: 1 @ 2. + +] + +{ + #category : #challenges, + #'squeak_changestamp' : 'KD 6/23/2024 20:58' +} +SKGrid >> challenge2 [ + + SKTrunk newInGrid: self at: 3 @ 2. + SKTrunk newInGrid: self at: 5 @ 2. + SKTrunk newInGrid: self at: 7 @ 2. + + SKCloverleaf newInGrid: self at: 9 @ 2. + + ^SKKara newInGrid: self at: 1 @ 2. + +] + +{ + #category : #challenges, + #'squeak_changestamp' : 'KD 6/23/2024 20:59' +} +SKGrid >> challenge3 [ + + SKTrunk newInGrid: self at: 2 @ 1. + SKTrunk newInGrid: self at: 3 @ 1. + SKTrunk newInGrid: self at: 4 @ 1. + SKTrunk newInGrid: self at: 5 @ 1. + SKTrunk newInGrid: self at: 6 @ 1. + + SKTrunk newInGrid: self at: 4 @ 3. + SKTrunk newInGrid: self at: 5 @ 3. + SKTrunk newInGrid: self at: 6 @ 3. + SKTrunk newInGrid: self at: 7 @ 3. + SKTrunk newInGrid: self at: 8 @ 3. + SKTrunk newInGrid: self at: 9 @ 3. + + ^SKKara newInGrid: self at: 1 @ 2. +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'LK 5/24/2024 11:18' +} +SKGrid >> gridCoordinator [ + + ^ gridCoordinator ifNil: [gridCoordinator := SKGridCoordinator newForGrid: self] +] + +{ + #category : #layout, + #'squeak_changestamp' : 'LK 5/22/2024 16:34' +} +SKGrid >> gridHeight [ + + ^ gridHeight ifNil: [gridHeight := 0] +] + +{ + #category : #layout, + #'squeak_changestamp' : 'LK 5/22/2024 16:34' +} +SKGrid >> gridHeight: aNumber [ + + gridHeight := aNumber. + self updateDimensions +] + +{ + #category : #layout, + #'squeak_changestamp' : 'LK 5/22/2024 16:35' +} +SKGrid >> gridWidth [ + + ^ gridWidth ifNil: [gridWidth := 0] +] + +{ + #category : #layout, + #'squeak_changestamp' : 'LK 5/22/2024 16:33' +} +SKGrid >> gridWidth: aNumber [ + + gridWidth := aNumber. + self updateDimensions +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'JJG 6/12/2024 16:47' +} +SKGrid >> initialize [ + + super initialize. + self openInWorld; + color: self backgroundColor + + +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'JJG 6/12/2024 16:47' +} +SKGrid >> initializeWithExtent: aPoint andScale: aFloat [ + + self initialize. + self scaleFactor: aFloat; + gridWidth: aPoint x; + gridHeight: aPoint y; + addTexture + + + + +] + +{ + #category : #layout, + #'squeak_changestamp' : 'LK 5/24/2024 11:07' +} +SKGrid >> isPointInGridDimensions: aPoint [ + + ^ (aPoint x between: 1 and: self gridWidth) + and: (aPoint y between: 1 and: self gridHeight) +] + +{ + #category : #texture, + #'squeak_changestamp' : 'JJG 6/12/2024 16:45' +} +SKGrid >> lineColor [ + + ^ Color gray lighter + + +] + +{ + #category : #texture, + #'squeak_changestamp' : 'JJG 6/12/2024 16:22' +} +SKGrid >> lineWidth [ + + ^ 1 px + + +] + +{ + #category : #layout, + #'squeak_changestamp' : 'JJG 6/5/2024 16:42' +} +SKGrid >> pixelPerBlock [ + + ^ SKGridObject textureDimension px * self scaleFactor +] + +{ + #category : #layout, + #'squeak_changestamp' : 'JJG 6/5/2024 17:29' +} +SKGrid >> scaleFactor [ + + ^ scaleFactor +] + +{ + #category : #layout, + #'squeak_changestamp' : 'JJG 6/5/2024 16:48' +} +SKGrid >> scaleFactor: aNumber [ + + scaleFactor := aNumber + +] + +{ + #category : #layout, + #'squeak_changestamp' : 'LK 5/22/2024 16:35' +} +SKGrid >> updateDimensions [ + + self width: self pixelPerBlock * self gridWidth; + height: self pixelPerBlock * self gridHeight +] diff --git a/src/SqueakKara/SKGridCoordinator.class.st b/src/SqueakKara/SKGridCoordinator.class.st new file mode 100644 index 0000000..37dd0e1 --- /dev/null +++ b/src/SqueakKara/SKGridCoordinator.class.st @@ -0,0 +1,152 @@ +Class { + #name : #SKGridCoordinator, + #superclass : #Object, + #instVars : [ + 'grid', + 'gridMatrix' + ], + #category : #'SqueakKara-Core' +} + +{ + #category : #'instance creation', + #'squeak_changestamp' : 'LK 5/24/2024 11:18' +} +SKGridCoordinator class >> newForGrid: aGrid [ + + ^ self basicNew initializeForGrid: aGrid +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'LK 5/24/2024 10:50' +} +SKGridCoordinator >> createGridMatrix [ + + | aMatrix | + + aMatrix := Matrix rows: self grid gridWidth columns: self grid gridHeight. + + 1 to: self grid gridWidth + do: [:x | 1 to: self grid gridHeight + do: [:y | aMatrix at: x at: y put: SKGridTile new]]. + + ^ aMatrix +] + +{ + #category : #'object storing', + #'squeak_changestamp' : 'LK 5/24/2024 11:07' +} +SKGridCoordinator >> getTileAtCoordinates: aPoint [ + + (self grid isPointInGridDimensions: aPoint) + ifTrue: [^ self gridMatrix at: aPoint x at: aPoint y] + ifFalse: [^ SKGridNullTile new] +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'LK 5/24/2024 10:48' +} +SKGridCoordinator >> grid [ + + ^ grid +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'LK 5/24/2024 10:48' +} +SKGridCoordinator >> grid: aGrid [ + + grid := aGrid +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'LK 5/24/2024 10:49' +} +SKGridCoordinator >> gridMatrix [ + + ^ gridMatrix ifNil: [gridMatrix := self createGridMatrix] +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'LK 5/24/2024 11:17' +} +SKGridCoordinator >> initializeForGrid: aGrid [ + + super initialize. + self grid: aGrid +] + +{ + #category : #private, + #'squeak_changestamp' : 'LK 5/24/2024 10:52' +} +SKGridCoordinator >> privateAdd: aGridObject to: aPoint [ + + (self gridMatrix at: aPoint x at: aPoint y) + add: aGridObject +] + +{ + #category : #private, + #'squeak_changestamp' : 'LK 5/24/2024 10:59' +} +SKGridCoordinator >> privateFind: aGridObject [ + + ^ self gridMatrix + detect: [:each | each includes: aGridObject] + ifNone: [SKGridNullTile new] +] + +{ + #category : #private, + #'squeak_changestamp' : 'LK 5/24/2024 10:53' +} +SKGridCoordinator >> privateMove: aGridObject fromTile: aGridTile to: aPoint [ + + self privateRemove: aGridObject fromTile: aGridTile; + privateAdd: aGridObject to: aPoint +] + +{ + #category : #private, + #'squeak_changestamp' : 'LK 5/24/2024 10:54' +} +SKGridCoordinator >> privateRemove: aGridObject fromTile: aGridTile [ + + aGridTile remove: aGridObject +] + +{ + #category : #'object storing', + #'squeak_changestamp' : 'LK 5/24/2024 11:04' +} +SKGridCoordinator >> removeObject: aGridObject [ + + | currentGridTile | + + currentGridTile := self privateFind: aGridObject. + + self privateRemove: aGridObject fromTile: currentGridTile + +] + +{ + #category : #'object storing', + #'squeak_changestamp' : 'LK 5/24/2024 11:03' +} +SKGridCoordinator >> storeObject: aGridObject at: aPoint [ + + | currentGridTile | + + currentGridTile := self privateFind: aGridObject. + + self privateMove: aGridObject fromTile: currentGridTile to: aPoint + + +] diff --git a/src/SqueakKara/SKGridCoordinatorTest.class.st b/src/SqueakKara/SKGridCoordinatorTest.class.st new file mode 100644 index 0000000..ee595e2 --- /dev/null +++ b/src/SqueakKara/SKGridCoordinatorTest.class.st @@ -0,0 +1,170 @@ +Class { + #name : #SKGridCoordinatorTest, + #superclass : #TestCase, + #instVars : [ + 'grid' + ], + #category : #'SqueakKara-Tests' +} + +{ + #category : #accessing, + #'squeak_changestamp' : 'LK 5/24/2024 11:39' +} +SKGridCoordinatorTest >> grid [ + + ^ grid +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'LK 5/24/2024 11:39' +} +SKGridCoordinatorTest >> gridSize [ + + ^ 20 @ 20 +] + +{ + #category : #setup, + #'squeak_changestamp' : 'LK 5/24/2024 11:34' +} +SKGridCoordinatorTest >> setUp [ + + grid := SKGrid newWithExtent: self gridSize +] + +{ + #category : #setup, + #'squeak_changestamp' : 'JJG 6/18/2024 11:14' +} +SKGridCoordinatorTest >> tearDown [ + + grid abandon +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/12/2024 16:10' +} +SKGridCoordinatorTest >> testDeleteObject [ + + | anObject anotherObject | + + anObject := SKKara newInGrid: self grid. + anotherObject := SKKara newInGrid: self grid. + anotherObject abandon. + + self deny: ((anObject neighboursHere includes: anotherObject) or: (anObject neighboursHere size = 2)) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:27' +} +SKGridCoordinatorTest >> testNeighbourAbove [ + + | anObject anotherObject | + + anObject := SKKara newInGrid: self grid at: 1 @ 1. + anotherObject := SKKara newInGrid: self grid at: 1 @ 1 + SKDirection below. + + self assert: ((anotherObject neighboursAbove includes: anObject) and: (anotherObject neighboursAbove size = 1)) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:28' +} +SKGridCoordinatorTest >> testNeighbourBelow [ + + | anObject anotherObject | + + anObject := SKKara newInGrid: self grid at: 1 @ 1. + anotherObject := SKKara newInGrid: self grid at: 1 @ 1 + SKDirection below. + + self assert: ((anObject neighboursBelow includes: anotherObject) and: (anObject neighboursBelow size = 1)) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/12/2024 16:10' +} +SKGridCoordinatorTest >> testNeighbourLeft [ + + | anObject anotherObject | + + anObject := SKKara newInGrid: self grid at: 1 @ 1 + SKDirection right. + anotherObject := SKKara newInGrid: self grid. + + self assert: ((anObject neighboursLeft includes: anotherObject) and: (anObject neighboursLeft size = 1)) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/12/2024 16:10' +} +SKGridCoordinatorTest >> testNeighbourLeftAfterDelete [ + + | anObject anotherObject | + + anObject := SKKara newInGrid: self grid at: 1 @ 1 + SKDirection right. + anotherObject := SKKara newInGrid: self grid. + anotherObject abandon. + + self deny: ((anObject neighboursLeft includes: anotherObject) or: (anObject neighboursLeft size = 1)) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/12/2024 16:11' +} +SKGridCoordinatorTest >> testNeighbourLeftAfterMove [ + + | anObject anotherObject | + + anObject := SKKara newInGrid: self grid at: 1 @ 1 + SKDirection right. + anotherObject := SKKara newInGrid: self grid. + anotherObject coordinateX: anotherObject coordinateX + 2. + + self assert: ((anotherObject neighboursLeft includes: anObject) and: (anotherObject neighboursLeft size = 1)) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:24' +} +SKGridCoordinatorTest >> testNeighbourRight [ + + | anObject anotherObject | + + anObject := SKKara newInGrid: self grid at: 1 @ 1 + SKDirection right. + anotherObject := SKKara newInGrid: self grid. + + self assert: ((anotherObject neighboursRight includes: anObject) and: (anotherObject neighboursRight size = 1)) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/12/2024 16:11' +} +SKGridCoordinatorTest >> testNeighboursHereSingleObject [ + + | object | + + object := SKKara newInGrid: self grid. + self assert: ((object neighboursHere includes: object) and: (object neighboursHere size = 1)) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/12/2024 16:11' +} +SKGridCoordinatorTest >> testNeighboursHereTwoObjects [ + + | anObject anotherObject | + + anObject := SKKara newInGrid: self grid. + anotherObject := SKKara newInGrid: self grid. + self assert: ((anObject neighboursHere includes: anotherObject) and: (anObject neighboursHere size = 2)) +] diff --git a/src/SqueakKara/SKGridNullTile.class.st b/src/SqueakKara/SKGridNullTile.class.st new file mode 100644 index 0000000..c27688f --- /dev/null +++ b/src/SqueakKara/SKGridNullTile.class.st @@ -0,0 +1,14 @@ +Class { + #name : #SKGridNullTile, + #superclass : #SKGridTile, + #category : #'SqueakKara-Core' +} + +{ + #category : #deletion, + #'squeak_changestamp' : 'LK 5/24/2024 10:54' +} +SKGridNullTile >> remove: aGridObject [ + + "do nothing" +] diff --git a/src/SqueakKara/SKGridObject.class.st b/src/SqueakKara/SKGridObject.class.st new file mode 100644 index 0000000..aed9298 --- /dev/null +++ b/src/SqueakKara/SKGridObject.class.st @@ -0,0 +1,309 @@ +Class { + #name : #SKGridObject, + #superclass : #ImageMorph, + #instVars : [ + 'grid' + ], + #category : #'SqueakKara-Core' +} + +{ + #category : #'instance creation', + #'squeak_changestamp' : 'LK 5/22/2024 17:24' +} +SKGridObject class >> newInGrid: aGrid [ + + ^ self newInGrid: aGrid at: 1 @ 1 +] + +{ + #category : #'instance creation', + #'squeak_changestamp' : 'LK 5/22/2024 16:59' +} +SKGridObject class >> newInGrid: aGrid at: aPoint [ + + ^ self basicNew initializeInGrid: aGrid at: aPoint +] + +{ + #category : #texture, + #'squeak_changestamp' : 'JJG 6/5/2024 16:41' +} +SKGridObject class >> textureDimension [ + + ^ 32 +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'LK 5/22/2024 16:56' +} +SKGridObject >> addToGrid [ + + self grid addMorph: self +] + +{ + #category : #positioning, + #'squeak_changestamp' : 'LK 5/22/2024 16:54' +} +SKGridObject >> alignToGrid [ + + self coordinateX: self coordinateX; + coordinateY: self coordinateY +] + +{ + #category : #positioning, + #'squeak_changestamp' : 'LK 5/22/2024 16:46' +} +SKGridObject >> coordinateX [ + + ^ 1 + (self relativePosition x / self grid pixelPerBlock) rounded + clampLow: 1 + high: self grid gridWidth +] + +{ + #category : #positioning, + #'squeak_changestamp' : 'LK 5/24/2024 11:11' +} +SKGridObject >> coordinateX: aNumber [ + + | anotherNumber aPoint | + + anotherNumber := (aNumber clampLow: 1 high: self grid gridWidth) - 1. + aPoint := anotherNumber * self grid pixelPerBlock @ self relativePosition y. + + super position: self grid position + aPoint. + + self notifyGridCoordinator +] + +{ + #category : #positioning, + #'squeak_changestamp' : 'LK 5/22/2024 16:45' +} +SKGridObject >> coordinateY [ + + ^ 1 + (self relativePosition y / self grid pixelPerBlock) rounded + clampLow: 1 + high: self grid gridHeight +] + +{ + #category : #positioning, + #'squeak_changestamp' : 'LK 5/24/2024 11:11' +} +SKGridObject >> coordinateY: aNumber [ + + | anotherNumber aPoint | + + anotherNumber := (aNumber clampLow: 1 high: self grid gridHeight) - 1. + aPoint := self relativePosition x @ (anotherNumber * self grid pixelPerBlock). + + super position: self grid position + aPoint. + + self notifyGridCoordinator +] + +{ + #category : #positioning, + #'squeak_changestamp' : 'LK 5/22/2024 16:50' +} +SKGridObject >> coordinates [ + + ^ self coordinateX @ self coordinateY +] + +{ + #category : #positioning, + #'squeak_changestamp' : 'KD 6/11/2024 11:31' +} +SKGridObject >> coordinates: aPoint [ + + self coordinateX: aPoint x; + coordinateY: aPoint y. + +] + +{ + #category : #deletion, + #'squeak_changestamp' : 'LK 5/24/2024 11:14' +} +SKGridObject >> delete [ + + self gridCoordinator removeObject: self. + super delete +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'LK 5/22/2024 16:57' +} +SKGridObject >> grid [ + + ^ grid +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'LK 5/22/2024 16:56' +} +SKGridObject >> grid: aGrid [ + + grid := aGrid +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'LK 5/24/2024 11:14' +} +SKGridObject >> gridCoordinator [ + + ^ self grid gridCoordinator +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'JJG 6/5/2024 17:23' +} +SKGridObject >> initializeInGrid: aGrid at: aPoint [ + + self grid: aGrid. + super initialize. + + self coordinates: aPoint; + addToGrid; + height: self grid pixelPerBlock; + width: self grid pixelPerBlock; + setTexture +] + +{ + #category : #type, + #'squeak_changestamp' : 'jt 6/11/2024 13:18' +} +SKGridObject >> isCloverleaf [ + + ^ false +] + +{ + #category : #type, + #'squeak_changestamp' : 'jt 6/11/2024 13:18' +} +SKGridObject >> isTrunk [ + + ^ false +] + +{ + #category : #'neighbour detection', + #'squeak_changestamp' : 'LK 5/24/2024 11:29' +} +SKGridObject >> neighboursAbove [ + + ^ self neighboursAt: SKDirection above +] + +{ + #category : #'neighbour detection', + #'squeak_changestamp' : 'LK 5/24/2024 11:29' +} +SKGridObject >> neighboursAt: aDirection [ + + ^ self gridCoordinator getTileAtCoordinates: aDirection + self coordinates +] + +{ + #category : #'neighbour detection', + #'squeak_changestamp' : 'LK 5/24/2024 11:30' +} +SKGridObject >> neighboursBelow [ + + ^ self neighboursAt: SKDirection below +] + +{ + #category : #'neighbour detection', + #'squeak_changestamp' : 'LK 5/24/2024 11:30' +} +SKGridObject >> neighboursHere [ + + ^ self neighboursAt: SKDirection here +] + +{ + #category : #'neighbour detection', + #'squeak_changestamp' : 'LK 5/24/2024 11:30' +} +SKGridObject >> neighboursLeft [ + + ^ self neighboursAt: SKDirection left +] + +{ + #category : #'neighbour detection', + #'squeak_changestamp' : 'LK 5/24/2024 11:30' +} +SKGridObject >> neighboursRight [ + + ^ self neighboursAt: SKDirection right +] + +{ + #category : #positioning, + #'squeak_changestamp' : 'LK 5/24/2024 11:10' +} +SKGridObject >> notifyGridCoordinator [ + + self gridCoordinator storeObject: self at: self coordinates +] + +{ + #category : #positioning, + #'squeak_changestamp' : 'LK 5/22/2024 17:00' +} +SKGridObject >> position: aPoint [ + "overwritten position method forces blocks to stay aligned when moving + them with the halo" + + super position: aPoint. + self alignToGrid +] + +{ + #category : #positioning, + #'squeak_changestamp' : 'LK 5/22/2024 16:53' +} +SKGridObject >> relativePosition [ + + ^ self position - self grid position +] + +{ + #category : #appearance, + #'squeak_changestamp' : 'JJG 6/5/2024 17:25' +} +SKGridObject >> setTexture [ + + | aTextureLoader aForm | + + aTextureLoader := SKTextureLoader new. + + aForm := aTextureLoader + getTexture: self textureFilename + scaledToWidth: self grid pixelPerBlock. + + self image: aForm +] + +{ + #category : #appearance, + #'squeak_changestamp' : 'JJG 6/5/2024 17:21' +} +SKGridObject >> textureFilename [ + + ^ SubclassResponsibility +] diff --git a/src/SqueakKara/SKGridObjectTest.class.st b/src/SqueakKara/SKGridObjectTest.class.st new file mode 100644 index 0000000..2ab5c8a --- /dev/null +++ b/src/SqueakKara/SKGridObjectTest.class.st @@ -0,0 +1,184 @@ +Class { + #name : #SKGridObjectTest, + #superclass : #TestCase, + #instVars : [ + 'grid' + ], + #category : #'SqueakKara-Tests' +} + +{ + #category : #accessing, + #'squeak_changestamp' : 'LK 5/24/2024 11:42' +} +SKGridObjectTest >> grid [ + + ^ grid +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'LK 5/22/2024 17:37' +} +SKGridObjectTest >> gridSize [ + + ^ 20 @ 20 +] + +{ + #category : #setup, + #'squeak_changestamp' : 'LK 5/22/2024 17:37' +} +SKGridObjectTest >> setUp [ + + grid := SKGrid newWithExtent: self gridSize +] + +{ + #category : #setup, + #'squeak_changestamp' : 'LK 5/22/2024 17:21' +} +SKGridObjectTest >> tearDown [ + + grid abandon +] + +{ + #category : #'initialization testing', + #'squeak_changestamp' : 'JJG 6/12/2024 16:08' +} +SKGridObjectTest >> testAbsolutePositionAfterInitialize [ + + | object | + + object := SKKara newInGrid: self grid. + self assert: object position = self grid position + + +] + +{ + #category : #'initialization testing', + #'squeak_changestamp' : 'JJG 6/12/2024 16:08' +} +SKGridObjectTest >> testAbsolutePositionAfterInitializeAt22 [ + + | object | + + object := SKKara newInGrid: self grid at: 2 @ 2. + self assert: object position = (self grid position + (self grid pixelPerBlock @ self grid pixelPerBlock)) + + +] + +{ + #category : #'movement testing', + #'squeak_changestamp' : 'JJG 6/12/2024 16:08' +} +SKGridObjectTest >> testAlignment [ + + | object | + + object := SKKara newInGrid: self grid. + object position: object position + ((1/4 * self grid pixelPerBlock) @ (1/4 * self grid pixelPerBlock)). + + self assert: object coordinates = (1 @ 1) +] + +{ + #category : #'initialization testing', + #'squeak_changestamp' : 'JJG 6/12/2024 16:09' +} +SKGridObjectTest >> testCoordinatesAfterInitialize [ + + | object | + + object := SKKara newInGrid: self grid. + self assert: object coordinates = (1 @ 1) + + +] + +{ + #category : #'initialization testing', + #'squeak_changestamp' : 'JJG 6/12/2024 16:09' +} +SKGridObjectTest >> testCoordinatesAfterInitializeAt22 [ + + | object | + + object := SKKara newInGrid: self grid at: 2 @ 2. + self assert: object coordinates = (2 @ 2) + + +] + +{ + #category : #'movement testing', + #'squeak_changestamp' : 'JJG 6/12/2024 16:09' +} +SKGridObjectTest >> testGridOutOfBounds1 [ + + | object | + + object := SKKara newInGrid: self grid. + object position: self grid position - (30 @ 30). + + self assert: object coordinates = (1 @ 1) +] + +{ + #category : #'movement testing', + #'squeak_changestamp' : 'JJG 6/12/2024 16:09' +} +SKGridObjectTest >> testGridOutOfBounds2 [ + + | object | + + object := SKKara newInGrid: self grid at: self gridSize. + object position: object position + (30 @ 30). + + self assert: object coordinates = self gridSize +] + +{ + #category : #'movement testing', + #'squeak_changestamp' : 'JJG 6/12/2024 16:09' +} +SKGridObjectTest >> testMovement [ + + | object | + + object := SKKara newInGrid: self grid. + object position: object position + (self grid pixelPerBlock @ self grid pixelPerBlock). + + self assert: object coordinates = (2 @ 2) +] + +{ + #category : #'initialization testing', + #'squeak_changestamp' : 'JJG 6/12/2024 16:09' +} +SKGridObjectTest >> testRelativePositionAfterInitialize [ + + | object | + + object := SKKara newInGrid: self grid. + self assert: object relativePosition = (0 @ 0) + + +] + +{ + #category : #'initialization testing', + #'squeak_changestamp' : 'JJG 6/12/2024 16:09' +} +SKGridObjectTest >> testRelativePositionAfterInitializeAt22 [ + + | object | + + object := SKKara newInGrid: self grid at: 2 @ 2. + self assert: object relativePosition = (self grid pixelPerBlock @ self grid pixelPerBlock) + + +] diff --git a/src/SqueakKara/SKGridTile.class.st b/src/SqueakKara/SKGridTile.class.st new file mode 100644 index 0000000..d915ad2 --- /dev/null +++ b/src/SqueakKara/SKGridTile.class.st @@ -0,0 +1,5 @@ +Class { + #name : #SKGridTile, + #superclass : #Set, + #category : #'SqueakKara-Core' +} diff --git a/src/SqueakKara/SKKara.class.st b/src/SqueakKara/SKKara.class.st new file mode 100644 index 0000000..772791f --- /dev/null +++ b/src/SqueakKara/SKKara.class.st @@ -0,0 +1,142 @@ +Class { + #name : #SKKara, + #superclass : #SKGridObject, + #instVars : [ + 'viewDirection' + ], + #category : #'SqueakKara-Core' +} + +{ + #category : #turning, + #'squeak_changestamp' : 'jt 6/11/2024 12:44' +} +SKKara >> convertAngleToDirection: angle [ + + | AngleToDirection | + + AngleToDirection := Dictionary newFrom: { + 0 -> SKDirection above. + 90 -> SKDirection right. + 180 -> SKDirection below. + 270 -> SKDirection left.}. + + ^ AngleToDirection at: angle +] + +{ + #category : #turning, + #'squeak_changestamp' : 'jt 6/11/2024 13:22' +} +SKKara >> convertDirectionToAngle: direction [ + + | DirectionToAngle | + + DirectionToAngle := Dictionary newFrom: { + SKDirection above -> 0. + SKDirection right -> 90. + SKDirection below -> 180. + SKDirection left -> 270.}. + + ^ DirectionToAngle at: direction +] + +{ + #category : #appearance, + #'squeak_changestamp' : 'jt 6/11/2024 19:59' +} +SKKara >> getTextureForDirection [ + + self viewDirection caseOf: { + [SKDirection above] -> [^ 'Kara-FacingUp.png' ]. + [SKDirection right] -> [^ 'Kara-FacingRight.png']. + [SKDirection below] -> [^ 'Kara-FacingDown.png']. + [SKDirection left] -> [^ 'Kara-FacingLeft.png'] + } +] + +{ + #category : #movement, + #'squeak_changestamp' : 'jt 6/11/2024 13:26' +} +SKKara >> move [ + + (self trunkAhead) + ifFalse: [self coordinates: self coordinates + self viewDirection] + + +] + +{ + #category : #'object detection', + #'squeak_changestamp' : 'jt 6/11/2024 13:21' +} +SKKara >> onCloverleaf [ + + ^ self neighboursHere anySatisfy: [:each | each isCloverleaf] +] + +{ + #category : #appearance, + #'squeak_changestamp' : 'jt 6/11/2024 19:58' +} +SKKara >> textureFilename [ + + ^ self getTextureForDirection +] + +{ + #category : #'object detection', + #'squeak_changestamp' : 'jt 6/11/2024 13:20' +} +SKKara >> trunkAhead [ + + | tileAhead | + + tileAhead := self neighboursAt: self viewDirection. + ^ tileAhead anySatisfy: [:each | each isTrunk] + + +] + +{ + #category : #turning, + #'squeak_changestamp' : 'JJG 6/17/2024 16:30' +} +SKKara >> turn: aDirection [ + + "also update SKWorkspace initialize, when kara turn method is updated to use SKDirection" + + | angle | + + angle := self convertDirectionToAngle: self viewDirection. + + aDirection = 'left' + ifTrue: [angle := (angle - 90) \\\ 360] + ifFalse: + [aDirection = 'right' + ifTrue: [angle := (angle + 90) \\\ 360]]. + + self viewDirection: (self convertAngleToDirection: angle). + self setTexture + + +] + +{ + #category : #movement, + #'squeak_changestamp' : 'jt 6/11/2024 11:41' +} +SKKara >> viewDirection [ + + ^ viewDirection ifNil: [viewDirection:= SKDirection right] +] + +{ + #category : #movement, + #'squeak_changestamp' : 'jt 6/11/2024 11:29' +} +SKKara >> viewDirection: aDirection [ + + viewDirection := aDirection +] diff --git a/src/SqueakKara/SKKaraDecorator.class.st b/src/SqueakKara/SKKaraDecorator.class.st new file mode 100644 index 0000000..9774a71 --- /dev/null +++ b/src/SqueakKara/SKKaraDecorator.class.st @@ -0,0 +1,86 @@ +Class { + #name : #SKKaraDecorator, + #superclass : #Object, + #instVars : [ + 'kara', + 'executer' + ], + #category : #'SqueakKara-Core' +} + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:34' +} +SKKaraDecorator >> executer [ + + ^ executer +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:34' +} +SKKaraDecorator >> executer: anObject [ + + executer := anObject +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:34' +} +SKKaraDecorator >> kara [ + + ^ kara +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/17/2024 16:34' +} +SKKaraDecorator >> kara: anObject [ + + kara := anObject +] + +{ + #category : #'SKKara functions', + #'squeak_changestamp' : 'EB 6/11/2024 10:04' +} +SKKaraDecorator >> move [ + + self kara move. + self executer step. +] + +{ + #category : #'SKKara functions', + #'squeak_changestamp' : 'EB 6/11/2024 10:01' +} +SKKaraDecorator >> onCloverleaf [ + + ^ self kara onCloverleaf + +] + +{ + #category : #'SKKara functions', + #'squeak_changestamp' : 'EB 6/11/2024 10:01' +} +SKKaraDecorator >> trunkAhead [ + + ^ self kara trunkAhead + +] + +{ + #category : #'SKKara functions', + #'squeak_changestamp' : 'EB 6/11/2024 10:04' +} +SKKaraDecorator >> turn: aDirection [ + + self kara turn: aDirection. + self executer step. + +] diff --git a/src/SqueakKara/SKKaraDecoratorTest.class.st b/src/SqueakKara/SKKaraDecoratorTest.class.st new file mode 100644 index 0000000..2004639 --- /dev/null +++ b/src/SqueakKara/SKKaraDecoratorTest.class.st @@ -0,0 +1,141 @@ +Class { + #name : #SKKaraDecoratorTest, + #superclass : #TestCase, + #instVars : [ + 'decorator', + 'grid', + 'kara' + ], + #category : #'SqueakKara-Tests' +} + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:52' +} +SKKaraDecoratorTest >> decorator [ + + ^ decorator + +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:52' +} +SKKaraDecoratorTest >> grid [ + + ^ grid +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:54' +} +SKKaraDecoratorTest >> gridSize [ + + ^ 20 @ 20 + +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:52' +} +SKKaraDecoratorTest >> kara [ + + ^ kara +] + +{ + #category : #setup, + #'squeak_changestamp' : 'JJG 6/18/2024 18:56' +} +SKKaraDecoratorTest >> setUp [ + + grid := SKGrid newWithExtent: self gridSize. + kara := SKKara newInGrid: self grid at: 1 @ 1. + decorator := SKKaraDecorator new. + self decorator kara: self kara. + self decorator executer: SKExecuter new +] + +{ + #category : #setup, + #'squeak_changestamp' : 'JJG 6/18/2024 18:51' +} +SKKaraDecoratorTest >> tearDown [ + + self grid abandon +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:58' +} +SKKaraDecoratorTest >> testKaraMove [ + + + self decorator move. + self assert: decorator kara coordinates = (2 @ 1) +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 19:00' +} +SKKaraDecoratorTest >> testKaraNoTrunkAhead [ + + self deny: decorator kara trunkAhead +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:59' +} +SKKaraDecoratorTest >> testKaraNotOnCloverleaf [ + + self deny: decorator kara onCloverleaf +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:59' +} +SKKaraDecoratorTest >> testKaraOnCloverleaf [ + + SKCloverleaf newInGrid: self grid at: 1 @ 1. + self assert: decorator kara onCloverleaf +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 19:01' +} +SKKaraDecoratorTest >> testKaraTrunkAhead [ + + SKTrunk newInGrid: self grid at: 2 @ 1. + self assert: decorator kara trunkAhead +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:57' +} +SKKaraDecoratorTest >> testKaraTurnLeft [ + + + self decorator turn: 'left'. + self assert: decorator kara viewDirection = SKDirection above +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:56' +} +SKKaraDecoratorTest >> testKaraTurnRight [ + + + self decorator turn: 'right'. + self assert: decorator kara viewDirection = SKDirection below +] diff --git a/src/SqueakKara/SKKaraTest.class.st b/src/SqueakKara/SKKaraTest.class.st new file mode 100644 index 0000000..ae3705d --- /dev/null +++ b/src/SqueakKara/SKKaraTest.class.st @@ -0,0 +1,263 @@ +Class { + #name : #SKKaraTest, + #superclass : #TestCase, + #instVars : [ + 'grid' + ], + #category : #'SqueakKara-Tests' +} + +{ + #category : #accessing, + #'squeak_changestamp' : 'jt 6/11/2024 11:14' +} +SKKaraTest >> grid [ + + ^ grid +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'jt 6/11/2024 11:14' +} +SKKaraTest >> gridSize [ + + ^ 20 @ 20 +] + +{ + #category : #setup, + #'squeak_changestamp' : 'jt 6/11/2024 11:14' +} +SKKaraTest >> setUp [ + + grid := SKGrid newWithExtent: self gridSize +] + +{ + #category : #setup, + #'squeak_changestamp' : 'jt 6/11/2024 11:14' +} +SKKaraTest >> tearDown [ + + grid abandon +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:41' +} +SKKaraTest >> testAbsolutePositionAfterMoveWithChangedDirection [ + + | kara | + + kara := SKKara newInGrid: self grid. + kara viewDirection: 0 @ 1. + kara move. + self assert: kara position = (self grid position + (0 @ self grid pixelPerBlock)) + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:41' +} +SKKaraTest >> testAbsolutePositionAfterMoveWithDefaultDirection [ + + | kara | + + kara := SKKara newInGrid: self grid. + kara move. + self assert: kara position = (self grid position + (self grid pixelPerBlock @ 0)) + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:40' +} +SKKaraTest >> testKaraStartTurnLeftRight [ + + | kara | + + kara := SKKara newInGrid: self grid. + kara turn: SKDirection right. + kara turn: SKDirection left. + self assert: kara viewDirection = SKDirection right + + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:40' +} +SKKaraTest >> testKaraStartViewDirection [ + + | kara | + + kara := SKKara newInGrid: self grid. + self assert: kara viewDirection = SKDirection right + + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:40' +} +SKKaraTest >> testKaraTurnLeft [ + + | kara | + + kara := SKKara newInGrid: self grid. + kara turn: 'left'. + self assert: kara viewDirection = SKDirection above + + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:40' +} +SKKaraTest >> testKaraTurnLeftTwice [ + + | kara | + + kara := SKKara newInGrid: self grid. + kara turn: 'left'. + kara turn: 'left'. + self assert: kara viewDirection = SKDirection left + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:40' +} +SKKaraTest >> testKaraTurnRight [ + + | kara | + + kara := SKKara newInGrid: self grid. + kara turn: 'right'. + self assert: kara viewDirection = SKDirection below + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:40' +} +SKKaraTest >> testKaraTurnRightThrice [ + + | kara | + + kara := SKKara newInGrid: self grid. + kara turn: 'right'. + kara turn: 'right'. + kara turn: 'right'. + self assert: kara viewDirection = SKDirection above + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:40' +} +SKKaraTest >> testKaraTurnRightTwice [ + + | kara | + + kara := SKKara newInGrid: self grid. + kara turn: 'right'. + kara turn: 'right'. + self assert: kara viewDirection = SKDirection left + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'jt 6/11/2024 13:27' +} +SKKaraTest >> testMoveWhenTrunkAhead [ + + | kara trunk | + + kara := SKKara newInGrid: self grid. + trunk := SKTrunk newInGrid: self grid at: 2 @ 1. + kara move. + self assert: kara coordinates = (1 @ 1) + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:40' +} +SKKaraTest >> testNoTrunkAhead [ + + | kara | + + kara := SKKara newInGrid: self grid. + self deny: kara trunkAhead + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:40' +} +SKKaraTest >> testNotOnCloverleaf [ + + | kara | + + kara := SKKara newInGrid: self grid. + SKCloverleaf newInGrid: self grid at: 2 @ 1. + self deny: kara onCloverleaf + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:40' +} +SKKaraTest >> testOnCloverleaf [ + + | kara | + + kara := SKKara newInGrid: self grid. + SKCloverleaf newInGrid: self grid. + self assert: kara onCloverleaf + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'JJG 6/18/2024 18:39' +} +SKKaraTest >> testTrunkAhead [ + + | kara | + + kara := SKKara newInGrid: self grid. + SKTrunk newInGrid: self grid at: 2 @ 1. + self assert: kara trunkAhead + +] + +{ + #category : #testing, + #'squeak_changestamp' : 'jt 6/11/2024 13:56' +} +SKKaraTest >> testTrunkAheadAfterTurn [ + + | kara trunk | + + kara := SKKara newInGrid: self grid. + trunk := SKTrunk newInGrid: self grid at: 1 @ 2. + self assert: false = kara trunkAhead. + kara turn: 'right'. + self assert: true = kara trunkAhead +] diff --git a/src/SqueakKara/SKLandingPage.class.st b/src/SqueakKara/SKLandingPage.class.st new file mode 100644 index 0000000..cd5f06c --- /dev/null +++ b/src/SqueakKara/SKLandingPage.class.st @@ -0,0 +1,192 @@ +Class { + #name : #SKLandingPage, + #superclass : #SystemWindow, + #category : #'SqueakKara-Core' +} + +{ + #category : #actions, + #'squeak_changestamp' : 'LK 6/21/2024 23:02' +} +SKLandingPage >> actionExample1 [ + + SKEnvironment basicNew initializeWithChallenge1. + self delete +] + +{ + #category : #actions, + #'squeak_changestamp' : 'KD 6/23/2024 20:59' +} +SKLandingPage >> actionExample2 [ + + SKEnvironment basicNew initializeWithChallenge2. + self delete +] + +{ + #category : #actions, + #'squeak_changestamp' : 'KD 6/23/2024 20:59' +} +SKLandingPage >> actionExample3 [ + + SKEnvironment basicNew initializeWithChallenge3. + self delete +] + +{ + #category : #actions, + #'squeak_changestamp' : 'LK 6/21/2024 23:01' +} +SKLandingPage >> actionNew [ + + SKEnvironment newWithKaraAt: 1@1. + self delete +] + +{ + #category : #buttons, + #'squeak_changestamp' : 'LK 6/21/2024 22:55' +} +SKLandingPage >> addAllButtons [ + + self addButton: self buildButtonNew atIndex: 0. + + self addButton: self buildButtonExample1 atIndex: 1. + self addButton: self buildButtonExample2 atIndex: 2. + self addButton: self buildButtonExample3 atIndex: 3. +] + +{ + #category : #buttons, + #'squeak_changestamp' : 'LK 6/21/2024 22:52' +} +SKLandingPage >> addButton: aButton atIndex: anInteger [ + + | anOffset | + + self addMorph: aButton. + + anOffset := 2 * aButton height * anInteger. + + aButton position: self center - (aButton width / 2) + (0 @ anOffset). +] + +{ + #category : #buttons, + #'squeak_changestamp' : 'LK 6/21/2024 23:02' +} +SKLandingPage >> buildButtonExample1 [ + + ^ SimpleButtonMorph new + label: self buttonExample1Label; + target: self; + actionSelector: #actionExample1; + color: Color lightGray +] + +{ + #category : #buttons, + #'squeak_changestamp' : 'LK 6/21/2024 23:02' +} +SKLandingPage >> buildButtonExample2 [ + + ^ SimpleButtonMorph new + label: self buttonExample2Label; + target: self; + actionSelector: #actionExample2; + color: Color lightGray +] + +{ + #category : #buttons, + #'squeak_changestamp' : 'LK 6/21/2024 23:02' +} +SKLandingPage >> buildButtonExample3 [ + + ^ SimpleButtonMorph new + label: self buttonExample3Label; + target: self; + actionSelector: #actionExample3; + color: Color lightGray +] + +{ + #category : #buttons, + #'squeak_changestamp' : 'LK 6/21/2024 23:01' +} +SKLandingPage >> buildButtonNew [ + + ^ SimpleButtonMorph new + label: self buttonNewLabel; + target: self; + actionSelector: #actionNew. +] + +{ + #category : #labels, + #'squeak_changestamp' : 'LK 6/21/2024 22:53' +} +SKLandingPage >> buttonExample1Label [ + + ^ 'Example Project 1' +] + +{ + #category : #labels, + #'squeak_changestamp' : 'LK 6/21/2024 22:53' +} +SKLandingPage >> buttonExample2Label [ + + ^ 'Example Project 2' +] + +{ + #category : #labels, + #'squeak_changestamp' : 'LK 6/21/2024 22:53' +} +SKLandingPage >> buttonExample3Label [ + + ^ 'Example Project 3' +] + +{ + #category : #labels, + #'squeak_changestamp' : 'LK 6/21/2024 22:52' +} +SKLandingPage >> buttonNewLabel [ + + ^ 'New Blank Project' +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'LK 6/21/2024 22:53' +} +SKLandingPage >> defaultExtent [ + + ^ 200 px @ 200 px +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'LK 6/21/2024 22:53' +} +SKLandingPage >> initialize [ + + super initialize. + + self setLabel: self windowTitle; + openInHand; + extent: self defaultExtent; + addAllButtons +] + +{ + #category : #labels, + #'squeak_changestamp' : 'LK 6/21/2024 22:44' +} +SKLandingPage >> windowTitle [ + + ^ 'SqueakKara' +] diff --git a/src/SqueakKara/SKTextureLoader.class.st b/src/SqueakKara/SKTextureLoader.class.st new file mode 100644 index 0000000..6f5cd1e --- /dev/null +++ b/src/SqueakKara/SKTextureLoader.class.st @@ -0,0 +1,57 @@ +Class { + #name : #SKTextureLoader, + #superclass : #Object, + #instVars : [ + 'assetLoader' + ], + #category : #'SqueakKara-Core' +} + +{ + #category : #assessing, + #'squeak_changestamp' : 'JJG 6/5/2024 17:11' +} +SKTextureLoader >> assetLoader [ + + ^ assetLoader ifNil: [assetLoader := GitAssetLoader for: self repositoryName basePath: self basePath] +] + +{ + #category : #configuration, + #'squeak_changestamp' : 'JJG 6/5/2024 17:08' +} +SKTextureLoader >> basePath [ + + ^ 'assets' +] + +{ + #category : #assessing, + #'squeak_changestamp' : 'JJG 6/5/2024 17:09' +} +SKTextureLoader >> getTexture: aFilename [ + + ^ self assetLoader loadForm: aFilename + + +] + +{ + #category : #assessing, + #'squeak_changestamp' : 'JJG 6/5/2024 17:12' +} +SKTextureLoader >> getTexture: aFilename scaledToWidth: aNumber [ + + ^ (self getTexture: aFilename) scaledToSize: aNumber @ aNumber + + +] + +{ + #category : #configuration, + #'squeak_changestamp' : 'JJG 6/5/2024 17:07' +} +SKTextureLoader >> repositoryName [ + + ^ 'SqueakKara' +] diff --git a/src/SqueakKara/SKTrunk.class.st b/src/SqueakKara/SKTrunk.class.st new file mode 100644 index 0000000..2b372f6 --- /dev/null +++ b/src/SqueakKara/SKTrunk.class.st @@ -0,0 +1,23 @@ +Class { + #name : #SKTrunk, + #superclass : #SKGridObject, + #category : #'SqueakKara-Core' +} + +{ + #category : #type, + #'squeak_changestamp' : 'jt 6/11/2024 13:01' +} +SKTrunk >> isTrunk [ + + ^ true +] + +{ + #category : #appearance, + #'squeak_changestamp' : 'jt 6/11/2024 19:54' +} +SKTrunk >> textureFilename [ + + ^ 'Trunk.png' +] diff --git a/src/SqueakKara/SKWorkspace.class.st b/src/SqueakKara/SKWorkspace.class.st new file mode 100644 index 0000000..3a01189 --- /dev/null +++ b/src/SqueakKara/SKWorkspace.class.st @@ -0,0 +1,104 @@ +Class { + #name : #SKWorkspace, + #superclass : #Workspace, + #instVars : [ + 'kara' + ], + #category : #'SqueakKara-Core' +} + +{ + #category : #'as yet unclassified', + #'squeak_changestamp' : 'KD 6/12/2024 18:43' +} +SKWorkspace class >> newWithKara: aKara [ + + ^self basicNew initializeWithKara: aKara. +] + +{ + #category : #commands, + #'squeak_changestamp' : 'JJG 6/18/2024 18:43' +} +SKWorkspace >> close [ + + self changed: #close +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'KD 6/12/2024 18:29' +} +SKWorkspace >> getExampleCode [ + + ^'[kara onCloverleaf not] + whileTrue: [ + kara trunkAhead + ifTrue: [kara turn: right] + ifFalse: [kara move]]' + +] + +{ + #category : #initialization, + #'squeak_changestamp' : 'KD 6/12/2024 18:41' +} +SKWorkspace >> initializeWithKara: aKara [ + + super initialize. + self buildAndOpen. + self windowTitle: 'SKWorkspace'. + + "replace, when kara turn method is updated" + "self bindings at: #left put: SKDirection left." + self bindings at: #left put: 'left'. + self bindings at: #right put: 'right'. + self bindings at: #kara put: aKara. + self contents: self getExampleCode. + +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'KD 6/12/2024 11:35' +} +SKWorkspace >> kara [ + + ^kara +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'KD 6/12/2024 11:37' +} +SKWorkspace >> kara: aKara [ + + kara := aKara. + self bindings at: #kara put: aKara. +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/18/2024 11:09' +} +SKWorkspace >> userCode [ + + "user code with appended other stuff" + + |code| + + code := self contents. + ^ code +] + +{ + #category : #accessing, + #'squeak_changestamp' : 'JJG 6/18/2024 11:10' +} +SKWorkspace >> userCode: aString [ + + "to be used only for testing" + + self contents: aString + +] diff --git a/src/SqueakKara/package.st b/src/SqueakKara/package.st new file mode 100644 index 0000000..e5f6bb2 --- /dev/null +++ b/src/SqueakKara/package.st @@ -0,0 +1,4 @@ +Package { + #'squeak_changestamp' : true, + #name : #SqueakKara +}