Белый экран при использовании `CanvasRenderingContext2D.putImageData ()`, даже если данные содержат изображение - PullRequest
0 голосов
/ 08 апреля 2020

Я пытаюсь разместить эмулятор NES ( JSNES ) на сервере Node. Я знаю, что вы можете встроить JSNES в веб-страницу с помощью команды unpkg, но я хочу, чтобы она работала на сервере, потому что я хочу, чтобы несколько клиентов имели одно и то же состояние. Я написал скопировал код для запуска эмулятора на сервере (который работал) и отправки буферов кадров клиенту в ответ на запросы GET (что также работало) и, наконец, для отображения этого буфера кадров на холсте , Я могу console.log данные изображения, и они выглядят правильно (под «выглядит правильно» я имею в виду, что они содержат в основном черные пиксели с несколькими элементами в середине изображения), но все, что я получаю, это белый экран. Кто-нибудь может определить, что я делаю неправильно?

index. html:

<!DOCTYPE html>

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Example</title>

    </head>
    <body>
        <div style="">
            <canvas id="canvas" width="256" height="240" style="border: 1px solid black;"/>
        </div>
        <script type="text/javascript" src="game.js"></script>
    </body>
</html>

game. js

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var image = context.getImageData(0, 0, 256, 240);

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        var response = JSON.parse(this.responseText);
        console.log(response);
        console.log(Object.keys(response).length);
        image.data.set(response);
        context.putImageData(image, 0, 0);
    }
};

xhttp.open("GET", "data", true);
xhttp.send();

server. js

const fs = require('fs');
var express = require('express');
var jsnes = require('jsnes');
var path = require('path');

var app = express();

var SCREEN_WIDTH = 256;
var SCREEN_HEIGHT = 240;
var FRAMEBUFFER_SIZE = SCREEN_WIDTH * SCREEN_HEIGHT;
var buffer = new ArrayBuffer(FRAMEBUFFER_SIZE);
var framebuffer_u8 = new Uint8ClampedArray(buffer);
var framebuffer_u32 = new Uint32Array(buffer);

var nes = new jsnes.NES({
    onFrame: function(framebuffer_24) {
        for (var i = 0; i < FRAMEBUFFER_SIZE; i++) framebuffer_u32[i] = 0xFF000000 | framebuffer_24[i];
    },
});

var romData = fs.readFileSync('InterglacticTransmissing.nes', {
    encoding: 'binary'
});

nes.loadROM(romData);

app.get('/', function(request, response) {
    response.sendFile(path.join(__dirname, 'index.html'));
    console.log('/');
});

app.get('/game.js', function(request, response) {
    response.sendFile(path.join(__dirname, 'game.js'));
    console.log('/game');
});

app.get('/data', function(request, response) {
    response.setHeader('Content-Type', 'application/json');
    response.send(JSON.stringify(framebuffer_u8));
    console.log('/data');
});

setInterval(function() {
    nes.frame();
}, 1000 / 60);

app.listen(3000);

Вывод (я удалил много данных, потому что они вызывали проблемы с веб-страницей):

{
  "0": 0,
  "1": 0,
  "2": 0,
  "3": 255,
  "4": 0,
  "5": 0,
  "6": 0,
  "7": 255,
  "8": 0,
  "9": 0,
  "10": 0,
  "11": 255,
  "12": 0,
  "13": 0,
  "14": 0,
  "15": 255,
  "16": 0,
  "17": 0,
  "18": 0,
  "19": 255,
  "20": 0,
  "21": 0,
  "22": 0,
  "23": 255,
  "24": 0,
  "25": 0,
  "26": 0,
  "27": 255,
  "28": 0,
  "29": 0,
  "30": 0,
  "31": 255,
  "32": 0,
  "33": 0,
  "34": 0,
  "35": 255,
  "36": 0,
  "37": 0,
  "38": 0,
  "39": 255,
  "40": 0,
  "41": 0,
  "42": 0,
  "43": 255,
  "44": 0,
  "45": 0,
  "46": 0,
  "47": 255,
  "48": 0,
  "49": 0,
  "50": 0,
  "51": 255,
  "52": 0,
  "53": 0,
  "54": 0,
  "55": 255,
  "56": 0,
  "57": 0,
  "58": 0,
  "59": 255,
  "60": 0,
  "61": 0,
  "62": 0,
  "63": 255,
  "64": 0,
  "65": 0,
  "66": 0,
  "67": 255,
  "68": 0,
  "69": 0,
  "70": 0,
  "71": 255,
  "72": 0,
  "73": 0,
  "74": 0,
  "75": 255,
  "76": 0,
  "77": 0,
  "78": 0,
  "79": 255,
  "80": 0,
  "81": 0,
  "82": 0,
  "83": 255,
  "84": 0,
  "85": 0,
  "86": 0,
  "87": 255,
  "88": 0,
  "89": 0,
  "90": 0,
  "91": 255,
  "92": 0,
  "93": 0,
  "94": 0,
  "95": 255,
  "96": 0,
  "97": 0,
  "98": 0,
  "99": 255,
  "100": 0,
  "101": 0,
  "102": 0,
  "103": 255,
  "104": 0,
  "105": 0,
  "106": 0,
  "107": 255,
  "108": 0,
  "109": 0,
  "110": 0,
  "111": 255,
  "112": 0,
  "113": 0,
  "114": 0,
  "115": 255,
  "116": 0,
  "117": 0,
  "118": 0,
  "119": 255,
  "120": 0,
  "121": 0,
  "122": 0,
  "123": 255,
  "124": 0,
  "125": 0,
  "126": 0,
  "127": 255,
  "128": 0,
  "129": 0,
  "130": 0,
  "131": 255,
  "132": 0,
  "133": 0,
  "134": 0,
  "135": 255,
  "136": 0,
  "137": 0,
  "138": 0,
  "139": 255,
  "140": 0,
  "141": 0,
  "142": 0,
  "143": 255,
  "144": 0,
  "145": 0,
  "146": 0,
  "147": 255,
  "148": 0,
  "149": 0,
  "150": 0,
  "151": 255,
  "152": 0,
  "153": 0,
  "154": 0,
  "155": 255,
  "156": 0,
  "157": 0,
  "158": 0,
  "159": 255,
  "160": 0,
  "161": 0,
  "162": 0,
  "163": 255,
  "164": 0,
  "165": 0,
  "166": 0,
  "167": 255,
  "168": 0,
  "169": 0,
  "170": 0,
  "171": 255,
  "172": 0,
  "173": 0,
  "174": 0,
  "175": 255,
  "176": 0,
  "177": 0,
  "178": 0,
  "179": 255,
  "180": 0,
  "181": 0,
  "182": 0,
  "183": 255,
  "184": 0,
  "185": 0,
  "186": 0,
  "187": 255,
  "188": 0,
  "189": 0,
  "190": 0,
  "191": 255,
  "192": 0,
  "193": 0,
  "194": 0,
  "195": 255,
  "196": 0,
  "197": 0,
  "198": 0,
  "199": 255,
  "200": 0,
  "201": 0,
  "202": 0,
  "203": 255,
  "204": 0,
  "205": 0,
  "206": 0,
  "207": 255,
  "208": 0,
  "209": 0,
  "210": 0,
  "211": 255,
  "212": 0,
  "213": 0,
  "214": 0,
  "215": 255,
  "216": 0,
  "217": 0,
  "218": 0,
  "219": 255,
  "220": 0,
  "221": 0,
  "222": 0,
  "223": 255,
  "224": 0,
  "225": 0,
  "226": 0,
  "227": 255,
...
  "17670": 0,
  "17671": 255,
  "17672": 0,
  "17673": 0,
  "17674": 0,
  "17675": 255,
  "17676": 0,
  "17677": 0,
  "17678": 0,
  "17679": 255,
  "17680": 0,
  "17681": 0,
  "17682": 0,
  "17683": 255,
  "17684": 0,
  "17685": 0,
  "17686": 0,
  "17687": 255,
  "17688": 0,
  "17689": 0,
  "17690": 0,
  "17691": 255,
  "17692": 0,
  "17693": 0,
  "17694": 0,
  "17695": 255,
  "17696": 0,
  "17697": 0,
  "17698": 0,
  "17699": 255,
  "17700": 0,
  "17701": 0,
  "17702": 0,
  "17703": 255,
  "17704": 64,
  "17705": 24,
  "17706": 0,
  "17707": 255,
  "17708": 64,
  "17709": 24,
  "17710": 0,
  "17711": 255,
  "17712": 177,
  "17713": 84,
  "17714": 0,
  "17715": 255,
  "17716": 64,
  "17717": 24,
  "17718": 0,
  "17719": 255,
  "17720": 247,
  "17721": 180,
  "17722": 0,
  "17723": 255,
  "17724": 177,
  "17725": 84,
  "17726": 0,
  "17727": 255,
  "17728": 177,
  "17729": 84,
  "17730": 0,
  "17731": 255,
  "17732": 247,
  "17733": 180,
  "17734": 0,
  "17735": 255,
  "17736": 247,
  "17737": 180,
  "17738": 0,
...
}

1 Ответ

1 голос
/ 09 апреля 2020

Когда вы вызываете JSON.stringify() для экземпляра Uint8ClampedArray на стороне сервера, он будет сериализован как объект JS, хотя можно ожидать, что он будет массивом.

const data = new Uint8ClampedArray(3);
data.set([1,2,3]);

const json = JSON.stringify(data);

JSON

{
  "0":1,
  "1":2,
  "2":3
}

Когда вы десериализуете его с помощью JSON.parse() на стороне клиента, вы получаете объект JS и пытаетесь передать его ImageData.data.set().

ImageData.data равен Uint8ClampedArray и ожидает передачи массива в его метод set(), но при передаче объекта он автоматически игнорирует его.

You может

  1. преобразовать буфер кадров в массив на стороне сервера, используя Array.from , а затем сериализовать его:

    const data = new Uint8ClampedArray(3);
    data.set([1,2,3]);
    
    const dataArray = Array.from(data);
    
    const json = JSON.stringify(dataArray);
    
    // response.send(json);
    

    JSON

    [1,2,3]
    
  2. Или преобразовать десериализованный объект в массив на стороне клиента

    const dataArray = Object.values(response);
    image.data.set(dataArray);
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...