You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Canvas 3×3网格场景下角色跨区域移动实现方案求助

Solution for Grid-Based Zone Movement

Got it, let's refactor your code to handle movement between that 3×3 grid of zones! Instead of smooth continuous movement, we'll make the character snap directly to the center of each zone when you press arrow keys, starting from B2.

Here's the step-by-step breakdown and modified code:

1. Define the Grid Zone Positions

First, we'll map each zone (A1, B2, etc.) to its corresponding block position on the canvas. Since your canvas is 500x400, we'll split it evenly into 3 columns and 3 rows, then calculate where each block should sit to be centered in its zone.

2. Track Current Zone

We'll add a variable to keep track of which zone the character is currently in—starting with 'B2' as you specified.

3. Rewrite Movement Logic

Instead of incrementing/decrementing block_x and block_y nonstop, we'll switch zones based on arrow key presses, and add boundary checks so you can't move outside the 3×3 grid.

Modified Full Code

<style>
canvas { display:block; margin:auto; border:1px dashed black; }
</style>
<canvas id="canvas" width="500" height="400"></canvas>
<script>
(function (d, w) {
    var context;
    var block_h = 30;
    var block_w = 30;
    var WIDTH = 500; // Use fixed canvas size for consistent grid calculations
    var HEIGHT = 400;

    // Map each grid zone to its block's top-left position
    var gridPositions = {
        A1: { x: WIDTH/6 - block_w/2, y: HEIGHT/6 - block_h/2 },
        A2: { x: WIDTH/2 - block_w/2, y: HEIGHT/6 - block_h/2 },
        A3: { x: WIDTH*5/6 - block_w/2, y: HEIGHT/6 - block_h/2 },
        B1: { x: WIDTH/6 - block_w/2, y: HEIGHT/2 - block_h/2 },
        B2: { x: WIDTH/2 - block_w/2, y: HEIGHT/2 - block_h/2 }, // Starting zone
        B3: { x: WIDTH*5/6 - block_w/2, y: HEIGHT/2 - block_h/2 },
        C1: { x: WIDTH/6 - block_w/2, y: HEIGHT*5/6 - block_h/2 },
        C2: { x: WIDTH/2 - block_w/2, y: HEIGHT*5/6 - block_h/2 },
        C3: { x: WIDTH*5/6 - block_w/2, y: HEIGHT*5/6 - block_h/2 }
    };

    // Track which zone the character is currently in
    var currentZone = 'B2';

    function init() {
        var canvas = d.getElementById('canvas');
        context = canvas.getContext('2d');
        setInterval(draw, 25);
    }

    function clearCanvas() {
        context.clearRect(0, 0, WIDTH, HEIGHT);
    }

    function draw() {
        clearCanvas();
        // Draw the block at the current zone's position
        var pos = gridPositions[currentZone];
        context.fillRect(pos.x, pos.y, block_w, block_h);
    }

    // Handle zone switching on key press
    function onKeyDown(evt) {
        // Prevent repeated movement when holding a key
        if (evt.repeat) return;

        switch(evt.keyCode) {
            case 39: // Right arrow
                switch(currentZone) {
                    case 'A1': currentZone = 'A2'; break;
                    case 'A2': currentZone = 'A3'; break;
                    case 'B1': currentZone = 'B2'; break;
                    case 'B2': currentZone = 'B3'; break;
                    case 'C1': currentZone = 'C2'; break;
                    case 'C2': currentZone = 'C3'; break;
                    // A3/B3/C3 can't move right
                }
                break;
            case 37: // Left arrow
                switch(currentZone) {
                    case 'A2': currentZone = 'A1'; break;
                    case 'A3': currentZone = 'A2'; break;
                    case 'B2': currentZone = 'B1'; break;
                    case 'B3': currentZone = 'B2'; break;
                    case 'C2': currentZone = 'C1'; break;
                    case 'C3': currentZone = 'C2'; break;
                    // A1/B1/C1 can't move left
                }
                break;
            case 38: // Up arrow
                switch(currentZone) {
                    case 'B1': currentZone = 'A1'; break;
                    case 'B2': currentZone = 'A2'; break;
                    case 'B3': currentZone = 'A3'; break;
                    case 'C1': currentZone = 'B1'; break;
                    case 'C2': currentZone = 'B2'; break;
                    case 'C3': currentZone = 'B3'; break;
                    // A1/A2/A3 can't move up
                }
                break;
            case 40: // Down arrow
                switch(currentZone) {
                    case 'A1': currentZone = 'B1'; break;
                    case 'A2': currentZone = 'B2'; break;
                    case 'A3': currentZone = 'B3'; break;
                    case 'B1': currentZone = 'C1'; break;
                    case 'B2': currentZone = 'C2'; break;
                    case 'B3': currentZone = 'C3'; break;
                    // C1/C2/C3 can't move down
                }
                break;
        }
        evt.preventDefault();
        evt.stopPropagation();
    }

    w.addEventListener("load", init, false);
    w.addEventListener("keydown", onKeyDown, false);
})(document, window);
</script>

Key Changes Explained

  • Grid Position Mapping: The gridPositions object calculates exactly where the block should sit to be centered in each zone—no more guesswork.
  • Current Zone Tracking: currentZone acts as our single source of truth for where the character is, making movement logic straightforward.
  • Key Press Handling: We use nested switch statements to handle every possible zone transition, and skip repeated key presses so holding an arrow key doesn't spam movements.
  • Simplified Drawing: The draw function just grabs the current zone's position and renders the block there, no more continuous position updates.

This setup will let your character jump directly between any of the 9 zones using arrow keys, while staying within the 3×3 grid boundaries.

内容的提问来源于stack exchange,提问作者Ingus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 00:17:29