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

Username/Email:
  

Password
  





Search Forums

(Advanced Search)

Forum Statistics
» Members: 483
» Latest member: aplus
» Forum threads: 2,799
» Forum posts: 26,378

Full Statistics

Latest Threads
Merry Christmas Globes!
Forum: Programs
Last Post: SierraKen
2 hours ago
» Replies: 3
» Views: 29
List of file sound extens...
Forum: Help Me!
Last Post: SMcNeill
2 hours ago
» Replies: 13
» Views: 181
Merry Christmas Globes!
Forum: Christmas Code
Last Post: SierraKen
6 hours ago
» Replies: 1
» Views: 22
fast file find with wildc...
Forum: Help Me!
Last Post: madscijr
6 hours ago
» Replies: 2
» Views: 48
Raspberry OS
Forum: Help Me!
Last Post: Pete
8 hours ago
» Replies: 1
» Views: 36
Tenary operator in QB64 w...
Forum: Utilities
Last Post: Pete
8 hours ago
» Replies: 6
» Views: 84
Video Renamer
Forum: Works in Progress
Last Post: Pete
9 hours ago
» Replies: 3
» Views: 55
Need help capturng unicod...
Forum: General Discussion
Last Post: SMcNeill
9 hours ago
» Replies: 24
» Views: 323
QB64PE v4.0 is now live!!
Forum: Announcements
Last Post: RhoSigma
9 hours ago
» Replies: 35
» Views: 1,048
Remark Remover (WIP)
Forum: Works in Progress
Last Post: Pete
10 hours ago
» Replies: 0
» Views: 12

 
  Tic-Tac-Toe
Posted by: SierraKen - 08-26-2024, 09:07 PM - Forum: SierraKen - No Replies

This is a one-player Tic-Tac-Toe game using the mouse. 

Code: (Select All)

'I've wanted to make this game for decades and finally am able to!
'This game was made on August 14, 2019 by SierraKen.
'This is Freeware.
'Jan. 28, 2021 update: Choose at random who goes first.
'Jan. 29, 2021 update: Random colored grid, better looking X's, faster welcome screen, centered welcome screen better, made the ability to click to play a new game and another game,
'and added text colors.
'Jan. 30, 2021 update: Added background blue shades. Also added a score in the Title Bar. Turned the game into 3D - Thanks to B+ for the idea!


Dim a(10), b(10)
_Limit 60
_Title "Tic-Tac-Toe    by SierraKen"
Screen _NewImage(600, 480, 32)
Cls
Print: Print: Print
Locate 10, 34: Print "-"
Locate 10, 40: Print "-"
For tic = 1 To 10
    Locate tic, 30: Print "TIC"
    _Delay .1
    Locate tic, 30: Print "  "
Next tic
Locate 10, 30: Print "TIC"
For tac = 20 To 10 Step -1
    Locate tac, 36: Print "TAC"
    _Delay .1
    Locate tac, 36: Print "  "
Next tac
Locate 10, 36: Print "TAC"
For toe = 1 To 10
    Locate toe, 42: Print "TOE"
    _Delay .1
    Locate toe, 42: Print "  "
Next toe
Locate 10, 42: Print "TOE"
computer = 0
you = 0

Print: Print: Print
Print "                              By  SierraKen"
Print: Print: Print
Print "      Play against the computer in this classic game of Tic-Tac-Toe."
Print "                      Whoever gets 3 in a row wins."
Print
Print "                    Choose a sqace by using your mouse."
Print "                    Computer chooses who goes first."

Color _RGB32(255, 255, 255), _ClearColor
_PrintString (220, 430), "Click Here To Start"
Color _RGB32(255, 255, 255), _RGB32(0, 0, 0)

Do
    _Limit 60
    mouseWheel = 0
    Do While _MouseInput
        mouseX = _MouseX
        mouseY = _MouseY
        mouseLeftButton = _MouseButton(1)
        mouseRightButton = _MouseButton(2)
        mouseMiddleButton = _MouseButton(3)
        mouseWheel = mouseWheel + _MouseWheel
    Loop
    ag$ = InKey$
    If ag$ = Chr$(27) Then End
    If ag$ = " " Then Cls: GoTo start:
    If mouseLeftButton = -1 And mouseX > 220 And mouseX < 370 And mouseY > 430 And mouseY < 446 Then Cls: GoTo start:
Loop

start:
ag$ = ""
t = 0
turn = 0
comp = 0

For cc = 0 To 480
    cl = cl + .5
    Line (0, cc)-(640, cc), _RGB32(0, 0, cl)
Next cc
cl = 0
Randomize Timer
c1 = Int(Rnd * 155) + 100
c2 = Int(Rnd * 155) + 100
c3 = Int(Rnd * 155) + 100

GoSub grid:

whosfirst:
Randomize Timer
first = Int(Rnd * 2) + 1
If first = 1 Then GoTo computerchoice:

Go:
_Limit 60
a$ = InKey$
If a$ = Chr$(27) Then End
mouseWheel = 0
Do While _MouseInput
    mouseX = _MouseX
    mouseY = _MouseY
    mouseLeftButton = _MouseButton(1)
    mouseRightButton = _MouseButton(2)
    mouseMiddleButton = _MouseButton(3)
    mouseWheel = mouseWheel + _MouseWheel
Loop

If mouseLeftButton = -1 Then
    If mouseX > 88 And mouseX < 218 And mouseY > 93 And mouseY < 182 And b(1) = 0 And a(1) = 0 And t = 0 Then GoSub space1:
    If mouseX > 241 And mouseX < 357 And mouseY > 93 And mouseY < 182 And b(2) = 0 And a(2) = 0 And t = 0 Then GoSub space2:
    If mouseX > 381 And mouseX < 509 And mouseY > 93 And mouseY < 182 And b(3) = 0 And a(3) = 0 And t = 0 Then GoSub space3:
    If mouseX > 88 And mouseX < 218 And mouseY > 205 And mouseY < 302 And b(4) = 0 And a(4) = 0 And t = 0 Then GoSub space4:
    If mouseX > 241 And mouseX < 357 And mouseY > 205 And mouseY < 302 And b(5) = 0 And a(5) = 0 And t = 0 Then GoSub space5:
    If mouseX > 381 And mouseX < 509 And mouseY > 205 And mouseY < 302 And b(6) = 0 And a(6) = 0 And t = 0 Then GoSub space6:
    If mouseX > 88 And mouseX < 218 And mouseY > 326 And mouseY < 410 And b(7) = 0 And a(7) = 0 And t = 0 Then GoSub space7:
    If mouseX > 241 And mouseX < 357 And mouseY > 326 And mouseY < 410 And b(8) = 0 And a(8) = 0 And t = 0 Then GoSub space8:
    If mouseX > 381 And mouseX < 509 And mouseY > 326 And mouseY < 410 And b(9) = 0 And a(9) = 0 And t = 0 Then GoSub space9:
End If

If mouseLeftButton = -1 And ending = 1 Then GoTo start:
If mouseRightButton = -1 And ending = 1 Then End

If t = 1 Then GoSub computer:

GoTo Go:

checkwin:
'Check to see if you won.
If a(1) = 1 And a(2) = 1 And a(3) = 1 Then GoTo won:
If a(4) = 1 And a(5) = 1 And a(6) = 1 Then GoTo won:
If a(7) = 1 And a(8) = 1 And a(9) = 1 Then GoTo won
If a(1) = 1 And a(4) = 1 And a(7) = 1 Then GoTo won:
If a(2) = 1 And a(5) = 1 And a(8) = 1 Then GoTo won:
If a(3) = 1 And a(6) = 1 And a(9) = 1 Then GoTo won:
If a(1) = 1 And a(5) = 1 And a(9) = 1 Then GoTo won:
If a(3) = 1 And a(5) = 1 And a(7) = 1 Then GoTo won:
turn = turn + 1
Sound 100, .25
If turn = 9 Then GoTo catsgame:
GoTo Go:
won:
For snd = 300 To 900 Step 50
    Sound snd, .5
Next snd
For tt = 1 To 9
    a(tt) = 0
    b(tt) = 0
Next tt
you = you + 1
you$ = Str$(you)
computer$ = Str$(computer)
_Title "You: " + you$ + "  Computer: " + comp$
t = 0
Color _RGB32(255, 0, 0), _ClearColor
Locate 2, 32: Print "Y O U  W I N ! !"
Color _RGB32(255, 255, 255), _RGB32(0, 0, 0)
GoTo playagain:

computer:

'Check to win.
'Last space gone.
If b(1) = 1 And b(2) = 1 And a(3) = 0 And b(3) = 0 Then GoTo compspace3:
If b(4) = 1 And b(5) = 1 And a(6) = 0 And b(6) = 0 Then GoTo compspace6:
If b(7) = 1 And b(8) = 1 And a(9) = 0 And b(9) = 0 Then GoTo compspace9:
If b(1) = 1 And b(4) = 1 And a(7) = 0 And b(7) = 0 Then GoTo compspace7:
If b(2) = 1 And b(5) = 1 And a(8) = 0 And b(8) = 0 Then GoTo compspace8:
If b(3) = 1 And b(6) = 1 And a(9) = 0 And b(9) = 0 Then GoTo compspace9:
If b(1) = 1 And b(5) = 1 And a(9) = 0 And b(9) = 0 Then GoTo compspace9:
If b(3) = 1 And b(5) = 1 And a(7) = 0 And b(7) = 0 Then GoTo compspace7:
'First space gone.
If b(2) = 1 And b(3) = 1 And a(1) = 0 And b(1) = 0 Then GoTo compspace1:
If b(5) = 1 And b(6) = 1 And a(4) = 0 And b(4) = 0 Then GoTo compspace4:
If b(8) = 1 And b(9) = 1 And a(7) = 0 And b(7) = 0 Then GoTo compspace7:
If b(4) = 1 And b(7) = 1 And a(1) = 0 And b(1) = 0 Then GoTo compspace1:
If b(5) = 1 And b(8) = 1 And a(2) = 0 And b(2) = 0 Then GoTo compspace2:
If b(6) = 1 And b(9) = 1 And a(3) = 0 And b(3) = 0 Then GoTo compspace3:
If b(5) = 1 And b(9) = 1 And a(1) = 0 And b(1) = 0 Then GoTo compspace1:
If b(7) = 1 And b(5) = 1 And a(3) = 0 And b(3) = 0 Then GoTo compspace3:
'Middle space gone.
If b(1) = 1 And b(3) = 1 And a(2) = 0 And b(2) = 0 Then GoTo compspace2:
If b(4) = 1 And b(6) = 1 And a(5) = 0 And b(5) = 0 Then GoTo compspace5:
If b(7) = 1 And b(9) = 1 And a(8) = 0 And b(8) = 0 Then GoTo compspace8:
If b(1) = 1 And b(7) = 1 And a(4) = 0 And b(4) = 0 Then GoTo compspace4:
If b(2) = 1 And b(8) = 1 And a(5) = 0 And b(5) = 0 Then GoTo compspace5:
If b(3) = 1 And b(9) = 1 And a(6) = 0 And b(6) = 0 Then GoTo compspace6:
If b(1) = 1 And b(9) = 1 And a(5) = 0 And b(5) = 0 Then GoTo compspace5:
If b(3) = 1 And b(7) = 1 And a(5) = 0 And b(5) = 0 Then GoTo compspace5:

'Check to block.
'Last space gone.
If a(1) = 1 And a(2) = 1 And a(3) = 0 And b(3) = 0 Then GoTo compspace3:
If a(4) = 1 And a(5) = 1 And a(6) = 0 And b(6) = 0 Then GoTo compspace6:
If a(7) = 1 And a(8) = 1 And a(9) = 0 And b(9) = 0 Then GoTo compspace9:
If a(1) = 1 And a(4) = 1 And a(7) = 0 And b(7) = 0 Then GoTo compspace7:
If a(2) = 1 And a(5) = 1 And a(8) = 0 And b(8) = 0 Then GoTo compspace8:
If a(3) = 1 And a(6) = 1 And a(9) = 0 And b(9) = 0 Then GoTo compspace9:
If a(1) = 1 And a(5) = 1 And a(9) = 0 And b(9) = 0 Then GoTo compspace9:
If a(3) = 1 And a(5) = 1 And a(7) = 0 And b(7) = 0 Then GoTo compspace7:
'First space gone.
If a(2) = 1 And a(3) = 1 And a(1) = 0 And b(1) = 0 Then GoTo compspace1:
If a(5) = 1 And a(6) = 1 And a(4) = 0 And b(4) = 0 Then GoTo compspace4:
If a(8) = 1 And a(9) = 1 And a(7) = 0 And b(7) = 0 Then GoTo compspace7:
If a(4) = 1 And a(7) = 1 And a(1) = 0 And b(1) = 0 Then GoTo compspace1:
If a(5) = 1 And a(8) = 1 And a(2) = 0 And b(2) = 0 Then GoTo compspace2:
If a(6) = 1 And a(9) = 1 And a(3) = 0 And b(3) = 0 Then GoTo compspace3:
If a(5) = 1 And a(9) = 1 And a(1) = 0 And b(1) = 0 Then GoTo compspace1:
If a(7) = 1 And a(5) = 1 And a(3) = 0 And b(3) = 0 Then GoTo compspace3:
'Middle space gone.
If a(1) = 1 And a(3) = 1 And a(2) = 0 And b(2) = 0 Then GoTo compspace2:
If a(4) = 1 And a(6) = 1 And a(5) = 0 And b(5) = 0 Then GoTo compspace5:
If a(7) = 1 And a(9) = 1 And a(8) = 0 And b(8) = 0 Then GoTo compspace8:
If a(1) = 1 And a(7) = 1 And a(4) = 0 And b(4) = 0 Then GoTo compspace4:
If a(2) = 1 And a(8) = 1 And a(5) = 0 And b(5) = 0 Then GoTo compspace5:
If a(3) = 1 And a(9) = 1 And a(6) = 0 And b(6) = 0 Then GoTo compspace6:
If a(1) = 1 And a(9) = 1 And a(5) = 0 And b(5) = 0 Then GoTo compspace5:
If a(3) = 1 And a(7) = 1 And a(5) = 0 And b(5) = 0 Then GoTo compspace5:

'Computer decides a random space.
computerchoice:
Randomize Timer
comp = Int(Rnd * 9) + 1
If b(comp) = 1 Then GoTo computerchoice:
If a(comp) = 1 Then GoTo computerchoice:
If comp = 1 Then GoTo compspace1:
If comp = 2 Then GoTo compspace2:
If comp = 3 Then GoTo compspace3:
If comp = 4 Then GoTo compspace4:
If comp = 5 Then GoTo compspace5:
If comp = 6 Then GoTo compspace6:
If comp = 7 Then GoTo compspace7:
If comp = 8 Then GoTo compspace8:
If comp = 9 Then GoTo compspace9:

'Cat's Game
catsgame:
For snd = 400 To 300 Step -25
    Sound snd, .5
Next snd
For tt = 1 To 9
    a(tt) = 0
    b(tt) = 0
Next tt
t = 0
Color _RGB32(255, 0, 255), _ClearColor
Locate 2, 29: Print "Cat's Game - No Winners"
Color _RGB32(255, 255, 255), _RGB32(0, 0, 0)
GoTo playagain:

'Check to see if the computer won.
check:
If b(1) = 1 And b(2) = 1 And b(3) = 1 Then GoTo compwon:
If b(4) = 1 And b(5) = 1 And b(6) = 1 Then GoTo compwon:
If b(7) = 1 And b(8) = 1 And b(9) = 1 Then GoTo compwon
If b(1) = 1 And b(4) = 1 And b(7) = 1 Then GoTo compwon:
If b(2) = 1 And b(5) = 1 And b(8) = 1 Then GoTo compwon:
If b(3) = 1 And b(6) = 1 And b(9) = 1 Then GoTo compwon:
If b(1) = 1 And b(5) = 1 And b(9) = 1 Then GoTo compwon:
If b(3) = 1 And b(5) = 1 And b(7) = 1 Then GoTo compwon:
turn = turn + 1
If turn = 9 Then GoTo catsgame:
t = 0
GoTo Go:

compwon:
For snd = 900 To 300 Step -50
    Sound snd, .5
Next snd
For tt = 1 To 9
    a(tt) = 0
    b(tt) = 0
Next tt
t = 0
computer = computer + 1
you$ = Str$(you)
comp$ = Str$(computer)
_Title "You: " + you$ + "  Computer: " + comp$
Color _RGB32(128, 255, 255), _ClearColor
Locate 2, 33: Print "Computer  Wins"
Color _RGB32(255, 255, 255), _RGB32(0, 0, 0)
GoTo playagain:

'This part draws the computer's circle.
compspace1:
t = 0
b(1) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Circle (160 - xx, 140 - xx), 40 - s, _RGB32(255 - (xx * 10), 0, 0)
    Next s
Next xx
GoSub grid:
GoTo check:
compspace2:
t = 0
b(2) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Circle (300 - xx, 140 - xx), 40 - s, _RGB32(255 - (xx * 10), 0, 0)
    Next s
Next xx
GoSub grid:
GoTo check:
compspace3:
t = 0
b(3) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Circle (440 - xx, 140 - xx), 40 - s, _RGB32(255 - (xx * 10), 0, 0)
    Next s
Next xx
GoSub grid:
GoTo check:
compspace4:
t = 0
b(4) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Circle (160 - xx, 260 - xx), 40 - s, _RGB32(255 - (xx * 10), 0, 0)
    Next s
Next xx
GoSub grid:
GoTo check:
compspace5:
t = 0
b(5) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Circle (300 - xx, 260 - xx), 40 - s, _RGB32(255 - (xx * 10), 0, 0)
    Next s
Next xx
GoSub grid:
GoTo check:
compspace6:
t = 0
b(6) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Circle (440 - xx, 260 - xx), 40 - s, _RGB32(255 - (xx * 10), 0, 0)
    Next s
Next xx
GoSub grid:
GoTo check:
compspace7:
t = 0
b(7) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Circle (160 - xx, 375 - xx), 40 - s, _RGB32(255 - (xx * 10), 0, 0)
    Next s
Next xx
GoTo check:
compspace8:
t = 0
b(8) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Circle (300 - xx, 375 - xx), 40 - s, _RGB32(255 - (xx * 10), 0, 0)
    Next s
Next xx
GoTo check:
compspace9:
t = 0
b(9) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Circle (440 - xx, 375 - xx), 40 - s, _RGB32(255 - (xx * 10), 0, 0)
    Next s
Next xx
GoTo check:
'This last part draws your X.
space1:
a(1) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Line (115 + s - xx, 104 - xx)-(195 + s - xx, 169 - xx), _RGB32(0, 255 - (xx * 10), 0)
        Line (195 + s - xx, 104 - xx)-(115 + s - xx, 169 - xx), _RGB32(0, 255 - (xx * 10), 0)
    Next s
Next xx
t = 1
GoTo checkwin:
space2:
a(2) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Line (255 + s - xx, 104 - xx)-(335 + s - xx, 169 - xx), _RGB32(0, 255 - (xx * 10), 0)
        Line (335 + s - xx, 104 - xx)-(255 + s - xx, 169 - xx), _RGB32(0, 255 - (xx * 10), 0)
    Next s
Next xx
t = 1
GoTo checkwin:
space3:
a(3) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Line (395 + s - xx, 104 - xx)-(475 + s - xx, 169 - xx), _RGB32(0, 255 - (xx * 10), 0)
        Line (475 + s - xx, 104 - xx)-(395 + s - xx, 169 - xx), _RGB32(0, 255 - (xx * 10), 0)
    Next s
Next xx
t = 1
GoTo checkwin:
space4:
a(4) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Line (110 + s - xx, 224 - xx)-(190 + s - xx, 289 - xx), _RGB32(0, 255 - (xx * 10), 0)
        Line (190 + s - xx, 224 - xx)-(110 + s - xx, 289 - xx), _RGB32(0, 255 - (xx * 10), 0)
    Next s
Next xx
t = 1
GoTo checkwin:
space5:
a(5) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Line (255 + s - xx, 224 - xx)-(335 + s - xx, 289 - xx), _RGB32(0, 255 - (xx * 10), 0)
        Line (335 + s - xx, 224 - xx)-(255 + s - xx, 289 - xx), _RGB32(0, 255 - (xx * 10), 0)
    Next s
Next xx
t = 1
GoTo checkwin:
space6:
a(6) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Line (395 + s - xx, 224 - xx)-(475 + s - xx, 289 - xx), _RGB32(0, 255 - (xx * 10), 0)
        Line (475 + s - xx, 224 - xx)-(395 + s - xx, 289 - xx), _RGB32(0, 255 - (xx * 10), 0)
    Next s
Next xx
t = 1
GoTo checkwin:
space7:
a(7) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Line (110 + s - xx, 339 - xx)-(190 + s - xx, 404 - xx), _RGB32(0, 255 - (xx * 10), 0)
        Line (190 + s - xx, 339 - xx)-(110 + s - xx, 404 - xx), _RGB32(0, 255 - (xx * 10), 0)
    Next s
Next xx
t = 1
GoTo checkwin:
space8:
a(8) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Line (255 + s - xx, 339 - xx)-(335 + s - xx, 404 - xx), _RGB32(0, 255 - (xx * 10), 0)
        Line (335 + s - xx, 339 - xx)-(255 + s - xx, 404 - xx), _RGB32(0, 255 - (xx * 10), 0)
    Next s
Next xx
t = 1
GoTo checkwin:
space9:
a(9) = 1
For xx = .1 To 10 Step .1
    For s = .25 To 10 Step .25
        Line (395 + s - xx, 339 - xx)-(475 + s - xx, 404 - xx), _RGB32(0, 255 - (xx * 10), 0)
        Line (475 + s - xx, 339 - xx)-(395 + s - xx, 404 - xx), _RGB32(0, 255 - (xx * 10), 0)
    Next s
Next xx
t = 1
GoTo checkwin:

playagain:
Color _RGB32(255, 0, 0), _ClearColor
_PrintString (220, 55), "Click Here To Play Again"
Color _RGB32(255, 255, 255), _RGB32(0, 0, 0)

Do
    _Limit 60
    mouseWheel = 0
    Do While _MouseInput
        mouseX = _MouseX
        mouseY = _MouseY
        mouseLeftButton = _MouseButton(1)
        mouseRightButton = _MouseButton(2)
        mouseMiddleButton = _MouseButton(3)
        mouseWheel = mouseWheel + _MouseWheel
    Loop
    ag$ = InKey$
    If ag$ = Chr$(27) Then End
    If ag$ = " " Then Cls: GoTo start:
    If mouseLeftButton = -1 And mouseX > 220 And mouseX < 412 And mouseY > 55 And mouseY < 69 Then Cls: GoTo start:
Loop

grid:
'Draw Grid
'Vertical Lines
For xx = .1 To 15 Step .1
    Line (220 - xx, 100 - xx)-(240 - xx, 410 - xx), _RGB32(c1 - (xx * 10), c2 - (xx * 10), c3 - (xx * 10)), BF
    Line (360 - xx, 100 - xx)-(380 - xx, 410 - xx), _RGB32(c1 - (xx * 10), c2 - (xx * 10), c3 - (xx * 10)), BF
Next xx
For xx = .1 To 15 Step .1
    'Horizontal Lines
    Line (90 - xx, 185 - xx)-(510 - xx, 205 - xx), _RGB32(c1 - (xx * 10), c2 - (xx * 10), c3 - (xx * 10)), BF
    Line (90 - xx, 305 - xx)-(510 - xx, 325 - xx), _RGB32(c1 - (xx * 10), c2 - (xx * 10), c3 - (xx * 10)), BF
Next xx
Return

Print this item

Question Close Encounters of the Fourth Kind
Posted by: Kernelpanic - 08-25-2024, 07:18 PM - Forum: General Discussion - Replies (2)

Out of over 1000 comments, suddenly only 994? Is there an explanation for this?  Rolleyes

Print this item

  Extended KotD #21: _MIDISOUNDBANK
Posted by: a740g - 08-25-2024, 04:07 PM - Forum: Keyword of the Day! - Replies (8)

_MIDISOUNDBANK is a QB64-PE v3.14.0 feature. However, before we dive straight into it, let's take a look at a bit of history.

What is MIDI?

MIDI (Musical Instrument Digital Interface) is a communication protocol that enables the control and synchronization of electronic musical instruments, software, and other devices. Unlike audio data, MIDI messages are lightweight, making them ideal for real-time performance and control. MIDI was standardized in 1983 by the MIDI Manufacturers Association (MMA), and its continued use today highlights its enduring versatility.

What is a MIDI File?

A MIDI file is a digital file format that stores MIDI data. Unlike audio files, which contain actual sound recordings, a MIDI file contains instructions for generating sound. These instructions include information such as note pitch, duration, velocity, and timing, as well as control changes and other parameters. MIDI files are highly compact because they do not store actual audio, making them ideal for efficient storage and manipulation of musical compositions. MIDI files can be played back by any MIDI-compatible device, which interprets the data and generates the corresponding sounds.

What is a MIDI soundbank?

A MIDI soundbank is a collection of audio samples and settings that a synthesizer uses to generate sounds when playing a MIDI file. It defines how the notes and instructions in the MIDI file will sound, allowing for different instrument tones and qualities.

QB64 and MIDI

The last SDL version of QB64 (v0.954) was the version that had native MIDI playback support. MIDI and several other audio formats were dropped in the OpenGL version of QB64. QB64-PE v3.2.0 reintroduced support for MIDI playback, although it was initially hidden behind $UNSTABLE:MIDI. QB64-PE v3.14.0 moved MIDI playback support out of $UNSTABLE:MIDI and made it a first-class feature. $UNSTABLE:MIDI and $MIDISOUNDFONT were deprecated, and the new _MIDISOUNDBANK statement was added.

_MIDISOUNDBANK Syntax

Code: (Select All)
_MIDISOUNDBANK: fileName$[, capabilities$]

fileName$ is the file name of the soundbank or a buffer containing the soundbank data.
capabilities$ (optional) can be two flags if specified.
  • "memory" - indicating that the fileName$ is a buffer and not a file name and one of the following.
  • "ad": Global Timbre Library format for Audio Interface Library.
  • "op2": DMX OPL-2 format.
  • "opl": Global Timbre Library format for Audio Interface Library.
  • "sf2": Creative's SoundFont 2.0 format.
  • "sf3": MuseScore's Ogg compressed Creative SoundFont 2.0 format.
  • "sfo": Bernhard Schelling's Ogg compressed Creative SoundFont 2.0 format.
  • "tmb": Apogee Sound System timbre format.
  • "wopl": Vitaly Novichkov's OPL3BankEditor format.

Example: Using an embedded soundbank
Code: (Select All)
$EMBED:'./tiny.sf2','mysf2'

_MIDISOUNDBANK _EMBEDDED$("mysf2"), "memory, sf2"

handle = _SNDOPEN("canyon.xmi")
_SNDPLAY handle

QB64-PE MIDI Player Engine

The QB64-PE MIDI player engine heavily borrows from the foobar2000 MIDI Player plugin (https://www.foobar2000.org/components/view/foo_midi). Unlike the foobar2000 plugin, however, the QB64-PE implementation is cross-platform, except for VSTi support (more on this later). The player internally uses various backends to play MIDI files. All backends need a soundbank. However, the Opal+yfmidi backend has a tiny soundbank embedded by default that is used to play MIDI files if no other soundbank is loaded.

Synth Type Setup Difficulty Platform Quality
Opal+yfmidi Frequency modulation None Can I play, Daddy? All Retro
Primesynth/TinySoundFontSample-based Less Don't hurt me. All Awesome
VSTi Implementation defined More Bring 'em on! Windows Hell yeah!

Playing a MIDI file without any soundbank loaded will default the MIDI engine to use the Opal+yfmidi backend and the default embedded soundbank. Note that the FM Synthesis used is similar to that of a real Yamaha OPL3. However, unlike hardware OPL3 that supports only 18 channels, the Opal+yfmidi backend supports 108 (18 x 6) channels. This allows it to produce exceptional quality retro-sounding music. External AD, OPL2, OPL, TMB, and WOPL FM bank formats are also supported by this backend.

Example: Playing a MIDI files using FM synthesis
Code: (Select All)
handle = _SNDOPEN("groove.xmi")

_SNDPLAY handle

The Primesynth/TinySoundFont backends support sample-based synthesis using SoundFonts (SF2). As such, they can reproduce music using real-life instrument sounds at very high quality. The TinySoundFont backend supports compressed SoundFonts like SF3 & SFO. Note that compression is lossy (OGG), and hence some degradation in quality can be perceived. QB64-PE does not contain any SoundFonts, so the user must specify a SoundFont using _MIDISOUNDBANK to use this backend.

Example: Playing a MIDI file using a SoundFont
Code: (Select All)
_MIDISOUNDBANK "4mgmgsmt.sf2"

handle = _SNDOPEN("onestop.mid")
_SNDPLAY handle

The VSTi backend is Windows-only because it uses a VSTi DLL. QB64-PE itself does not include any code from Steinberg Media Technologies. Therefore, it uses a VST Host module to communicate with the VSTi DLL. Yours truly has taken the effort to adapt the foobar2000 MIDI VST Host for QB64-PE, and the same is available at https://github.com/a740g/vsthost. One should compile the project using Visual Studio 2022 to get the vsthost32.exe and vsthost64.exe files. My sole motivation to add VSTi support to QB64-PE was to get MIDI playing using the Yamaha S-YXG50 VSTi found at https://veg.by/en/projects/syxg50/. A VSTi can be specified using _MIDISOUNDBANK. However, QB64-PE expects the VST Host to be in the same directory as the VSTi DLL. Otherwise, the VSTi will not be loaded, and playback will fail.

Example: Playing a MIDI file using a VSTi
Code: (Select All)
$IF WINDOWS THEN
_MIDISOUNDBANK "syxg50.dll" ' load VSTi on Windows
$ELSE
_MIDISOUNDBANK "4mgmgsmt.sf2" ' fallback to a SoundFont on other platforms
$ENDIF

handle = _SNDOPEN("onestop.mid")
_SNDPLAY handle

The example player (MIDIPlayer64) below contains code that shows how to load various soundbanks, use the various backends, and several other features. Feel free to experiment and use the code in your own projects.

[Image: Screenshot-2024-08-25-194929.png] [Image: Screenshot-2024-08-25-195032.png]

Things to try
  • Play monkey.mid and Wolfenstein 3D*.mid from the midis directory using FM Synthesis.
  • Play THE_RAIN.mid, ECHOES.mid, striving.mid, and DOOM MIDIs in the midis directory using soundbanks/gzdoom.sf2.
  • Play COLDWAVE.mid, MHBB.mid, and TK_EATS.mid in the midis directory using soundbanks/wingroove.sf2.
  • On Windows, play bi2_polkovnik.mid, Cop Out by Sam Sketty YME '96.mid, Fool's World (XG).mid, The Major Seven (XG).mid, and Technocrat XG Sam Cardon.mid using soundbanks/syxg50.dll.

Cheers!

Questions?



Attached Files
.zip   MIDIPlayer64.zip (Size: 10.89 MB / Downloads: 34)
Print this item

  Bug in _SNDOPEN (fixed in v3.14.1)
Posted by: BDS107 - 08-25-2024, 03:56 PM - Forum: General Discussion - Replies (2)

Is it possible that there is a limit on the $EMBED or _EMBEDDED$?
When I have loaded some sounds, I get a repeat of the first or second sound. I can never play them all.

Example below where 5 different MP3 files are read. But the same sounds are played.
Can you test it? I am using the latest version, so the 3.14 of QB-PE.
In the example you choose 5 MP3 files yourself.


Code: (Select All)
$EMBED:'D:\Sound\Sound-1.MP3','SOUND1'
$EMBED:'D:\Sound\Sound-2.MP3','SOUND2'
$EMBED:'D:\Sound\Sound-3.MP3','SOUND3'
$EMBED:'D:\Sound\Sound-4.MP3','SOUND4'
$EMBED:'D:\Sound\Sound-5.MP3','SOUND5'

'DIM handles
DIM SHARED SND1&, SND2&, SND3&, SND4&, SND5&

DIM Gedaan AS INTEGER
Gedaan = 0

'LOAD the music files
SND1& = _SNDOPEN(_EMBEDDED$("SOUND1"), "MEMORY")
SND2& = _SNDOPEN(_EMBEDDED$("SOUND2"), "MEMORY")
SND3& = _SNDOPEN(_EMBEDDED$("SOUND3"), "MEMORY")
SND4& = _SNDOPEN(_EMBEDDED$("SOUND4"), "MEMORY")
SND5& = _SNDOPEN(_EMBEDDED$("SOUND5"), "MEMORY")

'Simple menu
DO
    PRINT "1 = sound 1"
    PRINT "2 = sound 2"
    PRINT "3 = sound 3"
    PRINT "4 = sound 4"
    PRINT "5 = sound 5"
    PRINT
    PRINT "ESC = END"
    a$ = INPUT$(1)

    IF a$ = CHR$(27) THEN Gedaan = 1

    IF a$ = "1" THEN
        IF SND1& THEN _SNDPLAY SND1&
    END IF

    IF a$ = "2" THEN
        IF SND2& THEN _SNDPLAY SND2&
    END IF

    IF a$ = "3" THEN
        IF SND3& THEN _SNDPLAY SND3&
    END IF

    IF a$ = "4" THEN
        IF SND4& THEN _SNDPLAY SND4&
    END IF

    IF a$ = "5" THEN
        IF SND5& THEN _SNDPLAY SND5&
    END IF

LOOP UNTIL Gedaan = 1

'END program
_SNDCLOSE SND1&
_SNDCLOSE SND2&
_SNDCLOSE SND3&
_SNDCLOSE SND4&
_SNDCLOSE SND5&
SYSTEM

Print this item

  BallShoot - A bare bones shooter game easy to expand on.
Posted by: Dav - 08-24-2024, 11:46 PM - Forum: Games - Replies (30)

Here's a bare-bones shooter game example that I *think* is easy to learn from and to expand on.  It's pretty simple.  Shoot the balls, don't let any pass you or touch you.  Move the piece at the bottom LEFT/RIGHT using the arrow keys, SPACE shoots.  ESC quits.   If a ball hits you or you let one pass the game is over.

Nothing much of a game, but it was a lazy Saturday and I just wanted to code something.  Maybe some can make use of it.  It would be easy to expand this little shooter.

- Dav

Note: Get the lastest ballshoot v8 HERE

Code: (Select All)
'=============
'ballshoot.bas
'=============
'A bare-bones small shooter game that you can expand on.
'Coded by Dav, AUG/2024 for QB64PE v3.13

'Move player using arrow keys - SPACE bar shoots.
'Shoot the balls. Don't let any hit you or pass you by.

'This is a basic shooter game that is easy enough to
'learn from and expand on so you can make your own game,
'I used balls as an enemy because I had a ball SUB handy,
'and it had a colorful effect.  I used it for the enemy
'as well has for the shots.  I also used an alpha screen
'clearing method using LINE instead of CLS.  This gave
'all the moving pieces a neat trailing/fade effect.

'Game is over if a ball hits you our you let one pass.

'There are many ways to exand this into something better.
'If you do make more out of it, please share it also.


Randomize Timer

balls = 6 'number of balls at one time
shots = 6 'number of shots allowed on screen

Dim ballx(1 To balls) 'ball x pos
Dim bally(1 To balls) 'ball y pos
Dim balld(1 To balls) 'ball direction
Dim ballr(1 To balls) 'ball radius

Dim shotx(1 To shots) 'shot x pos
Dim shoty(1 To shots) 'shot y pos
Dim shota(1 To shots) 'flag if shot is active


Screen _NewImage(640, 480, 32)
_FullScreen _SquarePixels

'set game defaults
score = 0 'score is zero
shotcount = 0 'no active shots
playerx = _Width / 2 'x pos of player
playery = 475 'y pos of player (this stays same)

'generate random ball info
For i = 1 To balls
    ballx(i) = Int(Rnd * _Width) + 1 'x pos
    bally(i) = Int(Rnd * (_Height / 4)) + 1 'y pos
    balld(i) = Int(Rnd * 3) - 1 'moving direction
    ballr(i) = 10 + Int(Rnd * 20) 'radius
Next

'=== main game loop ===

Do

    'this make the trailing fade effect on screen (cooler than doing CLS)
    Line (0, 0)-(_Width, _Height), _RGBA(0, 0, 0, 75), BF

    'add some screen sparklers
    Line (Rnd * _Width, Rnd * _Height)-Step(Rnd * 3, Rnd * 3), _RGBA(255, 255, 255, Rnd * 200), BF

    'handle all balls
    For i = 1 To balls

        'randomly change ball direction by making a -1, 0 or 1 to add to x pos , sometimes.
        If Rnd < .1 Then balld(i) = Int(Rnd * 3) - 1

        'update ball x/y pos
        ballx(i) = ballx(i) + balld(i) 'new ball x pos, with randomly generated direction
        bally(i) = bally(i) + 1 'drift ball y pos down...

        'make sure ball stays in bounds
        If ballx(i) < ballr(i) Then ballx(i) = ballr(i)
        If ballx(i) > (_Width - ballr(i)) Then ballx(i) = (_Width - ballr(i))

        'if you missed shooting a ball and it goes off screen, end game
        If bally(i) > _Height Then End

        'finally draw ball....
        glowball ballx(i), bally(i), ballr(i), 255, 255, 255, 255

    Next

    'draw player along bottom of screen
    Line (playerx - 5, playery - 5)-(playerx + 5, playery + 5), _RGB(255, Rnd * 125, Rnd * 128), BF
    Line (playerx - 5, playery - 5)-(playerx + 5, playery + 5), _RGB(0, 0, Rnd * 255), B

    'handle all active shots...
    For i = 1 To shotcount
        If shota(i) Then
            'draw the shot
            glowball shotx(i), shoty(i), 3, 255, 0, 0, 255
            shoty(i) = shoty(i) - 5 'make shot go up
            'if shot goes up off screen...
            If shoty(i) < 0 Then shota(i) = 0 'set shot active flag off
        End If
    Next

    'left/right arrows move player
    If _KeyDown(19200) Then playerx = playerx - 5 'left arrow, move left
    If _KeyDown(19712) Then playerx = playerx + 5 'right arrow, move right

    'make sure player doesn't go off screen
    If playerx < 0 Then
        playerx = 0
    ElseIf playerx > (_Width - 1) Then
        playerx = (_Width - 1)
    End If

    'Spacebar fires a shot
    If _KeyDown(32) Then
        'look for first inactive shot to shoot
        For i = 1 To UBound(shota)
            'if this one is free, and lastshot time passed...
            If shota(i) = 0 And Timer - lastshot > .2 Then
                shotx(i) = playerx 'give it our x/y
                shoty(i) = playery
                shota(i) = 1 'mark it as active
                'update shot count
                If i > shotcount Then shotcount = i
                lastshot = Timer 'mark time of this shot....
                'Note: I'm using shot timer to prevent too rapid fire of shots
                Exit For
            End If
        Next
    End If

    'see if shot hits a ball
    For i = 1 To balls
        For j = 1 To shotcount
            If shota(j) Then
                If Abs(ballx(i) - shotx(j)) < ballr(i) And Abs(bally(i) - shoty(j)) < ballr(i) Then
                    'flash a circle around hit ball
                    Circle (ballx(i), bally(i)), ballr(i), _RGB(255, 255, 255)
                    'Line (0, 0)-(_Width, _Height), _RGBA(255, 255, 255, 10), BF
                    shota(j) = 0 'set shot active flag off
                    bally(i) = 1 'give ball new y pos (top)
                    ballx(i) = Int(Rnd * _Width) + 1 'give ball a new x pos
                    ballr(i) = 10 + Int(Rnd * 20) 'give ball new radius
                    score = score + 1 'update score
                End If
            End If
        Next
    Next

    'if a ball hits player, end game
    For i = 1 To balls
        If Abs(ballx(i) - playerx) < ballr(i) And Abs(bally(i) - playery) < ballr(i) Then End
    Next

    'show score
    Locate 1, 1: Print "Score: "; score;

    _Display

    _Limit 30

Loop Until _KeyDown(27) 'ESC quits

End

Sub glowball (x, y, size, r, g, b, a)
    t = Timer
    For y2 = y - size To y + size
        For x2 = x - size To x + size
            If Sqr((x2 - x) ^ 2 + (y2 - y) ^ 2) <= size Then
                clr = (size - (Sqr((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y)))) / size
                noise = Int(Rnd * 50)
                r = Sin(6.005 * t) * size - y2 + size + 255 * 2
                g = Sin(3.001 * t) * size - x2 + size + 255
                b = Sin(2.001 * x2 / size + t + y2 / size) * r + 255
                t = t + .00195
                PSet (x2, y2), _RGBA(clr * r - noise, clr * g - noise, clr * b - noise, a)
            End If
        Next
    Next
End Sub

Print this item

  Throw or Hit The Ball Example
Posted by: SierraKen - 08-23-2024, 10:40 PM - Forum: Programs - Replies (9)

This can be used in an unlimited amount of games. It shows a ball (or cannonball) randomly being thrown or hit in a 3D perspective toward the Z axis. There is no Z axis in the code though, it uses a parabola equation I found on ChatGPT and after experimentation I came up with this. I also found the SGN command on ChatGPT that helps with choosing either a positive or negative random number. I used to do it a different way in my games, but had forgotten how I did it, so I found this. 

Feel free to use this in any of your games or programs. Would make a cool baseball or golf game I would think. Smile 

Left click the mouse to throw each time.

Code: (Select All)

'Ken's Throw The Ball Demonstration

'I got the parabola equation and SGN command for random numbers from ChatGPT and I made the rest.
'Feel free to use this as you wish.

Screen _NewImage(800, 600, 32)
Cls
_Title "Click The Left Mouse Button To Throw"
' Define the coefficients for the parabola y = ax^2 + bx + c
Dim a As Double, b As Double, c As Double

centerX = 400
centerY = 300
c = 0
s = 100
ball = 8
Do
    Do
        Do While _MouseInput
            oldm = m
            m = _MouseWheel
            If _MouseButton(1) Then
                b = Int(Rnd * _Pi) + 6
                a = Int(Rnd * 7) - 7
                randomx = (Rnd * 10) * Sgn(Rnd - 0.5)
                Cls
            End If
        Loop
    Loop Until _MouseButton(1)
    If m > oldm Then
        a = a + .1
        b = b + .1
        Cls
        oldm = m
    End If
    If m < oldm Then
        a = a - .1
        Cls
        oldm = m
    End If
    ' Set up a loop to draw the parabola
    For x = -20 To 30 + a Step .5
        ' Calculate y using the parabola equation
        y = a * (x / 10) ^ 2 + b * (x / 10) + c

        ' Convert to screen coordinates
        screenX = centerX + x * randomx
        screenY = centerY - y * 10
        If ball > 1.5 Then ball = ball - .2
        ' Plot the point
        Circle (screenX, screenY), ball, _RGB32(255, 255, 255)
        _Delay .05
        s = s + .1
        Sound s, 1
        _Display
        Cls
    Next x
    s = 100
    ball = 8
Loop Until InKey$ = Chr$(27)
End

Print this item

  SOUNDBALLS - Sound immersion environment
Posted by: Dav - 08-23-2024, 03:05 PM - Forum: Dav - Replies (11)

SOUNDBALLS is a sound immersion environmet experiment.  Enter a world where balls have their own unique sound.  By placing the balls in desired poisitions in the stereo field, and control it's volume, you can create your own special soundscape.

Each ball has a different sound.
Move the balls to place its sound in the environment.
Move ball left to place its sound more left in the stereo field.
Move ball right to place its sound more right in the stereo field.
Move the balls upward in the distance to make it get softer.
Move the balls down closer towards you to make it get louder.

Right click on a ball to turn its sound On/Off.  
Ball will glow when it's turn on, doesn't when off.

By default only 1 ball is turned on when program starts.

Press any key to leave the sound ball world.

USE HEADPHONES OR EXTERNAL SPEAKERS FOR BEST RESULTS

- Dav


.zip   soundballs.zip (Size: 1.63 MB / Downloads: 100)

   

Print this item

Big Grin Helicopter Rescue
Posted by: Trial And Terror - 08-22-2024, 11:53 AM - Forum: Games - Replies (6)

Hi,

 I consider this game finished, for the time being. Keyboard controls are optional, it's really a mouse game. (Don't mind the distorted 3D view, it's a long story Tongue )

Grts, T&T

[Edit] Click in the text box at the bottom of the menu screen to see how to handle the mouse and the spacebar to play level 1

[Image: p1.jpg]

[Image: p2.jpg]

[Image: p3.jpg]

[Image: p4.jpg]

[Image: p5.jpg]

[Image: p6.jpg]



Attached Files
.zip   Helicopter Rescue 1.6.21 Developer.zip (Size: 14.44 MB / Downloads: 76)
Print this item

  Use of _STARTDIR$
Posted by: krovit - 08-22-2024, 10:04 AM - Forum: Help Me! - Replies (2)

The operation and logic of the command seem clear.
However, I would like to point out that at least in one case, the execution causes a problem.

Specifically, it concerns my case:

1) With a Windows launcher (there are many free ones), I start the QB64 IDE (I often use DavisIDE because it is more comfortable and less cumbersome);

2) It performs the compilation (the EXE file is produced in the same folder as the BAS files, and that folder also contains the entire series of folders that make up the application);

3) That said, it would seem that the EXE file correctly sees where it is launched from and behaves as it should.

But no! The path detected by _STARTDIR$ is that of the launcher! So, you have to manually open the folder and launch the executable directly from there.

It's not a serious problem... I created a BAT file that executes everything and runs the execution without this annoying setback.


Perhaps - I say perhaps, but I understand that nothing is easy - _STARTDIR$ should read what it needs to read by looking at itself and where it is located.

I'm just mentioning this for the record...

Thank you!

Print this item

  ICO of the executable file
Posted by: krovit - 08-22-2024, 09:50 AM - Forum: Help Me! - Replies (10)

Good morning/good evening everyone

I often go crazy over this simple sequence of commands: 

$EXEICON: 'myicon.ico' 
_ICON 
_title title$

What happens is: 
1) I don't know because, but sometimes it "fixes" itself so that the icon is not myicon.ico (with the corresponding absolute path) but an old icon that - once the instruction had worked - now it carries along as if it has the memory of an elephant. In other words... it ignores myicon.ico and the icon of the EXE file is that old one, which QB64 seems to like so much... 
2) At the same time, the icon that appears on the title bar of the window (along with _TITLE) is the correct one.
3) _ICON with or without the file (_ICON 'myico.ico') seems to have no effect.

Question: why does this behavior occur and how can I correct it?

Thank you!

Print this item