33fae37838
User Management (Backend): - schema-v2.sql: students, licenses, student_results, activity_log Tabellen - auth.php: Lehrer-Registrierung/Login, Schueler-Login, Status-Check - classes.php: CRUD fuer Klassenverwaltung (mit Join-Code-Generator) - students.php: Schueler erstellen (einzeln + Batch), bearbeiten, loeschen - modules.php: Modulfreigabe pro Klasse (locked/free/teacher_started) Didaktisches Handbuch: - handbuch.html: Vollstaendiger Lehrpersonen-Guide - 6 Module detailliert beschrieben (Lernziele, Kompetenzen) - Vor/Nach-Fragen fuer jede Simulation - Empfohlener Unterrichtsablauf (45-min-Einheit) - Differenzierungshinweise, Bewertungsempfehlungen Stadt-Editor: - stadt-editor.html: Funktionierendes 8x8 Raster mit Kachel-Platzierung - 15 Emoji-Gebaude-Kacheln (Kirche, Moschee, Wohngebiet, Fabrik, etc.) - Spielplatz: Rutsche+Karussell statt schwebende Koepfe - Hochhaeuser: 6 Gebaeude in 2 Reihen Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
490 lines
18 KiB
HTML
490 lines
18 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Kachel-Test — Gebäude</title>
|
|
<style>
|
|
body { margin:0; display:flex; align-items:flex-start; justify-content:center; min-height:100vh; background:#e0e0d8; gap:10px; flex-wrap:wrap; font-family:Inter,sans-serif; padding:15px; }
|
|
.tile { display:flex; flex-direction:column; align-items:center; gap:2px; }
|
|
.tile span { font-size:9px; color:#666; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="tile"><canvas id="t01" width="200" height="200"></canvas><span>Kirche</span></div>
|
|
<div class="tile"><canvas id="t02" width="200" height="200"></canvas><span>Moschee</span></div>
|
|
<div class="tile"><canvas id="t03" width="200" height="200"></canvas><span>Wohngebiet</span></div>
|
|
<div class="tile"><canvas id="t04" width="200" height="200"></canvas><span>Fabrik</span></div>
|
|
<div class="tile"><canvas id="t05" width="200" height="200"></canvas><span>Spital</span></div>
|
|
<div class="tile"><canvas id="t06" width="200" height="200"></canvas><span>Feuerwehr</span></div>
|
|
<div class="tile"><canvas id="t07" width="200" height="200"></canvas><span>Polizei</span></div>
|
|
<div class="tile"><canvas id="t08" width="200" height="200"></canvas><span>Schule</span></div>
|
|
<div class="tile"><canvas id="t09" width="200" height="200"></canvas><span>Supermarkt</span></div>
|
|
<div class="tile"><canvas id="t10" width="200" height="200"></canvas><span>Park</span></div>
|
|
|
|
<script>
|
|
var SZ = 200
|
|
var RW = SZ * 0.4, M = SZ / 2, HR = RW / 2
|
|
var LW = 2
|
|
var GREEN = '#b8ccaa', ROAD = '#2e2e2e', WHITE = '#fff'
|
|
var DASH = [SZ*0.07, SZ*0.05]
|
|
var DOFF = -SZ*0.035
|
|
|
|
// === Strassen-Grundfunktionen ===
|
|
|
|
function base(id) {
|
|
var c = document.getElementById(id).getContext('2d')
|
|
c.fillStyle = GREEN; c.fillRect(0,0,SZ,SZ)
|
|
return c
|
|
}
|
|
|
|
function drawRoadNS(c, x) {
|
|
// Vertikale Strasse bei x-Mitte = x
|
|
c.fillStyle = ROAD; c.fillRect(x-HR, 0, RW, SZ)
|
|
c.strokeStyle = WHITE; c.lineWidth = LW
|
|
c.beginPath(); c.moveTo(x-HR,0); c.lineTo(x-HR,SZ); c.stroke()
|
|
c.beginPath(); c.moveTo(x+HR,0); c.lineTo(x+HR,SZ); c.stroke()
|
|
c.setLineDash(DASH); c.lineDashOffset = DOFF
|
|
c.beginPath(); c.moveTo(x,0); c.lineTo(x,SZ); c.stroke()
|
|
c.setLineDash([]); c.lineDashOffset = 0
|
|
}
|
|
|
|
function drawRoadEW(c, y) {
|
|
c.fillStyle = ROAD; c.fillRect(0, y-HR, SZ, RW)
|
|
c.strokeStyle = WHITE; c.lineWidth = LW
|
|
c.beginPath(); c.moveTo(0,y-HR); c.lineTo(SZ,y-HR); c.stroke()
|
|
c.beginPath(); c.moveTo(0,y+HR); c.lineTo(SZ,y+HR); c.stroke()
|
|
c.setLineDash(DASH); c.lineDashOffset = DOFF
|
|
c.beginPath(); c.moveTo(0,y); c.lineTo(SZ,y); c.stroke()
|
|
c.setLineDash([]); c.lineDashOffset = 0
|
|
}
|
|
|
|
function drawStubN(c) {
|
|
// Sackgasse von oben — kurzer Stummel
|
|
var stubY = 4
|
|
c.fillStyle = ROAD; c.fillRect(M-HR, 0, RW, stubY)
|
|
c.beginPath(); c.arc(M, stubY, HR, 0, Math.PI); c.fill()
|
|
c.strokeStyle = WHITE; c.lineWidth = LW
|
|
c.beginPath(); c.moveTo(M-HR,0); c.lineTo(M-HR,stubY); c.stroke()
|
|
c.beginPath(); c.moveTo(M+HR,0); c.lineTo(M+HR,stubY); c.stroke()
|
|
c.beginPath(); c.arc(M, stubY, HR, 0, Math.PI); c.stroke()
|
|
}
|
|
|
|
function drawStubS(c) {
|
|
var stubY = SZ - 4
|
|
c.fillStyle = ROAD; c.fillRect(M-HR, stubY, RW, 4)
|
|
c.beginPath(); c.arc(M, stubY, HR, Math.PI, 0); c.fill()
|
|
c.strokeStyle = WHITE; c.lineWidth = LW
|
|
c.beginPath(); c.moveTo(M-HR,SZ); c.lineTo(M-HR,stubY); c.stroke()
|
|
c.beginPath(); c.moveTo(M+HR,SZ); c.lineTo(M+HR,stubY); c.stroke()
|
|
c.beginPath(); c.arc(M, stubY, HR, Math.PI, 0); c.stroke()
|
|
}
|
|
|
|
function drawStubE(c) {
|
|
var stubX = SZ - 4
|
|
c.fillStyle = ROAD; c.fillRect(stubX, M-HR, 4, RW)
|
|
c.beginPath(); c.arc(stubX, M, HR, Math.PI*1.5, Math.PI*0.5); c.fill()
|
|
c.strokeStyle = WHITE; c.lineWidth = LW
|
|
c.beginPath(); c.moveTo(SZ,M-HR); c.lineTo(stubX,M-HR); c.stroke()
|
|
c.beginPath(); c.moveTo(SZ,M+HR); c.lineTo(stubX,M+HR); c.stroke()
|
|
c.beginPath(); c.arc(stubX, M, HR, Math.PI*1.5, Math.PI*0.5); c.stroke()
|
|
}
|
|
|
|
function drawStubW(c) {
|
|
var stubX = 4
|
|
c.fillStyle = ROAD; c.fillRect(0, M-HR, 4, RW)
|
|
c.beginPath(); c.arc(stubX, M, HR, Math.PI*0.5, Math.PI*1.5); c.fill()
|
|
c.strokeStyle = WHITE; c.lineWidth = LW
|
|
c.beginPath(); c.moveTo(0,M-HR); c.lineTo(stubX,M-HR); c.stroke()
|
|
c.beginPath(); c.moveTo(0,M+HR); c.lineTo(stubX,M+HR); c.stroke()
|
|
c.beginPath(); c.arc(stubX, M, HR, Math.PI*0.5, Math.PI*1.5); c.stroke()
|
|
}
|
|
|
|
// === Gebaeude-Hilfszeichnung ===
|
|
|
|
function drawBuilding(c, x, y, w, h, color, label) {
|
|
// Gebaeude als Rechteck mit Farbe + Label
|
|
c.fillStyle = color
|
|
c.fillRect(x, y, w, h)
|
|
c.strokeStyle = 'rgba(0,0,0,0.15)'; c.lineWidth = 1
|
|
c.strokeRect(x, y, w, h)
|
|
// Dach-Effekt (dunklere Oberkante)
|
|
c.fillStyle = 'rgba(0,0,0,0.08)'
|
|
c.fillRect(x, y, w, 4)
|
|
// Label
|
|
if (label) {
|
|
c.fillStyle = 'rgba(255,255,255,0.9)'
|
|
c.font = 'bold 10px Inter, sans-serif'
|
|
c.textAlign = 'center'; c.textBaseline = 'middle'
|
|
c.fillText(label, x + w/2, y + h/2)
|
|
}
|
|
}
|
|
|
|
function drawHouse(c, x, y, w, h) {
|
|
// Kleines Haus mit Dach
|
|
c.fillStyle = '#d4a574'
|
|
c.fillRect(x, y + h*0.35, w, h*0.65)
|
|
// Dach
|
|
c.fillStyle = '#8B4513'
|
|
c.beginPath()
|
|
c.moveTo(x - 2, y + h*0.35)
|
|
c.lineTo(x + w/2, y)
|
|
c.lineTo(x + w + 2, y + h*0.35)
|
|
c.closePath()
|
|
c.fill()
|
|
// Fenster
|
|
c.fillStyle = '#a8d0e0'
|
|
c.fillRect(x + w*0.2, y + h*0.5, w*0.25, h*0.2)
|
|
// Tuer
|
|
c.fillStyle = '#6a4a3a'
|
|
c.fillRect(x + w*0.55, y + h*0.55, w*0.2, h*0.4)
|
|
}
|
|
|
|
function drawTree(c, x, y, sz) {
|
|
c.fillStyle = '#5a4020'
|
|
c.fillRect(x + sz*0.4, y + sz*0.5, sz*0.2, sz*0.5)
|
|
c.fillStyle = '#3a8a2a'
|
|
c.beginPath(); c.arc(x + sz*0.5, y + sz*0.4, sz*0.4, 0, Math.PI*2); c.fill()
|
|
}
|
|
|
|
// ============================================================
|
|
// 1. KIRCHE — Sackgasse S, grosses Gebaeude
|
|
// ============================================================
|
|
;(function(){
|
|
var c = base('t01')
|
|
drawStubS(c)
|
|
// Grosses Kirchengebaeude
|
|
drawBuilding(c, 30, 15, 140, 110, '#c8b090', '')
|
|
// Turm
|
|
c.fillStyle = '#a08060'
|
|
c.fillRect(80, 5, 40, 60)
|
|
// Kreuz oben
|
|
c.strokeStyle = '#5a4a3a'; c.lineWidth = 3
|
|
c.beginPath(); c.moveTo(100, 2); c.lineTo(100, 18); c.stroke()
|
|
c.beginPath(); c.moveTo(92, 10); c.lineTo(108, 10); c.stroke()
|
|
// Tuer
|
|
c.fillStyle = '#5a3a2a'
|
|
c.beginPath(); c.arc(100, 125, 15, Math.PI, 0); c.fill()
|
|
c.fillRect(85, 115, 30, 15)
|
|
// Label
|
|
c.fillStyle = '#5a4a3a'; c.font = 'bold 11px Inter,sans-serif'; c.textAlign = 'center'
|
|
c.fillText('Kirche', 100, 85)
|
|
})()
|
|
|
|
// ============================================================
|
|
// 2. MOSCHEE — Sackgasse N + S (zwei Zufahrten)
|
|
// ============================================================
|
|
;(function(){
|
|
var c = base('t02')
|
|
drawStubN(c)
|
|
drawStubS(c)
|
|
// Gebaeude
|
|
drawBuilding(c, 25, 35, 150, 90, '#d8c8a8', '')
|
|
// Kuppel
|
|
c.fillStyle = '#c0a878'
|
|
c.beginPath(); c.arc(100, 50, 35, Math.PI, 0); c.fill()
|
|
// Halbmond
|
|
c.fillStyle = '#e8d8a0'; c.font = '18px serif'; c.textAlign = 'center'
|
|
c.fillText('☪', 100, 42)
|
|
// Minarett
|
|
c.fillStyle = '#b8a878'
|
|
c.fillRect(150, 25, 12, 70)
|
|
c.fillRect(147, 22, 18, 6)
|
|
// Label
|
|
c.fillStyle = '#6a5a3a'; c.font = 'bold 10px Inter,sans-serif'
|
|
c.fillText('Moschee', 100, 100)
|
|
})()
|
|
|
|
// ============================================================
|
|
// 3. WOHNGEBIET — Gerade N-S, Haeuser links und rechts
|
|
// ============================================================
|
|
;(function(){
|
|
var c = base('t03')
|
|
drawRoadNS(c, M)
|
|
// Haeuser links
|
|
drawHouse(c, 8, 20, 30, 30)
|
|
drawHouse(c, 12, 70, 28, 28)
|
|
drawHouse(c, 6, 120, 32, 30)
|
|
// Haeuser rechts
|
|
drawHouse(c, 160, 15, 30, 28)
|
|
drawHouse(c, 162, 65, 28, 30)
|
|
drawHouse(c, 158, 115, 32, 28)
|
|
drawHouse(c, 164, 160, 26, 26)
|
|
})()
|
|
|
|
// ============================================================
|
|
// 4. FABRIK — Kurve (N→E), Fabrik im gruenen Bereich (unten-links)
|
|
// ============================================================
|
|
;(function(){
|
|
var c = base('t04')
|
|
// Kurve N→E
|
|
var px = M+HR, py = M-HR
|
|
c.fillStyle = ROAD
|
|
c.fillRect(M-HR, 0, RW, py)
|
|
c.fillRect(px, M-HR, SZ-px, RW)
|
|
c.beginPath(); c.moveTo(px,py); c.arc(px,py,RW,Math.PI,Math.PI*0.5,true); c.closePath(); c.fill()
|
|
// Raender
|
|
c.strokeStyle=WHITE;c.lineWidth=LW
|
|
c.beginPath();c.arc(px,py,RW,Math.PI,Math.PI*0.5,true);c.stroke()
|
|
c.beginPath();c.moveTo(M+HR,0);c.lineTo(M+HR,py);c.stroke()
|
|
c.beginPath();c.moveTo(px,M-HR);c.lineTo(SZ,M-HR);c.stroke()
|
|
c.beginPath();c.moveTo(M-HR,0);c.lineTo(M-HR,py);c.stroke()
|
|
c.beginPath();c.moveTo(px,M+HR);c.lineTo(SZ,M+HR);c.stroke()
|
|
// Mittellinie
|
|
c.setLineDash(DASH);c.lineDashOffset=DOFF
|
|
c.beginPath();c.moveTo(M,0);c.lineTo(M,py);c.arc(px,py,HR,Math.PI,Math.PI*0.5,true);c.lineTo(SZ,M);c.stroke()
|
|
c.setLineDash([]);c.lineDashOffset=0
|
|
// Fabrik unten-links
|
|
drawBuilding(c, 10, 130, 70, 55, '#8a8a8a', '')
|
|
// Schornstein
|
|
c.fillStyle = '#6a6a6a'
|
|
c.fillRect(55, 110, 12, 20)
|
|
c.fillRect(30, 115, 10, 15)
|
|
// Rauch
|
|
c.fillStyle = 'rgba(100,100,100,0.25)'
|
|
c.beginPath(); c.arc(61, 105, 6, 0, Math.PI*2); c.fill()
|
|
c.beginPath(); c.arc(58, 96, 5, 0, Math.PI*2); c.fill()
|
|
// Label
|
|
c.fillStyle = '#fff'; c.font = 'bold 10px Inter,sans-serif'; c.textAlign = 'center'
|
|
c.fillText('Fabrik', 45, 160)
|
|
})()
|
|
|
|
// ============================================================
|
|
// 5. SPITAL — Sackgasse E + W (zwei Zufahrten seitlich)
|
|
// ============================================================
|
|
;(function(){
|
|
var c = base('t05')
|
|
drawStubE(c)
|
|
drawStubW(c)
|
|
// Grosses Gebaeude
|
|
drawBuilding(c, 20, 15, 160, 80, '#e8e0d0', '')
|
|
// Rotes Kreuz
|
|
c.fillStyle = '#cc3333'
|
|
c.fillRect(90, 30, 20, 50)
|
|
c.fillRect(75, 42, 50, 20)
|
|
// Label
|
|
c.fillStyle = '#6a3a3a'; c.font = 'bold 11px Inter,sans-serif'; c.textAlign = 'center'
|
|
c.fillText('Spital', 100, 120)
|
|
// Rettungswagen-Parkplatz
|
|
c.fillStyle = '#7a7a7a'; c.fillRect(30, 100, 50, 25)
|
|
c.fillStyle = '#ddd'; c.font = '16px serif'
|
|
c.fillText('🚑', 55, 117)
|
|
})()
|
|
|
|
// ============================================================
|
|
// 6. FEUERWEHR — Sackgasse S
|
|
// ============================================================
|
|
;(function(){
|
|
var c = base('t06')
|
|
drawStubS(c)
|
|
// Gebaeude
|
|
drawBuilding(c, 25, 10, 150, 100, '#cc4444', '')
|
|
// Tore (2 Garagen)
|
|
c.fillStyle = '#8a2a2a'
|
|
c.fillRect(40, 70, 45, 40)
|
|
c.fillRect(105, 70, 45, 40)
|
|
// Tor-Linien
|
|
c.strokeStyle = '#6a1a1a'; c.lineWidth = 1
|
|
for (var i = 0; i < 5; i++) { c.beginPath(); c.moveTo(40, 75+i*7); c.lineTo(85, 75+i*7); c.stroke() }
|
|
for (var i = 0; i < 5; i++) { c.beginPath(); c.moveTo(105, 75+i*7); c.lineTo(150, 75+i*7); c.stroke() }
|
|
// Label
|
|
c.fillStyle = '#fff'; c.font = 'bold 11px Inter,sans-serif'; c.textAlign = 'center'
|
|
c.fillText('Feuerwehr', 100, 45)
|
|
// Schlauchturm
|
|
c.fillStyle = '#aa3333'
|
|
c.fillRect(160, 15, 15, 55)
|
|
})()
|
|
|
|
// ============================================================
|
|
// 7. POLIZEI — Sackgasse N
|
|
// ============================================================
|
|
;(function(){
|
|
var c = base('t07')
|
|
drawStubN(c)
|
|
// Gebaeude
|
|
drawBuilding(c, 20, 50, 160, 85, '#4a6a9a', '')
|
|
// Stern/Abzeichen
|
|
c.fillStyle = '#c0d0e8'; c.font = '24px serif'; c.textAlign = 'center'
|
|
c.fillText('⭐', 100, 85)
|
|
// Label
|
|
c.fillStyle = '#fff'; c.font = 'bold 11px Inter,sans-serif'
|
|
c.fillText('Polizei', 100, 115)
|
|
// Parkplatz
|
|
c.fillStyle = '#7a7a7a'; c.fillRect(30, 145, 60, 20)
|
|
c.fillStyle = '#ddd'; c.font = '14px serif'
|
|
c.fillText('🚔', 60, 160)
|
|
})()
|
|
|
|
// ============================================================
|
|
// 8. SCHULE — Gerade E-W, Gebaeude oben
|
|
// ============================================================
|
|
;(function(){
|
|
var c = base('t08')
|
|
drawRoadEW(c, M)
|
|
// Schulgebaeude oben
|
|
drawBuilding(c, 15, 10, 170, 60, '#e0c888', '')
|
|
// Fensterreihe
|
|
c.fillStyle = '#a8d0e0'
|
|
for (var i = 0; i < 5; i++) c.fillRect(25 + i*34, 25, 22, 18)
|
|
// Label
|
|
c.fillStyle = '#5a4a2a'; c.font = 'bold 11px Inter,sans-serif'; c.textAlign = 'center'
|
|
c.fillText('Schule', 100, 58)
|
|
// Schulhof unten (Wiese ist schon gruen, ein paar Details)
|
|
drawTree(c, 30, 145, 20)
|
|
drawTree(c, 140, 150, 18)
|
|
c.fillStyle = '#aaa'; c.fillRect(70, 155, 50, 3) // Bank
|
|
})()
|
|
|
|
// ============================================================
|
|
// 9. SUPERMARKT — Gerade N-S, Gebaeude rechts mit Parkplatz
|
|
// ============================================================
|
|
;(function(){
|
|
var c = base('t09')
|
|
drawRoadNS(c, M)
|
|
// Supermarkt rechts
|
|
drawBuilding(c, 140, 20, 55, 80, '#e0d0a0', '')
|
|
// Label
|
|
c.fillStyle = '#5a4a2a'; c.font = 'bold 9px Inter,sans-serif'; c.textAlign = 'center'
|
|
c.fillText('Super-', 167, 50)
|
|
c.fillText('markt', 167, 62)
|
|
// Parkplatz
|
|
c.fillStyle = '#8a8a8a'
|
|
c.fillRect(140, 110, 55, 40)
|
|
// Parkplatz-Linien
|
|
c.strokeStyle = '#aaa'; c.lineWidth = 1
|
|
for (var i = 0; i < 4; i++) { c.beginPath(); c.moveTo(152+i*12, 110); c.lineTo(152+i*12, 150); c.stroke() }
|
|
// Einkaufswagen
|
|
c.fillStyle = '#ddd'; c.font = '12px serif'
|
|
c.fillText('🛒', 167, 135)
|
|
})()
|
|
|
|
// ============================================================
|
|
// 10. PARK — Sackgasse N, viel Gruen
|
|
// ============================================================
|
|
;(function(){
|
|
var c = base('t10')
|
|
drawStubN(c)
|
|
// Baeume
|
|
drawTree(c, 15, 40, 28)
|
|
drawTree(c, 60, 55, 24)
|
|
drawTree(c, 130, 35, 30)
|
|
drawTree(c, 155, 80, 22)
|
|
drawTree(c, 25, 120, 26)
|
|
drawTree(c, 100, 110, 20)
|
|
drawTree(c, 150, 140, 24)
|
|
// Teich
|
|
c.fillStyle = 'rgba(60,140,200,0.4)'
|
|
c.beginPath(); c.ellipse(80, 140, 30, 18, 0.1, 0, Math.PI*2); c.fill()
|
|
c.strokeStyle = 'rgba(60,140,200,0.3)'; c.lineWidth = 1; c.stroke()
|
|
// Bank
|
|
c.fillStyle = '#8a7050'
|
|
c.fillRect(95, 82, 20, 6)
|
|
c.fillRect(95, 82, 3, 10)
|
|
c.fillRect(112, 82, 3, 10)
|
|
// Weg (kleiner Pfad)
|
|
c.strokeStyle = 'rgba(160,140,100,0.4)'; c.lineWidth = 3; c.setLineDash([4,3])
|
|
c.beginPath(); c.moveTo(M, 10); c.quadraticCurveTo(60, 80, 80, 140); c.stroke()
|
|
c.setLineDash([])
|
|
// Label
|
|
c.fillStyle = 'rgba(0,0,0,0.35)'; c.font = 'bold 11px Inter,sans-serif'; c.textAlign = 'center'
|
|
c.fillText('Park', 100, 175)
|
|
})()
|
|
|
|
// ============================================================
|
|
// EMOJI-VERSIONEN (Gegenversuch)
|
|
// ============================================================
|
|
|
|
var emojiTiles = [
|
|
{id:'e01', label:'Kirche', stub:'S', emoji:'⛪', size:95},
|
|
{id:'e02', label:'Moschee', stub:'NS', emoji:'🕌', size:85},
|
|
{id:'e03', label:'Wohngebiet', road:'NS', emojis:[
|
|
{e:'🏠',x:-0.32,y:-0.3,s:32},{e:'🏡',x:-0.3,y:0,s:30},{e:'🏠',x:-0.32,y:0.28,s:28},
|
|
{e:'🏘️',x:0.32,y:-0.25,s:30},{e:'🏠',x:0.3,y:0.05,s:32},{e:'🏡',x:0.32,y:0.3,s:28}]},
|
|
{id:'e04', label:'Fabrik', stub:'S', emoji:'🏭', size:85},
|
|
{id:'e05', label:'Spital', stub:'EW', emoji:'🏥', size:75, extra:[{e:'🚑',x:0,y:0.3,s:32}]},
|
|
{id:'e06', label:'Feuerwehr', stub:'S', bg:'rgba(200,50,40,0.12)', emojis:[
|
|
{e:'🏠',x:0,y:-0.15,s:60},{e:'🚒',x:-0.2,y:0.22,s:40},{e:'🚒',x:0.2,y:0.22,s:40}]},
|
|
{id:'e07', label:'Polizei', stub:'N', emoji:'🚔', size:45, extra:[{e:'🏢',x:0,y:0.15,s:55}]},
|
|
{id:'e08', label:'Schule', road:'EW', emoji:'🏫', size:60, yoff:-0.28},
|
|
{id:'e09', label:'Supermarkt', road:'NS', emoji:'🏪', size:55, xoff:0.3, extra:[
|
|
{e:'🚗',x:0.22,y:0.25,s:26},{e:'🚙',x:0.35,y:0.15,s:24},{e:'🚗',x:0.22,y:0.38,s:22}]},
|
|
{id:'e10', label:'Park', stub:'N', emojis:[
|
|
{e:'🌳',x:-0.3,y:-0.1,s:32},{e:'🌳',x:-0.1,y:-0.1,s:32},{e:'🌳',x:0.1,y:-0.1,s:32},{e:'🌳',x:0.3,y:-0.1,s:32},
|
|
{e:'🌳',x:-0.2,y:0.1,s:28},{e:'🌳',x:0,y:0.1,s:28},{e:'🌳',x:0.2,y:0.1,s:28},
|
|
{e:'🌷',x:-0.35,y:0.3,s:16},{e:'🌷',x:-0.2,y:0.32,s:14},{e:'🌷',x:-0.05,y:0.3,s:16},
|
|
{e:'🌷',x:0.1,y:0.32,s:14},{e:'🌷',x:0.25,y:0.3,s:16},{e:'🌷',x:0.38,y:0.32,s:14}]},
|
|
{id:'e11', label:'Rathaus', stub:'S', emoji:'🏛️', size:85},
|
|
{id:'e13', label:'Tankstelle', road:'NS', emojis:[
|
|
{e:'⛽',x:0.28,y:-0.2,s:32},{e:'⛽',x:0.28,y:0,s:32},{e:'⛽',x:0.28,y:0.2,s:32},
|
|
{e:'🚗',x:0.38,y:-0.15,s:26},{e:'🚙',x:0.38,y:0.15,s:26}]},
|
|
{id:'e14', label:'Spielplatz', stub:'N', emojis:[
|
|
{e:'🛝',x:-0.2,y:0,s:42},{e:'🎠',x:0.2,y:0,s:36},{e:'⚽',x:0,y:0.25,s:22},
|
|
{e:'🌳',x:-0.35,y:0.3,s:26},{e:'🌳',x:0.35,y:0.3,s:26}]},
|
|
{id:'e15', label:'Bauernhof', stub:'EW', emojis:[
|
|
{e:'🏠',x:0,y:-0.05,s:55},
|
|
{e:'🌾',x:-0.35,y:-0.3,s:24},{e:'🌾',x:-0.2,y:-0.3,s:24},{e:'🌾',x:-0.05,y:-0.3,s:24},
|
|
{e:'🌾',x:0.1,y:-0.3,s:24},{e:'🌾',x:0.25,y:-0.3,s:24},{e:'🌾',x:0.4,y:-0.3,s:24},
|
|
{e:'🐄',x:-0.25,y:0.28,s:30},{e:'🐔',x:0.15,y:0.3,s:22},{e:'🐔',x:0.28,y:0.28,s:22}]},
|
|
{id:'e16', label:'Hochhäuser', road:'NS', emojis:[
|
|
{e:'🏢',x:0.22,y:-0.2,s:38},{e:'🏢',x:0.32,y:-0.2,s:38},{e:'🏢',x:0.42,y:-0.2,s:38},
|
|
{e:'🏢',x:0.22,y:0.15,s:38},{e:'🏢',x:0.32,y:0.15,s:38},{e:'🏢',x:0.42,y:0.15,s:38}]},
|
|
]
|
|
|
|
// Erzeuge HTML fuer Emoji-Tiles
|
|
var hr = document.createElement('div')
|
|
hr.style.cssText = 'width:100%;text-align:center;color:#888;font-size:11px;margin:8px 0;border-top:1px solid #ccc;padding-top:6px'
|
|
hr.textContent = '▼ Emoji-Versionen ▼'
|
|
document.body.appendChild(hr)
|
|
|
|
emojiTiles.forEach(function(t) {
|
|
var div = document.createElement('div')
|
|
div.className = 'tile'
|
|
var cv = document.createElement('canvas')
|
|
cv.width = 200; cv.height = 200; cv.id = t.id
|
|
var span = document.createElement('span')
|
|
span.textContent = t.label
|
|
div.appendChild(cv); div.appendChild(span)
|
|
document.body.appendChild(div)
|
|
|
|
var c = cv.getContext('2d')
|
|
c.fillStyle = GREEN; c.fillRect(0, 0, SZ, SZ)
|
|
|
|
// Hintergrundfarbe (z.B. rot fuer Feuerwehr)
|
|
if (t.bg) { c.fillStyle = t.bg; c.fillRect(0, 0, SZ, SZ) }
|
|
|
|
// Strasse
|
|
if (t.road === 'NS') drawRoadNS(c, M)
|
|
if (t.road === 'EW') drawRoadEW(c, M)
|
|
if (t.stub) {
|
|
if (t.stub.indexOf('N') >= 0) drawStubN(c)
|
|
if (t.stub.indexOf('S') >= 0) drawStubS(c)
|
|
if (t.stub.indexOf('E') >= 0) drawStubE(c)
|
|
if (t.stub.indexOf('W') >= 0) drawStubW(c)
|
|
}
|
|
|
|
// Emojis
|
|
c.textAlign = 'center'; c.textBaseline = 'middle'
|
|
if (t.emoji) {
|
|
c.font = (t.size || 50) + 'px serif'
|
|
c.fillText(t.emoji, M + (t.xoff || 0) * SZ, M + (t.yoff || 0) * SZ)
|
|
}
|
|
if (t.emojis) {
|
|
t.emojis.forEach(function(em) {
|
|
c.font = (em.s || 24) + 'px serif'
|
|
c.fillText(em.e, M + em.x * SZ, M + em.y * SZ)
|
|
})
|
|
}
|
|
if (t.extra) {
|
|
t.extra.forEach(function(em) {
|
|
c.font = (em.s || 24) + 'px serif'
|
|
c.fillText(em.e, M + (em.x||0) * SZ, M + (em.y||0) * SZ)
|
|
})
|
|
}
|
|
|
|
// Keine Beschriftung auf der Kachel
|
|
})
|
|
</script>
|
|
</body>
|
|
</html>
|