awacke1 commited on
Commit
04d3523
·
verified ·
1 Parent(s): ed6a27c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +125 -229
app.py CHANGED
@@ -1,257 +1,153 @@
1
  import streamlit as st
2
 
3
- def create_animation_app():
4
- st.title("Bouncing Yellow Balls & Jellyfish in a Rotating Sphere")
5
- # We embed an HTML document that includes:
6
- # 1. p5.js (from a CDN)
7
- # 2. a container div for our canvas
8
- # 3. our p5.js sketch that simulates 100 bouncing yellow balls with collision detection
9
- # and one bouncing jellyfish (using a spiral drawing similar to your jellyfish code)
10
- # all inside a sphere (drawn as a circle) that slowly rotates.
11
  html_code = r"""
12
  <!DOCTYPE html>
13
  <html>
14
  <head>
15
  <meta charset="UTF-8">
16
- <!-- Include p5.js from a CDN -->
 
17
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.min.js"></script>
18
  <style>
19
- /* Remove default margins & center the canvas */
20
- body {
21
- margin: 0;
22
- padding: 0;
23
- overflow: hidden;
24
- background: black;
25
- }
26
- #p5-container {
27
- display: flex;
28
- justify-content: center;
29
- align-items: center;
30
- }
31
  </style>
32
  </head>
33
  <body>
34
- <div id="p5-container"></div>
35
  <script>
36
- // --- Global Variables ---
37
- let balls = [];
38
- let jellyfish;
39
- const sphereRadius = 300; // radius of the bounding sphere
40
- let sphereCenter;
41
- let rotationAngle = 0;
42
- const numBalls = 100;
 
 
 
 
 
 
 
 
 
 
 
43
 
44
- // --- p5.js Setup ---
45
- function setup() {
46
- // Create an 800x800 canvas and attach it to our container
47
- let canvas = createCanvas(800, 800);
48
- canvas.parent('p5-container');
49
- sphereCenter = createVector(width/2, height/2);
50
-
51
- // Set color mode to HSB for our jellyfish drawing.
52
- colorMode(HSB, 360, 100, 100, 1);
53
-
54
- // Create 100 balls. Each ball is given a random position (inside the sphere)
55
- // and a random velocity.
56
- for (let i = 0; i < numBalls; i++) {
57
- balls.push(new Ball());
58
- }
59
-
60
- // Create one jellyfish object. (Its drawn “shape” is produced by the jellyA() and getJellyColor() functions below.)
61
- jellyfish = new Jellyfish();
62
  }
63
 
64
- // --- p5.js Draw Loop ---
65
- function draw() {
66
- // Create a fade/trail effect by drawing a semi-transparent black background.
67
- // (Note: using HSB mode so black is 0 saturation and 0 brightness.)
68
- background(0, 0, 0, 0.1);
69
-
70
- // Increment our rotation angle very slowly.
71
- rotationAngle += 0.005;
72
-
73
- // All drawing and physics is done in a coordinate system with origin at sphereCenter.
74
- push();
75
- translate(sphereCenter.x, sphereCenter.y);
76
- // Slowly rotate the entire coordinate system.
77
- rotate(rotationAngle);
78
-
79
- // Draw the bounding sphere (a circle)
80
- noFill();
81
- stroke(255);
82
- strokeWeight(2);
83
- ellipse(0, 0, sphereRadius * 2, sphereRadius * 2);
84
-
85
- // --- Update Physics ---
86
- // 1. Update positions for all balls and the jellyfish.
87
- for (let ball of balls) {
88
- ball.update();
89
- }
90
- jellyfish.update();
91
-
92
- // 2. Check and resolve ball-ball collisions.
93
- for (let i = 0; i < balls.length; i++) {
94
- for (let j = i + 1; j < balls.length; j++) {
95
- balls[i].collide(balls[j]);
96
- }
97
- }
98
-
99
- // 3. Check each ball for collisions with the sphere boundary and display them.
100
- for (let ball of balls) {
101
- ball.checkBoundaryCollision();
102
- ball.display();
103
- }
104
-
105
- // 4. Check the jellyfish for sphere collisions and display it.
106
- jellyfish.checkBoundaryCollision();
107
- jellyfish.display();
108
-
109
- pop();
110
  }
 
 
 
 
111
 
112
- // --- Ball Class ---
113
- class Ball {
114
- constructor() {
115
- this.r = 5; // radius of the ball
116
- // Random position inside the sphere (by picking a random angle and radius)
117
- let angle = random(TWO_PI);
118
- let rad = random(sphereRadius - this.r);
119
- this.pos = createVector(rad * cos(angle), rad * sin(angle));
120
- // Random speed and direction
121
- let speed = random(1, 3);
122
- let vAngle = random(TWO_PI);
123
- this.vel = createVector(speed * cos(vAngle), speed * sin(vAngle));
124
- // Yellow color in HSB (hue=60, saturation=100, brightness=100)
125
- this.col = color(60, 100, 100);
126
- }
127
-
128
- update() {
129
- this.pos.add(this.vel);
130
- }
131
-
132
- // Check for collision with the circular (spherical) boundary.
133
- checkBoundaryCollision() {
134
- let d = this.pos.mag();
135
- if (d + this.r > sphereRadius) {
136
- // Compute the normal (pointing outward)
137
- let normal = this.pos.copy().normalize();
138
- // Reflect the velocity: v = v - 2*(v·normal)*normal
139
- let dot = this.vel.dot(normal);
140
- this.vel.sub(p5.Vector.mult(normal, 2 * dot));
141
- // Ensure the ball is repositioned just inside the boundary.
142
- this.pos = normal.mult(sphereRadius - this.r);
143
- }
144
- }
145
-
146
- // Check for collisions with another ball (elastic collision for equal masses)
147
- collide(other) {
148
- let diff = p5.Vector.sub(other.pos, this.pos);
149
- let distBetween = diff.mag();
150
- if (distBetween < this.r + other.r) {
151
- // Separate the overlapping balls by moving them apart equally.
152
- let overlap = (this.r + other.r) - distBetween;
153
- let displacement = diff.copy().normalize().mult(overlap / 2);
154
- this.pos.sub(displacement);
155
- other.pos.add(displacement);
156
-
157
- // Compute collision response
158
- let normal = diff.copy().normalize();
159
- let relativeVelocity = p5.Vector.sub(this.vel, other.vel);
160
- let dotProd = relativeVelocity.dot(normal);
161
- // Only resolve if balls are moving toward each other.
162
- if (dotProd > 0) {
163
- // For equal masses, exchange the velocity components along the collision normal.
164
- let impulse = normal.copy().mult(dotProd);
165
- this.vel.sub(impulse);
166
- other.vel.add(impulse);
167
- }
168
- }
169
- }
170
-
171
- display() {
172
- noStroke();
173
- fill(this.col);
174
- ellipse(this.pos.x, this.pos.y, this.r * 2, this.r * 2);
175
- }
176
- }
177
 
178
- // --- Jellyfish Class ---
179
- class Jellyfish {
180
- constructor() {
181
- // For the jellyfish we choose a larger effective “radius” (for collision) of about 40.
182
- this.size = 40;
183
- // Start at a random position inside the sphere (with a margin)
184
- this.pos = createVector(random(-sphereRadius + this.size, sphereRadius - this.size),
185
- random(-sphereRadius + this.size, sphereRadius - this.size));
186
- // Give it a random velocity.
187
- let speed = random(1, 2);
188
- let angle = random(TWO_PI);
189
- this.vel = createVector(speed * cos(angle), speed * sin(angle));
190
- // A time parameter used in the jellyfish drawing.
191
- this.t = 0;
192
- }
193
-
194
- update() {
195
- this.pos.add(this.vel);
196
- this.t += 0.05;
197
- }
198
-
199
- // Bounce off the sphere boundary using a simple circular collision.
200
- checkBoundaryCollision() {
201
- if (this.pos.mag() + this.size > sphereRadius) {
202
- let normal = this.pos.copy().normalize();
203
- let dot = this.vel.dot(normal);
204
- this.vel.sub(p5.Vector.mult(normal, 2 * dot));
205
- this.pos = normal.mult(sphereRadius - this.size);
206
- }
207
- }
208
-
209
- display() {
210
- push();
211
- translate(this.pos.x, this.pos.y);
212
- // Draw the jellyfish using a grid of points computed by the jellyA() function.
213
- // (We subtract 200 from the computed positions so that the drawing is centered.)
214
- strokeWeight(1.5);
215
- for (let y = 99; y < 300; y += 4) {
216
- for (let x = 99; x < 300; x += 2) {
217
- let res = jellyA(x, y, this.t);
218
- let px = res[0] - 200;
219
- let py = res[1] - 200;
220
- stroke(getJellyColor(x, y, this.t));
221
- point(px, py);
222
- }
223
- }
224
- pop();
225
  }
 
226
  }
227
-
228
- // --- Jellyfish Drawing Functions ---
229
- // Replicate the provided jellyfish a(x,y)” function.
230
- function jellyA(x, y, t) {
231
- let k = x / 8 - 25;
232
- let e = y / 8 - 25;
233
- // d is computed as (k^2+e^2)/99
234
- let d = (k * k + e * e) / 99;
235
- let q = x / 3 + k * 0.5 / cos(y * 5) * sin(d * d - t);
236
- let c = d / 2 - t / 8;
237
- let xPos = q * sin(c) + e * sin(d + k - t) + 200;
238
- let yPos = (q + y / 8 + d * 9) * cos(c) + 200;
239
- return [xPos, yPos];
 
 
 
 
 
 
 
 
 
240
  }
241
-
242
- // Replicate the provided getColor function for the jellyfish.
243
- function getJellyColor(x, y, t) {
244
- let hue = (sin(t / 2) * 360 + x / 3 + y / 3) % 360;
245
- let saturation = 70 + sin(t) * 30;
246
- let brightness = 50 + cos(t / 2) * 20;
247
- return color(hue, saturation, brightness, 0.5);
 
 
 
248
  }
 
249
  </script>
250
  </body>
251
  </html>
252
  """
253
- # The height is set to 800px; adjust if needed.
254
- st.components.v1.html(html_code, height=820, scrolling=False)
 
255
 
256
- if __name__ == "__main__":
257
- create_animation_app()
 
1
  import streamlit as st
2
 
3
+ def create_app():
4
+ st.title("3D Python Snake Matrix Code ❤️🐍")
5
+
 
 
 
 
 
6
  html_code = r"""
7
  <!DOCTYPE html>
8
  <html>
9
  <head>
10
  <meta charset="UTF-8">
11
+ <title>3D Python Snake Matrix Code ❤️</title>
12
+ <!-- Load p5.js (with WEBGL support) from a CDN -->
13
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.min.js"></script>
14
  <style>
15
+ /* Remove margins and set a black background */
16
+ body { margin: 0; padding: 0; overflow: hidden; background: black; }
17
+ #sketch-container { display: flex; justify-content: center; align-items: center; }
 
 
 
 
 
 
 
 
 
18
  </style>
19
  </head>
20
  <body>
21
+ <div id="sketch-container"></div>
22
  <script>
23
+ // ❤️ 3D Python Snake Matrix Code with Heart Emojis ❤️
24
+ // Global variables for the Matrix rain overlay
25
+ let matrixColumns = [];
26
+ let fontSize = 16;
27
+ let numColumns;
28
+
29
+ // Global variables for the snake
30
+ let snake = []; // Array to hold 3D positions of the snake segments
31
+ const maxSnakeLength = 50; // Maximum number of segments
32
+ let t = 0; // Time variable for snake movement
33
+
34
+ function setup() {
35
+ // Create a WEBGL canvas that fills the window and attach it to our container
36
+ let canvas = createCanvas(windowWidth, windowHeight, WEBGL);
37
+ canvas.parent('sketch-container');
38
+ textFont('monospace');
39
+ textSize(fontSize);
40
+ noStroke();
41
 
42
+ // Setup Matrix rain columns (we work in 2D for the overlay)
43
+ numColumns = floor(width / fontSize);
44
+ for (let i = 0; i < numColumns; i++) {
45
+ matrixColumns[i] = random(-1000, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  }
47
 
48
+ // Initialize the snake: start with all segments at the center (0,0,0)
49
+ for (let i = 0; i < maxSnakeLength; i++) {
50
+ snake.push(createVector(0, 0, 0));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
+ }
53
+
54
+ function draw() {
55
+ background(0);
56
 
57
+ // Set up some lights for 3D shading
58
+ ambientLight(50);
59
+ directionalLight(255, 255, 255, 0, -1, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
+ // Rotate the entire 3D scene slowly for an extra cool effect
62
+ rotateY(frameCount * 0.005);
63
+ rotateX(frameCount * 0.003);
64
+
65
+ // Update and draw our snake in 3D
66
+ updateSnake();
67
+ drawSnake();
68
+
69
+ // Draw the Matrix rain overlay on top (in 2D)
70
+ drawMatrixRain();
71
+ }
72
+
73
+ // Update the snake's position using Perlin noise for a fluid, organic motion
74
+ function updateSnake() {
75
+ t += 0.01;
76
+ // Compute new head position using noise to vary x, y, and z independently
77
+ let x = map(noise(t, 0), 0, 1, -width/3, width/3);
78
+ let y = map(noise(t, 100), 0, 1, -height/3, height/3);
79
+ let z = map(noise(t, 200), 0, 1, -300, 300);
80
+ let newHead = createVector(x, y, z);
81
+ snake.push(newHead);
82
+ // Maintain a fixed length by removing the tail segment
83
+ if (snake.length > maxSnakeLength) {
84
+ snake.shift();
85
+ }
86
+ }
87
+
88
+ // Draw the snake: each segment is rendered as a Matrix-style character,
89
+ // and every 10th segment is rendered as a heart emoji for extra love ❤️.
90
+ function drawSnake() {
91
+ for (let i = 0; i < snake.length; i++) {
92
+ let pos = snake[i];
93
+ push();
94
+ translate(pos.x, pos.y, pos.z);
95
+ // Every 10th segment, show a heart emoji instead of a random character
96
+ if (i % 10 === 0) {
97
+ textSize(fontSize + 4);
98
+ fill(255, 0, 100);
99
+ text("❤️", 0, 0);
100
+ } else {
101
+ fill(0, 255, 70);
102
+ textSize(fontSize);
103
+ let matrixChars = "01ABCDEFGHIJKLMNOPQRSTUVWXYZ";
104
+ let char = matrixChars.charAt(floor(random(matrixChars.length)));
105
+ text(char, 0, 0);
 
 
106
  }
107
+ pop();
108
  }
109
+ }
110
+
111
+ // Draw a classic Matrix rain effect as a 2D overlay on top of the 3D scene
112
+ function drawMatrixRain() {
113
+ push();
114
+ // Reset to 2D drawing mode
115
+ resetMatrix();
116
+ // Shift the origin to the top-left corner
117
+ translate(0, 0);
118
+ textSize(fontSize);
119
+ fill(0, 255, 70);
120
+ for (let i = 0; i < numColumns; i++) {
121
+ let x = i * fontSize;
122
+ let y = matrixColumns[i];
123
+ let matrixChars = "01ABCDEFGHIJKLMNOPQRSTUVWXYZ";
124
+ let char = matrixChars.charAt(floor(random(matrixChars.length)));
125
+ text(char, x, y);
126
+ matrixColumns[i] += fontSize;
127
+ // If the drop goes off the screen, reset it to the top with a random offset
128
+ if (matrixColumns[i] > height) {
129
+ matrixColumns[i] = random(-100, 0);
130
+ }
131
  }
132
+ pop();
133
+ }
134
+
135
+ // When the window is resized, adjust the canvas and recalc matrix columns
136
+ function windowResized() {
137
+ resizeCanvas(windowWidth, windowHeight);
138
+ numColumns = floor(width / fontSize);
139
+ matrixColumns = [];
140
+ for (let i = 0; i < numColumns; i++) {
141
+ matrixColumns[i] = random(-1000, 0);
142
  }
143
+ }
144
  </script>
145
  </body>
146
  </html>
147
  """
148
+
149
+ # Embed the HTML (with the p5.js sketch) into the Streamlit app.
150
+ st.components.v1.html(html_code, height=700, scrolling=True)
151
 
152
+ if __name__ == '__main__':
153
+ create_app()