Since starting the QBJS effort there have been a number of inquiries around support for an offline mode. For the next release, QBJS will offer offline deployment as a progressive web application (PWA).
This change allows you to install QBJS locally directly from the browser. A new icon will appear in the address bar. Here's an example of what it looks like in Edge:
After the install is complete you can then run QBJS in a standalone application window:
The best part though is that all of the content needed to run QBJS will be installed on your device. So you will be able to use it when completely disconnected from the internet. But you'll still get the best of both worlds as it will download any updates when new releases come out.
This feature will be included in the next release of QBJS along with a number of additional features that are still in progress. I thought I would go ahead and mention it here as I would love to have any feedback from anyone who is game to try it out in the dev site. I'd be very interested to hear how it worked (or didn't) for you and what OS/browser combo you have.
A couple of notes:
The install as app feature is available in most major browsers but for some reason this is not fully supported on Firefox desktop version (although it is on the Android version of Firefox)
On iOS this can be installed by selecting the "Add to Home Screen" option.
_Title "Fireworks 3 translation to QB64 2017-12-26 bplus"
'fireworks 3.bas SmallBASIC 0.12.2 [B+=MGA] 2015-05-09
'fireworks 2.bas 2016-05-05 now with Gravity, Newtonian bounce, smoke debris
'fireworks 3.bas try with map variables make bursts around a central point
Const xmax = 1000
Const ymax = 720
Screen _NewImage(xmax, ymax, 32)
_ScreenMove 180, 0
Type placeType
x As Single
y As Single
End Type
Type flareType
x As Single
y As Single
dx As Single
dy As Single
c As Long
End Type
Type debrisType
x As Single
y As Single
c As Long
End Type
Common Shared debris() As debrisType
flareMax = 1000: debrisMax = 5000: debrisStack = 0
Dim flare(flareMax) As flareType
Dim debris(debrisMax) As debrisType
Dim burst As placeType
While 1
rndCycle = Rnd * 30
loopCount = 0
burst.x = .75 * xmax * Rnd + .125 * xmax
burst.y = .5 * ymax * Rnd + .125 * ymax
While loopCount < 7
Cls
'color 14 : locate 0,0: ? debris_stack; " Debris" 'debug line
For i = 1 To 200 'new burst using random old flames to sim burnout
nxt = Int(Rnd * flareMax)
angle = Rnd * _Pi(2)
flare(nxt).x = burst.x + Rnd * 5 * Cos(angle)
flare(nxt).y = burst.y + Rnd * 5 * Sin(angle)
angle = Rnd * _Pi(2)
flare(nxt).dx = Rnd * 15 * Cos(angle)
flare(nxt).dy = Rnd * 15 * Sin(angle)
rc = Int(Rnd * 3)
If rc = 0 Then
flare(nxt).c = _RGB32(255, 100, 0)
ElseIf rc = 1 Then
flare(nxt).c = _RGB32(0, 0, 255)
Else
flare(nxt).c = _RGB32(255, 255, 255)
End If
Next
For i = 0 To flareMax
If flare(i).dy <> 0 Then 'while still moving vertically
Line (flare(i).x, flare(i).y)-Step(flare(i).dx, flare(i).dy), _RGB32(98, 98, 98)
flare(i).x = flare(i).x + flare(i).dx
flare(i).y = flare(i).y + flare(i).dy
Color flare(i).c
Circle (flare(i).x, flare(i).y), 1
flare(i).dy = flare(i).dy + .4 'add gravity
flare(i).dx = flare(i).dx * .95 'add some air resistance
If flare(i).x < 0 Or flare(i).x > xmax Then flare(i).dy = 0 'outside of screen
'add some spark bouncing here
If flare(i).y > ymax Then
If Abs(flare(i).dy) > .5 Then
flare(i).y = ymax: flare(i).dy = flare(i).dy * -.25
Else
flare(i).dy = 0
End If
End If
End If
Next
For i = 0 To debrisStack
PSet (debris(i).x, debris(i).y), debris(i).c
debris(i).x = debris(i).x + Rnd * 3 - 1.5
debris(i).y = debris(i).y + Rnd * 3.5 - 1.5
If debris(i).x < 0 Or debris(i).y < 0 Or debris(i).x > xmax Or debris(i).y > ymax Then NewDebris (i)
Next
_Display
_Limit 20
loopCount = loopCount + 1
Wend
If debrisStack < debrisMax Then
For i = 1 To 20
NewDebris i + debrisStack
Next
debrisStack = debrisStack + 20
End If
Wend
Sub NewDebris (i)
debris(i).x = Rnd * xmax
debris(i).y = Rnd * ymax
c = Rnd * 255
debris(i).c = _RGB32(c, c, c)
End Sub
State of the Art
Code: (Select All)
_Title "Happy Trails 2020" 'from Happy Trails 2018
' 2017-12-29 another redesign of fireworks
' 2017-12-28 redesign fireworks
' now with lake refelction 2017-12-27 forget the bouncing sparks
' combine Welcome Plasma Font with landscape
'_title "Fireworks 3 translation to QB64 2017-12-26 bplus"
'fireworks 3.bas SmallBASIC 0.12.2 [B+=MGA] 2015-05-09
'fireworks 2.bas 2016-05-05 now with Gravity, Newtonian bounce, smoke debris
'fireworks 3.bas try with map variables make bursts around a central point
Randomize Timer
Const xmax = 1200
Const ymax = 720
Const waterline = 600 ' 600 = ratio 5 to 1 sky to water
' raise and lower waterline as desired highest about 400?
Const lTail = 15
Const bluey = 5 * 256 ^ 2 + 256 * 5 + 5
Const debrisMax = 28000
Type fireWorkType
x As Integer
y As Integer
seed As Integer
age As Integer
life As Integer
End Type
Type debrisType
x As Single
y As Single
c As Long
End Type
Common Shared fw() As fireWorkType
Common Shared debris() As debrisType
Common Shared cN, pR!, pG!, pB!
Screen _NewImage(xmax, ymax, 32)
'prepare message font
mess$ = " Happy New Year 2020"
Print mess$
w = 8 * Len(mess$): h = 16
Dim p(w, h)
black&& = Point(0, 10)
For y = 0 To h
For x = 0 To w
If Point(x, y) <> black&& Then
p(x, y) = 1
End If
Next
Next
xo = 0: yo = 15: m = 7.2
resetPlasma
'prepare fire works
nFW = 3
Dim fw(1 To 10) As fireWorkType
For i = 1 To nFW
initFireWork (i)
Next
''debris feild
'DIM debris(debrisMax) AS debrisType
'OK start the show
While 1
'cls screen with land image
_PutImage , land&, 0
'draw fireworks
For f = 1 To nFW
If fw(f).age <= fw(f).life Then drawfw (f) Else initFireWork f
Next
''debris
'FOR i = 0 TO debrisStack
' PSET (debris(i).x, debris(i).y), debris(i).c
' debris(i).x = debris(i).x + RND * 3 - 1.5
' debris(i).y = debris(i).y + RND * 3.5 - 1.5
' IF debris(i).x < 0 OR debris(i).y < 0 OR debris(i).x > xmax OR debris(i).y > waterline + RND * 20 THEN NewDebris (i)
'NEXT
'text message in plasma
For y = 0 To h - 1
For x = 0 To w - 1
If p(x, y) Then
changePlasma
Else
Color 0
End If
Line (xo + x * m, yo + y * m)-(xo + x * m + m, yo + y * m + m), , BF
Next
Next
lc = lc + 1
If lc Mod 200 = 0 Then resetPlasma
'reflect sky
skyWaterRatio = waterline / (ymax - waterline) - .05
For y = waterline To ymax
For x = 0 To xmax
c&& = Point(x, waterline - ((y - waterline - 1) * skyWaterRatio) + Rnd * 5)
PSet (x, y + 1), c&& + bluey
Next
Next
_Display
_Limit 200 'no limit needed on my system!
''accumulate debris
'IF lc MOD 2000 THEN
' IF debrisStack < debrisMax THEN
' FOR i = 1 TO 2
' NewDebris i + debrisStack
' NEXT
' debrisStack = debrisStack + 2
' END IF
'END IF
Wend
'SUB NewDebris (i)
' debris(i).x = RND * xmax
' debris(i).y = RND * ymax
' c = RND * 155
' debris(i).c = _RGB32(c, c, c)
'END SUB
Sub changePlasma ()
cN = cN + .01
Color _RGB(127 + 127 * Sin(pR! * .3 * cN), 127 + 127 * Sin(pG! * .3 * cN), 127 + 127 * Sin(pB! * .3 * cN))
End Sub
Sub resetPlasma ()
pR! = Rnd ^ 2: pG! = Rnd ^ 2: pB! = Rnd ^ 2
End Sub
Sub drawLandscape
'the sky
For i = 0 To ymax
midInk 0, 0, 0, 78, 28, 68, i / ymax
Line (0, i)-(xmax, i)
Next
'the land
startH = waterline - 80
rr = 10: gg = 20: bb = 15
For mountain = 1 To 6
Xright = 0
y = startH
While Xright < xmax
' upDown = local up / down over range, change along Y
' range = how far up / down, along X
upDown = (Rnd * .8 - .35) * (1 / (1 * mountain))
range = Xright + rand&&(5, 35) * 2.5 / mountain
lastx = Xright - 1
For X = Xright To range
y = y + upDown
Color _RGB32(rr, gg, bb)
Line (lastx, y)-(X, ymax), , BF 'just lines weren't filling right
lastx = X
Next
Xright = range
Wend
rr = rand&&(rr + 5, rr): gg = rand&&(gg + 5, gg): bb = rand&&(bb + 4, bb)
If rr < 0 Then rr = 0
If gg < 0 Then gg = 0
If bb < 0 Then bb = 0
startH = startH + rand&&(1, 10)
Next
'LINE (0, waterline)-(xmax, ymax), _RGB32(0, 0, 0), BF
End Sub
Sub midInk (r1, g1, b1, r2, g2, b2, fr)
Color _RGB(r1 + (r2 - r1) * fr, g1 + (g2 - g1) * fr, b1 + (b2 - b1) * fr)
End Sub
Function rand&& (lo&&, hi&&)
rand&& = Int(Rnd * (hi&& - lo&& + 1)) + lo&&
End Function
Sub drawfw (i)
'here's how to "save" a bunch of random numbers without data and arrays but tons of redundant calculations
Randomize Using fw(i).seed 'this repeats all random numbers generated by seed in same sequence
'recreate our firework from scratch!
red = rand&&(200, 255)
green = rand&&(200, 255)
blue = rand&&(200, 255)
x = rand&&(1, 4)
If x = 1 Then
red = 0
ElseIf x = 2 Then
green = 0
ElseIf x = 3 Then
blue = 0
Else
x = rand&&(1, 4)
If x = 1 Then
red = 0: green = 0
ElseIf x = 2 Then
green = 0: blue = 0
ElseIf x = 3 Then
blue = 0: red = 0
End If
End If
ne = rand&&(80, 300)
Dim embers(ne, 1)
For e = 0 To ne
r = Rnd * 3
embers(e, 0) = r * Cos(e * _Pi(2) / 101)
embers(e, 1) = r * Sin(e * _Pi(2) / 101)
Next
start = fw(i).age - lTail ' don't let tails get longer than lTail const
If start < 1 Then start = 1
For e = 0 To ne
cx = fw(i).x: cy = fw(i).y: dx = embers(e, 0): dy = embers(e, 1)
For t = 1 To fw(i).age
cx = cx + dx
cy = cy + dy
If t >= start Then
'too much like a flower?
midInk 60, 60, 60, red, green, blue, (t - start) / lTail
'midInk 60, 60, 60, 128, 160, 150, (t - start) / lTail
fcirc cx, cy, (t - start) / lTail
End If
dx = dx * .99 'air resitance
dy = dy + .01 'gravity
Next
Color _RGB32(255, 255, 255)
'COLOR _RGB32(red, green, blue)
cx = cx + dx: cy = cy + dy
fcirc cx, cy, (t - start) / lTail
Next
fw(i).age = fw(i).age + 1
End Sub
'Steve McNeil's copied from his forum note: Radius is too common a name
Sub fcirc (CX As Long, CY As Long, R As Long)
Dim subRadius As Long, RadiusError As Long
Dim X As Long, Y As Long
subRadius = Abs(R)
RadiusError = -subRadius
X = subRadius
Y = 0
If subRadius = 0 Then PSet (CX, CY): Exit Sub
' Draw the middle span here so we don't draw it twice in the main loop,
' which would be a problem with blending turned on.
Line (CX - X, CY)-(CX + X, CY), , 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), , BF
Line (CX - Y, CY + X)-(CX + Y, CY + X), , BF
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
Line (CX - X, CY - Y)-(CX + X, CY - Y), , BF
Line (CX - X, CY + Y)-(CX + X, CY + Y), , BF
Wend
End Sub
Ascii move mousewheel or Dave for Pete
Code: (Select All)
DefInt A-Z
_Title "ASCII Fireworks !!! Move Mousewheel !!! to Expand or Contract #2" '2020-01-01
' 2020-01-02 update with graivity effect by tsh73 from JB forum
' 2020-08-11 modified for xpanding and contracting screen size
' 2020-08-11 Steve catches memory leak, fixed!
' 2020-08-12 manstersoft gives me idea for Font 8, added more works and switched color to more! RGB32
Const nR = 9, t = " Happy New Year QB64 Forum, ASCII Fireworks Brought To You By Bplus Inspired by Pete, TempodiBasic and Code Hunter Recent Efforts, Gravity Effect by tsh73 at JB Forum, Thanks Steve for saving memory and manstersoft for Font 8 idea, Go In Peace 2020!....."
Type rocket
x As Single
y As Single
bang As Integer
age As Integer
c As _Unsigned Long
End Type
Dim Shared r(1 To nR) As rocket
For i = 1 To nR
new i
Next
Dim Shared fire&
fire& = _NewImage(640, 400, 32)
Dim tmp&(0 To 10)
lastt = 20
sc& = _NewImage(640, 400, 32)
_Font 8
Do
_Dest fire&
_Font 16
Cls
Color &HFFFF88AA
lc = lc + 1
If lc Mod 3 = 0 Then p = (p + 1) Mod Len(t)
Locate 2, 20: Print Mid$(t, p + 1, 40);
_Font 8
rocs = rocs + 1
If rocs > nR Then rocs = nR
For i = 1 To rocs
drawRocket i
Next
_Dest 0
While _MouseInput
scroll = scroll + _MouseWheel
Wend
If scroll < 800 And scroll > -400 Then
tp = (tp + 1) Mod 10
tmp&(tp) = _NewImage(640 + scroll, 400 + scroll, 32)
Screen tmp&(tp)
_PutImage , fire&, 0
Else
lastt = 20
End If
If lastt <> 20 Then _FreeImage tmp&(lastt)
lastt = tp
_Display
_Limit 20
Loop Until _KeyDown(27)
Sub new (i)
r(i).x = Rnd * 60 + 10
r(i).y = 50
r(i).bang = Rnd * 30
r(i).age = 0
r(i).c = _RGB32(200 * Rnd + 55, 200 * Rnd + 55, 200 * Rnd + 55)
End Sub
Sub drawRocket (i)
If r(i).y > r(i).bang Then
Color r(i).c
Locate r(i).y, r(i).x: Print Chr$(24);
r(i).y = r(i).y - 1
Else
r(i).age = r(i).age + 1
If r(i).age > 50 Then
new i
Else
Color r(i).c
If r(i).age > 4 Then start = r(i).age - 4 Else start = 1
For a = start To r(i).age
For j = 1 To 12
xx = r(i).x + 1 * a * Cos(j * _Pi / 6)
yy = r(i).y + .5 * a * Sin(j * _Pi / 6)
yy = yy + (r(i).y - a) ^ 2 / 15 '<<<< tsh73 gravity
If xx > 0 And xx < 81 And yy > 0 And yy < 51 Then
Locate Int(yy), Int(xx)
Print "*";
End If
Next
Next
End If
End If
End Sub
So, as the math midget I am, I stumbled upon a way to make 3D looking wire frames using the ATAN2 command which turns "Cartesian coordinates into global coordinates" or so I read. I don't understand why/how the position of the ship on the screen affects the rendering of the eleven 2D points I created. For example, pressing z and putting the ship on the left-hand side of the screen smooshes it flat. Can anyone explain to me on, say, an 8th grade level, what's going on triginomically here? What have I done?!
DATA180,25 ' 1 11 POINTS TO PLAY WITH, 1 is nose point DATA265,30 ' 2 DATA = THETA ANGLE, RADIUS - larger radius = closer to viewer DATA275,30 ' 3 DATA340,4 ' 4 DATA0,5 ' 5 DATA20,4 ' 6 DATA85,30 ' 7 DATA95,30 ' 8 DATA130,4 ' 9 DATA230,4 ' 10 DATA0,0 ' 11 DATA270,27 ' 12, side panel point DATA90,27 ' 13, other side panel FOR c = 1TOUBOUND(pnt) ' init points array READ angle, radius
pnt(c).ang = angle
pnt(c).radius = radius NEXT c
sizeChange2.5
sizeFactor = 38' start up settings
adder = .25
angle = 270
fpChange = 66' the nose point
pnt(1).radius = pnt(1).radius + fpChange drawStars
DO CLS FOR c = 1TOUBOUND(pnt) ' rotate ship
pnt(c).ang = pnt(c).ang + adder
radians = _D2R(pnt(c).ang)
pnt(c).x = pnt(c).radius * COS(radians) + shipX ' atan2 subbed for x/cos value spins in Y axis, neg for left side, pos for right
pnt(c).y = pnt(c).radius * _ATAN2(pnt(c).x, pnt(c).y) + shipY ' atan2 subbed for y/sin value spins in X axis, upside down, rightside up... NEXT c
_PUTIMAGE , starScape, 0 ' -----------------------------******************* LINE (pnt(1).x, pnt(1).y)-(pnt(2).x, pnt(2).y), yellow ' draw ship FOR c = 3TO8 LINE -(pnt(c).x, pnt(c).y), yellow NEXT c LINE (pnt(8).x, pnt(8).y)-(pnt(1).x, pnt(1).y), yellow LINE (pnt(3).x, pnt(3).y)-(pnt(1).x, pnt(1).y), yellow LINE (pnt(7).x, pnt(7).y)-(pnt(1).x, pnt(1).y), yellow LINE (pnt(2).x, pnt(2).y)-(pnt(10).x, pnt(10).y), yellow LINE (pnt(8).x, pnt(8).y)-(pnt(9).x, pnt(9).y), yellow LINE (pnt(10).x, pnt(10).y)-(pnt(11).x, pnt(11).y), yellow LINE (pnt(9).x, pnt(9).y)-(pnt(11).x, pnt(11).y), yellow LINE (pnt(5).x, pnt(5).y)-(pnt(11).x, pnt(11).y), yellow
IF_KEYDOWN(19200) THEN IF fpChange > -500THEN
pnt(1).radius = pnt(1).radius - 1' far point changes
fpChange = fpChange - 1 END IF END IF IF_KEYDOWN(19712) THEN IF fpChange < 500THEN
pnt(1).radius = pnt(1).radius + 1
fpChange = fpChange + 1 END IF END IF IF_KEYDOWN(97) THEN adder = -.5' angle changes IF_KEYDOWN(100) THEN adder = .5 IF_KEYDOWN(18432) THENIF sizeFactor < 150THENsizeChange1.01: sizeFactor = sizeFactor + .5' size changes IF_KEYDOWN(20480) THENIF sizeFactor > -250THENsizeChange.99: sizeFactor = sizeFactor - .5 IF_KEYDOWN(114) THEN adder = .2' r to rotate IF_KEYDOWN(115) THEN adder = 0' s to stop
angle = angle + adder ' auto-spin IF angle > 359THEN angle = 0' mind the angle IF angle < 0THEN angle = 359
handle& = _NewImage(800, 600, 32)
Screen handle&
Dim palentry As String * 3
Dim rgbpalette(256) As Long
Dim dat As String * 1
Open "c:\shu01.pcx" For Binary As #1
header$ = Space$(128)
Get #1, , header$: Cls
bitsper = Asc(Mid$(header$, 4, 1))
plane = Asc(Mid$(header$, 66, 1))
Seek #1, &H81
c = 1: sum = 1: j% = 1
Do
Get #1, , dat
Select Case Asc(dat)
Case Is < 192
mqh(c, j) = Asc(dat)
c = c + 1
sum = sum + 1
If c = scanline + 1 Then
j% = j% + 1
If j% = YRes + 1 Then Exit Do
c = 1
End If
Case Is > 192 And Asc(dat) <= 255
lps = Asc(dat) - 192
Seek #1, 129 + sum
Get #1, , dat
For a = 1 To lps
mqh(c, j%) = Asc(dat)
c = c + 1
If c = scanline + 1 Then
j% = j% + 1
If j% = YRes + 1 Then Exit Do
c = 1
End If
Next a
sum = sum + 2
End Select
Loop
For i% = 1 To YRes
For j% = 1 To XRes
PSet (j%, i%), rgbpalette&(mqh(j%, i%))
Next j%, i%
Close #1
End If
I highly prefer forums over chat rooms such as Discord, but there is one bad habit I don't miss from the message board era: excessive quotations. Here's a screenshot to provide an example, not with intent to pick on anyone:
Though the screenshot is on a cell phone which exacerbates the issue, "mobile" traffic is a substantial amount of Web traffic, so it seems ridiculous for a post to use an entire screen length. The actual content of the post is one sentence! Even on a laptop screen or external monitor, it's a slight irritation scrolling past multiple duplicates of both posts and code as one works their way through reading a thread.
Here's my etiquette: If I'm responding to the newest post in the thread, I don't think there is a need to quote at all. When I do quote, I try to reduce it to the specific part of the message being replied to. I cannot think of a common purpose to nest multiple quotes within each other. You can click the green arrow icon () next to a person's quote to revisit their post in full when additional context is needed.
The MyBB software provides a built-in way to eliminate excessive quoting by setting a value for Maximum Nested Quote Tags. It should be found here if they have not changed their UI: Admin Control Panel -> Configuration -> Settings -> Posting
TYPE Tile
Symbol AS STRING * 1
IsBox AS INTEGER
IsGoal AS INTEGER
HasBox AS INTEGER
HasPlayer AS INTEGER
END TYPE
TYPE Box
X AS INTEGER
Y AS INTEGER
Symbol AS STRING * 1
END TYPE
DIM SHARED Boxes(6) AS Box
DIM SHARED key$
DIM SHARED levelMap(1 TO 25) AS STRING * 25
DIM SHARED tileSymbol AS STRING
DIM SHARED MapTiles(MapWidth, MapHeight) AS Tile
DIM SHARED PlayerX, PlayerY
DIM SHARED NumGoals, GoalsCompleted
DIM SHARED GoalsCoveredCount AS INTEGER
DIM SHARED prevX AS INTEGER
DIM SHARED prevY AS INTEGER
DIM SHARED newX AS INTEGER
DIM SHARED newY AS INTEGER
DIM SHARED newBoxX AS INTEGER
DIM SHARED newBoxY AS INTEGER
DIM SHARED fontfile$
DIM SHARED f&
DIM SHARED ascIIcode AS SINGLE
DIM SHARED unicode
DIM SHARED currentTile AS Tile
DIM SHARED boxTile AS Tile
DIM SHARED newTile AS Tile
' Icons
DIM SHARED playerIcon AS LONG
DIM SHARED boxIcon AS LONG
DIM SHARED goalIcon AS LONG
DIM SHARED emptyTileIcon AS LONG
DIM SHARED boxOnGoalIcon AS LONG
DIM SHARED playerOnGoalIcon AS LONG
DIM SHARED wallIcon AS LONG
DIM SHARED folder$
folder$ = "D:\qb64pe\Assets\"
SCREEN _NEWIMAGE(1264, 878, 32) ' Create new screen
' Load a font that supports Greek characters
fontfile$ = "C:\windows\fonts\lucon.ttf"
f& = _LOADFONT(fontfile$, 20, "MONOSPACE")
_FONT f&
' Load icons and check for errors
playerIcon = _LOADIMAGE(folder$ + "player.png", 32)
' Initialize GoalsCoveredCount to 0
GoalsCoveredCount = 0
' Initialize the game
InitializeGame
' Load level 1
LoadLevel 1
DO
_LIMIT 60
DrawMap
_DISPLAY
DO
key$ = INKEY$
IF LEN(key$) > 0 THEN EXIT DO
LOOP
IF key$ = CHR$(27) THEN EXIT DO ' Exit on Escape key
newX = PlayerX
newY = PlayerY
SELECT CASE UCASE$(key$)
CASE "W", CHR$(0) + CHR$(72) ' Up arrow or "w" key
newY = PlayerY - 1
CASE "S", CHR$(0) + CHR$(80) ' Down arrow or "s" key
newY = PlayerY + 1
CASE "A", CHR$(0) + CHR$(75) ' Left arrow or "a" key
newX = PlayerX - 1
CASE "D", CHR$(0) + CHR$(77) ' Right arrow or "d" key
newX = PlayerX + 1
END SELECT
' Check player movement
IF newX >= 1 AND newX <= MapWidth AND newY >= 1 AND newY <= MapHeight THEN
IF MapTiles(newX, newY).Symbol = " " OR MapTiles(newX, newY).Symbol = "." THEN
MovePlayer newX, newY
ELSEIF MapTiles(newX, newY).Symbol = "$" OR MapTiles(newX, newY).Symbol = "*" THEN
newBoxX = newX + (newX - PlayerX)
newBoxY = newY + (newY - PlayerY)
IF newBoxX >= 1 AND newBoxX <= MapWidth AND newBoxY >= 1 AND newBoxY <= MapHeight THEN
IF MapTiles(newBoxX, newBoxY).Symbol = " " OR MapTiles(newBoxX, newBoxY).Symbol = "." THEN
MoveBox newX, newY, newBoxX, newBoxY
MovePlayer newX, newY
END IF
END IF
END IF
END IF
LOOP UNTIL GoalsCompleted = NumGoals
CLS
PRINT "Congratulations! You completed the level."
END
' Subroutine to draw the map
SUB DrawMap
DIM x AS INTEGER
DIM y AS INTEGER
CLS
FOR y = 1 TO MapHeight
FOR x = 1 TO MapWidth
SELECT CASE MapTiles(x, y).Symbol
CASE "@"
IF playerIcon <> -1 THEN _PUTIMAGE (x * TileWidth, y * TileHeight), playerIcon
CASE "$"
IF MapTiles(x, y).IsGoal THEN
IF boxOnGoalIcon <> -1 THEN _PUTIMAGE (x * TileWidth, y * TileHeight), boxOnGoalIcon
ELSE
IF boxIcon <> -1 THEN _PUTIMAGE (x * TileWidth, y * TileHeight), boxIcon
END IF
CASE "."
IF goalIcon <> -1 THEN _PUTIMAGE (x * TileWidth, y * TileHeight), goalIcon
CASE " "
IF emptyTileIcon <> -1 THEN _PUTIMAGE (x * TileWidth, y * TileHeight), emptyTileIcon
CASE "+"
IF playerOnGoalIcon <> -1 THEN _PUTIMAGE (x * TileWidth, y * TileHeight), playerOnGoalIcon
CASE "*"
IF boxOnGoalIcon <> -1 THEN _PUTIMAGE (x * TileWidth, y * TileHeight), boxOnGoalIcon
CASE "#"
IF wallIcon <> -1 THEN _PUTIMAGE (x * TileWidth, y * TileHeight), wallIcon
END SELECT
NEXT x
NEXT y
GreekChange
_PRINTSTRING (10, 10), "Goals completed: " + STR$(GoalsCoveredCount) + "/" + STR$(NumGoals)
EnglChange
END SUB
' Subroutine to move the player
SUB MovePlayer (newX, newY)
prevX = PlayerX
prevY = PlayerY
' Update the tile the player is leaving
currentTile = MapTiles(prevX, prevY)
IF currentTile.IsGoal = 1 THEN
MapTiles(prevX, prevY).Symbol = "."
ELSE
MapTiles(prevX, prevY).Symbol = " "
END IF
' Move the player to the new position
PlayerX = newX
PlayerY = newY
' Update the tile the player is moving to
currentTile = MapTiles(PlayerX, PlayerY)
IF currentTile.IsGoal = 1 THEN
MapTiles(PlayerX, PlayerY).Symbol = "+"
ELSE
MapTiles(PlayerX, PlayerY).Symbol = "@"
END IF
END SUB
' Subroutine to move a box
SUB MoveBox (boxX AS INTEGER, boxY AS INTEGER, newBoxX AS INTEGER, newBoxY AS INTEGER)
DIM i AS INTEGER
boxTile = MapTiles(boxX, boxY)
newTile = MapTiles(newBoxX, newBoxY)
IF newTile.Symbol = "." OR newTile.Symbol = " " THEN
' Update the tile the box is leaving
IF boxTile.IsGoal = 1 THEN
MapTiles(boxX, boxY).Symbol = "."
ELSE
MapTiles(boxX, boxY).Symbol = " "
END IF
' Update the tile the box is moving to
MapTiles(newBoxX, newBoxY).Symbol = "$"
MapTiles(newBoxX, newBoxY).HasBox = 1
MapTiles(boxX, boxY).HasBox = 0
' Update the position of the box
FOR i = 1 TO 6
IF Boxes(i).X = boxX AND Boxes(i).Y = boxY THEN
Boxes(i).X = newBoxX
Boxes(i).Y = newBoxY
EXIT FOR
END IF
NEXT i
' Update the goals covered
IF MapTiles(newBoxX, newBoxY).IsGoal = 1 THEN
GoalsCoveredCount = GoalsCoveredCount + 1
END IF
IF MapTiles(boxX, boxY).IsGoal = 1 THEN
GoalsCoveredCount = GoalsCoveredCount - 1
END IF
' Check if all goals are covered
IF GoalsCoveredCount = NumGoals THEN
GoalsCompleted = GoalsCompleted + 1
END IF
END IF
END SUB
' Subroutine to initialize the game
SUB InitializeGame ()
DIM y AS INTEGER
DIM x AS INTEGER
NumGoals = 0 ' Initialize the goals
GoalsCompleted = 0
PlayerX = 14
PlayerY = 4
MapTiles(PlayerX, PlayerY).Symbol = "@"
FOR y = 1 TO MapHeight
FOR x = 1 TO MapWidth
MapTiles(x, y).Symbol = " "
MapTiles(x, y).IsGoal = 0
MapTiles(x, y).IsBox = 0
NEXT x
NEXT y
END SUB
IF tileSymbol = "$" THEN
FOR i = 1 TO 6
IF Boxes(i).X = 0 AND Boxes(i).Y = 0 THEN
Boxes(i).Symbol = "$"
Boxes(i).X = col
Boxes(i).Y = row
EXIT FOR
END IF
NEXT i
MapTiles(col, row).IsBox = 1
MapTiles(col, row).HasBox = 1
END IF
IF tileSymbol = "." OR tileSymbol = "*" THEN
MapTiles(col, row).IsGoal = 1
NumGoals = NumGoals + 1 ' Update total goals
END IF
' Check if box is on a goal
IF tileSymbol = "*" THEN
GoalsCoveredCount = GoalsCoveredCount + 1 ' Update goals covered count
MapTiles(col, row).HasBox = 1
END IF
NEXT col
NEXT row
END SUB
' Subroutine to switch to Greek characters
SUB GreekChange
RESTORE GreekUnicodeMap
FOR ascIIcode = 128 TO 255
READ unicode
_MAPUNICODE unicode TO ascIIcode
NEXT
GreekUnicodeMap:
'Microsoft_windows_cp1253
DATA 8364,0,8218,402,8222,8230,8224,8225,0,8240,0,8249,0,0,0,0
DATA 0,8216,8217,8220,8221,8226,8211,8212,0,8482,0,8250,0,0,0,0
DATA 160,901,902,163,164,165,166,167,168,169,0,171,172,173,174,8213
DATA 176,177,178,179,900,181,182,183,904,905,906,187,908,189,910,911
DATA 912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927
DATA 928,929,0,931,932,933,934,935,936,937,938,939,940,941,942,943
DATA 944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959
DATA 960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,0
END SUB
' Subroutine to switch to English characters
SUB EnglChange
RESTORE EnglUnicodeMap
FOR ascIIcode = 128 TO 255
READ unicode
_MAPUNICODE unicode TO ascIIcode
NEXT
EnglUnicodeMap:
'Microsoft_pc_cp437
DATA 199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197
DATA 201,230,198,244,246,242,251,249,255,214,220,162,163,165,8359,402
DATA 225,237,243,250,241,209,170,186,191,8976,172,189,188,161,171,187
DATA 9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488
DATA 9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575
DATA 9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600
DATA 945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745
DATA 8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160
END SUB
Enjoy the Game
Guslouk
To be continue.
Assets.zip (Size: 238.69 KB / Downloads: 32)
This error reported in QB45 has been there forever:
Code: (Select All)
Rem oldest QB45 bug ever known.
x$ = "9"
x = Int(Val(x$))
Print x ' returns 8
x = Int(Val(x$) + .5)
Print x ' returns 9
Rem no bug here:
x = CSng(Val(x$))
Print x ' returns 9
x = CInt(Val(x$))
Print x ' returns 9
x = Int(Val("&H" + x$))
Print x ' returns 9
End
However QB64 does not duplicate this error.
Am I incorrect in assuming this bug has been squashed?
So, using arrays as record elements is not possible in QB. OK, but declaring record arrays is also possible in QB.
I've tried this according to the QBasic manual, only a rudimentary guide, but something isn't working. The program runs without errors, but there is no meaningful output. I'm thinking wrong.
Code: (Select All)
Type Motorrad
Modell As String * 30
Kilowatt As Double
Preis As Double
End Type
Onwards and backwards, as we're now down to the new version 3.4+ keywords! To start with, let's just start at the top of the list and discuss _NotifyPopUp.
Not at all like our last keyword (BACK! BACK, EVIL _UCHARPOS!! BACK, I SAY!!), this one is rather simple to make use of and understand.
A simple SUB, this command will sent one of those annoying little pop-up notifications to your PC, that we all love to hate. You know the ones I'm talking about -- those little square boxes that usually pop up over in some corner of the screen saying junk like, "Your Firewall is Turned Off. Do you want to fix it now?". Or, "We've discovered an update for Spammy Spam-Spam! Would you like to enable it now?" Or, "Download finished at 1:13:47AM."
Yeah... This creates THOSE annoying little notification pop-ups.
Usage is simple enough that it's almost a waste to go over it. Call the command, supply it a few parameters. Presto -- done!!
So what is the command and those parameters??
_NOTIFYPOPUP [title$][, message$][, iconType$]
_NOTIFYPOPUP -- the name of the command! (Phew! That was hard to explain!) title$ -- the title that appears at the top of the notification. message$ -- the body of text that makes up the message for the notification. icontype$ -- "info", "error", ot "warning". Choose from one of those three so your notification will have the corresponding gpahiic stamped on it.
Code: (Select All)
_NOTIFYPOPUP "My Cool App", "Conversion complete!", "info"
Run the above and it'll either do something.... or it won't.
If you have notifications turned off, or "Do Not Disturb" turned on, then your system will simply ignore the command and not bother you. It's not that you did anything wrong, or that the command doesn't work -- it's just that you've disabled notifications and can't recieve them. (Think of it as turning off your phone and then someone trying to call you... Nothing happens on your end as the phone is off; but that doesn't mean the other person's phone isn't dialing out, or working as it's supposed to. You're just not responding to it.)
If notifications are on, and "Do not disturb" is off, then you should see one of those annoying little pop-ups appear at the corner of your screen telling you that an imaginary conversion is now completed.