Saturday, June 27, 2026

🖥 Geometric Mandalas

As a coding exercise, I wanted to make use of DRAW statements to get plot points for regular polygons repeated around an axis to create geometric mandalas.





🪲 Fix in The Works: DRAW statement: Circle Creation: The problem of Asymmetric Pixels

I want to write about a little problem I think I've fixed (in the development version of BASIC Anywhere Machine), and I hope to soon release this fix in a new version of BASIC Anywhere Machine:

🪲 Asymetric pixels in the quadrants or a circle generated with the DRAW statement.

By quadrants, I mean each pie shape created by dividing the top-bottom, and left-right parts of the circle:

By the way, later, keep in mind that from the center coordinate of the circle:

  • travelling directly right, that is at an angle of 0 degrees
  • travelling directly up, that is at an angle of 90 degrees
  • travelling directly left, that is at an angle of 180 degrees
  • travelling directly down, that is at an angle of 270 degrees

Here's a little program using DRAW to create a circle on a small-resolution screen:

d% = 20

SCREEN _NEWIMAGE( d% * 2 + 1, d% * 2 + 1, 17)

FOR A% = 0 TO 359 STEP 1
    COLOR 63
    draw "BM " + d% + "," + d%
    DRAW "TA " + A%
    DRAW "BU" + (d% - 1)
    pset (point(0), point(1)), 61
NEXT A%

The Result:


In each highlighted part of the circle, we find cases where the pixels in the mirror image across the vertical axis, and/or the mirror image across the horizontal axis, do not match.

In the scheme of things, this wouldn't matter in regards to the job of creating circles.  The asymmetry is noticeable at low resolutions, but becomes indistinguishable by the naked eye at high resolutions.

However, this does cause some noticeable problems, even at high resolutions, when using this process to create polygons which ought to have  one or more perfectly horizontal and/or perfectly vertical sides, like this triangle, for example:

d% = 20
SCREEN _NEWIMAGE( d% * 2, d% * 2, 17)
FOR A% = 0 TO 360 STEP 120
    COLOR 63
    draw "BM " + d% + "," + d%
    DRAW "TA " + A%
    DRAW "BU" + (d% - 1)
    NEWX% = POINT(0) : NEWY% = POINT(1)
    IF A% > 0 THEN COLOR 7 : _
                   LINE (NEWX%, NEWY%) TO (LASTX%, LASTY%)
    LASTX% = NEWX% : LASTY% = NEWY%
NEXT A%

The result:


I suspect (without, for lack of interest, researching this thoroughly) that I'm dealing with what might be either a floating point issue, and/or the following, and/or some other related issue(s):

From Google AI's answer to "Using javascript, why would the process of creating a circle of a certain radius not result in symmetric pixels between the quadrants ?":

When you write JavaScript to create a raster (pixel-based) circle, quadrants often lack symmetry because of integer rounding and the discrete nature of pixel grids. Circles rely on continuous math, but monitors have a fixed resolution, creating several common issues: [1, 2, 3]
    • Off-Center Origins: If your radius is an even number (e.g., \(r = 10\)), there is no single middle pixel, forcing the circle to round up or down on the grid. This shifts the center, making left/right or up/down sizes unequal. [1]
    • Coordinate Truncation: Converting float coordinates to whole pixels (using Math.round(), Math.floor(), or Math.ceil()) can bias where lines fall on the grid, stretching or shrinking one quadrant over another. [1]
    • Aspect Ratio: If the canvas CSS scales the element unevenly (e.g., non-square pixels or mismatched width and height settings), what should be a symmetrical equation acts like an oval, shifting pixel densities per quadrant. [1]
    • Algorithm Bias: Algorithms like the Midpoint Circle or Bresenham’s often use directional bias (preferring to step horizontally, vertically, or diagonally) to optimize speed. This "step" decision breaks quadrant reflection. [1]

What I've decided to do (I wanted to solve this on my own without looking for already existing solutions):

Modify BAM's implementation of DRAW such that whatever angle is used to draw (using the TA command to set the angle and/or whatever angles needed to perform commands like U,D,R,L = Up,Down,Right,Left) convert that angle to the equivalent between 0 and 90 degree, figure out the X and Y coordinates for the destination pixel, and then negate the value of X and/or Y (if applicable) to get the symmetric point for the originally intended angle.

For your interest, here's the relevant javascript code to figure out the destination pixel:

  function AngleStep(a) {
       var xstep = 0;
       var ystep = 0;
       var tota = (+draw_angle + +a) % 360;
       var af = tota;
       if (tota > 90 && tota < 180) {af = 180 - tota;}
       else if (tota > 180 && tota < 270) {af = tota - 180;}
       else if (tota > 270) {af = 360 - tota;}
       af = af * Math.PI / 180;
       if (tota % 180 === 0) { xstep = n; }
       else if (tota % 90 === 0)  { ystep = n; }
       else {xstep = n * Math.cos(af); ystep = n * Math.sin(af);}
       xstep=Math.round(xstep); ystep=Math.round(ystep);
       if ((tota % 360 > 90) && (tota % 360 < 270)) { xstep = -xstep;  }
       if ((tota % 360 < 180)) { ystep = -ystep;  }
       Step(xstep,ystep);
     }

  • a is the angle if the pen movement
  • tota is the calculated angle of movement
    • a would be, for example:
      • 0 degrees if the drawing command is Right
      • 90 degrees if the drawing command is Up
      • 180 degrees if the drawing command is Left
      • 270 degrees if the drawing command is Down
    • draw_angle would be an angular offset applied with a TA command; for example, an offset of 5 degrees would result in:
      • 5 degrees if the drawing command is Right
      • 95 degrees if the drawing command is Up
      • 185 degrees if the drawing command is Left
      • 275 degrees if the drawing command is Down
  • af is the tota angle transposed to the first quadrant (between 0 and 90 degrees)
  • n is the distance (the number of pixels) travelled from the current pen position to the destination pen position
  • xstep and ystep are the relative destination coordinates of the pen based on wherever the pen is currently located when the DRAW statement is performed)
Let's say that the "tota" angle is 125 degrees, then the "af" angle will be 55 degrees.  When the function figures out the values of xstep and ystep at 55 degrees: ystep does not change (the value of ystep is the same at 55 degrees and 125 degrees), however xstep is switched to the negative value (for example: if xstep is 100 pixels to the right of the starting pen position when the angle is 55 degrees, then xstep is -100 to the left of the starting pen position when the angle is 125 degrees.)

With this modified implementation of DRAW, the same BASIC programs now result in this circle and this triangle:





WOOHOO !

If you want to try the BASIC programs above, before the next release of BAM:



Sunday, June 21, 2026

📚 How I go about testing a little fix to a DRAW statement bug

EDIT: After this video, I did some more "proof in the pudding" testing of my supposed fix, and discovered that although the fix worked for a triangle of that size, the fix broke the triangle at a size that was working before. 



Monday, June 15, 2026

🖥 Circular Meander

About Meanders: read this Wikipedia article

This program is based on the image shared by bplus in this post (QB64 Phoenix Edition forum).

NOTE: Somebody is insisting (or "some may insist") that the graphic generated by my program is NOT a meander.  To me, although the program's process does not draw the pattern in one continuous line, the result is "a decorative border that is a continuous line, shaped into a repeated motif."

This animated program repeatedly draws the same style of meander in an infinite loop, with plot points that are relative to each other, but together varying depending on random screen resolution on every iteration, and random colors.

This is an unstructured program, coded very organically/incrementally without any planning, and without any desire to minimize the amount of code.

Although I originally created the program to generate the graph in one step, I've setup the animation to draw the graph in four steps.  This gives a visual idea of how circles are used, and plot points used at specific angles on points of each of the eight circles.

The program has short pauses throughout.  At any time, you can click/touch the screen to pause the animation.



Thursday, June 11, 2026

🖥 Golden Ball 1 Crop Circle

Over in the QB64 Phoenix Edition community, bplus (one of their prolific programmers) suggested (in this post) a little programming challenge to recreate the pretty awesome "Golden Ball Hill" crop circles:



In this program, I tackled the formation that interested me the most, but stopped short of the partial doughnut holes in the "half moon" shapes in the formation.  For me, the gist of this as a "brain age" kind of exercise involved just getting the fundamental process figured out, and graphing the thing via a simple animation in an infinite loop with random colors:






Monday, June 8, 2026

🖥 Café Wall Illusion

This program is based on the graphic output of a BBC-BASIC-for-SDL program created by Kurt Moerman and shared with the "BASIC Programming Language" Facebook Group.  (Although Kurt's post cannot be shared, his code is available on Github here.)

This BAM program:


Wednesday, May 20, 2026

🎉 New version of Blitkrieg Stratagem Chooser

Barely a moment after sharing the program, I decided to immediately tackle a few personal annoyances:

  • I decided to let my coding style freak flag fly  That involved:
    • slight reorganization of the code to fit my tastes, including moving some bode into GOSUB routines
    • some "strategic" use of emojis here and there to help me quickly spot certain particular things
    • naming conventions for my GOSUB routines (I like to start them with an alphabetic character followed by a three digit number, and an emoji) 
  • I added the ability to, at any time, copy the current A.I. Turn statistics to the clipboard, which you can then paste anywhere of use
    • I figured, if the program is presenting that info, might as well make it possible to "export" that info via the no fuss no muss approach that is making use of the clipboard.
    • I pasted sample output at the bottom of this post
  • Because I needed different actions when clicking/touching the screen:
    • I modified the program to require clicking a defined area of the screen related to getting the stratagem for the A.I. Bot's Next Turn
    • I added another defined area of the screen related to sending game statistics to the clipboard
  • I reconsidered my use of colors in the bottom half of the screen to keep usage of color to a minimum (as in only for those very important things we really want to highlight)
Compare the screenshot of today's new version to the screenshot of the previous version found in the earlier blog post.



Sample stats copied to the clipboard (best formatted with a fixed font after pasting):

Statistics:
    BigGun: 4
    CounterAttack: 4
    EconomicWarfare: 2
    ForTheGlory: 4
    RapidDeployment: 3
    ResearchAndDevelopment: 6
    Secure: 2
    SteamRoll: 6

Turn  Stratagem
----  ---------
   1  CounterAttack
   2  EconomicWarfare
   3  ForTheGlory
   4  BigGun
   5  SteamRoll (BigGun)
   6  ResearchAndDevelopment
   7  ForTheGlory
   8  EconomicWarfare
   9  CounterAttack
  10  Secure
  11  CounterAttack
  12  ResearchAndDevelopment
  13  CounterAttack
  14  ForTheGlory
  15  SteamRoll (ForTheGlory)
  16  RapidDeployment
  17  SteamRoll (RapidDeployment)
  18  Secure
  19  ResearchAndDevelopment
  20  SteamRoll (ResearchAndDevelopment)
  21  BigGun
  22  SteamRoll (BigGun)
  23  ResearchAndDevelopment
  24  SteamRoll (ResearchAndDevelopment)
  25  RapidDeployment


🖥 Geometric Mandalas

As a coding exercise, I wanted to make use of DRAW statements to get plot points for regular polygons repeated around an axis to create geom...