News Shooter-Hoffnung Marathon: Bungie verkündet Reboot und gewährt tiefe Einblicke

PCGH_Sven

PCGH-Autor
Nachdem die Shooter-Hoffnung Marathon nach teils harscher Spieler-Kritik vom Destiny-Entwicklerstudio Bungie im Juni vorerst auf unbekannte Zeit verschoben wurde, stehen das Release und der Preis für den Reboot jetzt fest.

Was sagt die PCGH-X-Community zu Shooter-Hoffnung Marathon: Bungie verkündet Reboot und gewährt tiefe Einblicke

Bitte beachten: Thema dieses Kommentar-Threads ist der Inhalt der Meldung. Kritik und allgemeine Fragen zu Online-Artikeln von PC Games Hardware werden hier gemäß der Forenregeln ohne Nachfrage entfernt, sie sind im Feedback-Thread besser aufgehoben.
 
Früher hätte man dumme Kommentare schriebn müssen, wie man meint, dass sich so ein Extraktionshooter für die Mehrheit spielt, dank der unheiligen Kraft des KI Mülls, kann man es direkt demonstrieren. Den HTML Code in ein File einfügen, das man xyz.html nennt und öffnen.


HTML:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Langstreckenlauf</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background-color: #050510;
            overflow: hidden;
            font-family: 'Courier New', Courier, monospace;
            color: #00ffcc;
            user-select: none;
        }

        #gameContainer {
            position: relative;
            width: 100vw;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        canvas {
            background: linear-gradient(to bottom, #02020a, #1a0b2e);
            box-shadow: 0 0 20px #00ffcc;
        }

        #uiLayer {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            text-align: center;
        }

        .hidden {
            display: none !important;
        }

        h1 {
            font-size: 60px;
            text-transform: uppercase;
            text-shadow: 4px 4px 0px #ff0055;
            margin-bottom: 10px;
        }

        p {
            font-size: 20px;
            background: rgba(0, 0, 0, 0.7);
            padding: 10px;
        }

        button {
            pointer-events: auto;
            background: #ff0055;
            border: 4px solid #fff;
            color: #fff;
            font-family: inherit;
            font-size: 24px;
            padding: 15px 30px;
            cursor: pointer;
            text-transform: uppercase;
            margin-top: 20px;
            transition: transform 0.1s;
        }

        button:hover {
            transform: scale(1.1);
            background: #ff3377;
        }

        #scoreBoard {
            position: absolute;
            top: 20px;
            left: 20px;
            font-size: 24px;
            text-align: left;
        }
    </style>
</head>
<body>

<div id="gameContainer">
    <canvas id="gameCanvas"></canvas>
    <div id="scoreBoard" class="hidden">LOOT: 0</div>
   
    <!-- Start Screen -->
    <div id="startScreen" class="uiLayer">
        <h1>Langstreckenlauf</h1>
        <p>A Sci-Fi Infinite Runner</p>
        <p>Use ⬅️ and ➡️ to move the Robot.</p>
        <p>Collect Loot. Avoid... actually, you can't avoid the inevitable.</p>
        <button onclick="startGame()">Start Run</button>
    </div>

    <!-- Game Over Screen -->
    <div id="gameOverScreen" class="uiLayer hidden">
        <h1 style="color: #ff0055; text-shadow: 4px 4px 0 #fff;">TERMINATED</h1>
        <p>You were shot from offscreen.</p>
        <p id="finalScore">Loot Collected: 0</p>
        <button onclick="startGame()">Try Again</button>
    </div>
</div>

<script>
/**
 * GAME ENGINE & LOGIC
 */

const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreEl = document.getElementById('scoreBoard');
const startScreen = document.getElementById('startScreen');
const gameOverScreen = document.getElementById('gameOverScreen');
const finalScoreEl = document.getElementById('finalScore');

// Resize canvas
function resize() {
    canvas.width = window.innerWidth * 0.9;
    canvas.height = window.innerHeight * 0.9;
}
window.addEventListener('resize', resize);
resize();

// Game State
let gameState = 'START'; // START, PLAYING, GAMEOVER
let score = 0;
let frame = 0;
let lastTime = 0;
let gameSpeed = 5;

// Timers
let lootTimer = 0;
let nextLootTime = 0;
let killTimer = 0;
let nextKillTime = 0;

// Inputs
const keys = {
    left: false,
    right: false
};

window.addEventListener('keydown', (e) => {
    if(e.key === "ArrowLeft") keys.left = true;
    if(e.key === "ArrowRight") keys.right = true;
});

window.addEventListener('keyup', (e) => {
    if(e.key === "ArrowLeft") keys.left = false;
    if(e.key === "ArrowRight") keys.right = false;
});

// Objects
const player = {
    x: 100,
    y: 0, // Set in update
    width: 40,
    height: 80,
    color: '#00ffcc',
    speed: 7,
    animFrame: 0
};

let loots = [];
let laserBeam = null; // {x, y, opacity}

/**
 * AUDIO SYSTEM (Web Audio API) - 8-Bit Style
 */
let audioCtx;
let musicInterval;

function initAudio() {
    if (!audioCtx) {
        audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    }
    if (audioCtx.state === 'suspended') {
        audioCtx.resume();
    }
}

// Simple oscillator wrapper
function playTone(freq, type, duration, vol = 0.1) {
    if (!audioCtx) return;
    const osc = audioCtx.createOscillator();
    const gain = audioCtx.createGain();
    osc.type = type;
    osc.frequency.setValueAtTime(freq, audioCtx.currentTime);
    gain.gain.setValueAtTime(vol, audioCtx.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + duration);
   
    osc.connect(gain);
    gain.connect(audioCtx.destination);
    osc.start();
    osc.stop(audioCtx.currentTime + duration);
}

function playNoise(duration) {
    if (!audioCtx) return;
    const bufferSize = audioCtx.sampleRate * duration;
    const buffer = audioCtx.createBuffer(1, bufferSize, audioCtx.sampleRate);
    const data = buffer.getChannelData(0);
    for (let i = 0; i < bufferSize; i++) {
        data[i] = Math.random() * 2 - 1;
    }

    const noise = audioCtx.createBufferSource();
    noise.buffer = buffer;
    const gain = audioCtx.createGain();
    gain.gain.setValueAtTime(0.2, audioCtx.currentTime);
    gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + duration);
   
    noise.connect(gain);
    gain.connect(audioCtx.destination);
    noise.start();
}

function startMusic() {
    if (musicInterval) clearInterval(musicInterval);
    let beat = 0;
    // Simple bassline loop
    musicInterval = setInterval(() => {
        if(gameState !== 'PLAYING') return;
        const time = audioCtx.currentTime;
        const osc = audioCtx.createOscillator();
        const gain = audioCtx.createGain();
        osc.connect(gain);
        gain.connect(audioCtx.destination);
       
        // Bass line notes
        let freq = 110; // A2
        if (beat % 4 === 0) freq = 110;
        else if (beat % 4 === 1) freq = 110;
        else if (beat % 4 === 2) freq = 87.31; // F2
        else if (beat % 4 === 3) freq = 98.00; // G2

        osc.frequency.setValueAtTime(freq, time);
        osc.type = 'square';
        gain.gain.setValueAtTime(0.05, time);
        gain.gain.exponentialRampToValueAtTime(0.001, time + 0.15);
       
        osc.start();
        osc.stop(time + 0.2);

        // Hi-hat noise every offbeat
        if(beat % 2 !== 0) {
            playTone(800, 'sawtooth', 0.05, 0.02);
        }

        beat++;
    }, 250); // 120ms tick
}

function stopMusic() {
    clearInterval(musicInterval);
}

/**
 * GAME LOGIC
 */

function startGame() {
    initAudio();
    startMusic();
   
    gameState = 'PLAYING';
    score = 0;
    loots = [];
    laserBeam = null;
   
    // Reset positions
    player.x = 100;
    gameSpeed = 5;
   
    // Set Timers
    lootTimer = performance.now();
    killTimer = performance.now();
    nextLootTime = getRandomRange(2000, 5000);
    nextKillTime = getRandomRange(15000, 20000);
   
    // UI
    startScreen.classList.add('hidden');
    gameOverScreen.classList.add('hidden');
    scoreEl.classList.remove('hidden');
    scoreEl.innerText = "LOOT: 0";
   
    requestAnimationFrame(gameLoop);
}

function gameOver() {
    gameState = 'GAMEOVER';
    stopMusic();
   
    // Play explosion/death sound
    playNoise(1.0);
    playTone(100, 'sawtooth', 1.0, 0.3);
   
    finalScoreEl.innerText = "Loot Collected: " + score;
    gameOverScreen.classList.remove('hidden');
}

function getRandomRange(min, max) {
    return Math.random() * (max - min) + min;
}

function spawnLoot() {
    loots.push({
        x: canvas.width + 50,
        y: canvas.height - 150 - (Math.random() * 100), // Variable height
        width: 30,
        height: 30,
        type: Math.floor(Math.random() * 3) // 0, 1, 2 for colors
    });
}

function killShot() {
    // Visual Laser
    laserBeam = {
        startX: canvas.width,
        startY: Math.random() * canvas.height,
        endX: player.x + player.width/2,
        endY: player.y + player.height/2,
        alpha: 1
    };
   
    // Play Laser Sound
    playTone(800, 'square', 0.5, 0.3);
    setTimeout(() => playTone(200, 'sawtooth', 0.5, 0.3), 100);

    // Instant Death
    setTimeout(gameOver, 200);
}

function update(dt) {
    const now = performance.now();
   
    // Player Movement
    if (keys.left && player.x > 0) player.x -= player.speed;
    if (keys.right && player.x < canvas.width - player.width) player.x += player.speed;
   
    // Player Animation
    player.animFrame += 0.2;
    player.y = canvas.height - 120; // Floor level

    // Loot Spawning
    if (now - lootTimer > nextLootTime) {
        spawnLoot();
        lootTimer = now;
        nextLootTime = getRandomRange(2000, 5000);
    }

    // Kill Timer
    if (now - killTimer > nextKillTime) {
        killShot();
        killTimer = now + 999999; // Prevent double trigger
    }

    // Update Loot
    for (let i = loots.length - 1; i >= 0; i--) {
        let l = loots[i];
        l.x -= gameSpeed;

        // Collision Detection
        if (
            player.x < l.x + l.width &&
            player.x + player.width > l.x &&
            player.y < l.y + l.height &&
            player.y + player.height > l.y
        ) {
            // Collect
            score++;
            scoreEl.innerText = "LOOT: " + score;
            playTone(1200 + (score * 50), 'sine', 0.1, 0.2); // Ding!
            loots.splice(i, 1);
            continue;
        }

        // Remove offscreen
        if (l.x < -50) loots.splice(i, 1);
    }
}

function draw() {
    // 1. Clear Screen
    ctx.fillStyle = "#050510";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // 2. Draw Background (Sci-Fi Grid)
    ctx.strokeStyle = "rgba(0, 255, 204, 0.3)";
    ctx.lineWidth = 2;
    const gridOffset = (Date.now() / 2) % 100;
   
    // Horizontal Floor Lines
    for (let i = canvas.height - 120; i < canvas.height; i += 20) {
        // Perspective effect
        let p = (i - (canvas.height-120)) / 120;
        ctx.beginPath();
        ctx.moveTo(0, i);
        ctx.lineTo(canvas.width, i);
        ctx.stroke();
    }
   
    // Vertical Scrolling Lines
    for (let i = 0; i < canvas.width + 100; i += 100) {
        let x = i - gridOffset;
        ctx.beginPath();
        ctx.moveTo(x, canvas.height - 120);
        ctx.lineTo(x - 200, canvas.height); // Slant for perspective
        ctx.stroke();
    }

    // 3. Draw Player (Robot)
    ctx.save();
    ctx.translate(player.x, player.y);
   
    // Legs Animation
    const legOffset = Math.sin(player.animFrame) * 10;
   
    // Robot Body
    ctx.fillStyle = "#8899aa"; // Metal
    ctx.fillRect(0, 0, 40, 50); // Torso
   
    // Head
    ctx.fillStyle = "#aaccdd";
    ctx.fillRect(5, -25, 30, 25);
    // Eye
    ctx.fillStyle = "#ff0055";
    ctx.fillRect(15, -15, 20, 5); // Visor

    // Arms
    ctx.fillStyle = "#667788";
    const armSwing = Math.cos(player.animFrame) * 10;
    ctx.fillRect(-10 + armSwing, 5, 10, 30); // Left arm
    ctx.fillRect(40 - armSwing, 5, 10, 30); // Right arm

    // Legs
    ctx.fillStyle = "#556677";
    ctx.fillRect(5 - legOffset, 50, 12, 30); // Left Leg
    ctx.fillRect(23 + legOffset, 50, 12, 30); // Right Leg

    ctx.restore();

    // 4. Draw Loot
    loots.forEach(l => {
        ctx.save();
        ctx.translate(l.x, l.y);
        // Glow
        ctx.shadowBlur = 15;
        if(l.type === 0) ctx.shadowColor = "#00ff00";
        if(l.type === 1) ctx.shadowColor = "#ffff00";
        if(l.type === 2) ctx.shadowColor = "#00ffff";
       
        ctx.fillStyle = "#ffffff";
        ctx.beginPath();
        ctx.moveTo(15, 0);
        ctx.lineTo(30, 15);
        ctx.lineTo(15, 30);
        ctx.lineTo(0, 15);
        ctx.fill();
        ctx.restore();
    });

    // 5. Draw Laser Shot (if active)
    if (laserBeam) {
        ctx.save();
        ctx.beginPath();
        ctx.moveTo(laserBeam.startX, laserBeam.startY);
        ctx.lineTo(laserBeam.endX, laserBeam.endY);
        ctx.strokeStyle = `rgba(255, 0, 0, ${laserBeam.alpha})`;
        ctx.lineWidth = 10 + (Math.random() * 5); // flicker size
        ctx.shadowColor = "#ff0000";
        ctx.shadowBlur = 20;
        ctx.stroke();
       
        // Impact circle
        ctx.fillStyle = "#ffffff";
        ctx.beginPath();
        ctx.arc(laserBeam.endX, laserBeam.endY, 20, 0, Math.PI*2);
        ctx.fill();
        ctx.restore();
    }
}

function gameLoop() {
    if (gameState === 'PLAYING') {
        update();
        draw();
        requestAnimationFrame(gameLoop);
    } else if (gameState === 'GAMEOVER') {
        draw(); // Keep last frame
    }
}

</script>
</body>
</html>
 
Ich verschwende meine Zeit lieber in Battlefield 6, CS2 und Anno 117. Ab morgen dann mal wieder in Total War: Warhammer 3. Gibt doch schon genug Müll da draußen und meine Steam-Liste an Spielen, die ich nicht spiele, ist exorbitant.
Wir haben Destiny 2 bis zur Hexenerweiterung, sorry Lightfall, gespielt, aber danach war die Luft raus.
 
Reboot bei einem Spiel welches noch nie fertig erschienen ist? Okay :schief: Na ob das noch was wird? Hoffnung :hmm: Die HALO Zeiten von Bungie sind eindeutig vorbei.
 
Die einzige Hoffnung hier ist die Hoffnung der Entwickler, dass sich jemand für das Spiel interessiert.

Ansonsten ist der Live Service PvP Shooter Markt völlig übersättigt, wie man schön an den Reaktionen auf die Highguard Präsentation sehen konnte. Alle hoffen auf HL3... okay, kein HL3, aber vielleicht ein neues Titanfall... und dann wird der drölfzigste Schema-F Overwatch Klon (der sogar den Namen dreist kopiert) präsentiert. Kein Wunder, das das allen zum Hals raushängt...

Und die Zielgruppe braucht auch keinen neuen Hoffnungsträger. Die haben soviel Auswahl, dass sie gelassen warten und sich das Spiel anschauen können, bevor sie einsteigen oder halt was Anderes spielen. Da hilft kein Marketing Hype, sondern nur ein gutes Produkt. Wenn man da abliefert, klappts auch mit den Spielerzahlen, wie Arc Raiders gerade mal wieder schön demonstriert.

Es gibt keinen Hype für Marathon. Die Hälfte interessiert sich nicht für so ein Spiel und die andere Hälfte zuckt lässig mit den Schultern und sagt "Schaun mer mal...". Entweder Bungie liefert einen Kracher, oder sie gehen krachen...
 
Einzig das es auch auf die Konsole kommt klingt nicht so gut..
Bei einem Dev der tief verwurzelt ist mit den Konsolen und dazu nun zu einem primären Konsolen Hersteller gehört, ist das allerdings auch absolut nicht verwunderlich ;)

Sehe da allerdings auch kein Problem, sofern man fähig ist - für die die es stört (ich gehöre nicht dazu) - ein Crossplay Button einzubauen.
 
Noch mehr Spiele die den Trends hinterherlaufen, die kaum ein Mensch braucht.
Wenn ich Sony wäre würde ich mich richtig ärgern.
 
Der Titel des Artikels ist, glaube ich, ein wenig irreführend. Das ist ein Reboot, war es schon immer und wird es auch immer sein. Dieses Reboot wird jetzt nicht nochmal rebootet, dafür wären 4 Monate zusätzlich auch viiiel zu wenig.

Was hier vielleicht gemacht wurde, ist, nochmal durch alles zu schauen, was vielleicht geklaut hätte sein können, ein bisschen die PR-Maschine kalibrieren, vielleicht eine Preis- und damit auch Content-Anpassung und das war's wahrscheinlich.

Ich finde, Bungie sollte sich für MP auf Destiny konzentrieren und hätte hier Marathon als SP heimlich ins Destiny-Universum einführen können (bzw. eigentlich ist es ja anders herum). Hier jetzt zwei MP-Titel zu bespaßen, wobei Bungie den Eindruck macht, dass denen sowieso bald die Puste ausgeht, lässt absolut nichts Gutes erahnen. Bungie kann / konnte SP (und MP) mal sehr gut, aber momentan sieht es eher nach Ende als nach Neuanfang aus.

Na ja, vielleicht klappt's. Wahrscheinlich bleibt hier aber der Charakter mal wieder voll auf der Strecke.
 
Ich freue mich auf Marathon, und ich glaube Bungie ist hier auf dem richtigen Weg.

Die ersten Testversionen die man vor ein paar Monaten in Streams sehen konnte waren eher "langweilig"
Jetzt hat man aber scheinbar ein paar neue features integriert (teilweise von anderen Spielen wie Arc Raiders) die das ganze interessanter machen.
(Das "Verwesungs" feature zb ist ein neues Element um die Situation in einem Extractionshooter zu beurteilen. Also wie kalkuliere ich die Wahrscheinlichkeit das noch feindliche Spieler hier aktiv sind... etc.)

Davon ab finde ich den Grafikstil erfrischend neu. (arc raiders zb sammelt auch wegen des 80s scifi Stil massiv Beliebtheitspunkte)
Der klassische military look wird mir langweilig.

Wieso redet man eigentlich ein Spiel schlecht bevor es da ist ? Total Irrationales verhalten...
 
Bungie ist schon lange tot ...

Und nach all der bisherigen Kritik um Bungie, dem Spiel selbst und Sony's Einfluss glaube ich nicht, dass man hier von "Shooter-Hoffnung" sprechen kann
 
Zuletzt bearbeitet:
Zurück