Connect with us

Künstliche Intelligenz

C++ für eingebettete Systeme: constexpr und consteval


Im heutigen Beitrag zeige ich, wie modernes C++ den Code für eingebettete Systeme beeinflussen kann. Der Code nutzt Features bis zu C++23.

Weiterlesen nach der Anzeige


Portrait von Andreas Fertig

Portrait von Andreas Fertig

Andreas Fertig ist erfahrener C++-Trainer und Berater, der weltweit Präsenz- sowie Remote-Kurse anbietet. Er engagiert sich im C++-Standardisierungskomitee und spricht regelmäßig auf internationalen Konferenzen. Mit C++ Insights ( hat er ein international anerkanntes Tool entwickelt, das C++-Programmierenden hilft, C++ noch besser zu verstehen.

Das Beispiel, das ich unten zeige, dreht sich um mindestens zwei Fragen, die mir Kunden schon oft gestellt haben:

  • Wozu ist consteval gut?
  • Was ist dieser benutzerdefinierte Literal-Operator und warum sollte mich das interessieren?

Ich werde diese beiden Fragen beantworten, aber es nicht dabei belassen. Das unten stehende Beispiel aus der Praxis zeigt auch die neuesten Ergänzungen zu C++, die dazu beitragen, Code robuster und sicherer zu machen.

Ich gebe viele Kurse für Kunden, die eingebettete Systeme entwickeln. Ich habe lange in diesem Bereich gearbeitet und es hat mir sehr viel Spaß gemacht.

Ein immer wiederkehrendes Thema ist die Vernetzung. Obwohl es heutzutage verschiedene Netzwerktypen und -technologien gibt, wollen wir uns in diesem Beitrag mit dem Internetprotokoll (IP) beschäftigen. Die Basis der Netzwerkkommunikation ist die Netzwerkkarte (NIC). Jede NIC hat eine eindeutige Medium Control Address (MAC) zugewiesen bekommen. Die MAC-Adresse ist die Basis für alles, was darauf aufbaut, wie TCP/IP.

Weiterlesen nach der Anzeige

Eine MAC-Adresse besteht aus genau sechs Bytes. Eine Möglichkeit, eine MAC-Adresse in Code darzustellen, ist folgende:


struct MACAddr {
  std::array data;
};


Die für Menschen lesbare Form der MAC-Adresse stellt diese sechs Bytes als Hexadezimalziffern dar, die zu zweit gruppiert und durch einen Doppelpunkt oder einen Bindestrich getrennt sind, wie hier:

12:34:56:78:90:AB

Einige dieser MAC-Adressen sind schon beim Kompilieren bekannt, andere können Nutzer während der Laufzeit eingeben.

Als ersten Schritt schauen wir uns an, wie eine Funktion, die eine MAC-Adresse in Zeichenfolgenform konvertiert, in eine 6-Byte-Version umgewandelt werden kann. Oben ist MACAddr als Basis. Aus Gründen der Speichersicherheit habe ich mit std::array angefangen. Ich ersetze alle C-Arrays durch die stärkere C++-Version, wo es geht. Der große Vorteil ist, dass ich jederzeit die Größe abfragen kann.

Für die Parsing-Funktion ist eine Zeichenfolge nur dann gültig, wenn sie mindestens 17 Zeichen enthält (6 Bytes mal 2 aufgrund des Hexadezimal-Formats plus 5 Trennzeichen). Das Auffinden der Trennzeichen ist ein weiterer Punkt.

In macFromString ist eine mögliche Implementierung:


constexpr std::expected  // #A
macFromString(std::span addr)    // #B
{
  // #C
  if(addr.size() < 17) { return std::unexpected(std::errc::message_size); }

  MACAddr res{};

  // #D
  for(int i = 0; auto& val : res.data) {
    // #E
    // C++26 will have .at!
    if((i < 5) and (addr[2] != ':')) {
      return std::unexpected(std::errc::message_size);
    }

    auto isAllowedHexChar = [](char c) {
      return ((('a' <= c) and ('f' >= c)) or  // isalpha reduced
              (('A' <= c) and ('F' >= c)) or  // isalpha reduced
              (('0' <= c) and ('9' >= c))     // is digit
      );
    };

    // #F
    if(not(isAllowedHexChar(addr[0]) and isAllowedHexChar(addr[1]))) {
      return std::unexpected(std::errc::invalid_argument);
    }

    // #G
    if(std::from_chars(addr.data(), addr.data() + 2, val, 16).ec !=
       std::errc()) {
      return std::unexpected(std::errc::message_size);
    }

    // #H
    addr = addr.subspan((addr.size() >= 3) ? 3 : addr.size());
    ++i;
  }

  return res;
}


Ich fange mit dem Rückgabedatentyp std::expected (#A) an. Dieser Typ ist seit C++23 verfügbar. Wie du siehst, ist der erste Template-Parameter der Datentyp, den du im besten Fall erwarten darfst (daher der Name expected), und der zweite Parameter ist der Datentyp für die Fehlerbedingung. Einfachheitshalber habe ich hier std:errc verwendet. Du solltest immer einen Datentypen wählen, der auf die Anforderungen in deiner Codebasis zugeschnitten ist.

Die Stärke von std::expected liegt darin, dass es entweder einen Wert oder einen Fehlercode enthält. Es gibt zwar ungültige MAC-Adressen, aber nehmen wir mal den einfachen Weg und betrachten die Adresse als ungültig, wenn die Zeichenfolge zu kurz ist, die erforderlichen Trennzeichen nicht enthält oder ungültige Zeichen enthält (wie T, das keine Hexadezimalzahl ist). Der Einsatz von std::expected hilft dabei, das Out-Parameter-Muster zu entfernen, das ich ungern mag.

Als Nächstes siehst du, dass macFromString in #B einen std::span als Parameter verwendet. Das Schöne an std::span, der in C++20 hinzugefügt wurde, ist, dass es eine sehr kostengünstige Ansicht der Originaldaten ist, während std::span die Datengröße beibehält. All diese Punkte machen std::span zum perfekten Datentyp, um Array-ähnliche Daten zu übergeben und dabei trotzdem die Grenzen sicher einzuhalten.

Als Erstes prüfe ich in macFromString, ob die Zeichenfolge lang genug ist (#C). Dank std::span ist das nicht nur einfach, sondern auch sicher.

Was passiert, wenn die Zeichenfolge zu kurz ist? Das wäre unerwartet. Deshalb gebe ich in diesem Fall ein std::unexpected mit einem std:errc-Code zurück. Hier zeigt sich die Schönheit von std::expected: Der Fehlerfall wird absolut klar gekennzeichnet.

Schauen wir uns jetzt die Konvertierung an, für die eine Schleife nötig ist. Ich setze eine bereichsbasierte For-Schleife (#D) ein und verwende dafür C++20 mit einem Initialisierer meiner Zählvariablen i.

Ich überprüfe innerhalb der Schleife auf das Trennzeichen, das sich an Position zwei in std::span befindet, wenn wir den letzten Teil nicht betrachten. Das ist dasselbe Verfahren wie oben in #C: Wenn kein Trennzeichen vorhanden ist (oder ein anderes), gebe ich in #D std::unexpected zurück.

In #F wird überprüft, ob die beiden aktuell betrachteten Zeichen im Bereich eines gültigen Hexadezimal-Zeichens liegen. Leider ist std::isdigit nicht constexpr. Das Gleiche gilt für std::isalpha, aber das fehlende constexpr bei dieser Funktion ist nicht so wichtig, da hier ein reduzierter Bereich erforderlich ist.

Als Nächstes kommt in #G die eigentliche Konvertierung. Ich benutze std::from_chars aus C++17. Das Schöne daran ist, dass ich die Werte aus std::span direkt übergeben kann, obwohl sie nicht mit dem üblichen Hexadezimalzahl-Indikator 0x beginnen. Ich kann std::from_chars mitteilen, welche Basis die Zahl hat.

Sollte die Konvertierung fehlschlagen, überprüfe ich den Fehlercode ec[/code und gebe erneut ein [code]std::unexpected zurück. Für deinen Code ist es nützlich, verschiedene Fehlerwerte zu verwenden, um anzuzeigen, an welcher Stelle die Konvertierung fehlgeschlagen ist.

Der letzte Schritt in #H besteht dann darin, das std::span mithilfe seiner subspan-Funktionalität weiterzuschieben. Hier musst du vorsichtig sein: Wenn du den Bereich verlässt, ist das Verhalten undefiniert. Deshalb überprüfe ich, wie viele Elemente noch übrig sind, und gehe entweder um diese Anzahl weiter oder um die Anzahl, die noch übrig ist. Der letzte Teil gilt immer für das letzte Ziffernpaar, das ohne nachfolgendes Trennzeichen kommt.

Es ist wichtig, nicht zu vergessen, i als letzten Schritt zu erhöhen. Dann haben wir einen robusten und sicheren MAC-Adressen-Parser, der die neuesten C++-Funktionen nutzt.

Ein kleines Detail, das ich bei der Erläuterung der Implementierung von macFromString noch nicht angesprochen habe, ist die erste Zeichenfolge in der Funktionsdeklaration, die das Schlüsselwort constexpr bildet.

Die Antwort ist einfach: Wir wollen macFromString zur Kompilierungszeit aufrufen können. Hier kommt der anfangs erwähnte Literal-Operator (UDL) zum Tragen.

Eine interessante Eigenschaft des UDL-Operators ist, dass er nur mit Konstanten zur Kompilierungszeit aufgerufen werden kann. Du kannst den UDL-Operator manuell und damit mit Laufzeitwerten aufrufen, aber das widerspricht völlig dem Zweck eines Operators.

Wir benötigen einen UDL _macaddr, der ein MACAddr-Objekt zurückgibt, damit der folgende Code gültig ist:


// #A
auto data{std::to_array("12:34:56:78:90:AB")};
auto m = macFromString(data);

auto compileTimeMAC = "12:34:56:78:90:AB"_macaddr;


Die Implementierung des UDL-Operators ist recht einfach:


consteval MACAddr operator""_macaddr(const char* str, size_t length)
{
  return macFromString({str, length}).value();
}


Ich benutze die UDL-Operatorform, die ein const char* und ein std::size_t nimmt. Der Compiler erkennt freundlicherweise die Größe der Konstantenzeichenfolge zur Kompilierungszeit und teilt sie dem Operator mit. Damit sind alle Informationen zum Aufruf von macFromString vorhanden. Das Beste daran ist, dass die Zeichenfolge und die Länge immer zu 100 % übereinstimmen, da wir absolut nichts damit zu tun haben. Gib einfach die Daten weiter und bilde beim Aufruf von macFromString ein std::span.

Aber macFromString gibt ein std::expected zurück, mehr als nur ein MACAddr. Was tun? Ich rufe einfach .value für das Ergebnis von macFromString auf. Falls std::expected keinen Wert enthält, löst der Datentyp eine Exception aus. Aber ist das nicht schlecht? In anderen Fällen vielleicht schon, aber hier finde ich es mehr als okay, ich finde es großartig!

Hast du das erste Schlüsselwort bemerkt, das ich für den UDL-Operator verwendet habe? Es ist consteval! Ich erzwinge, dass diese Funktion nur zur Kompilierungszeit ausgewertet wird. Bei einer ungültigen MAC-Adresszeichenfolge führt die Ausnahme zum Abbruch des Kompilierungsvorgangs. So kannst du solche Fehler effektiv während der Entwicklung abfangen. Keine fest codierte MAC-Adresse sollte ungültig sein, oder?

consteval hat hier noch einen weiteren Vorteil: Wenn die Implementierung von macFromString nicht constexpr wäre, beispielsweise wegen eines Throw oder anderen undefinierten Verhaltens, würde die Auswertung des UDL zu einem Laufzeitaufruf werden. Das ist sicher nicht das, was du willst.

Die gezeigten Elemente helfen dir, deinen Code robuster zu machen und die Sicherheit sowie die Lesbarkeit zu verbessern.

Die Anwendung der neuesten Funktionen von C++ ist in vielerlei Hinsicht vorteilhaft. Eine weitere Erkenntnis: Als Faustregel gilt, dass du jeden UDL-Operator in C++20 und höher als consteval definieren solltest.


(rme)



Source link

Künstliche Intelligenz

iX-Workshop: Netzwerkprobleme mit Wireshark analysieren und beheben


Langsame Verbindungen, ständige Unterbrechungen oder unerkannte Sicherheitslücken können den Betriebsablauf stark beeinträchtigen oder sogar zu Ausfällen führen. Mit Wireshark, einem Open-Source-Tool zur Netzwerkanalyse, können Administratoren den Netzwerkverkehr in Echtzeit überwachen, Sicherheitsrisiken identifizieren und Verbindungsprobleme diagnostizieren.

Weiterlesen nach der Anzeige

In dem praxisorientierten Workshop Netzwerkanalyse und Fehlersuche mit Wireshark erfahren Sie, wie Sie das Netzwerkanalyse-Tool Wireshark effizient einsetzen können. Sie lernen die Funktionsweise und Konfiguration von Wireshark kennen, entwickeln systematische Vorgehensweisen zur Fehleranalyse, verstehen die Bedeutung der Aufzeichnung von Netzwerkdaten und erfahren, wie Sie die Zuverlässigkeit Ihres Netzwerks steigern können.

Der Workshop ist interaktiv gestaltet und enthält praxisnahe Übungen in einer bereitgestellten Laborumgebung. Sie werden selbstständig Netzwerkdaten erfassen, Filter setzen, Analysen durchführen und Statistiken erstellen. Anhand konkreter Anwendungsszenarien vertiefen Sie dieses Wissen und verstehen beispielsweise, wie Sie Netzwerkprotokolle analysieren, Leistungsengpässe aufspüren und Auswirkungen von Paketstaus und Paketverlusten erkennen.

Juni
01.06. – 04.06.2026
Online-Workshop, 09:00 – 16:30 Uhr
10 % Frühbucher-Rabatt bis zum 04. Mai 2026
September
21.09. – 24.09.2026
Online-Workshop, 09:00 – 16:30 Uhr
10 % Frühbucher-Rabatt bis zum 24. Aug. 2026
November
16.11. – 19.11.2026
Online-Workshop, 09:00 – 16:30 Uhr
10 % Frühbucher-Rabatt bis zum 19. Okt. 2026

Ihr Trainer Henrik Wahsner ist ein erfahrener Experte in der Performanceanalyse und Fehlersuche in IP-Netzwerken. Als technischer Leiter der NETCOR GmbH kombiniert er tiefgehendes Fachwissen mit praxisnaher Expertise, die er in zahlreichen Kundenprojekten gesammelt hat.

Der Workshop dauert dreieinhalb Tage und richtet sich an Netzwerkadministratoren und technische Mitarbeiter, die für den Betrieb von Netzwerken verantwortlich sind. Er ist ideal für Einsteiger in die Arbeit mit Wireshark, aber auch für erfahrene Anwender, die ihr Wissen vertiefen möchten. Teilnehmer, die das Tool bereits nutzen, erhalten neue Perspektiven und Workflows für die Netzwerkanalyse.

Aufgrund des interaktiven Formats ist die Teilnehmerzahl auf 20 Personen begrenzt, um ausreichend Raum für den Austausch mit dem Trainer und den anderen Teilnehmern zu schaffen.

Weiterlesen nach der Anzeige


Upgrade für Ihre IT-Skills - Von Experte zu Experte

Upgrade für Ihre IT-Skills - Von Experte zu Experte


(ilk)



Source link

Weiterlesen

Künstliche Intelligenz

Core 300: Intel stellt Billigprozessor Wildcat Lake vor


close notice

This article is also available in
English.

It was translated with technical assistance and editorially reviewed before publication.

Intel geht mit der Prozessorbaureihe Core 300 alias Wildcat Lake neue Wege. Anders als bei den Core 100 und 200 (nicht Ultra) legt der Hersteller keine alten CPUs unter neuem Namen auf. Stattdessen gibt es eine Mini-Version der großen Core Ultra 300 (Panther Lake). Das komplette Design ist auf niedrige Kosten ausgelegt und folglich für günstige Notebooks gedacht.

Weiterlesen nach der Anzeige

Statt bis zu 16 CPU-Kerne gibt es mit Wildcat Lake nur noch maximal sechs: zwei Performance- und vier Low-Power-Effizienzkerne. Auf normale Effizienzkerne als Mittelstufe verzichtet Intel. Das Speicher-Interface ist auf 64 Bit halbiert (Single-Channel), der Level-3-Cache auf 6 MByte gedrittelt und auch die integrierte KI-Einheit (Neural Processing Unit, NPU) sowie GPU sind kompakt gehalten. Das spart Chipfläche und damit Fertigungskosten.


Infografik aus Intels Präsentation

Infografik aus Intels Präsentation

Links die großen Panther-Lake-Chipkonfigurationen, rechts der kleinere Wildcat Lake.

(Bild: Intel)

Die NPU schafft maximal 17 Billionen Berechnungen pro Sekunde (Tops) statt 50. Die GPU umfasst maximal zwei Xe-Kerne statt 12 wie in der Panther-Lake-Maximalkonfiguration.

Single-Channel-RAM hilft vor allem in Zeiten der Speicherkrise, die Kosten nach unten zu drücken. Für Intel ist das Timing trotzdem schlecht: Notebook-Hersteller priorisieren Oberklassemodelle, um ihre Margen zu halten. Vor allem die Einstiegs- und Mittelklasse leidet unter den immensen Speicherpreisen.

Die grundlegende Technik befindet sich trotz des Kostenfokus auf aktuellem Stand. Das Compute-Die mit der CPU, GPU, NPU und dem Speichercontroller fertigt Intel mit eigener 18A-Technik. Das Platform Controller Tile fertigt TSMC im N6-Prozess. Intel begnügt sich mit sechs PCI-Express-4.0-Lanes, integriert aber weiterhin Thunderbolt 4, Wi-Fi 7 und Bluetooth 6.0.

Weiterlesen nach der Anzeige


Infografik aus Intels Präsentation

Infografik aus Intels Präsentation

Aufbau von Wildcat Lake. Das Compute-Die stellt Intel mit 18A-Technik her.

(Bild: Intel)

Wildcat Lake kommt in Form von sechs Mobilprozessoren. Fünf Modelle unterscheiden sich nur marginal: Vom Core 7 360 bis zum Core 5 315 kommt immer der Vollausbau mit sechs CPU-Kernen und zwei GPU-Kernen zum Einsatz. Sie unterscheiden sich größtenteils durch die Taktfrequenzen und den Support für Intels Validierungsprogramm Stable IT Platform Program (SIPP). Hersteller zertifizieren dort das Zusammenspiel aus allen Komponenten; gedacht ist es für Unternehmenskunden.

Beim Core 3 304 sind ein CPU-Performance- und ein GPU-Kern deaktiviert. Er hat mit 4,3 GHz auch den niedrigsten Turbo-Takt.

Alle sechs Modelle verwenden die gleiche NPU, bloß mit unterschiedlichen Taktfrequenzen. Zudem können alle wahlweise 64 GByte DDR5-6400-RAM oder 48 GByte LPDDR5X-7467-Speicher ansprechen. Die standardmäßige Thermal Design Power (TDP) liegt bei 15 Watt, die maximale Turbo-Power bei 35 Watt.


Infografik aus Intels Präsentation

Infografik aus Intels Präsentation

Spezifikationen der Core 300. Fünf Modelle ähneln sich weitgehend.

(Bild: Intel)

Laut Intel planen Notebook-Hersteller über 70 Designs mit Wildcat Lake. Die ersten davon sollen zeitnah verfügbar sein. Acer bringt etwa verschiedene Aspire-Go-Notebooks, Asus Vivobooks und Expertbooks, HP ein Omnibook, Lenovo Thinkbooks, Thinkpads, Ideapads und einen Ideacentre-All-in-One-PC, und Samsung das Galaxy Book 6.


(mma)



Source link

Weiterlesen

Künstliche Intelligenz

„Replaced“: Cyberpunk-Blues in Pixel-Optik | heise online


close notice

This article is also available in
English.

It was translated with technical assistance and editorially reviewed before publication.

„Replaced“ sorgte mit seinem einzigartigen Grafikstil schon bei der Ankündigung im Jahr 2021 für Aufsehen. Jetzt ist der Action-Plattformer endlich da und kann die meisten Versprechen sogar einlösen – ein ungewöhnliches SciFi-Abenteuer auf den Spuren von „Another World“ und „Inside“.

Weiterlesen nach der Anzeige

Stellen wir uns mal vor, dass alles ganz anders gelaufen wäre. Dass es schon in den 1980er Jahren künstliche Intelligenzen und Supercomputer gab. Dass Autos fliegen können. Und dass Mensch sein noch lange nicht heißt, Mensch zu sein. Wo liegen die Grenzen zwischen Mensch und Maschine? Wofür lohnt es sich zu lieben, zu leben und zu kämpfen?

In dieser Sinnkrise steckt Wissenschaftler Warren Marsh. Der wacht nach einem missglückten Experiment auf und hat einen künstlichen Gast in seinem Körper: R.E.A.C.H. oder ausführlicher „Research Engine for Altering and Composing Humans“. Beide sind mit der Gesamtsituation nicht glücklich und wollen so schnell wie möglich die Trennung. Doch leichter gesagt als getan. Ein nahezu faschistischer Politik- und Polizeiapparat, gierige Konzerne und eine ziemlich triste Lebensperspektive machen den beiden ihren Plan beinahe zunichte.


Ein Pixeltraum: Dank ungewöhnlichem Stil und spannender Story wird „Replaced“ zu einem Genre-Hit für Science-Fiction-Fans. (Bild:

heise medien

)

Was vielleicht wie Satire klingt, ist eine zutiefst bedrückende Retro-Dystopie, die ein wenig an William Gibsons Roman „Neuromancer“ oder Ridley Scotts „Blade Runner“ erinnert. Die Welt ist dunkel und trist. Aber selbst in diesem Szenario der Hoffnungslosigkeit findet das Entwicklungsstudio Zeit und Ideen, sie zum Leben zu erwecken. Gemalt im Pixellook finden sich überall kleine Details und die Synthie-Musik dröhnt wie zu besten John-Carpenter-Zeiten aus den Boxen. Das ist stilistisch ein nahezu perfekter Neo-Noir-Traum.

Spielerisch wandelt das Abenteuer in den rund 12 Spielstunden auf Pfaden großer Vorbilder. Hauptfigur Warren bewegt sich in einer 2.5D-Welt in der Seitenansicht durch dunkle Tunnel, neonleuchtende Städte und verwirrende Forschungskomplexe. Die Perspektive spielt mit uns, dreht sich manchmal oder wechselt die Blickwinkel. „Replaced“ mag zwar nur ein Sidescroller sein, sorgt aber für Tiefe und Raumgefühl.

Meist muss Warren von einer Kante zur nächsten springen. Dafür krallt er sich an Wände oder verschiebt Container, um höher zu klettern. Manchmal weicht er Überwachungskameras aus oder hackt die Sicherheitsanlagen auf seinem tragbaren Handcomputer, indem er Symbole anordnet. Simpel, mit ein bisschen Zeitdruck, aber mit endlosen Versuchen.

Weiterlesen nach der Anzeige

Immer wieder trifft Warren auf ein paar Gegner, die er ordentlich vermöbeln darf. Zwei Nahkampfattacken, ein bisschen ausweichen und kontern. Später bekommt er noch eine Pistole, die sich bei jedem Treffer auflädt. Das wirkt in Aktion ein wenig wie „Batman: Arkham City“ in 2D. Da es oft Gegnerwellen sind und sie alle nur Geld für graue oder dunkle Klamotten haben, fällt der Überblick ein wenig schwer. Frust kommt aber selten auf. Selbst die Bosskämpfe gegen aufgepumpte Schlägertypen sind leicht zu meistern. Den Gegnern fehlt es an anspruchsvollen Angriffsmustern, die Spieler auf dem normalen Schwierigkeitsgrad fordern.

Warren ist auch ein Sammler. Überall finden sich, manchmal auch versteckt, Lebens- und Waffenupgrades. In kleinen Text- und Audiofiles wird die Hintergrundgeschichte erzählt. Wenn er dann auf einem Bahnhof für andere Ausgestoßene ein paar Aufgaben erfüllt, wird es emotional: einem Sterbenden die Bilder seiner Familie bringen, einen Hund füttern oder das Drama hinter einem ungewöhnlichen Zwillingspaar aufdecken. Witzig: An Spielautomaten darf er auch den Highscore in „Frogger“ oder „Space Invaders“ inspirierten Spielen knacken.

Lesen Sie auch

So entsteht langsam das dystopische Bild einer zerstörten Gesellschaft, am Ende sogar ziemlich blutig und derb. Das ist trist und ganz bestimmt kein „Feel-Good“-Game, auch wenn am Ende Hoffnung aufkeimt. Die Geschichte erzählt von Verlust, Einsamkeit und der Menschwerdung einer Maschine. Es ist ein existenzielles Science-Fiction-Abenteuer, das Spieler mit seiner ungewöhnlichen visuellen Umsetzung anzieht und mit seiner Story zum Nachdenken anregt.

„Replaced“ ist ein wahr gewordener Pixel-Traum. Detailverliebt spielt das Entwicklungsstudio Sad Cat mit Genre- und Spielelementen. Hektische Action-Phasen wechseln sich mit besinnlichen Momenten ab und sorgen für ein spannendes wie nachdenklich machendes Cyberpunk-Abenteuer.

Sicher gibt es auch Ecken und Kanten. Manchmal steht der Pixel-Stil der Übersicht im Weg, und die Bewegungsanimationen der Hauptfigur könnten flüssiger sein. Auch fehlt es den Gegner-Typen an Abwechslung. Wer in eine stilistisch nahezu perfekte Retro-Dystopie der 1980er eintauchen will, liegt bei diesem Indie-Abenteuer aber genau richtig.

„Replaced“ ist für Windows und Xbox Series X/S erschienen. USK ab 16. Es kostet ca. 20 €. Für unseren Text haben wir die Windows-Version durchgespielt.


(dahe)



Source link

Weiterlesen

Beliebt