'From Squeak3.1alpha of 19 February 2001 [latest update: #3848] on 4 April 2001 at 2:15:24 am'! Morph subclass: #MyGame instanceVariableNames: 'myForm myCanvas room displayCanvas paddleVertices ' classVariableNames: '' poolDictionaries: '' category: 'MyGame'! Object subclass: #Point3D instanceVariableNames: 'x y z transformContext ' classVariableNames: 'TheTransformContext ' poolDictionaries: '' category: 'MyGame'! Object subclass: #Room instanceVariableNames: 'xBorder yBorder zBorder ' classVariableNames: '' poolDictionaries: '' category: 'MyGame'! Object subclass: #TransformContext instanceVariableNames: 'multiplier viewerDistanceFromCenter viewerYOffset xOffset yOffset xBorder yBorder zBorder desiredBounds ' classVariableNames: '' poolDictionaries: '' category: 'MyGame'! !AtomMorph methodsFor: 'as yet unclassified' stamp: 'dew 4/3/2001 01:59'! drawOn: aCanvas "Note: Set 'drawAsRect' to true to make the atoms draw faster. When testing the speed of other aspects of Morphic, such as its damage handling efficiency for large numbers of atoms, it is useful to make drawing faster." | drawAsRect | "FirstHalt ifTrue: [FirstHalt _ false. self halt]." drawAsRect _ true. "rectangles are faster to draw" drawAsRect ifTrue: [aCanvas fillRectangle: self bounds color: color] ifFalse: [super drawOn: aCanvas].! ! !BouncingAtomsMorph methodsFor: 'other' stamp: 'dew 4/3/2001 01:59'! invalidRect: damageRect from: aMorph "Try setting 'quickRedraw' to true. This invalidates the entire morph, whose bounds typically subsume all it's submorphs. (However, this code checks that assumption and passes through any damage reports for out-of-bounds submorphs. Note that atoms with super-high velocities do occaisionally shoot through the walls!!) An additional optimization is to only submit only damage report per display cycle by using the damageReported flag, which is reset to false when the morph is drawn." | quickRedraw | FirstHalt ifTrue: [FirstHalt _ false. self halt]. quickRedraw _ true. "false gives the original invalidRect: behavior" (quickRedraw and: [(bounds origin <= damageRect topLeft) and: [damageRect bottomRight <= bounds corner]]) ifTrue: [ "can use quick redraw if damage is within my bounds" damageReported ifFalse: [super invalidRect: bounds from: self]. "just report once" damageReported _ true. ] ifFalse: [super invalidRect: damageRect from: aMorph]. "ordinary damage report"! ! !MyGame methodsFor: 'drawing' stamp: 'dew 4/4/2001 02:14'! drawOn: aCanvas FirstHalt ifTrue: [FirstHalt _ false. self halt]. super drawOn: aCanvas. "aCanvas image: myForm at: bounds origin + 20." "self invalidRect: ..." aCanvas drawPolygon: paddleVertices color: (Color h: 50 s: 0.7 v: 0.8) borderWidth: 1 borderColor: Color white. ! ! !MyGame methodsFor: 'drawing' stamp: 'dew 4/4/2001 02:12'! drawPaddle | vertices3D paddlePoint | paddlePoint _ World primaryHand position * (1@-1) - (900@-100). vertices3D _ {Point3D x: paddlePoint x y: room floor z: paddlePoint y + 600. Point3D x: paddlePoint x + 500 y: room floor z: paddlePoint y + 600. Point3D x: paddlePoint x + 500 y: room floor z: paddlePoint y. Point3D x: paddlePoint x y: room floor z: paddlePoint y}. paddleVertices _ vertices3D collect: [:ea | ea transformTo2D]. self invalidRect: (Rectangle encompassing: paddleVertices) from: self.! ! !MyGame methodsFor: 'initialization' stamp: 'dew 4/1/2001 03:23'! initialize | roomBounds | super initialize. self extent: 500@400. self color: (Color h: 90 s: 0.6 v: 0.3). room _ Room new xBorder: 1000 yBorder: 1000 zBorder: 1000. roomBounds _ (bounds translateBy: self position) extendBy: -40. Point3D theTransformContext: (TransformContext new initialize; room: room desiredBounds: roomBounds; viewerYOffset: 200). myForm _ Form extent: roomBounds extent depth: 16. myCanvas _ FormCanvas on: myForm. room drawOn: myCanvas. self drawPaddle.! ! !MyGame methodsFor: 'stepping' stamp: 'dew 4/3/2001 02:22'! step self drawPaddle. "self changed." "displayCanvas ifNotNil: [self drawOn: displayCanvas]." ! ! !MyGame methodsFor: 'stepping' stamp: 'dew 4/2/2001 02:13'! stepTime ^ 30! ! !Point3D methodsFor: 'transforming' stamp: 'dew 4/1/2001 02:38'! flipOverAxis: anAxisSymbol "aSymbol will be #x or #y or #z" self perform: (anAxisSymbol, ':') asSymbol with: (self perform: anAxisSymbol) * -1.! ! !Point3D methodsFor: 'transforming' stamp: 'dew 4/2/2001 01:04'! transformTo2D "(maybe pass along a transformContext or somesuch)" "multiplier = aConst viewerDistanceFromCenter = bConst" | t | t _ TheTransformContext. "class variable for now" ^ Point x: ((x * t multiplier) // (z + t viewerDistanceFromCenter)) + t xOffset y: (((t viewerYOffset - y) * t multiplier) // (z + t viewerDistanceFromCenter)) + t yOffset ! ! !Point3D methodsFor: 'accessing' stamp: 'dew 3/30/2001 01:47'! transformContext ^ transformContext! ! !Point3D methodsFor: 'accessing' stamp: 'dew 4/1/2001 02:35'! x ^ x! ! !Point3D methodsFor: 'accessing' stamp: 'dew 4/1/2001 02:28'! x: aNumber x _ aNumber! ! !Point3D methodsFor: 'accessing' stamp: 'dew 4/1/2001 02:35'! y ^ y! ! !Point3D methodsFor: 'accessing' stamp: 'dew 4/1/2001 02:28'! y: aNumber y _ aNumber! ! !Point3D methodsFor: 'accessing' stamp: 'dew 4/1/2001 02:35'! z ^ z! ! !Point3D methodsFor: 'accessing' stamp: 'dew 4/1/2001 02:28'! z: aNumber z _ aNumber! ! !Point3D methodsFor: 'initialization' stamp: 'dew 3/30/2001 02:07'! x: newX y: newY z: newZ x _ newX. y _ newY. z _ newZ.! ! !Point3D methodsFor: 'printing' stamp: 'dew 4/1/2001 02:34'! printOn: aStream x printOn: aStream. aStream nextPut: $@. y printOn: aStream. aStream nextPut: $@. z printOn: aStream. ! ! !Point3D class methodsFor: 'initialization' stamp: 'dew 3/30/2001 02:04'! initialize "Point3D initialize" TheTransformContext _ TransformContext new.! ! !Point3D class methodsFor: 'instance creation' stamp: 'dew 3/30/2001 02:09'! x: newX y: newY z: newZ ^ self new x: newX y: newY z: newZ! ! !Point3D class methodsFor: 'accessing' stamp: 'dew 3/31/2001 03:12'! theTransformContext: aTransformContext TheTransformContext _ aTransformContext ! ! !Room methodsFor: 'accessing' stamp: 'dew 3/31/2001 03:42'! floor ^ yBorder * -1! ! !Room methodsFor: 'accessing' stamp: 'dew 3/31/2001 03:34'! xBorder ^ xBorder! ! !Room methodsFor: 'accessing' stamp: 'dew 3/31/2001 03:34'! yBorder ^ yBorder! ! !Room methodsFor: 'accessing' stamp: 'dew 3/31/2001 03:34'! zBorder ^ zBorder! ! !Room methodsFor: 'initialization' stamp: 'dew 3/31/2001 03:36'! xBorder: x yBorder: y zBorder: z xBorder _ x. yBorder _ y. zBorder _ z. ! ! !Room methodsFor: 'drawing' stamp: 'dew 4/2/2001 00:31'! drawOn: aCanvas | walls hue | hue _ 0. walls _ {self verticesForWallAt: #y isNegative: true. self verticesForWallAt: #y isNegative: false. self verticesForWallAt: #x isNegative: true. self verticesForWallAt: #x isNegative: false. self verticesForWallAt: #z isNegative: false}. walls do: [:wall | aCanvas drawPolygon: wall color: (Color h: hue s: 0.5 v: 0.7) borderWidth: 0 borderColor: Color white. hue _ hue + 40]! ! !Room methodsFor: 'querying' stamp: 'dew 4/1/2001 02:43'! verticesForWallAt: wallBorder isNegative: isNegative "Return a collection of the four vertices (corners) of a wall, where wallBorder (wallPlane?) is the symbol name of one of the borders. E.g. wallBorder = #x and isNegative = true would be the left wall. This method may be too clever for its own good." | otherBorders vertices negation point | isNegative ifTrue: [negation _ -1] ifFalse: [negation _ 1]. otherBorders _ {#x. #y. #z} copyWithoutAll: {wallBorder}. point _ Point3D new. point perform: (wallBorder, ':') asSymbol with: (self perform: (wallBorder, 'Border') asSymbol) * negation. point perform: (otherBorders first, ':') asSymbol with: (self perform: (otherBorders first, 'Border') asSymbol). point perform: (otherBorders second, ':') asSymbol with: (self perform: (otherBorders second, 'Border') asSymbol). vertices _ OrderedCollection new. vertices add: point. vertices add: (point copy flipOverAxis: otherBorders first). vertices add: (point copy flipOverAxis: otherBorders first; flipOverAxis: otherBorders second). vertices add: (point copy flipOverAxis: otherBorders second). ^ vertices collect: [:ea | ea transformTo2D]! ! !TransformContext methodsFor: 'accessing' stamp: 'dew 3/31/2001 03:19'! multiplier "^100.0" ^ multiplier! ! !TransformContext methodsFor: 'accessing' stamp: 'dew 3/31/2001 03:19'! viewerDistanceFromCenter "^3000.0" ^ viewerDistanceFromCenter! ! !TransformContext methodsFor: 'accessing' stamp: 'dew 3/31/2001 03:19'! viewerYOffset "^200.0" ^ viewerYOffset! ! !TransformContext methodsFor: 'accessing' stamp: 'dew 3/31/2001 03:19'! xOffset "^100.0" ^ xOffset! ! !TransformContext methodsFor: 'accessing' stamp: 'dew 3/31/2001 03:19'! yOffset "^100.0" ^ yOffset! ! !TransformContext methodsFor: 'accessing' stamp: 'dew 4/1/2001 03:20'! zBorder ^ zBorder! ! !TransformContext methodsFor: 'updating' stamp: 'dew 3/31/2001 23:26'! room: room desiredBounds: boundsRect xBorder _ room xBorder. "distance from center of room to left or right wall" yBorder _ room yBorder. "distance from center of room to ceiling or floor" zBorder _ room zBorder. "distance from center of room to front or back wall" "The 2D screen space alloted to displaying the room." desiredBounds _ boundsRect insetBy: 1. "inset to allow for pixel overlap" self updateAccessorVariables.! ! !TransformContext methodsFor: 'updating' stamp: 'dew 4/2/2001 01:04'! updateAccessorVariables "Update the variables which will be accessed externally (when transforming)." | viewerDistance wallRatio heightBasedOnWidth | "pick a reasonable distance from the viewer to the room" viewerDistance _ (xBorder // 2) + (yBorder // 2) + 800. wallRatio _ viewerDistance / (2 * zBorder + viewerDistance). viewerDistanceFromCenter _ viewerDistance + zBorder. multiplier _ (wallRatio * desiredBounds width * (viewerDistanceFromCenter + zBorder)) // (2 * xBorder). heightBasedOnWidth _ (2 * yBorder * multiplier) // (viewerDistanceFromCenter - zBorder). heightBasedOnWidth > desiredBounds height ifTrue: [multiplier _ (wallRatio * desiredBounds height * (viewerDistanceFromCenter + zBorder)) // (2 * yBorder)]. xOffset _ desiredBounds center x. yOffset _ desiredBounds center y - ((viewerYOffset * multiplier) // (viewerDistanceFromCenter - zBorder)). ! ! !TransformContext methodsFor: 'updating' stamp: 'dew 4/2/2001 00:58'! viewerYOffset: aNumber viewerYOffset _ aNumber. self updateAccessorVariables.! ! !TransformContext methodsFor: 'initialization' stamp: 'dew 3/31/2001 03:04'! initialize viewerYOffset _ 0.! ! TransformContext class removeSelector: #hello! TransformContext class removeSelector: #xBorder:yBorder:zBorder:desiredWidth:desiredHeight:! TransformContext removeSelector: #desiredWidth:desiredHeight:! TransformContext removeSelector: #room:desiredWidth:desiredHeight:! TransformContext removeSelector: #wallRatio:! TransformContext removeSelector: #xBorder:! TransformContext removeSelector: #xBorder:yBorder:zBorder:! TransformContext removeSelector: #xBorder:yBorder:zBorder:desiredWidth:desiredHeight:! TransformContext removeSelector: #yBorder:! TransformContext removeSelector: #zBorder:! Room removeSelector: #verticesForWallAt:! Room removeSelector: #xBorder:! Point3D initialize! Point3D removeSelector: #transformFrom3D! !Point3D reorganize! ('transforming' flipOverAxis: transformTo2D) ('accessing' transformContext x x: y y: z z:) ('initialization' x:y:z:) ('printing' printOn:) ! MyGame removeSelector: #drawOval! MyGame removeSelector: #drawRoom! MyGame removeSelector: #transformFrom3D:! MyGame removeSelector: #transformFrom3D:to2D:!