Canvas.paint has an auto-refresh built in?

ok! thinking a lot here.

first things first:

Avoid overlapping controls at all cost.

why not? (if someone could explain technically why not, i’ll be very happy)
canvas has this ability to be transparent… guess that’s the reason, right? to put one over another?

so, my idea of have 2 (or more) layers, is to avoid redrawing things like “walls” all the time. to do that, i need to put the walls on a canvas, and other stuff on other canvas.

but when i refresh one canvas, the other also refreshes.

then, i create a “static” picture of my wall, and it still refreshes all the time…
(ok… it’ll refresh “only” a picture, not the all drawing process to create the walls. it’s more efficient, of course)

but i’m thinking… isn’t clever to simply do not refresh what i don’t want to refresh?

No. I think that’s where you’re still missing what we’re saying. You do not need more than one canvas. You need more than one Picture. You draw to the Picture somewhere outside the canvas paint event, so you only have to draw it once. Thereafter, in canvas Paint, you draw the Picture, which already contains the walls, etc, so they don’t have to be calculated again. This is a very fast command. Pictures can have transparancy, too, which allows you to layer them.

Window Open: create and calculate/draw the picture (eg., with paintWalls)

Canvas Paint: draw the precalculated Picture with g.drawpicture. Do not call c_game.??? in Paint.

3 Likes

It sounds to me like you are concerned about frequent redraws. They are necessary to keep your game look smooth and responsive. Most commercial games go for a minimum of 60 FPS.

In the paint event, you should simply compose your final image. Consider the paint event like an old TV screen refresh. The area is blank for the next image to show, so you have to tell the system what should be shown.

Everything that is static should be rendered only once (or whenever necessary, like on a resize), because that is usually the bottleneck. It is ideal to use a picture to store these renderings, like background/walls, so that in the paint event you can use Graphics.DrawPicture which is pretty fast (and supports alpha so no need for additional compositing where the background should shine through).

Stacking of controls might cause unwanted redraws, because when a sub-canvas is refreshed it would have to look up the colors behind it for transparent controls. You can possibly get along with that method on macOS and Linux but not on Windows where transparent does not mean transparent. The current Xojo Windows drawing engine uses pseudo-transparency, which means it looks up the color behind it – which in the case of a background image will very probably cause drawing artefacts. In cannot look up the exact background color for each pixel behind it.
Plus a foreground canvas refresh might invalidate its area on the background, so that you can find yourself in nested redraws that slow your game down instead.

There will still be the window compositing engine having to stitch together all overlapping canvases, which – even if transparency works – is a time-consuming task. On the opposite painting ready-to-use images on their intended place is quite fast as the compositing engine has no additional work to do other than display the result of your paint event handler.

1 Like

Many console games are locked at 30fps due to hard to render scenes. Old arcade games could run at a fraction of it like 15fps. I’ve made animations and simple games in the past and our lowest spec was 12fps to serve old hardware. Don’t confuse the “monitor” (or CRT) refresh rate (60, 29.97, 25 …) with the render fps of the game engine. Any indie simple game will be very well served rendering at 30fps today.

1 Like

That is a good solution but it is much better (and faster) to use a ‘draw’ method for each object.
Then call that draw methode in the canvas paint event. It will not wait for each object to draw before going to the next object. It just start the method that does the calculations and draws as it goes. Basically several objects are being calculated and drawn at its own pace.

Way faster and you can get 60fps for even doing a lot of objects.

See http://macosbytes.com/asteroids.zip

In the early 90ties I made several vector based clones of Asteroids, Qix and Tempest for the Commodore Amiga (written in partly C and 68000 assembly).
They were very popular at that time and hidden games in several The Silents demos. :slight_smile:
For the small Xojo Asteroids game I easily could convert the algorithm code for ship and rocks. Could do this too for Qix and Tempest. :slight_smile:

So I am thinking of converting Qix and Tempest too. Especially Tempest was a spot on clone of the arcade version. :slight_smile:

2 Likes

That’s old school. :slight_smile: Nowadays 60fps is the minimum. And many aiming at 120fps (PS5 Pro and Xbox do this for most modern games).

2 Likes

I think you both are right. Where reality-like graphics are intended, the higher the frame rate, the better. Low-level consoles often lock the frame rate at 30 FPS and sometimes struggle even with that limit.
A retro-like Indie game can often absolutely live with lower frame rates as the imperfect animations can add to the retro charm.

I think we all can agree that it’s most advisable to aim for a steady frame rate rather than to go for a maximum that often cannot be reached for quite some portion of the time.

3 Likes

yes, understood!

this is much more efficient than create the walls. of course.
(i already did this change)

but on canvas Paint, if i do a refresh, it’ll draw the picture (already precalculated), over and over again, right?

For current powerful consoles people may WANT it and could get it if the game studio ported the game for a 60fps+ version, but there are lots out there as is. Here are some:

https://www.reddit.com/r/playstation/comments/1gmpar4/list_of_ps4_games_that_are_still_stuck_at_30_fps/

and there is no point to make a game with more than 30fps (or 60fps), if the hardware (monitor) does not refreshes more than 30fps (or 60fps)!

It will show it whenever the canvas is painted.
If it has no overlapping controls, that happens if you call .refresh
If you call refresh twice, it will paint twice, for no good reason.

Instead, call .invalidate after you have drawn everything.
If you keep calling .invalidate, the canvas will only refresh once per ‘batch’
For example, if you draw everything and call invalidate 3 times before the canvas can paint, it will paint once and discard the other invalidates
Only call invalidate if something changed.
In that way, the canvas will redraw only when there is something new to display.

But you don’t control the hardware though. My monitor goes up to 360 FPS, for example.

1 Like

I am on repeat here, I guess .. check the example I gave.
Use a timer to refresh the canvas (preferably at 13ms = 60fps). Do not refresh elsewhere.
Using this methode you will get steady frame rates. No erratic frames jumping.

PS: I think Alexandre muted me .. I gave him the complete solution several times but he keeps asking the same/wrong questions. :thinking:
What exactly game is he trying to make? I gladly make a shot at it. :face_without_mouth:

1 Like

Your Xojo Pacman experience in a 30Hz monitor and a 360Hz one will be the same.

1 Like

That is what I have done (even if games are not my tea cup): nice (even if I do not understand how to play it :wink: ).

Stuborn ? Locked in the 1990s / 2000s ?
(No offense sent).
I got no react for the two books I adviced… (“How I Wish to know… Threads and Timers” is free !)

Right, but that doesn’t have anything to do with what I was responding to. If the game is designed for 30, fine. But to say there’s no reason to design for more than 60 is flawed.

Now, getting a Xojo app to actually display that fast is a completely different story.

That’s some sort of Pacman game. Looks like a simple thing to make.
What’s the goal of the game? Player is the mice (pacman) and cat (ghost) hunts the mice?
Player needs to eat as many dots?

1 Like

Yes. Unless you do not want it to show …
You might be thinking “Gee, it’s a big picture, so it will take a lot of time to draw it” – it won’t. The CPU-consuming task is drawing the walls themselves into the background picture, although that graphics look so simple I bet you could do without a buffer.

Drawing a picture in a paint event will be done with GPU acceleration, so even if it will be resized that happens really fast, much faster than you could with pure Xojo code that would copy pixels from a picture into anther one. Please stop worrying about drawing the picture each time. You must, because the paint event is meant to compose the next frame of the “video” your game will consist of.

Just look for a constant frame rate as @ChristopheDV mentioned and don’t worry about drawing pictures. If things would really be time consuming, you would notice when your game begins to stutter. This would be with a refresh rate of 60 FPS when your complete paint event takes more than 16 ms, and even your first profiles were safely below that.

2 Likes