senäh

17senäh und so…

HTML/CSS/JS
22. Jul 2011
Kommentare: 6

Ein altes Spiel mit neuen Technologien: Pong!

Kategorien: HTML/CSS/JS | 22. Jul 2011 | Kommentare: 6

Die HTML5-Experimente gehen weiter. Heute steht Pong auf dem Plan. Warum Pong? Weil man es recht einfach programmieren kann und es mir das Testen der Steuerung über die Tastatur in JavaScript ermöglicht. Na dann stürzen wir uns gleich kopfüber in den Code!

Wie immer bei den HTML5-Experimenten präsentiere ich euch das Ganze eher als Code-Snippet, anstatt als vollwertiges Tutorial. Wenn ihr Fragen habt, schreibt einfach in die Kommentare.

Pong!

Pong. Kennste, ne? Gibt’s auch als Krawatte. Guckst du:

Pong Krawatte (Quelle - Engadget)

Pong Krawatte (Quelle - Engadget)

Geht mir aber ums Orignal. Guckst du hier. Von 1972. Hat Atari übrigens von Magnavox geklaut, interessiert aber heute keinen mehr. Hach 1972. ABBA gründet sich, CCR trennen sich. Watergate-Affäre. Hewlett Packard veröffentlicht den ersten wissenschaftlichen Taschenrechner. Die erste deutsche Ausgabe des Playboys erscheint. Die Apollo-17-Mission wird die letzte Mondmission. Schalke 04 gewinnt den DFB-Pokal 😉 Und Magnavox veröffentlicht mit Odyssey die erste Spielkonsole und Atari gründet sich u.a. auf der Basis von Pong. Und so schließt sich der Kreis 😉

Gehen wir vom Klassiker weg und schauen uns die neue Version an. Pong in HTML5! So soll es aussehen:

Pong! in HTML5

Pong! in HTML5

Und es folgt wie immer der Code:

index.html

<!DOCTYPE html>
<html lang="de">

<!--
You can use this code as you wish,
but please recommend our site http://www.senaeh.de.
@author Philipp Zins/Donald Pipowitch
-->

<head>
    <title>Canvas: Pong</title>

    <meta charset="UTF-8"/>
    <meta name="description" content="Pong mit dem Canvaselement."/>
    <meta name="keywords" content="HTML5, Canvas, Pong"/>
    <meta name="author" content="Philipp Zins/Donald Pipowitch"/>

    <link rel="stylesheet" type="text/css" href="css/style.css"/>

    <script type="text/javascript" src="js/pong/PongManager.js"></script>
</head>

<body onload="init()">

    <!-- canvasBalls -->
    <div>
        <h1>Pong!</h1>
        <p id="points">
            Ich: 0 | Computer: 0
        </p>
        <canvas id="canvasPong" width="500" height="400">
            Dein Browser unterstützt das Canvas-Element nicht.
        </canvas>
        <p id="FPS">
            <!-- place Stats from Stats.js here -->
        </p>
    </div>

</body>
</html>

style.css

canvas
{
    border: solid 1px #000000;
}

PongManager.js

/**
 * You can use this code as you wish,
 * but please recommend our site http://www.senaeh.de.
 * @author Philipp Zins/Donald Pipowitch
 */

document.write('<script type="text/javascript" src="js/pong/Ball.js"></script>');
document.write('<script type="text/javascript" src="js/pong/Paddle.js"></script>');
document.write('<script type="text/javascript" src="js/com/mrdoob/Stats.js"></script>');
document.write('<script type="text/javascript" src="js/de/senaeh/pipo/utils/math/GameMath.js"></script>');

var canvas;
var context;
var width;
var height;

var ball;
var player;
var computer;
var pointsPlayer = 0;
var pointsComputer = 0;

var up = false;
var down = false;
var speed = 7;
var computerSpeed = 7;

function init()
{
    // canvas
    canvas = document.getElementById("canvasPong");
    context = canvas.getContext("2d");
    width = canvas.width;
    height = canvas.height;
    // create objects
    createBall();
    player = new Paddle(0, height / 2, height);
    computer = new Paddle(width - 10, height / 2, height);
    // controls
    window.addEventListener('keydown', onKeyDown, true);
    window.addEventListener('keyup', onKeyUp, true);
    // loop
    startLoop();
    // stats
    var stats = new Stats();
    document.getElementById("FPS").appendChild(stats.domElement);
    setInterval(function ()
    {
        stats.update();
    }, 1000 / 60);
}

function startLoop()
{
    setInterval(updateLogic, 33); // 33 milliseconds = ~ 30 frames per sec
}

function updateLogic()
{
    // move player
    if (up)
        player.movePosition(-speed);
    else if (down)
        player.movePosition(speed);
    // move computer
    if (GameMath.withinRange(ball.y, 0, computer.y + computer.height *0.25))
        computerSpeed = -speed;
    else if (GameMath.withinRange(ball.y, computer.y + computer.height * 0.75, height))
        computerSpeed = speed;
    else
        computerSpeed *= 0.95;
    computer.movePosition(computerSpeed);
    // show points
    document.getElementById("points").innerHTML = "Ich: " + pointsPlayer + " | Computer: " + pointsComputer;
    // draw elements
    context.clearRect(0, 0, width, height);
    ball.update();
    context.fillStyle = "#000000";
    context.beginPath();
    context.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2, true);
    context.closePath();
    context.fillRect(player.x, player.y, player.width, player.height);
    context.fillRect(computer.x, computer.y, computer.width, computer.height);
    context.fill();
    // collision - ball with border
    if (ball.x + ball.radius < 0)
    {
        pointsComputer++;
        createBall();
    }
    if (ball.x - ball.radius > width)
    {
        pointsPlayer++;
        createBall();
    }
    if ((ball.y - ball.radius < 0 && ball.speedY < 0) ||
            (ball.y + ball.radius > height && ball.speedY > 0))
    {
        ball.speedY *= -1;
    }
    // collision - ball with player or computer
    if ((player.hitTestPoint(ball.x, ball.y) && ball.speedX < 0)
            || (computer.hitTestPoint(ball.x, ball.y) && ball.speedX > 0))
    {
        ball.speedX *= -1;
        ball.speedY *= 1.2;
        ball.speedX *= 1.2;
    }
}

function createBall()
{
    var x = width / 2;
    var y = height / 2;
    ball = new Ball(x, y);
}

/**
 * Controls
 */
function onKeyDown(e)
{
    switch (e.keyCode)
    {
        case 38:  // up arrow
            up = true;
            break;
        case 40:  // down arrow
            down = true;
            break;
        // 37 == left arrow
        // 39 == right arrow
    }
}

function onKeyUp(e)
{
    switch (e.keyCode)
    {
        case 38:  // up arrow
            up = false;
            break;
        case 40:  // down arrow
            down = false;
            break;
    }
}

Ball.js

/**
 * You can use this code as you wish,
 * but please recommend our site http://www.senaeh.de.
 * @author Philipp Zins/Donald Pipowitch
 */

var Ball = function (x, y)
{
    this.x = x;
    this.y = y;
    this.speedX = Math.random() * 1.5 + 2;
    if(Math.random() < 0.5)
        this.speedX *= -1;
    this.speedY = Math.random() * 1.5 + 2;
    if(Math.random() < 0.5)
        this.speedY *= -1;
    this.radius = 4;
    this.update = update;
}

function update()
{
    this.x += this.speedX;
    this.y += this.speedY;
}

Paddle.js

/**
 * You can use this code as you wish,
 * but please recommend our site http://www.senaeh.de.
 * @author Philipp Zins/Donald Pipowitch
 */

document.write('<script type="text/javascript" src="js/de/senaeh/pipo/utils/math/GameMath.js"></script>');

var Paddle = function (x, y, yMoveArea)
{
    this.x = x;
    this.y = y;
    this.yMoveArea = yMoveArea;
    this.width = 10;
    this.height = 50;
    this.movePosition = movePosition;
    this.hitTestPoint = hitTestPoint;
}

function movePosition(deltaY)
{
    this.y += deltaY;
    if (this.y < 0)
        this.y = 0;
    else if (this.y + this.height > this.yMoveArea)
        this.y = this.yMoveArea - this.height;
}

function hitTestPoint(x, y)
{
    if(GameMath.withinRange(x, this.x, this.x + this.width)
            && GameMath.withinRange(y, this.y, this.y + this.height))
        return true;
    else
        return false;
}

GameMath.js

/**
 * You can use this code as you wish,
 * but please recommend our site http://www.senaeh.de.
 * @author philippzins/Donald Pipowitch
 */

function GameMath()
{
}

/**
 * Check if a value is within a specific range.
 * @param value The specific value.
 * @param min Minimum value.
 * @param max Maximum value.
 * @return Returns true if value is within a specific range.
 */
GameMath.withinRange = function(value, min, max)
{
    if(value >= min && value <= max)
        return true;
    else
        return false;
}

Stats.js

Von MrDoob: hier der Download.

Spielen!

Und zum Schluss wie immer das Live-Beispiel. Ihr spielt den linken Schläger, den ihr mit den Pfeiltasten steuern könnt. Have fun!

Autor: Pipo

...kommt ursprünglich aus der Designerecke, ist aber im Laufe seines Studiums in die Webentwicklung gestolpert. Kann sich seit dem nicht so richtig entscheiden wo er hingehört und wagt deswegen vielleicht die Flucht nach vorne in ein komplett neues Gebiet. Vielleicht Management? Niemand weiß es. Auch er nicht.