image image


Kollisionserkennung mit Processing.py und P5.js (Teil 2: Rechtecke)

Mit diesem Beitrag möchte ich meine Mini-Serie über Kollisionserkennung mit Processing.py, dem Python-Mode von Processing, wie auch mit P5.js, Processings JavaScript-Ableger, fortsetzen, dieses mal mit der Kollision zweier Rechtecke:

Die Kollisionsüberprüfung zweier Rechtecke ist im Grunde eine Verallgemeinerung der Kollisionsüberprüfung zweier Kreise aus dem ersten Teil dieser Serie. Da jedoch ein Rechteck keinen Radius besitzt, sondern eine Höhe und eine Weite, müssen diese jeweils separat auf der horizontalen wie auch auf der vertikalen Achse überprüft werden. Dafür wird zuerst der jeweilige Abstand zwischen den beiden Rechtecken berechnet:

    distanceX = (r1.x + r1.w/2) - (r2.x + r2.w/2)
    distanceY = (r1.y + r1.h/2) - (r2.y + r2.h/2)

Da Rechtecke in Processing per Default nicht von ihrem Mittelpunkt, sondern der linken oberen Ecke definiert werden, muß dazu jeweils die halbe Weite und Höhe dazu addiert werden. Dann wird die jeweilige Gesamtbreite und -höhe der beiden Rechtecke ermittelt:

    halfW = r1.w/2 + r2.w/2
    halfH = r1.h/2 + r2.h/2

Wenn nun der absolute horizontale Abstand kleiner als die Gesamtbreite ist, liegt einer von zwei möglichen Fällen vor:

  1. Der absolute vertikale Abstand ist ebenfalls kleiner als die Gesamthöhe. Dann liegt eine Kollision vor.
  2. Der absolute vertikale Abstand ist größer als die Gesamthöhe. Dann ist eines der beiden Rechtecke entweder über oder unter dem anderen Rechteck, also liegt keine Kollision vor.

In Code gegossen sieht das so aus:

    if (abs(distanceX) < halfW):
        if (abs(distanceY) < halfH):
            return True
    return False

Im Sketch gibt es also dieses Mal zwei Rechtecke (eines davon oder beide können auch Quadrate sein, am Verhalten ändert sich dadurch nichts). Wie im ersten Teil habe ich der Übersichtlichkeit halber den Code in einzelne Tabs untergebracht, hier zuerst das Hauptprogramm mit der Kollisionserkennung:

from enemies import Enemy
from player import Player

def setup():
    global enemy, player
    size(420, 420)
    this.surface.setTitle("Rectangle Collision Detection")
    enemy = Enemy(width/2 - 64, height/2 - 32)
    player = Player(20, 20)

def draw():
    global enemy, player
    background("#95ee0f5")
    if rect_collision(enemy, player):
        background("#817ac6")
    else:
        background("#95ee0f5")
    enemy.show()
    player.update()
    player.show()

def rect_collision(r1, r2):
    distanceX = (r1.x + r1.w/2) - (r2.x + r2.w/2)
    distanceY = (r1.y + r1.h/2) - (r2.y + r2.h/2)
    halfW = r1.w/2 + r2.w/2
    halfH = r1.h/2 + r2.h/2
    if (abs(distanceX) < halfW):
        if (abs(distanceY) < halfH):
            return True
    return False

Die Klassen enemy und player unterscheiden sich nur geringfügig vom ersten Teil – es werden halt statt der Kreise je ein buntes Rechteck gezeichnet:

class Enemy(object):
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.w = 128
        self.h = 64
    
    def update(self):
        pass
    
    def show(self):
        strokeWeight(1)
        fill("#c666e6")
        rect(self.x, self.y, self.w, self.h) 
class Player(object):
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.w = 32
        self.h = 32
    
    def update(self):
        self.x = mouseX
        self.y = mouseY
    
    def show(self):
        strokeWeight(1)
        fill("#9757a5")
        rect(self.x, self.y, self.w, self.h)

Auch hier bewegt sich das gegnerische Rechteck nicht, nur der Player wird mit der Maus bewegt. Daher besitzt der Gegner nur eine symbolische update()-Funktion 🤓

Wenn Ihr den Sketch laufen läßt, sieht die Processing.py-Version so aus:

image

Auch dieses Mal habe ich mit P5.js eine JavaScript-Version erstellt und oben in diese Seite eingebunden, damit Ihr auch live die Kollisionserkennung überprüfen könnt. Das ist der JavaScript-Quelltext:

let enemy;
let player;

function setup() {
  let myCanvas = createCanvas(640, 320);
  myCanvas.parent("myCanvas");
  enemy = new Enemy(width/2 - 64, height/2 - 32);
  player = new Player(20, 20);
}

function draw() {
  background("#95e0f5");
  if (rectCollision(enemy, player)) {
    background("#817ac6");
  } else {
    background("#95e0f5");
  }
  enemy.show();
  player.update();
  player.show();
}

function rectCollision(r1, r2) {
  distanceX = (r1.x + r1.w/2) - (r2.x + r2.w/2);
  distanceY = (r1.y + r1.h/2) - (r2.y + r2.h/2);
  halfW = r1.w/2 + r2.w/2;
  halfH = r1.h/2 + r2.h/2;
  if (abs(distanceX) < halfW) {
    if (abs(distanceY) < halfH) {
      return true;
    }
  }
  return false;
}

class Enemy {
  
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.w = 128;
    this.h = 64;
  }
  
  show() {
    strokeWeight(1);
    fill("#c666e6");
    rect(this.x, this.y, this.w, this.h);
  }
}

class Player {
  
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.w = 32;
    this.h = 32;
  }
  
  update() {
    this.x = mouseX;
    this.y = mouseY;
  }
  
  show() {
    strokeWeight(1);
    fill("#9757a5");
    rect(this.x, this.y, this.w, this.h);

Caveat: Der Code funktioniert, aber ich taste mich immer noch ganz vorsichtig an JavaScript heran. Wenn Ihr also Verbesserungsvorschläge habt oder eine Idee, wie man den Code eleganter formulieren kann, bin ich für Mitteilungen via meiner (Email-) Kommentare dankbar. Still digging!


(Kommentieren) 

image image



Über …

Der Schockwellenreiter ist seit dem 24. April 2000 das Weblog digitale Kritzelheft von Jörg Kantel (Neuköllner, EDV-Leiter Rentner, Autor, Netzaktivist und Hundesportler — Reihenfolge rein zufällig). Hier steht, was mir gefällt. Wem es nicht gefällt, der braucht ja nicht mitzulesen. Wer aber mitliest, ist herzlich willkommen und eingeladen, mitzudiskutieren!

Alle eigenen Inhalte des Schockwellenreiters stehen unter einer Creative-Commons-Lizenz, jedoch können fremde Inhalte (speziell Videos, Photos und sonstige Bilder) unter einer anderen Lizenz stehen.

Der Besuch dieser Webseite wird aktuell von der Piwik Webanalyse erfaßt. Hier können Sie der Erfassung widersprechen.

Diese Seite verwendet keine Cookies. Warum auch? Was allerdings die iframes von Amazon, YouTube und Co. machen, entzieht sich meiner Kenntnis.


Werbung

Diese Spalte wurde absichtlich leergelassen!


Werbung


image  image  image
image  image  image


image