Skip to content

Instantly share code, notes, and snippets.

@tangentstorm
Last active November 21, 2023 22:56
Show Gist options
  • Save tangentstorm/bd799022f7e5ca1c545ed0c4e54202f6 to your computer and use it in GitHub Desktop.
Save tangentstorm/bd799022f7e5ca1c545ed0c4e54202f6 to your computer and use it in GitHub Desktop.
Port of Roassal's RSAnimationExamples >> example05ElasticEllipses to Bloc
random := Random new.
canvas := GsCanvas new. "BrVerticalPane new matchParent."
mouseClick := [ | c1 c2 color |
canvas children copy do: #removeFromParent.
c1 := Color random.
c2 := Color random.
color := NSScale linear range: { c1. c2 }.
1 to: 10000 do: [ :i |
| shape radius ang overlapped origin |
radius := random next * 250.
origin := canvas extent /2.
ang := random next * Float pi * 2.
shape := GsEllipse new
radius: random next * 30 + 1;
position: origin + (radius * (ang cos @ ang sin)).
overlapped := canvas children anySatisfy: [ :other |
(other position distanceTo: shape position)
< (shape radius + other radius * 1.4) ].
overlapped ifFalse: [
canvas addChild: shape.
"store the final radius for animation"
shape userData at: #radius put: shape radius.
shape background:
(color scale:
(shape position distanceTo: origin) / 250) ] ].
canvas addAnimation:(BlNumberTransition new
"!! why doesn't `from: 0; to: 1` work here?"
from: 1; to: 2.5; by: 0.025;
duration:1 seconds;
"!! bloc doesn't have elasticOut"
easing: BlEasing bounceOut;
onStepDo: [:t|
canvas childrenDo: [:c| |rt sc|
sc := NSScale linear
range: {1. (c userData at: #radius)}.
c radius: (rt := sc scale: t).
"Bloc ellipses aren't centered, so compensate"
c transform
translateBy: (rt@rt)/ -2;
apply]])].
canvas when: BlClickEvent do: mouseClick.
canvas when: BlElementExtentChangedEvent do: mouseClick.
Class {
#name : #GsEllipse,
#superclass : #GsObject,
#instVars : [
'radius',
'position'
],
#category : #GameSketchLib
}
{ #category : #accessing }
GsEllipse >> initialize [
super initialize.
self
geometry: BlEllipseGeometry new;
radius: 32;
background: GsColors gold.
self transform
origin: (BlAffineTransformationCenterOrigin);
apply.
]
{ #category : #accessing }
GsEllipse >> position [
^ position
]
{ #category : #accessing }
GsEllipse >> position: aPoint [
"Bloc doesn't provide position until the bounds are calculated, so this lets us bypass that."
position := aPoint.
self relocate: position.
]
{ #category : #accessing }
GsEllipse >> radius [
^ radius
]
{ #category : #accessing }
GsEllipse >> radius: x [
radius := x.
self size: x@x
]
"the original version from Roassal3"
example05ElasticEllipses
<script: 'self new example05ElasticEllipses open'>
| canvas random mouseClick |
canvas := RSCanvas new.
random := Random new.
mouseClick := [
| c1 c2 color |
canvas nodes copy do: #remove.
c1 := Color
r: random next
g: random next
b: random next.
c2 := Color
r: random next
g: random next
b: random next.
color := NSScale linear range: {
c1.
c2 }.
1 to: 10000 do: [ :i |
| shape radius ang overlapped |
shape := RSEllipse new.
shape radius: random next * 30 + 2.
radius := random next * 250.
ang := random next * Float pi * 2.
shape position: radius * (ang cos @ ang sin).
overlapped := canvas nodes anySatisfy: [ :other |
(other position distanceTo:
shape position)
< (shape radius + other radius * 1.4) ].
overlapped ifFalse: [
canvas add: shape.
shape propertyAt: #radius put: shape radius.
shape color:
(color scale:
(shape position distanceTo: 0 @ 0) / 250) ] ].
canvas newAnimation
easing: RSEasingInterpolator elasticOut;
onStepDo: [ :t |
canvas nodes do: [ :shape |
| scale |
scale := NSScale linear range: {
1.
(shape propertyAt: #radius) }.
shape radius: (scale scale: t) ] ] ].
mouseClick value.
canvas
when: RSExtentChangedEvent
do: [ :evt | canvas zoomToFit ]
for: self;
when: RSMouseClick do: mouseClick for: self.
^ canvas
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment