Skip to content

Commit b5f6fa0

Browse files
authored
tilt marble webapp
1 parent 24bf2d7 commit b5f6fa0

File tree

6 files changed

+226
-0
lines changed

6 files changed

+226
-0
lines changed

marble_webapp/app.js

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
const canvas = document.getElementById("gameCanvas");
2+
const ctx = canvas.getContext("2d");
3+
canvas.width = window.innerWidth;
4+
canvas.height = window.innerHeight;
5+
6+
let angleX = 0;
7+
let angleY = 0;
8+
let velocity = {x: 0, y: 0};
9+
let marble = {x: 50, y: 50, r: 10};
10+
const startPoint = {x: 50, y: 50};
11+
const goal = {x: canvas.width - 60, y: canvas.height - 60, r: 20};
12+
const holes = [
13+
{x: 150, y: 150, r: 15},
14+
{x: 300, y: 200, r: 15},
15+
{x: 400, y: 400, r: 15}
16+
];
17+
const friction = 0.98;
18+
const sensitivity = 0.5;
19+
20+
const keys = {};
21+
document.addEventListener('keydown', e => keys[e.key.toLowerCase()] = true);
22+
document.addEventListener('keyup', e => keys[e.key.toLowerCase()] = false);
23+
24+
// Mobile tilt support
25+
if (window.DeviceMotionEvent) {
26+
window.addEventListener('devicemotion', e => {
27+
if (e.accelerationIncludingGravity) {
28+
angleX = e.accelerationIncludingGravity.x;
29+
angleY = -e.accelerationIncludingGravity.y;
30+
}
31+
});
32+
}
33+
34+
function restartGame() {
35+
marble.x = startPoint.x;
36+
marble.y = startPoint.y;
37+
velocity = {x: 0, y: 0};
38+
}
39+
40+
function draw() {
41+
ctx.clearRect(0, 0, canvas.width, canvas.height);
42+
43+
// Goal
44+
ctx.fillStyle = "green";
45+
ctx.beginPath();
46+
ctx.arc(goal.x, goal.y, goal.r, 0, Math.PI * 2);
47+
ctx.fill();
48+
49+
// Holes
50+
ctx.fillStyle = "black";
51+
for (const hole of holes) {
52+
ctx.beginPath();
53+
ctx.arc(hole.x, hole.y, hole.r, 0, Math.PI * 2);
54+
ctx.fill();
55+
}
56+
57+
// Marble
58+
ctx.fillStyle = "blue";
59+
ctx.beginPath();
60+
ctx.arc(marble.x, marble.y, marble.r, 0, Math.PI * 2);
61+
ctx.fill();
62+
63+
// Debug
64+
ctx.fillStyle = "black";
65+
ctx.font = "14px sans-serif";
66+
ctx.fillText(`angleX: ${angleX.toFixed(2)} angleY: ${angleY.toFixed(2)}`, 10, 20);
67+
}
68+
69+
function update() {
70+
// WASD simulation
71+
let keyboardAngleX = 0;
72+
let keyboardAngleY = 0;
73+
if (keys['w']) keyboardAngleY -= 1;
74+
if (keys['s']) keyboardAngleY += 1;
75+
if (keys['a']) keyboardAngleX -= 1;
76+
if (keys['d']) keyboardAngleX += 1;
77+
78+
// Kombiniere Tastatur und DeviceMotion
79+
const totalAngleX = angleX + keyboardAngleX;
80+
const totalAngleY = angleY + keyboardAngleY;
81+
82+
velocity.x += totalAngleX * sensitivity;
83+
velocity.y += totalAngleY * sensitivity;
84+
velocity.x *= friction;
85+
velocity.y *= friction;
86+
87+
marble.x += velocity.x;
88+
marble.y += velocity.y;
89+
90+
// Wall clamp
91+
marble.x = Math.max(marble.r, Math.min(canvas.width - marble.r, marble.x));
92+
marble.y = Math.max(marble.r, Math.min(canvas.height - marble.r, marble.y));
93+
94+
// Hole check
95+
for (const hole of holes) {
96+
const dx = marble.x - hole.x;
97+
const dy = marble.y - hole.y;
98+
const dist = Math.sqrt(dx * dx + dy * dy);
99+
if (dist < marble.r + hole.r) {
100+
restartGame();
101+
return;
102+
}
103+
}
104+
105+
// Goal check
106+
const dx = marble.x - goal.x;
107+
const dy = marble.y - goal.y;
108+
const dist = Math.sqrt(dx * dx + dy * dy);
109+
if (dist < marble.r + goal.r) {
110+
alert("You reached the goal!");
111+
restartGame();
112+
}
113+
}
114+
115+
function gameLoop() {
116+
update();
117+
draw();
118+
requestAnimationFrame(gameLoop);
119+
}
120+
121+
gameLoop();

marble_webapp/icon.png

59.1 KB
Loading

marble_webapp/index.html

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Marble Maze Game</title>
7+
<style>
8+
html, body {
9+
margin: 0;
10+
padding: 0;
11+
overflow: hidden;
12+
font-family: sans-serif;
13+
}
14+
/*make the canvas be centered on the page and have a bit of border*/
15+
body {
16+
display: flex;
17+
justify-content: center;
18+
align-items: center;
19+
height: 100vh;
20+
box-sizing: border-box;
21+
}
22+
canvas {
23+
width: 90vw;
24+
height: 90vh;
25+
max-width: 1000px;
26+
max-height: 800px;
27+
display: block;
28+
background: #f0f0f0;
29+
border: 2px solid #ccc;
30+
border-radius: 12px;
31+
box-sizing: border-box;
32+
}
33+
#controls {
34+
position: absolute;
35+
top: 10px;
36+
left: 10px;
37+
z-index: 2;
38+
}
39+
button {
40+
padding: 8px 16px;
41+
font-size: 16px;
42+
}
43+
</style>
44+
</head>
45+
<body>
46+
<div id="controls">
47+
<button onclick="restartGame()">Restart</button>
48+
</div>
49+
<canvas id="gameCanvas"></canvas>
50+
<script src="app.js">
51+
52+
</script>
53+
</body>
54+
</html>

marble_webapp/manifest.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "Marble WebApp",
3+
"short_name": "Sensors",
4+
"start_url": "./index.html",
5+
"display": "standalone",
6+
"background_color": "#ffffff",
7+
"theme_color": "#317EFB",
8+
"icons": [
9+
{
10+
"src": "icon.png",
11+
"sizes": "192x192",
12+
"type": "image/png"
13+
}
14+
]
15+
}

marble_webapp/service-worker.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
self.addEventListener('install', function(e) {
2+
e.waitUntil(
3+
caches.open('sensor-cache').then(function(cache) {
4+
return cache.addAll([
5+
'/',
6+
'/index.html',
7+
'/style.css',
8+
'/app.js',
9+
'/manifest.json'
10+
]);
11+
})
12+
);
13+
});
14+
15+
self.addEventListener('fetch', function(e) {
16+
e.respondWith(
17+
caches.match(e.request).then(function(response) {
18+
return response || fetch(e.request);
19+
})
20+
);
21+
});

marble_webapp/style.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
body {
2+
font-family: sans-serif;
3+
text-align: center;
4+
background: #f2f2f2;
5+
color: #333;
6+
}
7+
.sensor {
8+
background: white;
9+
margin: 20px auto;
10+
padding: 15px;
11+
border-radius: 10px;
12+
width: 80%;
13+
max-width: 400px;
14+
box-shadow: 0 2px 6px rgba(0,0,0,0.2);
15+
}

0 commit comments

Comments
 (0)