1
\$\begingroup\$

I need to draw lines and curves on a canvas that is not rendered on the screen but just updates the array of pixels that would otherwise be rendered. I need this to separate my game engine from my renderer.

This has proven rather difficult for my case because I don't use sprites that are loaded, but I draw lines and curves on a canvas.

I have used the p5.js library to accomplish my game, but p5 doesn't let you work without a "setup()" and "draw()" function. I don't want any draw loop or something because that beats the purpose of separating my game engine from my rendering.

I want to use p5 to render after I have all my game logic separate and I can just call nextFrame() or something from my game logic inside draw() in a constant 60 fps.

In p5 it is possible to createGraphics() which works outside of the canvas and doesn't have to render but again, p5 needs a draw() loop to work.

Does anyone know how I can accomplish this?

\$\endgroup\$
  • \$\begingroup\$ Usually we call the process of assigning colours to an array of pixels "rendering". The final step of putting that data on the screen so it's visible to the player is called "presenting," but it's typically not where the bulk of the rendering workload happens. Populating that array of pixels is the hard part. So if you're managing the pixel-populating in your game engine code, you haven't really decoupled your game engine from the renderer — at best you've decoupled the presentation step alone. \$\endgroup\$ – DMGregory Apr 8 '19 at 14:00
  • \$\begingroup\$ Very interesting, I did not know this. So, even if I manage this, it would mean the game would not play much faster than when you "present" it to the screen? That is very important because I need this to train an agent to play the game. I need to be able to play many games every minute, and if rendering (populating the pixels array) is most of the workload, and not presenting it to the screen, then it won't be possible to play many games every minute for training \$\endgroup\$ – Milky Apr 8 '19 at 14:13
  • \$\begingroup\$ Try asking about your root problem "how do I make my game run without graphics, as fast as possible, for training AI agents?" Otherwise we get an XY Problem. \$\endgroup\$ – DMGregory Apr 8 '19 at 14:16
  • \$\begingroup\$ Perhaps so, yeah. I first asked about my root problem in stack overflow but it immediately got blocked because it was too broad and asking "too many questions at once". It just seemed that way because I was explaining what I need to be able to do. After giving it some thought, I narrowed down my problem to this. I was under the impression that if I can manage my game logic in pure JS, I can let it train fast. And for this, I needed to solve this canvas problem, hence my question here. \$\endgroup\$ – Milky Apr 8 '19 at 14:38
  • \$\begingroup\$ If your game logic needs pixel values, then you might have a more fundamental problem to solve. Try posting a question describing what information about the pixel array your AI/game logic needs to make its decisions, and we might be able to lead you to ways to abstract that away from a graphical requirement. \$\endgroup\$ – DMGregory Apr 8 '19 at 14:52
1
\$\begingroup\$

This is something which can actually be accomplished very easily with the regular canvas API without any additional libraries.

  1. Create a new canvas with var backgroundCanvas = document.createElement('canvas') but don't add it to the DOM tree. You now have an in-memory canvas which doesn't apper on the screen.
  2. Obtain the drawing context from it with var context = backgroundCanvas.getContext('2d'). The drawing context contains all the methods you need to draw on that canvas.
  3. Begin a path with the context method beginPath
  4. Add lines and curves to the current path with the context methods moveTo, lineTo, arc, arcTo, bezierCurveTo or quadraticCurveTo
  5. Draw the path as a line with stroke or as a filled shape with fill.
  6. To show the user what you have drawn, insert the canvas into the DOM tree or copy the content to a canvas which is already visible using context.drawImage on the destiantion canvas with the source canvas as the source image (not the context of the background canvas. Use the canvas object itself).
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.