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:
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:
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!
Ü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!