[SOLVED] How to render sprite in a react project?

HI everyone hope you are doing well, So I am totally new to playcanvas so I am stuck in whole lot things as I am not using the online editor but have installed playcanvas by npm.

So my biggest problem right now is that I am trying to make a 2D game with only code of course but I just have not been able to get the sprites render on screen, here is the code I found and was trying to use

var textureAsset = app.assets.find('512x512 v2.png', 'texture');

    var texture = textureAsset.resource;
    texture.addressU = pc.ADDRESS_CLAMP_TO_EDGE;
    texture.addressV = pc.ADDRESS_CLAMP_TO_EDGE;
    texture.minFilter = pc.FILTER_NEAREST;
    texture.magFilter = pc.FILTER_NEAREST;

    var atlas = new pc.TextureAtlas();
    atlas.frames = {
        "0": {
            rect: new pc.Vec4(0, 0, 512, 512),
            pivot: new pc.Vec2(0.5, 0.5)
        }
    };
    atlas.texture = texture;

    var sprite = new pc.Sprite(app.graphicsDevice, {
        atlas: atlas,
        frameKeys: '0',
        pixelsPerUnit: 100,
        renderMode: pc.SPRITE_RENDERMODE_SIMPLE
    });

    var spriteAsset = new pc.Asset('sprite', 'sprite', { url: '' });
    spriteAsset.resource = sprite;
    spriteAsset.loaded = true;
    app.assets.add(spriteAsset);

    var entity = new pc.Entity();
    entity.addComponent('sprite', {
        type: pc.SPRITETYPE_SIMPLE,
        spriteAsset: spriteAsset,
    });

    entity.addChild(entity);

what i think is that the image is stored in the asset registry but does that work for a react project?? I would really like some help here Thank you.

Does the code/project work outside a react environment?

Do you get an errors/logs from the devtools browser?

I have tried using the code in the online editor it works perfectly there sprites shows up but not in the react project. checking the console texture.resource was null but in the online editor resource has a texture object.

Do you get any errors/message in the console log in devtools?

it gives cannot set property of undefined addressU, probably because resource is null so it cant read it.

In the react project, are you adding the texture file to the asset registry? And have you waited for it to load before trying to use it as a sprite?

yeah i tried making a new asset of type texture first and adding that to registry and then doing app.assets.find() but still no luck

Can you share that code please?

let asset = new pc.Asset("sprite", "texture", {
      url: url,
    });

    app.assets.add(asset);

here i create an asset and add it to registry then i try to find it like in above code

The issue here is that the asset has been given the name “sprite”. This is why you can’t find it later by ‘find’ as you are searching for “512x512 v2.png”.

I suggest using ‘loadFromUrlAndFilename’ instead

https://developer.playcanvas.com/en/api/pc.AssetRegistry.html#loadFromUrlAndFilename

let asset = app.asset.loadFromUrlAndFilename(url, "512x512 v2.png", "texture", function (err, asset) {
    // Do stuff when asset is loaded
});
 let asset = app.assets.loadFromUrlAndFilename(
      bg_img,
      "post.png",
      "texture",
      function (err, asset) {
        console.log(asset);
        var texture = asset.resource;
        texture.addressU = pc.ADDRESS_CLAMP_TO_EDGE;
        texture.addressV = pc.ADDRESS_CLAMP_TO_EDGE;
        texture.minFilter = pc.FILTER_NEAREST;
        texture.magFilter = pc.FILTER_NEAREST;

        var atlas = new pc.TextureAtlas();
        atlas.frames = {
          0: {
            rect: new pc.Vec4(0, 0, 512, 512),
            pivot: new pc.Vec2(0.5, 0.5),
          },
        };
        atlas.texture = texture;

        var sprite = new pc.Sprite(app.graphicsDevice, {
          atlas: atlas,
          frameKeys: "0",
          pixelsPerUnit: 100,
          renderMode: pc.SPRITE_RENDERMODE_SIMPLE,
        });

        var spriteAsset = new pc.Asset("sprite", "sprite", { url: "" });
        spriteAsset.resource = sprite;
        spriteAsset.loaded = true;
        app.assets.add(spriteAsset);

        var entity = new pc.Entity();
        entity.addComponent("sprite", {
          type: pc.SPRITETYPE_SIMPLE,
          spriteAsset: spriteAsset,
        });

        entity.addChild(entity);
        console.log(entity);
      }
    );

i did this the now resource has a texture but it is giving me RangeError: Maximum call stack size exceeded and nothing shows up in the browser, am i doing something wrong again??

That would generally be due to an infinite loop/callback/recursive function call somewhere. I can’t see anything in the code you have posted that would would cause the issue

I ran the code into the PlayCanvas Editor and it looks like you are parenting an entity to itself, hence the error. Console logs should have showed:

        entity.addChild(entity);

Corrected code and test project here: https://playcanvas.com/editor/scene/1235400

Code: https://playcanvas.com/editor/code/833040?tabs=55764518

I’ve just changed it so it gets added to the engines root node:

        app.root.addChild(entity);

Thanks for your reply’s man, I really appreciate the help.

So i used your code and nothing shows up and it gives this error, here’s the image

And here is the complete code

import React, { useRef, useLayoutEffect } from "react";
import * as pc from "playcanvas";

const Playcanvas = () => {
  const canvasRef = useRef(null);
  const appRef = useRef(null);

  useLayoutEffect(() => {
    const app = new pc.Application(canvasRef.current, {});
    app.start();

    app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);
    app.setCanvasResolution(pc.RESOLUTION_AUTO);

    window.addEventListener("resize", function () {
      app.resizeCanvas();
    });

    const camera = new pc.Entity("camera");
    camera.addComponent("camera", {
      clearColor: new pc.Color(0.1, 0.1, 0.1),
    });

    const light = new pc.Entity("light");
    light.addComponent("light");

    //var app = this.app;
    var asset = app.assets.loadFromUrlAndFilename(
      "https://yaustar.github.io//textures/512x512.jpeg",
      "post.png",
      "texture",
      function (err, asset) {
        console.log(asset);
        var texture = asset.resource;
        texture.addressU = pc.ADDRESS_CLAMP_TO_EDGE;
        texture.addressV = pc.ADDRESS_CLAMP_TO_EDGE;
        texture.minFilter = pc.FILTER_NEAREST;
        texture.magFilter = pc.FILTER_NEAREST;

        var atlas = new pc.TextureAtlas();
        atlas.frames = {
          0: {
            rect: new pc.Vec4(0, 0, 512, 512),
            pivot: new pc.Vec2(0.5, 0.5),
          },
        };
        atlas.texture = texture;

        var sprite = new pc.Sprite(app.graphicsDevice, {
          atlas: atlas,
          frameKeys: "0",
          pixelsPerUnit: 100,
          renderMode: pc.SPRITE_RENDERMODE_SIMPLE,
        });

        var spriteAsset = new pc.Asset("sprite", "sprite", { url: "" });
        spriteAsset.resource = sprite;
        spriteAsset.loaded = true;
        app.assets.add(spriteAsset);

        var entity = new pc.Entity();
        entity.addComponent("sprite", {
          type: pc.SPRITETYPE_SIMPLE,
          spriteAsset: spriteAsset,
        });

        app.root.addChild(entity);
        console.log(entity);
      }
    );

app.on("update", (dt) => {
      camera.setPosition(0, 0, 10);
)};
 appRef.current = app;
  }, []);

  return (
    <>
      <div>
        <canvas ref={canvasRef} />
      </div>
    </>
  );
};

export default Playcanvas;

At this point I think the code we write in playcanvas does not work exactly in a react project, but when I create a box or a plane entity they show up, am I missing some steps or do there need be some additional configurations for react??

And if I use an image from my folder it gives the same “undefined addressU” error.

We’ve had developers use React with PlayCanvas before and I think our engine examples browser uses React too.

In which case, the path/URL is likely to be wrong.

Great it works now. I imported the image and gave it a name which then I passed into loadfilefromurlandfilename(). Thank you very much.

One more thing, my browser window has these vertical/horizontal scrolls, I think this part is the cause

 app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);
    app.setCanvasResolution(pc.RESOLUTION_AUTO);

    window.addEventListener("resize", function () {
      app.resizeCanvas();
    });

but I don’t know how to get rid of them.

Hi @Umair_Asim,

You need to add some CSS to your parent container element and likely to the canva element used by PlayCanvas. You can check an editor project on what CSS it injects:

Is the canvas not fullscreen? If not, you will need to use FIXED fillmode and set the resolution to be the size of the canvas.

Edit: This is due to change at some point: https://blog.playcanvas.com/transitioning-to-the-new-render-component-and-fill-mode-api/

Actually, looking at the changes I’ve made so far, as long as your canvas is sized correctly by the CSS, you should be able to do the following instead

    app.setCanvasResolution(pc.RESOLUTION_AUTO);
    app.updateCanvasSize()
    window.addEventListener("resize", function () {
      app.updateCanvasSize();
    });

All right I applied some css to the parent of canvas and the scolls are gone. Thank you really appreciate the help, great job you guys are doing with this engine.

1 Like