HTML5-Tutorium: Canvas: MiniPong 01
Dieser Artikel erfüllt die GlossarWiki-Qualitätsanforderungen nur teilweise:
Korrektheit: 3 (zu größeren Teilen überprüft) |
Umfang: 3 (einige wichtige Fakten fehlen) |
Quellenangaben: 5 (vollständig vorhanden) |
Quellenarten: 5 (ausgezeichnet) |
Konformität: 5 (ausgezeichnet) |
HTML-Tutorium: MiniPong
MiniPong: | Teil 1 | Teil 2 | Teil 3 | Teil 4 | Teil 5
Musterlösung: Minipong 1
(SVN-Repository)
Ziel
Im ersten Teil des Tutoriums wird beschrieben, wie man eine einfache Ball-Animation erstellt.
Voraussetzung
Die Inhalte des HTML5-Hello-World-Tutoriums sollten Ihnen bekannt sein.
Vorgehensweise
Neues Projekt anlegen
Legen Sie ein neues Projekt an:
Datei
→Neu
→Statisches Web-Projekt
- Project name:
MiniPong01
→Fertigstellen
und speichern Sie dieses Projekt auf die bekannte Weise in Ihrem SVN-Repository.
Dateien erstellen
main.css
Erstellen Sie im Ordner WebContent/css
des Projektes die Datei main.css
:
body
{
text-align: center;
padding: 10px;
background-color: #AAA;
}
#d_canvas
{
border-color: #777;
border-width: 2px;
border-style: solid;
background-color: #CCC;
}
CONSTANT.js
Erstellen Sie im Ordner WebContent/js
des Projektes die Datei CONSTANT.js
:
"use strict";
var CANVAS_WIDTH = 400;
var CANVAS_HEIGHT = 300;
var FPS = 50; // Frames Per Second
var BALL_RADIUS = 8; // pixels
var BALL_X = CANVAS_WIDTH / 2;
var BALL_Y = CANVAS_HEIGHT / 2;
var BALL_VX_MIN = 100; // pixels per second
var BALL_VX_MAX = 200; // pixels per second
var BALL_VY_MIN = 100; // pixels per second
var BALL_VY_MAX = 200; // pixels per second
var BALL_BORDER_WIDTH = 1;
var BALL_BORDER_COLOR = "#000000";
var BALL_COLOR = "#55AA55";
main.js
Erstellen Sie im Ordner WebContent/js
des Projektes die Datei main.js
.
In dieser wird zunächst ein Ball-Objekt erstellt. Diese Objekt hat fünf (öffentliche) Attribute, die mit sinnvollen Werten initialisiert werden:
r
(Radius des Balls)x
(Aktuelle x-Positions des Balls)y
(Aktuelle y-Positions des Balls)vx
(Aktuelle Geschwindigkeit des Balls in x-Richtung in Pixeln/Sekunde)vy
(Aktuelle Geschwindigkeit des Balls in y-Richtung in Pixeln/Sekunde)
Darüber hinaus besitzt dieses Objekt zwei Methoden:
move
bewegt den Ball an seine neue Position; dieses wird aus dem Geschwindigkeitsvektor und der Zeitspanne, die zwischen zwei Aufrufen desmove
-Befehls vergeht, berechnetdraw
visualisiert das (zweidimensionale) Ball-Objekt auf dem 2D-Kontext einer Bühne (Canvas).
// the ball
var g_ball =
{ r: BALL_RADIUS,
x: BALL_X,
y: BALL_Y,
vx: (Math.random() < 0.5 ? 1 : -1)
* (BALL_VX_MIN + Math.random() * (BALL_VX_MAX - BALL_VX_MIN)),
vy: (Math.random() < 0.5 ? 1 : -1)
* (BALL_VY_MIN + Math.random() * (BALL_VY_MAX - BALL_VY_MIN)),
move: function()
{ this.x += this.vx/FPS;
this.y += this.vy/FPS;
},
draw: function(p_context)
// Draw the ball at its current position onto a 2d context.
{ p_context.beginPath();
p_context.arc(this.x, this.y, this.r, 0, 2*Math.PI);
p_context.lineWidth = BALL_BORDER_WIDTH;
p_context.lineStyle = BALL_BORDER_COLOR;
p_context.fillStyle = BALL_COLOR;
p_context.stroke();
p_context.fill();
}
};
Für die Animation des Balles braucht man zwei weitere Objekte: Den 2D-Kontext, auf dem sich der
Ball bewegen soll sowie einen Timer, der regelmäßig (FPS
mal pro Sekunde; FPS
steht für Frames Per Second)
eine Neuberechnung der Ballposition sowie ein Neuzeichnen der Bühne veranlasst.
// the 2d context of the canvas
var g_context;
// the "physics engine" timer
var g_interval;
Sobald die HTML-Seite vollständig geladen worden ist, werden die Bühne initialisiert und der Timer gestartet.
// Execute the init function after the HTML page has been loaded.
window.onload = f_init;
// Has to be called after the HTML page has been loaded.
function f_init()
{ var l_canvas = document.getElementById("d_canvas");
// Initialize the canvas.
l_canvas.width = CANVAS_WIDTH;
l_canvas.height = CANVAS_HEIGHT;
g_context = l_canvas.getContext("2d");
// Start the timer for redrawing the canvas every 1000/FPS seconds.
g_interval = window.setInterval("o_redraw()", 1000/FPS);
}
Die so genannte Observer-Methode o_redraw()
wird alle paar Millisekunden
vom Timer aufgerufen. Diese Methode hat drei Aufgabe:
- Kollisionen zwischen Ball und Wand erkennen und gegebennenfalls die Bewegungsrichtung des Balls ändern.
- Den Ball an seine neue Position bewegen.
- Den aktuellen Inhalt der Bühne löschen und den Ball an der neuen Position auf die Bühne zeichnen.
// An event observer:
// It is called every 1000/FPS seconds.
function o_redraw()
{ // Collision detection: ball <-> wall
// Collision response: change the moving direction of the ball
if (g_ball.x <= g_ball.r || g_ball.x >= CANVAS_WIDTH - g_ball.r)
g_ball.vx = -g_ball.vx;
if (g_ball.y <= g_ball.r || g_ball.y >= CANVAS_HEIGHT - g_ball.r)
g_ball.vy = -g_ball.vy;
// Move the ball.
g_ball.move();
// Clear and redraw the canvas
g_context.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
g_ball.draw(g_context);
}
Dieses Skript realisiert die eigentliche Ball-Animation. Zum Einsatz kommen dabei Techniken, die im Tutorium von Alexander Lawrence genauer beschrieben werden: AS3-Tutorium:Physics. Sehen Sie sich insbesondere folgende Abschnitte an:
index.html
Erstellen Sie im Ordner WebContent
des Projektes die Datei index.html
:
<!DOCTYPE html>
<html>
<head>
<title>HTML5-Tutorium: Canvas: MiniPong 01</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<!--<link rel="stylesheet" href="css/all.min.css"/>-->
<link rel="stylesheet" href="css/main.css" />
<!--<script type="text/javascript" src="js/all.min.js" ></script>-->
<script type="text/javascript" src="js/CONSTANT.js"></script>
<script type="text/javascript" src="js/main.js" ></script>
</head>
<body>
<canvas id="d_canvas">
Ihr Browser unterstützt HTML5 leider nicht!
</canvas>
</body>
</html>
Anstelle von main.css
und main.js
können Sie auch wieder
all.min.css
und all.min.js
einbinden, sofern Sie diese
Dateien mit Hilfe von yuicompressor
erzeugen (vgl. HTML5-Tutorium: Canvas: Hello World 03).
Anwendung testen und sichern
Testen Sie Ihre Anwendung in gewohnter Weise.
Vergessen Sie nicht, sie im SVN-Repository zu sichern.
Probleme der Kollisionserkennung
Die A-posteriori-Kollissionserkennung, die in Minipong 1 bei der Erkennung von Kollisionen zwischen Ball und Wand angewandt wurde, ist nicht ganz unproblematisch.
- Eindringung (penetration)
- Der Ball dringt i.Allg. etwas in die Wand ein, bevor eine Kollision erkannt wird. Wenn dieses Eindringen durch die Kollissionsbehandlung nicht rückgängig gemacht wird, kann es passieren, dass der Ball in der Wand hängen bleibt, da er sich in allen folgenden Animationsschritten in der Wand befindet und daher in jedem Schritt seine Richtung ändert.
- Durchtunneln (tunneling)
- Wenn der Ball besonders schnell ist, kann er ein anderes Objekt eventuell durchtunneln. Dies kann immer dann passieren, wenn der Ball in einem Schritt eine Distanz zurücklegt, die größer ist als sein Durchmesser plus die Breite des anderen Objektes.
Beide Effekte können Sie beobachten, wenn Sie Ihren Minipong-1-Code etwas modifizieren.
- Eindringung
- Setzen Sie
BALL_Y = CANVAS_HEIGHT
, d.h., platzieren Sie den Ball gleich zu Beginn in der Wand, und starten Sie die Anwendung. Nach dem Sie den Effekt bewundert haben, sollten Sie den Fehler auch wieder beheben. :-) - Durchtunneln
- Da die Wände im Kollisionstest unendlich dick gewählt wurden, kann der Ball diese nicht durchdringen.Wenn Sie aber die Breite der Wände in der Funktion
0_redraw
auf Null reduzieren, haben Sie nicht lange Freude an Ihrem Ball:if (g_ball.x == g_ball.r || g_ball.x == CANVAS_WIDTH - g_ball.r) g_ball.vx = -g_ball.vx; if (g_ball.y == g_ball.r || g_ball.y == CANVAS_HEIGHT - g_ball.r) g_ball.vy = -g_ball.vy;
Erweiterung
Erweitern Sie die Anwendung so, dass sich zwanzig Bälle gleichzeitig über die Bühne bewegen. Kollisionen zwischen den Bällen brauchen Sie nicht zu behandeln. Beachten Sie aber das Programmierprinzip „Don't repeat yourself“ (Dry).
Musterlösung: Minipong 1a
(SVN-Repository)
Quellen
- Braun (2011): Herbert Braun; Webanimationen mit Canvas; in: c't Webdesign; Band: 2011; Seite(n): 44–48; Verlag: Heise Zeitschriften Verlag; Adresse: Hannover; 2011; Quellengüte: 5 (Artikel)
- Kowarschick (MMProg): Wolfgang Kowarschick; Vorlesung „Multimedia-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2018; Quellengüte: 3 (Vorlesung)
- Musterlösungen, Musterlösungen (SVN)
Fortsetzung des Tutoriums
Bearbeiten Sie nun Teil 2 des Tutoriums.