XT Knowledge Base
Hauptseite | Über | Hilfe | FAQ | Spezialseiten | Anmelden

Druckversion | Impressum | Datenschutz | Aktuelle Version

Spieleentwicklung mit JavaScript - Maus-Steuerung

Version vom 16:49, 2. Sep. 2010 bei Monettenom (Diskussion | Beiträge)

Inhaltsverzeichnis

Maus-Steuerung

Event-Handler installieren

Dank der Vorarbeit mit der pixelgenauen Positionierung des Kartenausschnitts ist die Steuerung mit der Maus relativ einfach. Beim Drücken der Maustaste wird die aktuelle Position gespeichert, beim Loslassen die Differenz der aktuellen Position und der gespeicherten auf die aktuelle Kartenposition addiert und dann die Karte neu gezeichnet.

Dmait sich die Karte auch bei gedrückter Maustaste mit der Maus bewegt, wird die Neu-Positionierung bei jeder Mausbewegung durchgeführt.

uerst werden allerdings die EventHandler installiert. Diese werden aber nicht dem Canvas-Objekt zugewiesen, sondern dem umschießenden DIV-Element:

  var div = document.getElementById("board_div");
  div.addEventListener('mousedown', OnMouseDown, false);
  div.addEventListener('mousemove', OnMouseMove, false);
  div.addEventListener('mouseup', OnMouseUp, false);

Dragging implementieren

Das DIV-Element ist bereits im HTML-Code vorhanden. Es muss lediglich eine ID zugewiesen werden:

    <div class="board frame" id="board_div"><canvas id="board" width="460" height="340">Dieser Browser ist nicht geeignet.</canvas></div>

Der MouseDown-Handler macht nichts weiter als die aktuelle Position zu speichern:

  var dragx = -1;
  var dragy = -1;
      
  function OnMouseDown( e )
  {
    dragx = e.pageX;
    dragy = e.pageY;
  }

Beim Loslassen der Maustaste muss nun die Differenz zwischen der neuen Position und der gespeicherten Position berechnet werden. Um diese Differenz ist der Ausschnitt zu verschieben:

  function OnMouseUp( e )
  {
    pfx += dragx - e.pageX;
    pfy += dragy - e.pageY;
    while( pfx < 0 ) pfx += map_pixel_width;
    while( pfy < 0 ) pfy += map_pixel_height;
    drawPlayfield( level, pfx, pfy );
    dragx = -1;
    dragy = -1;
  }

Wichtig ist, dass die Position nie negativ wird. Deshalb werden beide Werte solange um die Kartengröße erhöht, bis sie positiv sind. Anschließend kann der Ausschnitt gezeichnet werden. Um zu kennzeichnen, dass der Vorgang abgeschlossen ist (wird später für OnMouseMove benötigt) werden dragx und dragy mit -1 initialisiert.

Die Funktion OnMouseMove kann nun von der Implementierung der beiden anderen Handler profitieren:

  function OnMouseMove( e )
  {
    if( dragx > 0 && dragy > 0 )
    {
      OnMouseUp( e );
      OnMouseDown( e );
    }
  }

Wenn die beiden Werte größer 0 sind, wurde die Maustate gedrückt und bei einer Mausbewegung soll der Ausschnitt an der neuen Position neu gezeichnet werden. Dies geschieht mit dem Aufruf von OnMouseUp(). Durch einen erneuten Aufruf von OnMouseDown() wird die aktuelle Position gespeichert, die später wieder von OnMouseUp() verwendet werden kann.

Tile-Position ermitteln

Natürlich möchte man wissen, über welchem Element sich die Maus gerade befindet. Hierfür sind einige Berechnungen notwendig:

1. Die Position innerhalb des DIVs muss ermittelt werden

var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;

2. Zu dieser Position muss die Position des sichtbaren Ausschnitts innerhalb der Karte addiert werden, um die Pixelposition innerhalb der gesamten Karte zu erhalten:

var x = e.pageX - this.offsetLeft + pfx;
var y = e.pageY - this.offsetTop  + pfy;

3. Diese Position kann nun in eine Tile-Position umgerechnet werden. Es muss berücksichtigt werden, dass sich die Karte endlos wiederholt, weshalb der Modulo-Operator bemüht werden muss:

var x = Math.floor( (e.pageX - this.offsetLeft + pfx) / tile_pixel_width ) % map_tile_width;
var y = Math.floor( (e.pageY - this.offsetTop + pfy) / tile_pixel_height ) % map_tile_height;

Nun befindet sich in x und y die Position für das Level-Array.

Das gesamte Programm sieht nun folgendermaßen aus:

<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=UTF-8">
    <title>Sample</title>
    <style type="text/css">
        body
        {
            margin: 0px;
            padding: 0px;
        }
        .hidden 
        {
          visibility: hidden;
        }
        .frame
        {
            border:1px black solid;
        }
        .board
        {
            position: absolute;
            left: 10px;
            top: 10px;
        }
        .debug
        {
            position: absolute;
            left: 10px;
            top: 400px;
        }
    </style>
    <script type="text/javascript">
      var tile_count_x = 5;
      var tile_count_y = 1;

      var canvas;
      var context;
      var tiles = new Array();
      
      var display_pixel_width = 0;
      var display_pixel_height = 0;
      var display_tile_width = 0;
      var display_tile_height = 0;
      var tile_pixel_width = 0;
      var tile_pixel_height = 0;
      var map_tile_width = 0;
      var map_tile_height = 0;
      var map_pixel_width = 0;
      var map_pixel_height = 0;
      
      var level = new Array(
        new Array( 0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0 ),
        new Array( 2,1,1,1,1,1,1,2,2,1,1,1,1,1,1,2,2,1,1,1,1,1,1,2,2,1,1,1,1,1,1,2 ),
        new Array( 2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2 ),
        new Array( 2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2 ),
        new Array( 2,0,3,2,1,1,1,2,2,0,3,2,1,1,1,2,2,0,3,2,1,1,1,2,2,0,3,2,1,1,1,2 ),
        new Array( 2,4,3,2,0,0,0,4,2,4,3,2,0,0,0,4,2,4,3,2,0,0,0,4,2,4,3,2,0,0,0,4 ),
        new Array( 1,1,1,2,1,0,1,1,1,1,1,2,1,0,1,1,1,1,1,2,1,0,1,1,1,1,1,2,1,0,1,1 ),
        new Array( 4,0,0,2,0,0,4,0,4,0,0,2,0,0,4,0,4,0,0,2,0,0,4,0,4,0,0,2,0,0,4,0 ),
        new Array( 0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0 ),
        new Array( 2,1,1,1,1,1,1,2,2,1,1,1,1,1,1,2,2,1,1,1,1,1,1,2,2,1,1,1,1,1,1,2 ),
        new Array( 2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2 ),
        new Array( 2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2 ),
        new Array( 2,0,3,2,1,1,1,2,2,0,3,2,1,1,1,2,2,0,3,2,1,1,1,2,2,0,3,2,1,1,1,2 ),
        new Array( 2,4,3,2,0,0,0,4,2,4,3,2,0,0,0,4,2,4,3,2,0,0,0,4,2,4,3,2,0,0,0,4 ),
        new Array( 1,1,1,2,1,0,1,1,1,1,1,2,1,0,1,1,1,1,1,2,1,0,1,1,1,1,1,2,1,0,1,1 ),
        new Array( 4,0,0,2,0,0,4,0,4,0,0,2,0,0,4,0,4,0,0,2,0,0,4,0,4,0,0,2,0,0,4,0 ),
        new Array( 0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0 ),
        new Array( 2,1,1,1,1,1,1,2,2,1,1,1,1,1,1,2,2,1,1,1,1,1,1,2,2,1,1,1,1,1,1,2 ),
        new Array( 2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2 ),
        new Array( 2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2,2,0,3,0,0,0,0,2 ),
        new Array( 2,0,3,2,1,1,1,2,2,0,3,2,1,1,1,2,2,0,3,2,1,1,1,2,2,0,3,2,1,1,1,2 ),
        new Array( 2,4,3,2,0,0,0,4,2,4,3,2,0,0,0,4,2,4,3,2,0,0,0,4,2,4,3,2,0,0,0,4 ),
        new Array( 1,1,1,2,1,0,1,1,1,1,1,2,1,0,1,1,1,1,1,2,1,0,1,1,1,1,1,2,1,0,1,1 ),
        new Array( 4,0,0,2,0,0,4,0,4,0,0,2,0,0,4,0,4,0,0,2,0,0,4,0,4,0,0,2,0,0,4,0 )
      );
      
      
      var pfx = 0;
      var pfy = 0;
      
      function init()
      {
        canvas = document.getElementById("board");
        context = canvas.getContext("2d");
        
        var tileset = document.getElementById("tileset");
        context.drawImage( tileset, 0, 0 );
        
        display_pixel_width = canvas.width;
        display_pixel_height = canvas.height;
        tile_pixel_width = tileset.width / tile_count_x;
        tile_pixel_height = tileset.height / tile_count_y;
        
        //alert( "x: " + display_pixel_width + ", y: " + display_pixel_height );
        
        for( var y = 0; y < tile_count_y; y++ )
        {
            for( var x = 0; x < tile_count_x; x++ )
            {
                var i = y * tile_count_x + x;
                var imgData = context.getImageData( x * tile_pixel_width, y * tile_pixel_height, tile_pixel_width, tile_pixel_height );
                tiles[i] = document.getElementById("tile"+i);
                tiles[i].width = tile_pixel_width;
                tiles[i].height = tile_pixel_height;
                tiles[i].getContext("2d").putImageData( imgData, 0, 0 );
            }
        }
        
        display_tile_width = Math.ceil( display_pixel_width / tile_pixel_width )+1;
        display_tile_height = Math.ceil( display_pixel_height / tile_pixel_height )+1;
        map_tile_width = level[0].length;
        map_tile_height = level.length;
        map_pixel_width = map_tile_width * tile_pixel_width;
        map_pixel_height = map_tile_height * tile_pixel_height;
        
        drawPlayfield( level, pfx, pfy );
        
        var div = document.getElementById("board_div");
        div.addEventListener('mousedown', OnMouseDown, false);
        div.addEventListener('mousemove', OnMouseMove, false);
        div.addEventListener('mouseup', OnMouseUp, false);
      }
      
      var dragx = -1;
      var dragy = -1;
      
      function OnMouseDown( e )
      {
        dragx = e.pageX;
        dragy = e.pageY;
      }
      
      function OnMouseMove( e )
      {
        if( dragx > 0 && dragy > 0 )
        {
          OnMouseUp( e );
          OnMouseDown( e );
        }
	
	    x = Math.floor( (e.pageX - this.offsetLeft + pfx) / tile_pixel_width ) % map_tile_width;
	    y = Math.floor( (e.pageY - this.offsetTop + pfy) / tile_pixel_height ) % map_tile_height;
	    showXY( x, y );
      }
      
      function OnMouseUp( e )
      {
        pfx -= e.pageX - dragx;
        pfy -= e.pageY - dragy;        
        while( pfx < 0 ) pfx += map_pixel_width;
        while( pfy < 0 ) pfy += map_pixel_height;
        drawPlayfield( level, pfx, pfy );
        dragx = -1;
        dragy = -1;
      }
      
      function showXY( x, y )
      {
        document.f.t.value = "x: " + x + ", y: " + y;
      }
      
      function drawPlayfield( level, xpos, ypos )
      {
        var start_tile_x = Math.floor( xpos / tile_pixel_width );
        var start_tile_y = Math.floor( ypos / tile_pixel_height );
        var start_x = -(xpos % tile_pixel_width);
        var start_y = -(ypos % tile_pixel_height);
                
        for( y = 0; y <= display_tile_height; y++ )
        {
          var ty = (start_tile_y + y) % map_tile_height;
          var py = start_y + y * tile_pixel_height;
          
          for( x = 0; x <= display_tile_width; x++ )
          {
            var tx = (start_tile_x + x) % map_tile_width;
            var px = start_x + x * tile_pixel_width;
    
            context.drawImage( tiles[level[ty][tx]], px, py );
          }
        }
      }
    </script>
</head>
<body onLoad="init();">
    <div class="board frame" id="board_div"><canvas id="board" width="460" height="340">Dieser Browser ist nicht geeignet.</canvas></div>
    <img id="tileset" src="img/tileset.png" class="hidden">
    <canvas id="tile0" class="hidden" width="30" height="30"></canvas>
    <canvas id="tile1" class="hidden" width="30" height="30"></canvas>
    <canvas id="tile2" class="hidden" width="30" height="30"></canvas>
    <canvas id="tile3" class="hidden" width="30" height="30"></canvas>
    <canvas id="tile4" class="hidden" width="30" height="30"></canvas>
    <form name="f" class="debug">
    <textarea name="t" cols=80 rows=3></textarea>
    </form>
</body>
</html>

Finden

Blättern
Hauptseite
XT Knowledge Base-Portal
Aktuelle Ereignisse
Letzte Änderungen
Zufällige Seite
Konfiguration
Hilfe
Ändern
Quelltext betrachten
Bearbeitungshilfe
Seitenoptionen
Diskussion
Neuer Abschnitt
Druckversion
Seitendaten
Versionen
Links auf diese Seite
Änderungen an verlinkten Seiten
Meine Seiten
Anmelden
Spezialseiten
Neue Seiten
Dateiliste
Statistik
Mehr …