Welcome, Guest
You have to register before you can post on our site.

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 318
» Latest member: coletteleger
» Forum threads: 1,745
» Forum posts: 17,906

Full Statistics

Latest Threads
astuce pour survivre fina...
Forum: Utilities
Last Post: coletteleger
05-14-2025, 04:47 AM
» Replies: 0
» Views: 9
trouver permis de conduir...
Forum: Utilities
Last Post: nicolasrene
05-05-2025, 05:24 AM
» Replies: 0
» Views: 14
LIGHTBAR Menu
Forum: Programs
Last Post: nicolasrene
05-05-2025, 05:08 AM
» Replies: 15
» Views: 945
Learning Pallet Rack Safe...
Forum: Utilities
Last Post: Sandrapew
04-03-2025, 09:36 AM
» Replies: 0
» Views: 39
Choosing New Versus or Pr...
Forum: Utilities
Last Post: Sandrapew
03-18-2025, 01:11 AM
» Replies: 0
» Views: 33
The QB64 IDE shell
Forum: Utilities
Last Post: JasonPag
09-16-2024, 05:37 PM
» Replies: 9
» Views: 1,058
Importance regarding Ches...
Forum: Utilities
Last Post: JasonPag
09-01-2024, 06:34 PM
» Replies: 0
» Views: 71
Chess and Analysis and En...
Forum: Utilities
Last Post: JasonPag
08-28-2024, 02:37 PM
» Replies: 0
» Views: 68
DAY 009:_PutImage
Forum: Keyword of the Day!
Last Post: grymmjack
09-02-2023, 02:57 PM
» Replies: 54
» Views: 3,439
Fall Banner Contest?
Forum: Site Suggestions
Last Post: grymmjack
08-31-2023, 11:50 PM
» Replies: 36
» Views: 2,169

 
  Ported to BAM: David Ahl's "One Check" program ("solitaire checkers")
Posted by: CharlieJV - 08-04-2023, 12:38 AM - Forum: QBJS, BAM, and Other BASICs - Replies (1)

https://www.reddit.com/r/BASICAnywhereMa...k_program/

Print this item

  A Perplexing Issue
Posted by: NakedApe - 08-03-2023, 03:47 PM - Forum: Help Me! - Replies (5)

This sub took me hours to get going because it's behaving so strangely. It's a simple routine to print out some info, but it won't work unless an INPUT statement is used at the end, not an INPUT$() or INKEY$. Even SLEEP causes the sub not to run right. My first choice is for the user just to press a single key and exit the sub, but only the input statement works right - which requires a carriage return. I don't get it. Any help will be much appreciated! See remarks below...

SUB destTable () '

    SHARED destData() AS STRING
    SHARED destCounter AS INTEGER
    SHARED fuel AS SINGLE
    DIM range AS SINGLE
    DIM AS INTEGER counter, entry, entries(20) '
    DIM n AS STRING

    range = fuel / 35.29 '          fuel / rate of burn per light year
    counter = 0

    _FONT messFont: COLOR YELLOW
    n = _TRIM$(MID$(STR$(range), 1, 5))
    _PRINTSTRING (30, 40), "Destinations Within Present Range" + "  (" + n + " Light Years)"

    DO
        counter = counter + 1
        IF range >= VAL(destData(counter, 3)) THEN '    if range is greater than distance to destination...
            entry = entry + 1
            entries(entry) = counter
            _FONT messFont: COLOR ORANGE
            _PRINTSTRING (30, 66 + entry * 25), CHR$(64 + entry) + ") " + destData(counter, 1) '
            _FONT courseFont: COLOR GREEN
            _PRINTSTRING (340, 70 + entry * 25), destData(counter, 2)
            _FONT courseFont: COLOR PINK
            _PRINTSTRING (580, 72 + entry * 25), destData(counter, 3) + " Light Years"
        END IF
    LOOP UNTIL counter = 20

    _FONT messFont: COLOR YELLOW
    _PRINTSTRING (40, 138 + entry * 25), "Your Destination Choice is"
    LOCATE 30, 344
    INPUT n '          <======= !!                           reuse n string
    ' n = INPUT$(1) '                                                ALL THESE REMMED COMMANDS CAUSE THE ABOVE NOT TO DISPLAY TO SCREEN
    ' WHILE INKEY$ = "": n = INKEY$: WEND '           UNTIL *AFTER* USER PRESSES A KEY
    ' DO: n = INKEY$: LOOP UNTIL n <> "" '              only an INPUT statement gets the above table to print ...
    ' SLEEP                                ... otherwise program freezes w/o performing above code until key is hit, then the table appears for a sec
    counter = ASC(n) - 96 '                                        reuse counter
    destCounter = entries(counter) '
    pickDest

END SUB

Print this item

Sad Is there a way to determine screen resolution ?
Posted by: doppler - 08-03-2023, 12:50 PM - Forum: General Discussion - Replies (2)

Wondering if there is a way to get screen resolution size?  Knowing if the screen is 4k or 2k is nicer that making boxes off screen or over/under sized.

Print this item

Photo SVG lines to micro(A) string array initialization
Posted by: mnrvovrfc - 08-03-2023, 07:51 AM - Forum: QBJS, BAM, and Other BASICs - Replies (2)

This is a program that processes an SVG file and creates code for micro(A). This attempts to "steal" coordinates in millimeters of a "plain" SVG file and present them into strings of run-on 4-digit numbers, which are X and Y absolute coordinate pairs. The values will have to be scaled for a graphics screen according to the maximum dimensions out of the SVG. It looks like the graphics screen of micro(A) is 780x570.

This could probably be done with "sodipodi" format, which is that of Inkscape, but it's not recommended. That program could insert a lot of transformation commands which would make for an uneven picture, and this effort by a hobbyist doesn't provision for that.

N.B. The SVG is expected to have relative coordinates, except the first point of each path. But this is translated into code which employs absolute coordinates. Directly copying from the original document to a QB64 graphics program requires PSET or something else to anchor, then "LINE" with "STEP" option to draw things relatively.

The run-on strings will have sequences of "99999999". This is a reset which means a new shape will begin with the next point listed, and should not connect with the previous coordinate that was obtained. I had to do it this way because micro(A) doesn't process strings very well. Originally it was going to be a string check for "######" for three-digit coordinates. This program shouldn't be used for very large vector pictures anyway.

I had to make more edits to the program to account for "z" at the end of path command. However this could come up with missing lines. I will need more time to look into this.

As it stands, this does not produce useable running micro(A) code, it only creates a couple of array variables and initializes them. I should also offer some simple code in micro(A) to put the lines together for the drawing. But my cohort protested. :/ But why since it's only "line" statements to use? In fact this could be translated into a QB64 or any BASIC program that supports graphics and has a line-drawing statement supporting absolute coordinates.

I got a bit lazy with this program. I was supposed to add Dav's routine to get filenames on Linux or Windows and display them in a nice box in SCREEN 0, and allow this for any version of QB64. Instead if you don't have Phoenix Edition v3.4 or later, you will have to type in a filename for a file that exists inside "(home)/Pictures". Including the directories. This is hard-coded. Yes I know it should be better.

Despite this caveat, this code should run on QB64 v2.0 and up. It does nothing fancy except parse a few values in text format.

There are more explanations as comments in the source code.

Neat trick of the QB64 IDE! It makes "pale" the code that the "conditional" decides doesn't apply for "$IF... THEN... $ELSE... $END IF".

User "roquedrivel" from "BASIC4US" forum helped with this program. Smile

Code: (Select All)
'by mnrvovrfc 3-Aug-2023
'this needs extensive testing because Inkscape keeps mixing absolute and relative coordinates.
'it doesn't matter between "sodipodi" or "plain" SVG.
'GIMP exports paths in absolute coordinates only, but is clunkier to work with.
'this would be easier with relative coordinates only, with the first
' "m" command of a path having the only absolute coordinate.
'it helps sometimes setting, before creating any document:
' Preferences/Input and Output/SVG Output/Paths: choose "relative" from menu.
'this works with lines only! Not bezier paths! Any bezier paths need to have the
' two control points reset: press [N] to choose node tool,
' select the node then the first choice
' on the toolbar for path nodes on the top of the screen.
'one more thing: from a plain SVG the measurement
' is in millimeters *NOT* in pixels!
'This program is meant to be run from the terminal!
'It's up to you to select the terminal text, copy and then paste into a text editor
' or into micro(A)'s editor. Then keep developing the script from there.
'If this is not satisfactory then the user is free to add code
' to create an output file.
$CONSOLE:ONLY
OPTION _EXPLICIT
DIM SHARED sf(1 TO 20) AS STRING, sl(1 TO 20) AS STRING
DIM AS DOUBLE xx, yy, x0, y0, x1, y1
DIM AS LONG fe, x, y, u, v, gh, coma
DIM AS INTEGER g, h
DIM apath$, afile$, dee$, a$, c$, qu$, entry$
DIM f AS _BYTE, lut AS _BYTE

qu$ = CHR$(34)

h = 1
g = 0
gh = 0
sf(h) = "st[" + _TRIM$(STR$(h)) + "] = " + qu$
dee$ = " d=" + qu$
$IF WIN THEN
apath$ = environ$("USERPROFILE") + "\Pictures\"
$ELSE
apath$ = ENVIRON$("HOME") + "/Pictures/"
'/" let's see if this fixes the "qb" code block bug on forum
$END IF
$IF VERSION < 3.4 THEN
'sorry Dav's file list routine was supposed to be here...
' but that would require "direntry.h"
PRINT "The current path now is "; apath$
PRINT "Please type in the name of an SVG file to load."
LINE INPUT afile$
IF afile$ = "" THEN SYSTEM
afile$ = apath$ + afile$
IF NOT _FILEEXISTS(afile$) THEN
PRINT "Unable to proceed!"
PRINT "File not found: "; afile$
END IF
$ELSE
afile$ = _OPENFILEDIALOG$("Please choose an SVG file.", apath$, "*.svg", "Plain SVG")
IF afile$ = "" THEN SYSTEM
$END IF
fe = FREEFILE
OPEN afile$ FOR INPUT AS fe
DO UNTIL EOF(fe)
LINE INPUT #fe, entry$
u = INSTR(entry$, dee$)
IF u THEN
lut = 0
x = -1E+6
y = -1E+6
xx = 0
yy = 0
c$ = ""
a$ = ""
entry$ = MID$(entry$, LEN(dee$) + u)
entry$ = LEFT$(entry$, LEN(entry$) - 1)
PRINT entry$
'trying to squash a bug where it refuses to read the final pair
entry$ = entry$ + " "
sf(h) = sf(h) + "99999999"
gh = gh + 8
g = g + 1
v = 1
u = INSTR(entry$, " ")
DO WHILE u
a$ = MID$(entry$, v, u - v)
'must make sure there are lines only here.
'might also have to check "M" and "m", this only assumes "m" at beginning
' is absolute coordinate.
'this cannot handle "h" nor "v", requires manual editing of SVG file or a
' search-and-replace conversion in this program.
'at last moment I had to make a provision for "z" which means draw a line,
' going back to the first (absolute) point of the path.
IF a$ = "L" THEN lut = 1
IF a$ = "l" THEN lut = 0
IF a$ = "z" THEN EXIT DO
IF LEN(a$) <> 1 THEN
coma = INSTR(a$, ",")
x1 = VAL(LEFT$(a$, coma - 1))
y1 = VAL(MID$(a$, coma + 1))
IF x = -1E+6 AND y = -1E+6 THEN
x0 = x1
y0 = y1
xx = x1
yy = y1
x = INT(xx)
y = INT(yy)
ELSEIF lut THEN
xx = x1
yy = y1
ELSE
xx = xx + x1
yy = yy + y1
END IF
outtheline
END IF
v = u + 1
u = INSTR(v, entry$, " ")
LOOP
IF RIGHT$(entry$, 3) = " z " THEN
xx = x0
yy = y0
outtheline
END IF
PRINT "---"
END IF
LOOP
CLOSE fe

sf(h) = sf(h) + qu$
a$ = _TRIM$(STR$(h))
sl(h) = "sl[" + a$ + "] =" + STR$(gh)

PRINT "var i, j, x1, y1, x2, y2, xscale, yscale, xmove, first, stnumele"
PRINT "str a, b"
PRINT "str st["; a$; "]"
PRINT "var sl["; a$; "]"
FOR g = 1 TO h
PRINT sf(g)
PRINT sl(g)
NEXT
PRINT "stnumele ="; h + 1
PRINT "xscale = 1"
PRINT "yscale = 1"
PRINT "xmove = 0"
PRINT "wcolor 0, 0, 0"
PRINT "fcolor 255, 255, 255"
PRINT "i = 1"
PRINT "label lb02"
PRINT " j = 1"
PRINT " label lb03"
PRINT " x1 = x2"
PRINT " y1 = y2"
PRINT " b = st[i]"
PRINT " a = mstr(b, j, 4)"
PRINT " x2 = val(a)"
PRINT " if x2 = 9999"
PRINT " first = 1"
PRINT " j = j + 8"
PRINT " goto cb03"
PRINT " endif"
PRINT " x2 = x2 * xscale"
PRINT " x2 = x2 + xmove"
PRINT " j = j + 4"
PRINT " b = st[i]"
PRINT " a = mstr(b, j, 4)"
PRINT " y2 = val(a)"
PRINT " y2 = y2 * yscale"
PRINT " if first = 0"
PRINT " line x1, y1, x2, y2"
PRINT " endif"
PRINT " if first = 1 : first = 0 : endif"
PRINT " j = j + 4"
PRINT "label cb03"
PRINT " if j < sl[i] : goto lb03 : endif"
PRINT "i = i + 1"
PRINT "if i < stnumele : goto lb02 : endif"
PRINT "swap"
SYSTEM


SUB outtheline ()
SHARED AS LONG x, y, gh
SHARED AS DOUBLE xx, yy
SHARED AS INTEGER g, h
SHARED qu$
DIM hs$
x = INT(xx)
y = INT(yy)
PRINT x; ","; y
sf(h) = sf(h) + Zeroes$(x, 4) + Zeroes$(y, 4)
gh = gh + 8
g = g + 1
IF g >= 80 THEN
hs$ = _TRIM$(STR$(h))
sf(h) = sf(h) + qu$
sl(h) = "sl[" + hs$ + "] =" + STR$(gh)
gh = 0
g = 0
h = h + 1
hs$ = _TRIM$(STR$(h))
sf(h) = "st[" + hs$ + "] = " + qu$
END IF
END SUB


FUNCTION Zeroes$ (num AS LONG, numdig AS INTEGER)
DIM b$, v AS LONG
DIM AS INTEGER sg, hx
IF num < 0 THEN sg = -1: num = num * -1
IF numdig < 0 THEN hx = 1: numdig = numdig * -1 ELSE hx = 0
IF hx THEN
b$ = HEX$(num)
ELSE
b$ = LTRIM$(STR$(num))
END IF
v = numdig - LEN(b$)
IF v > 0 THEN b$ = STRING$(v, 48) + b$
IF sg = -1 THEN b$ = "-" + b$
Zeroes$ = b$
END FUNCTION

Print this item

  BAM: Added RemoveLocalStorageItem and ClearLocalStorage
Posted by: CharlieJV - 08-01-2023, 02:45 AM - Forum: QBJS, BAM, and Other BASICs - No Replies

https://basicanywheremachine-news.blogsp...m-and.html

Print this item

  LIGHTBAR Menu
Posted by: grymmjack - 07-31-2023, 08:45 AM - Forum: Programs - Replies (15)

Knocked up a little lightbar driven menu routine which will go in my library soon.

[Image: lightbar-routine-demo.png]

Code: (Select All)

''
' LIGHTBAR Menu
'
' Creating lightbar driven menus using arrow keys to choose, enter to select, and
' making it reusable and modular.
'
' Code is a bit long, I'm sure someone can do this better! Regardless, this will end
' up in my QB64_GJ_LIB library soon.
'
' @author Rick Christy <grymmjack@gmail.com>
'
OPTION _EXPLICIT
SCREEN 0 : _BLINK OFF : _CONTROLCHR OFF
_TITLE "LIGHTBAR Menu Routine DEMO"

TYPE LIGHTBAR ' bg|b = background, fg|f = foreground, k = key
opt_bg_color AS INTEGER
opt_fg_color AS INTEGER
bar_bg_color AS INTEGER
bar_fg_color AS INTEGER
bar_kf_color AS INTEGER
bar_kb_color AS INTEGER
key_bg_color AS INTEGER
key_fg_color AS INTEGER
opt_selected AS INTEGER
delimeter AS STRING
END TYPE

DIM menu AS LIGHTBAR : DIM opts(5) AS STRING : DIM choice AS INTEGER
menu.opt_bg_color = 0
menu.opt_fg_color = 12
menu.bar_bg_color = 3
menu.bar_fg_color = 11
menu.bar_kf_color = 14
menu.bar_kb_color = 11
menu.key_bg_color = 3
menu.key_fg_color = 14
menu.opt_selected = 0
menu.delimeter = "|"
opts$(0) = " |P|izza "
opts$(1) = " |R|ibs "
opts$(2) = " |W|ings "
opts$(3) = " |S|alad "
opts$(4) = " |B|readsticks "
opts$(5) = " |Q|uit "

COLOR 12, 0: PRINT "----------------------------------------"
COLOR 7, 0 : PRINT " Welcome to";
COLOR 12, 0: PRINT " ANTONIOS"; : COLOR 10, 0: PRINT " PIZZERIA!"
COLOR 7, 0 : PRINT " Pick your favorite food from our menu!"
COLOR 14, 0: PRINT "----------------------------------------"
COLOR 2, 0 : PRINT " ..if you're not hungry press ESCAPE.. "
COLOR 12, 0: PRINT "----------------------------------------"
PRINT
COLOR 9, 0 : PRINT " UP and DOWN choose and ENTER picks!"
PRINT

choice% = LIGHTBAR%(menu, opts$())
IF choice% <> -1 THEN
PRINT
COLOR 11, 0 : PRINT "You chose option ";
COLOR 14, 0 : PRINT UCASE$(_TRIM$(STR$(choice%)));
COLOR 11, 0 : PRINT ": ";
COLOR 12, 0 : PRINT _TRIM$(opts$(choice%))
IF choice% = 0 THEN
COLOR 10, 0 : PRINT "An excellent choice! It is also my favorite!"
END IF
ELSE
PRINT
COLOR 3, 0 : PRINT "Not hungry eh? OK you come back later!"
END IF
PRINT
COLOR 12, 0 : PRINT "Thank you! Come again!"



FUNCTION LIGHTBAR%(menu AS LIGHTBAR, options$())
DIM AS STRING opt_l, opt_r, k, opt_sel_l, opt_sel_r, opt_sel_k
DIM AS INTEGER obg, ofg, bbg, bfg, bkf, bkb, kbg, kfg, key_pos_s, key_pos_e
DIM AS INTEGER row, col, orig_bg, orig_fg, lb, ub, i, selected, choice_made
lb% = LBOUND(options$) : ub% = UBOUND(options$)

' fetch convenience colors
obg% = menu.opt_bg_color : ofg% = menu.opt_fg_color
bbg% = menu.bar_bg_color : bfg% = menu.bar_fg_color
bkf% = menu.bar_kf_color : bkb% = menu.bar_kb_color
kbg% = menu.key_bg_color : kfg% = menu.key_fg_color

DIM keys(lb% TO ub%) AS STRING ' holds hot keys (chars in delimeters)
row% = CSRLIN : col% = POS(0) ' store initial cursor position
orig_fg% = SCREEN(row%, col%, 1) AND 15 ' store initial foreground color
orig_bg% = SCREEN(row%, col%, 1) \ 16 ' store initial background color
selected% = menu.opt_selected ' get selected option

LIGHTBAR_draw:
LOCATE row%, col%
FOR i% = lb% TO ub%
key_pos_s% = INSTR(0, options$(i%), menu.delimeter)
key_pos_e% = INSTR(key_pos_s%, options$(i%), menu.delimeter)
keys$(i%) = MID$(options$(i%), key_pos_s% + 1, 1)
opt_l$ = MID$(options$(i%), 0, key_pos_s%)
opt_r$ = MID$(options$(i%), key_pos_s% + 3)
COLOR ofg%, obg% : PRINT opt_l$;
COLOR kfg%, kbg% : PRINT keys$(i%);
COLOR ofg%, obg% : PRINT opt_r$
IF i% = selected% THEN
opt_sel_l$ = opt_l$ : opt_sel_r$ = opt_r$ : opt_sel_k$ = keys$(i%)
END IF
NEXT i%

' draw selected option
LOCATE row% + selected%, col%
COLOR bfg%, bbg% : PRINT opt_sel_l$;
COLOR bkf%, bkb% : PRINT opt_sel_k$;
COLOR bfg%, bbg% : PRINT opt_sel_r$

LIGHTBAR_get_choice:
DO:
' handle arrow keys
k$ = INKEY$
SELECT CASE k$
CASE CHR$(27): ' escape to abort
selected% = -1
CASE CHR$(0) + CHR$(71): ' home to jump to first option
selected% = lb%
GOTO LIGHTBAR_draw
CASE CHR$(0) + CHR$(79): ' end to jump to last option
selected% = ub%
GOTO LIGHTBAR_draw
CASE CHR$(0) + CHR$(80): ' down arrow to go down an option
selected% = selected% + 1
IF selected% > ub% THEN selected% = lb%
GOTO LIGHTBAR_draw
CASE CHR$(0) + CHR$(72): ' up arrow to go up an option
selected% = selected% - 1
IF selected% < lb% THEN selected% = ub%
GOTO LIGHTBAR_draw
END SELECT
' handle hot keys
FOR i% = lb% TO ub%
IF LCASE$(k$) = LCASE$(keys$(i%)) THEN
selected% = i%
choice_made% = 1
GOTO LIGHTBAR_draw
END IF
NEXT i%
LOOP UNTIL k$ = CHR$(13) OR k$ = CHR$(27) OR choice_made% = 1

COLOR orig_fg%, orig_bg% ' restore original colors
LOCATE row% + (ub% - lb%) + 1, col% ' position cursor under menu
LIGHTBAR% = selected%
END FUNCTION

Print this item

  Can you prevent a QB64 program from being maximized under Linux?
Posted by: Dav - 07-31-2023, 12:51 AM - Forum: Help Me! - Replies (5)

All my QB64 programs under Linux (KDE Neon) can be resized/maximized anytime.  I'd like to prevent that.   Is there a way?  I tried $RESIZE:OFF but it doesn't seem to stop it.

- Dav

Print this item

Big Grin A puzzeltask
Posted by: Kernelpanic - 07-30-2023, 09:56 PM - Forum: General Discussion - Replies (36)

Since there is not much going on here at the moment, a small task:

A triangular track system with three points is given. (pic 36) Section a is a short dead end with a bumper block. Sections c and b are short distances between the points, the length of which can just accommodate one railroad wagon each.

Route D is a long, open-ended route. There is a goods wagon on section B and a container wagon on section C; on section D there is a locomotive with a tender. The section A bounded by the buffer stop is so short that it can accommodate the length of the freight wagon or container wagon, but not the locomotive and tender.
So while each of the cars can be moved from section B or C to the other side alone via the dead short distance A, this is not possible for the locomotive because of its length.

A locomotive driver now has the task of swapping the position of the two wagons by a shunting process, so that after the shunting process is complete, the container wagon is on track section B and the freight wagon is on track section C. The locomotive ends up on section D again (Fig. 37).

How is the shunting process to accomplish this?

[Image: Rangieraufgabe-Kl.jpg]

Print this item

  Laser Lovers
Posted by: bplus - 07-29-2023, 07:35 PM - Forum: Programs - Replies (4)

Here is yet another version, Cloud variation:

Code: (Select All)
_Title "Cloud" ' b+ 2023-07-29
Option _Explicit
' from Laser Blades replace Blade drawing with cloud drawing

Const NBolts = 50 ' max number of Bolt slots available, just like bullet science
Const PulseLength = 120 ' length of light pulses as they travel down BoltLine

Type BoltType 'see NewBolt for description of these variables
    As Single x1, y1, r1, dx, dy, dr, d, ang, frames, frame, active, speedX, speedY, x, y, r
    As _Unsigned Long k
End Type
Dim Shared Bolts(1 To NBolts) As BoltType

Dim Shared bk
Dim As Long mx, my, i, lpc, blastedShip, r

Randomize Timer
Screen _NewImage(1200, 700, 32)
_ScreenMove 50, 20

'test cloud first
'Cloud 600, 200, 50, 600, 500, 20, &H88FFFFFF ' OK
'Cls
makeBackground
Do
    Cls
    _PutImage , bk, 0
    If blastedShip Then
        DrawShip 600, 350, &HFF00CC66
        For r = blastedShip To 1 Step -2
            FCirc 600, 350, r, _RGB32(5 * (50 - r), 5 * (50 - r), 0, 20)
        Next
        blastedShip = blastedShip + 2
        If blastedShip > 50 Then blastedShip = 0
    Else
        DrawShip 600, 350, &HFF00CC66 ' bplus signature space ship, for rent :)
    End If
    ' fire off some more bolts at the ship from the screen corners!
    If lpc = 0 Then
        If Rnd < .7 Then NewBolt 0, 0, 1, 600, 350, 5, 15, &HFFFF4444
    ElseIf lpc = 30 Then
        If Rnd < .7 Then NewBolt _Width - 1, 0, 1, 600, 350, 13, 10, &HFF447744
    ElseIf lpc = 60 Then
        If Rnd < .7 Then NewBolt _Width - 1, _Height - 1, 1, 600, 350, 15, 7, &HFFFF44FF
    ElseIf lpc = 90 Then
        If Rnd < .7 Then NewBolt 0, _Height - 1, 1, 600, 350, 18, 5, &HFF448888
    End If
    lpc = (lpc + 1) Mod 120 ' loopscounter every 30 shoot from a corner
    For i = 1 To NBolts
        If Bolts(i).active Then DrawBolt (i) ' draws the bolts still active
    Next '                                     according to what frame they are on
    ' collision detection  blow up when ship is hit
    For i = 1 To NBolts
        If Bolts(i).active Then
            If _Hypot(Bolts(i).x - 600, Bolts(i).y - 350) < 20 + Bolts(i).r Then
                If Bolts(i).x1 <> 600 And Bolts(i).y1 <> 350 Then ' oops watch out for friendly fire!!!
                    If blastedShip = 0 Then blastedShip = 1
                    Bolts(i).active = 0
                End If
            End If
        End If
    Next
    While _MouseInput: Wend
    mx = _MouseX: my = _MouseY
    If _MouseButton(1) Then
        NewBolt 600, 340, 1, mx, my, 30, 10, _RGB32(200, 200, 255, 100)
        While _MouseInput Or _MouseButton(1): Wend
    End If
    _Display
    '_Limit 60
Loop Until _KeyDown(27)


Sub NewBolt (x1, y1, r1, x2, y2, r2, ppfSpeed, k~&) ' sets up for the DrawBolt Sub
    'x1, y1, r1 = location and radius at start of beam
    'x2, y2, r2 = target location and radius at beam end
    'ppfSpeed = how many pixels per frame in main loop  to transverse
    Dim i
    For i = 1 To NBolts
        If Bolts(i).active = 0 Then
            Bolts(i).x1 = x1 ' start x, y, radius
            Bolts(i).y1 = y1
            Bolts(i).r1 = r1
            Bolts(i).active = 1 ' bolt is activated
            Bolts(i).dx = x2 - x1 ' drawing the bolt line and thickness
            Bolts(i).dy = y2 - y1 ' as it changes from x1, y1, r1 to x2, y2, r2
            Bolts(i).dr = r2 - r1
            Bolts(i).d = _Hypot(Bolts(i).dx, Bolts(i).dy) ' distance of the bolt line
            Bolts(i).frames = Int(Bolts(i).d / ppfSpeed) + 1 ' divide that distance by pulse = PulseLength
            Bolts(i).frame = 1 ' set the frame you are on to locate the pulse in drawing
            Bolts(i).ang = _Atan2(y2 - y1, x2 - x1)
            Bolts(i).speedX = ppfSpeed * Cos(Bolts(i).ang)
            Bolts(i).speedY = ppfSpeed * Sin(Bolts(i).ang)
            Bolts(i).x = x1 ' track leading x, y, r of current bolt for collision detection
            Bolts(i).y = y1
            Bolts(i).r = r1
            Bolts(i).k = k~&
            Exit Sub
        End If
    Next
End Sub

Sub DrawBolt (idx) ' needs FCirc (Fill Circle) routine
    ' This sub draw a pulse of light on the BoltLine from .x1, .y1 on the way to .x2, .y2
    ' The start radius is .r1 and the end radius is .r2 and the pulse is thinned or thickened
    ' as it proceeds down the boltLine.

    'All this is setup in the NewBolt Sub and uses DIM Shared Bolts() as BoltType and Constants
    ' NBolts = max amount of activated Bolt "slots" available and PulseLength the length of
    ' BoltLine sections to draw in each frame.

    Dim d, d2, stepper, oldX, oldY, r2
    ' new lead position for tracking location for collision detection
    Bolts(idx).x = Bolts(idx).x1 + Bolts(idx).speedX * Bolts(idx).frame
    Bolts(idx).y = Bolts(idx).y1 + Bolts(idx).speedY * Bolts(idx).frame
    d = _Hypot(Bolts(idx).x1 - Bolts(idx).x, Bolts(idx).y1 - Bolts(idx).y)
    If Abs(Bolts(idx).dr / PulseLength) < .2 Then stepper = .5 Else stepper = 2
    Bolts(idx).r = Bolts(idx).r1 + d * Bolts(idx).dr / Bolts(idx).d
    If d < PulseLength Then
        'Blade Bolts(idx).x1, Bolts(idx).y1, Bolts(idx).r1 + d2 * Bolts(idx).dr / Bolts(idx).d, Bolts(idx).x, Bolts(idx).y, Bolts(idx).r, Bolts(idx).k
        'Blade Bolts(idx).x1, Bolts(idx).y1, .4 * Bolts(idx).r1 + d2 * Bolts(idx).dr / Bolts(idx).d, Bolts(idx).x, Bolts(idx).y, .4 * Bolts(idx).r, &H80FFFFFF
        Cloud Bolts(idx).x1, Bolts(idx).y1, Bolts(idx).r1 + d2 * Bolts(idx).dr / Bolts(idx).d, Bolts(idx).x, Bolts(idx).y, Bolts(idx).r, Bolts(idx).k
    Else
        oldX = Bolts(idx).x + PulseLength * Cos(Bolts(idx).ang - _Pi)
        oldY = Bolts(idx).y + PulseLength * Sin(Bolts(idx).ang - _Pi)
        d2 = _Hypot(Bolts(idx).x1 - oldX, Bolts(idx).y1 - oldY)
        r2 = Bolts(idx).r1 + d2 * Bolts(idx).dr / Bolts(idx).d
        'Blade oldX, oldY, r2, Bolts(idx).x, Bolts(idx).y, Bolts(idx).r, Bolts(idx).k
        'Blade oldX, oldY, .4 * r2, Bolts(idx).x, Bolts(idx).y, .4 * Bolts(idx).r, &H80FFFFFF
        Cloud oldX, oldY, r2, Bolts(idx).x, Bolts(idx).y, Bolts(idx).r, Bolts(idx).k
    End If

    Bolts(idx).frame = Bolts(idx).frame + 1 ' update frame number
    If Bolts(idx).frame > Bolts(idx).frames Then Bolts(idx).active = 0 ' job done!
End Sub

Sub Blade (x1, y1, r1, x2, y2, r2, K As _Unsigned Long)
    Dim PD2 As Double
    Dim As Single a, x3, y3, x4, y4, x5, y5, x6, y6, r1d2, r2d2
    PD2 = 1.570796326794897 ' pi/2
    a = _Atan2(y2 - y1, x2 - x1)
    r1d2 = r1 / 2: r2d2 = r2 / 2
    x3 = x1 + r1d2 * Cos(a + PD2)
    y3 = y1 + r1d2 * Sin(a + PD2)
    x4 = x1 + r1d2 * Cos(a - PD2)
    y4 = y1 + r1d2 * Sin(a - PD2)
    x5 = x2 + r2d2 * Cos(a + PD2)
    y5 = y2 + r2d2 * Sin(a + PD2)
    x6 = x2 + r2d2 * Cos(a - PD2)
    y6 = y2 + r2d2 * Sin(a - PD2)
    ftri x6, y6, x4, y4, x3, y3, K
    ftri x3, y3, x5, y5, x6, y6, K
End Sub

'2019-12-16 fix by Steve saves some time with STATIC and saves and restores last dest
Sub ftri (x1, y1, x2, y2, x3, y3, K As _Unsigned Long)
    Dim D As Long
    Static a&
    D = _Dest
    If a& = 0 Then a& = _NewImage(1, 1, 32)
    _Dest a&
    _DontBlend a& '  '<<<< new 2019-12-16 fix
    PSet (0, 0), K
    _Blend a& '<<<< new 2019-12-16 fix
    _Dest D
    _MapTriangle _Seamless(0, 0)-(0, 0)-(0, 0), a& To(x1, y1)-(x2, y2)-(x3, y3)
End Sub

Sub FCirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
    Dim Radius As Integer, RadiusError As Integer
    Dim X As Integer, Y As Integer
    Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
    If Radius = 0 Then PSet (CX, CY), C: Exit Sub
    Line (CX - X, CY)-(CX + X, CY), C, BF
    While X > Y
        RadiusError = RadiusError + Y * 2 + 1
        If RadiusError >= 0 Then
            If X <> Y + 1 Then
                Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
                Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
            End If
            X = X - 1
            RadiusError = RadiusError - X * 2
        End If
        Y = Y + 1
        Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
        Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
    Wend
End Sub

Sub DrawShip (x, y, colr As _Unsigned Long) 'needs FCirc and FEllipse subs
    Static ls ' tracks the last light position in string of lights
    Dim light As Long, r As Long, g As Long, b As Long
    r = _Red32(colr): g = _Green32(colr): b = _Blue32(colr)
    FEllipse x, y, 6, 15, _RGB32(r, g - 120, b - 100)
    FEllipse x, y, 18, 11, _RGB32(r, g - 60, b - 50)
    FEllipse x, y, 30, 7, _RGB32(r, g, b)
    For light = 0 To 5
        FCirc x - 30 + 11 * light + ls, y, 1, _RGB32(ls * 50, ls * 50, ls * 50)
    Next
    ls = ls + 1
    If ls > 5 Then ls = 0
End Sub

Sub FEllipse (CX As Long, CY As Long, xr As Long, yr As Long, C As _Unsigned Long)
    If xr = 0 Or yr = 0 Then Exit Sub
    Dim h2 As _Integer64, w2 As _Integer64, h2w2 As _Integer64
    Dim x As Long, y As Long
    w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
    Line (CX - xr, CY)-(CX + xr, CY), C, BF
    Do While y < yr
        y = y + 1
        x = Sqr((h2w2 - y * y * w2) \ h2)
        Line (CX - x, CY + y)-(CX + x, CY + y), C, BF
        Line (CX - x, CY - y)-(CX + x, CY - y), C, BF
    Loop
End Sub

Sub makeBackground
    bk = _NewImage(_Width, _Height, 32)
    _Dest bk
    Dim As Long i, stars, horizon
    For i = 0 To _Height
        Line (0, i)-(_Width, i), _RGB32(70, 60, i / _Height * 160)
    Next
    stars = _Width * _Height * 10 ^ -4
    For i = 1 To stars 'stars in sky
        PSet (Rnd * _Width, Rnd * _Height), _RGB32(175 + Rnd * 80, 175 + Rnd * 80, 175 + Rnd * 80)
    Next
    stars = stars / 2
    For i = 1 To stars
        FCirc Rnd * _Width, Rnd * _Height, 1, _RGB32(175 + Rnd * 80, 175 + Rnd * 80, 175 + Rnd * 80)
    Next
    stars = stars / 2
    For i = 1 To stars
        FCirc Rnd * _Width, Rnd * horizon, 2, _RGB32(175 + Rnd * 80, 175 + Rnd * 80, 175 + Rnd * 80)
    Next
    _PutImage , 0, bk
    _Dest 0
End Sub


Sub Cloud (xx1, yy1, rr1, xx2, yy2, rr2, c~&) ' another attempt at a Laser Pulse or Bolt
    ' scatter pixels over area from p1 to p2 with the radius spec
    Dim x1, y1, r1, x2, y2, r2
    If xx1 > xx2 Then ' orientate
        x1 = xx2: x2 = xx1
        y1 = yy2: y2 = yy1
        r1 = rr2: r2 = rr1
    Else
        x1 = xx1: x2 = xx2
        y1 = yy1: y2 = yy2
        r1 = rr1: r2 = rr2
    End If
    Dim ang, dx, dy, dr, d, pd2, p2, a, stepper, n, r, i, x, y, r3
    pd2 = _Pi / 2
    p2 = _Pi * 2
    ang = _Atan2(y2 - y1, x1 - x2)
    dx = x2 - x1
    dy = y2 - y1
    dr = r2 - r1
    d = _Hypot(dx, dy)

    ' one end
    stepper = 2 / (p2 * r1)
    For a = -ang To -ang + pd2 Step stepper
        For n = 1 To .1 * r1
            r = randWeight(0, r1, 1)
            PSet (x1 + r * Cos(a), y1 + r * Sin(a)), c~&
        Next
    Next
    For a = -ang To -ang - pd2 Step -stepper
        For n = 1 To .1 * r1
            r = randWeight(0, r1, 1)
            PSet (x1 + r * Cos(a), y1 + r * Sin(a)), c~&
        Next
    Next
    ' the other end
    stepper = 2 / (p2 * r2)
    For a = ang To ang + pd2 Step stepper
        For n = 1 To .1 * r2
            r = -randWeight(0, r2, 1)
            PSet (x2 + r * Cos(-a), y2 + r * Sin(-a)), c~&
        Next
    Next
    For a = ang To ang - pd2 Step -stepper
        For n = 1 To .1 * r1
            r = -randWeight(0, r2, 1)
            PSet (x2 + r * Cos(-a), y2 + r * Sin(-a)), c~&
        Next
    Next
    ' down the line   for some reason I have to jiggle the minus signs for x's ???
    dy = dy / d
    dx = dx / d
    dr = dr / d
    For i = 0 To d
        x = x1 + i * dx: y = y1 + i * dy: r = r1 + i * dr
        'PSet (x - r * Cos(ang + pd2), y + r * Sin(ang + pd2)), c~&
        'PSet (x - r * Cos(ang - pd2), y + r * Sin(ang - pd2)), c~&
        For n = 1 To 1 * r
            r3 = randWeight(0, r, 4)
            PSet (x - r3 * Cos(ang + pd2), y + r3 * Sin(ang + pd2)), c~&
            r3 = randWeight(0, r, 4)
            PSet (x - r3 * Cos(ang - pd2), y + r3 * Sin(ang - pd2)), c~&
        Next
    Next

End Sub

Function randWeight (manyValue, fewValue, power)
    randWeight = manyValue + Rnd ^ power * (fewValue - manyValue)
End Function

   

Print this item

  300 Members
Posted by: bplus - 07-28-2023, 05:15 PM - Forum: Announcements - Replies (4)

Welcome JFPM Smile

Print this item