Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import random
|
3 |
+
import base64
|
4 |
+
|
5 |
+
# Mad Lib Generator
|
6 |
+
templates = [
|
7 |
+
"The {adjective} {noun} {verb} over the {adjective} {noun}.",
|
8 |
+
"In a {adjective} land, a {noun} and a {noun} went on a {adjective} adventure.",
|
9 |
+
"The {noun} {verb} {adverb} while the {adjective} {noun} watched in amazement."
|
10 |
+
]
|
11 |
+
|
12 |
+
parts_of_speech = {
|
13 |
+
"adjective": ["brave", "mysterious", "colorful", "gigantic", "tiny"],
|
14 |
+
"noun": ["wizard", "dragon", "knight", "castle", "forest"],
|
15 |
+
"verb": ["flew", "danced", "sang", "fought", "explored"],
|
16 |
+
"adverb": ["quickly", "silently", "gracefully", "fiercely", "carefully"]
|
17 |
+
}
|
18 |
+
|
19 |
+
def generate_mad_lib():
|
20 |
+
template = random.choice(templates)
|
21 |
+
for part in parts_of_speech:
|
22 |
+
while "{" + part + "}" in template:
|
23 |
+
template = template.replace("{" + part + "}", random.choice(parts_of_speech[part]), 1)
|
24 |
+
return template
|
25 |
+
|
26 |
+
# Kaboom.js Breakout Game HTML
|
27 |
+
kaboom_game_html = """
|
28 |
+
<script src="https://kaboomjs.com/lib/0.6.0/kaboom.js"></script>
|
29 |
+
<canvas id="game"></canvas>
|
30 |
+
<script>
|
31 |
+
kaboom({
|
32 |
+
global: true,
|
33 |
+
width: 800,
|
34 |
+
height: 600,
|
35 |
+
scale: 1,
|
36 |
+
debug: true,
|
37 |
+
canvas: document.getElementById("game")
|
38 |
+
});
|
39 |
+
|
40 |
+
loadSprite("paddle", "https://kaboomjs.com/pub/examples/breakout/paddle.png");
|
41 |
+
loadSprite("ball", "https://kaboomjs.com/pub/examples/breakout/ball.png");
|
42 |
+
loadSprite("brick", "https://kaboomjs.com/pub/examples/breakout/brick.png");
|
43 |
+
loadSprite("brick2", "https://kaboomjs.com/pub/examples/breakout/brick2.png");
|
44 |
+
|
45 |
+
scene("main", () => {
|
46 |
+
let score = 0;
|
47 |
+
let lifePoints = 100;
|
48 |
+
|
49 |
+
const scoreLabel = add([
|
50 |
+
text(`Score: ${score}`),
|
51 |
+
pos(24, 24)
|
52 |
+
]);
|
53 |
+
|
54 |
+
const lifeLabel = add([
|
55 |
+
text(`Life: ${lifePoints}`),
|
56 |
+
pos(24, 48)
|
57 |
+
]);
|
58 |
+
|
59 |
+
const paddle = add([
|
60 |
+
sprite("paddle"),
|
61 |
+
pos(width() / 2, height() - 48),
|
62 |
+
area(),
|
63 |
+
scale(3),
|
64 |
+
"paddle"
|
65 |
+
]);
|
66 |
+
|
67 |
+
onKeyDown("left", () => {
|
68 |
+
paddle.move(-10, 0);
|
69 |
+
});
|
70 |
+
|
71 |
+
onKeyDown("right", () => {
|
72 |
+
paddle.move(10, 0);
|
73 |
+
});
|
74 |
+
|
75 |
+
function spawnBall() {
|
76 |
+
const ball = add([
|
77 |
+
sprite("ball"),
|
78 |
+
pos(width() / 2, height() - 64),
|
79 |
+
area(),
|
80 |
+
scale(0.5),
|
81 |
+
{ vel: vec2(300, -300) },
|
82 |
+
"ball"
|
83 |
+
]);
|
84 |
+
|
85 |
+
ball.onCollide("paddle", (paddle) => {
|
86 |
+
ball.vel = vec2(ball.vel.x, -Math.abs(ball.vel.y));
|
87 |
+
});
|
88 |
+
|
89 |
+
ball.onCollide("brick", (brick) => {
|
90 |
+
destroy(brick);
|
91 |
+
ball.vel = vec2(ball.vel.x, -ball.vel.y);
|
92 |
+
score += brick.points;
|
93 |
+
scoreLabel.text = `Score: ${score}`;
|
94 |
+
});
|
95 |
+
|
96 |
+
return ball;
|
97 |
+
}
|
98 |
+
|
99 |
+
let ball = spawnBall();
|
100 |
+
|
101 |
+
function spawnBricks() {
|
102 |
+
const brickTypes = [
|
103 |
+
{ sprite: "brick", points: 1, health: 1 },
|
104 |
+
{ sprite: "brick2", points: 2, health: 2 },
|
105 |
+
];
|
106 |
+
|
107 |
+
for (let i = 0; i < 8; i++) {
|
108 |
+
for (let j = 0; j < 5; j++) {
|
109 |
+
const type = choose(brickTypes);
|
110 |
+
add([
|
111 |
+
sprite(type.sprite),
|
112 |
+
pos(i * 96 + 64, j * 32 + 64),
|
113 |
+
area(),
|
114 |
+
scale(2),
|
115 |
+
"brick",
|
116 |
+
{
|
117 |
+
points: type.points,
|
118 |
+
health: type.health
|
119 |
+
}
|
120 |
+
]);
|
121 |
+
}
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
spawnBricks();
|
126 |
+
|
127 |
+
onUpdate("ball", (ball) => {
|
128 |
+
if (ball.pos.y > height()) {
|
129 |
+
destroy(ball);
|
130 |
+
lifePoints -= 10;
|
131 |
+
lifeLabel.text = `Life: ${lifePoints}`;
|
132 |
+
if (lifePoints <= 0) {
|
133 |
+
go("gameOver", score);
|
134 |
+
} else {
|
135 |
+
ball = spawnBall();
|
136 |
+
}
|
137 |
+
}
|
138 |
+
});
|
139 |
+
});
|
140 |
+
|
141 |
+
scene("gameOver", (score) => {
|
142 |
+
add([
|
143 |
+
text(`Game Over!\nFinal Score: ${score}`),
|
144 |
+
pos(width() / 2, height() / 2),
|
145 |
+
origin("center")
|
146 |
+
]);
|
147 |
+
|
148 |
+
onKeyPress("space", () => {
|
149 |
+
go("main");
|
150 |
+
});
|
151 |
+
});
|
152 |
+
|
153 |
+
start("main");
|
154 |
+
</script>
|
155 |
+
"""
|
156 |
+
|
157 |
+
# A-Frame 3D Scene HTML
|
158 |
+
aframe_scene_html = """
|
159 |
+
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
|
160 |
+
<script src="https://cdn.jsdelivr.net/gh/donmccurdy/[email protected]/dist/aframe-extras.min.js"></script>
|
161 |
+
<a-scene embedded style="height: 400px;">
|
162 |
+
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
|
163 |
+
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
|
164 |
+
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
|
165 |
+
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
|
166 |
+
<a-sky color="#ECECEC"></a-sky>
|
167 |
+
<a-entity id="rig" position="0 1.6 0">
|
168 |
+
<a-camera></a-camera>
|
169 |
+
</a-entity>
|
170 |
+
<a-entity id="model-container" position="0 0 -5"></a-entity>
|
171 |
+
</a-scene>
|
172 |
+
|
173 |
+
<script>
|
174 |
+
function loadModel(url, fileType) {
|
175 |
+
const scene = document.querySelector('a-scene');
|
176 |
+
const modelContainer = document.getElementById('model-container');
|
177 |
+
|
178 |
+
// Remove any existing model
|
179 |
+
while (modelContainer.firstChild) {
|
180 |
+
modelContainer.removeChild(modelContainer.firstChild);
|
181 |
+
}
|
182 |
+
|
183 |
+
// Create new entity for the model
|
184 |
+
const modelEntity = document.createElement('a-entity');
|
185 |
+
if (fileType === 'obj') {
|
186 |
+
modelEntity.setAttribute('obj-model', `obj: ${url}`);
|
187 |
+
} else if (fileType === 'glb') {
|
188 |
+
modelEntity.setAttribute('gltf-model', url);
|
189 |
+
}
|
190 |
+
|
191 |
+
modelEntity.setAttribute('scale', '0.5 0.5 0.5');
|
192 |
+
modelEntity.setAttribute('animation', 'property: rotation; to: 0 360 0; loop: true; dur: 10000');
|
193 |
+
|
194 |
+
modelContainer.appendChild(modelEntity);
|
195 |
+
}
|
196 |
+
</script>
|
197 |
+
"""
|
198 |
+
|
199 |
+
def upload_model(file):
|
200 |
+
if file is not None:
|
201 |
+
file_extension = file.name.split('.')[-1].lower()
|
202 |
+
encoded_file = base64.b64encode(file.read()).decode()
|
203 |
+
data_url = f"data:application/octet-stream;base64,{encoded_file}"
|
204 |
+
load_model_js = f"""
|
205 |
+
<script>
|
206 |
+
loadModel("{data_url}", "{file_extension}");
|
207 |
+
</script>
|
208 |
+
"""
|
209 |
+
return aframe_scene_html + load_model_js
|
210 |
+
return aframe_scene_html
|
211 |
+
|
212 |
+
# Define the Gradio interface
|
213 |
+
with gr.Blocks() as demo:
|
214 |
+
gr.Markdown("# Game Development and 3D Content Showcase")
|
215 |
+
|
216 |
+
with gr.Tab("Breakout Game"):
|
217 |
+
gr.HTML(kaboom_game_html)
|
218 |
+
|
219 |
+
with gr.Tab("Mad Lib Generator"):
|
220 |
+
mad_lib_button = gr.Button("Generate Mad Lib")
|
221 |
+
mad_lib_output = gr.Textbox(label="Generated Mad Lib")
|
222 |
+
mad_lib_button.click(generate_mad_lib, inputs=None, outputs=mad_lib_output)
|
223 |
+
|
224 |
+
with gr.Tab("A-Frame 3D Scene"):
|
225 |
+
model_upload = gr.File(label="Upload 3D Model (OBJ or GLB)")
|
226 |
+
scene_output = gr.HTML(aframe_scene_html)
|
227 |
+
model_upload.upload(upload_model, inputs=model_upload, outputs=scene_output)
|
228 |
+
|
229 |
+
# Launch the Gradio app
|
230 |
+
if __name__ == "__main__":
|
231 |
+
demo.launch()
|