Omnimaga
Calculator Community => HP Calculators => Topic started by: MacBernick on January 15, 2014, 09:18:39 am
-
After a discussion an another thread about filled circles, I made a little program using FILLPOLY_P to simulate a fillled circle. It was really slow because of the use of a FOR loop to make a list of coordinates to feed the FILLPOLY function. One day Han told me it would be more efficient to call MAKELIST for building lists, so I modified it a bit, and this is now REALLY faster :)
You can push the attached program in your calc or the simulator, run "circles" for a quick demo drawing random circles on screen at a nice speed, or use the EXPORTed FILLCIRCLE_P(centerX, centerY, radius, color) function in your program.
You can also copy/past the function in your program if you want to use it but don't want to rely on an external lib.
NB : these are not perfect circles, they are not suitable for mathematics purposes. Also, very small circle may look weird.
Enjoy
-
I have even gone as far as replacing loops with either a makelist or makemat (double loop) even if I'm not generating lists or matrices. Simply create a procedural function that returns garbage data and don't store the resulting list or matrix. Have the procedural function do what you would normally do in a loop.
mainprogram()
begin
makemat(prg(I,J),25,25);
end;
prg(x,y)
begin
// code that loops x from 1 to 25 and y from 1 to 25 goes here
return(0);
end;
I don't remember if the speed difference is still significant ever since the most recent firmware (never retested).
-
If they just throw away the outputs as they go instead of making a list and throwing it away, then that's nice; we just got speedy effectual mapping.
-
Yeah that's clever. FOR loops deprecated ? ^^
-
Very good work :D
-
Actually, couldn't you just do
mainprogram()
begin
makemat(
// code that loops x from 1 to 25 and y from 1 to 25 goes here
return(0);
,25,25);
end;
if the code was short enough?
-
I'm not sure MAKEMAT would support multiple statements. Did you try it ?
I replaced the two FOR loops in render routine in Trailblazer by a MAKEELIST, that's about 3 or 4 FPS earned.
If I got it right, only a Home variable can be used with MAKELIST ?
-
Actually, couldn't you just do
mainprogram()
begin
makemat(
// code that loops x from 1 to 25 and y from 1 to 25 goes here
return(0);
,25,25);
end;
if the code was short enough?
Not really. They only way it could be short enough is if it were a single "command" (i.e. built-in command or procedural function created either in the same source file or made available via export). If your code requires more than a single semicolon, then I am pretty sure it won't work (though I never tried myself) because the arguments of makelist or makemat must be comma-separated.
-
Han: Confirmed; from Home 'MAKEMAT(PRINT(I); PRINT(J); RETURN 0,25,25)' fails syntax checking with the cursor positioned right before the first ";". Also, I've had problems with 'MAKELIST(MAKELIST(X,X,1,10),X,1,10)' passing the syntax check but presently failing with 'Error: Bad argument type'.
-
Necrobump:
Thanks to this routine, we can actually do circle-based fade-in/out animations, like in Zelda, in addition to stuff like dark cavern/dungeon effects! :D
(http://img.ourl.ca/circlefadeout.gif)
The edited code by MacBernick looks like this:
FILLCIRCLE_P(cx, cy, r, color);
EXPORT circles()
BEGIN
DIMGROB_P(G1,320,240);
DIMGROB_P(G2,320,240);
DIMGROB_P(G3,320,240);
BLIT_P(G1,G0);
FOR A FROM 220 DOWNTO 0 DO
RECT_P(G2,#000000);
FILLCIRCLE_P(160, 120, A, #FF00FF);
BLIT_P(G3,G1);
BLIT_P(G3,0,0,320,240,G2,0,0,320,240,#FF00FF);
BLIT_P(G3);
END;
END;
EXPORT FILLCIRCLE_P(cx, cy, r, color)
BEGIN
LOCAL s, cl := {}, angle := HAngle;
HAngle := 1;
LOCAL cl :=
MAKELIST({EVAL(r * COS(S) + cx), EVAL(r * SIN(S) + cy)},
S, 0, 359, 10);
HAngle := angle;
FILLPOLY_P(G2,cl, #FF00FF,255);
END;
You need multiple GROBs or at least a GROB large enough for each frame, because it involves transparency.
-
Necrobump:
Thanks to this routine, we can actually do circle-based fade-in/out animations, like in Zelda, in addition to stuff like dark cavern/dungeon effects! :D
(http://img.ourl.ca/circlefadeout.gif)
The edited code by MacBernick looks like this:
FILLCIRCLE_P(cx, cy, r, color);
EXPORT circles()
BEGIN
DIMGROB_P(G1,320,240);
DIMGROB_P(G2,320,240);
DIMGROB_P(G3,320,240);
BLIT_P(G1,G0);
FOR A FROM 220 DOWNTO 0 DO
RECT_P(G2,#000000);
FILLCIRCLE_P(160, 120, A, #FF00FF);
BLIT_P(G3,G1);
BLIT_P(G3,0,0,320,240,G2,0,0,320,240,#FF00FF);
BLIT_P(G3);
END;
END;
EXPORT FILLCIRCLE_P(cx, cy, r, color)
BEGIN
LOCAL s, cl := {}, angle := HAngle;
HAngle := 1;
LOCAL cl :=
MAKELIST({EVAL(r * COS(S) + cx), EVAL(r * SIN(S) + cy)},
S, 0, 359, 10);
HAngle := angle;
FILLPOLY_P(G2,cl, #FF00FF,255);
END;
You need multiple GROBs or at least a GROB large enough for each frame, because it involves transparency.
Why the EVALs? Also, angle should be a pragma.
-
Not sure what the evals do and about the Angle, nor why it prompts me for which program to run at startup. I just took MacBernick code at http://www.omnimaga.org/hp-prime/fast-filled-circles-routine/?action=post;quote=373410;last_msg=386862 and replaced both colors and the FILLCIRCLE arguments so that the circle is always centered. Then I added DIMGROB/BLIT commands for the effect.
-
Every time I see cool stuff for the prime, it makes me wish my parents let me buy one...
Nice job!
-
By the way, the S, 0, 359, 10 part can be changed to stuff like S, 0, 359, 20 for faster, but lower quality circle. Don't set the last number too high, else it looks weird. Lower results in higher quality, but slower circles and possible glitches when the circle becomes smaller.
-
Now I wish I got a HP Prime instead of a V200
:P
It looks like it would be useful for games with circles.
-
Yeah that's great. I'm not exactly sure how much we'll be blown by native code on this platform.
-
Hello,
[quoteJBy the way, the S, 0, 359, 10 part can be changed to stuff like S, 0, 359, 20 for faster, but lower quality circle. Don't set the last number too high, else it looks weird.
the 20 should be based on the radius... the larger the radius, the more segments you need to draw...
Also, in the case of your circle fade out, instead of using multiple graphics and blits, you could try creating one single polygon of the type:
0,0, 319,0, 319, 239 160, 239, 190, bottom of circle, circle.... 190, bottom of circle, 160, 239 0, 239
This would allow you do to the animation without any extra graphics...
If this does not work well (unpainted pixels), try spliting it in 2 halfs. the right and left half of the screen... might work better..
The reason why in your program it asks you which function to run is because you have multiple EXPORTED functions in your program (FILLPOLY in this case)... remove the EXPORT in front of FILLPOLY and it will not ask you again.
Cyrille
-
Ok thanks for the info :)
EDIT: Ok I removed the EVAL commands now and yes they weren't needed after all.