Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help needed regarding Lesson 17
#21
(10-09-2024, 03:33 PM)TerryRitchie Wrote: LOL, yeah, well, I asked for help when I was beginning lesson 17 way back in early 2022 however no one had the time to help. When I finished it I asked those with math inclinations to look it over for correctness. Again, nothing, so I figured what I had was good. I am completely self taught when it comes to math.

What is happening here is my confusion over mixing the need to orientate everything to match the screen versus the correct orientation. I've gotten much better over the past 2.5 years and yes, I see the issues you have pointed out.

I would gladly welcome help to correct this lesson.

An update for you from Discord so you won't be as down with yourself.  Big Grin

Quote::17 PM]Pouli: Yeah maybe, but I am doing a Q64 progammin so that should of been obvious. And since Im doing that, I thinking Qb64 cordinate system. And thats why the lessons are set like that, I think. But I found exact part of that lesson yesterday that I believe has the answer Im looking for. I was thinking to actually dig it in to it today with fresh mind. (edited)
[7:57 PM]Pouli: So... This is what I wanted to do. I was thinking it wrong way as I assumed. And I have made mistakes with the cordinates too.

'Moving one point (x1,y1) towards another (x2,y2)

'Set up screen
screen1 = _NewImage(1280, 720, 32)
Screen screen1

'Point 1 (from)
x1 = 636
y1 = 356

'Point 2 (to)
x2 = 900
y2 = 100

vx = x2 - x1
vy = y2 - y1

D = _Hypot(vx, vy) 'Distance between two points

'Normalize to vectors if distance is not 0
If D <> 0 Then
    vx = vx / D
    vy = vy / D
Else
    vx = 0
    vy = 0
End If

Do
    Cls

    'Move points
    x1 = x1 + vx
    y1 = y1 + vy

    'Draw points
    PSet (x1, y1)
    PSet (x2, y2)

    _Display
    _Limit 60
Loop
[8:05 PM]Pouli: I might be able to compress this even further if needed, but the idea works now. I really like Terry's lessons. These topics are not exactly my strong suit, as we have seen. However, the examples and the way the lessons present them help a lot, and now I actually understand how and why it's solved like this. Or maybe this is just one way to do it. This is also why I wanted to try something I'm not super good at, and to learn new things along the way. This is why I think programming is so cool, and QB64 is the perfect tool to try and learn new things. Thanks, Terry, for the lessons, and thanks to everyone for the help and patience.



THIS:

I might be able to compress this even further if needed, but the idea works now. I really like Terry's lessons. These topics are not exactly my strong suit, as we have seen. However, the examples and the way the lessons present them help a lot, and now I actually understand how and why it's solved like this. Or maybe this is just one way to do it. This is also why I wanted to try something I'm not super good at, and to learn new things along the way. This is why I think programming is so cool, and QB64 is the perfect tool to try and learn new things. Thanks, Terry, for the lessons, and thanks to everyone for the help and patience.

Never forget this!  Big Grin
Reply
#22
Quote:I would gladly welcome help to correct this lesson.

OK @TerryRitchie we'll see about that Smile
Code: (Select All)
_Title "Ship Demo for lesson 17, Degrees Only" ' bplus overhaul 2024-10-09

Type XYPAIR '            x,y value definition
    X As Single '        x value
    Y As Single '        y value
End Type

Type SHIP_Type '         ship definition First 2 needed for DrawShip
    Loc As XYPAIR '      where the ship center is on screen
    Heading As Single '  Degree angle the ship is pointed towards
    V As XYPAIR '        Normal vector: V.X = CosD(Ship.Heading) V.Y = SinD(Ship.Heading)
    Velocity As Single ' mult. Normal Vector by Velocity add to old Loc for new Location
End Type

Dim ship As SHIP_Type '         get our ship started!
Dim angle '                     degrees for the compass
Dim showCompass As Integer '    show Compass toggle flag
showCompass = -1 '              turn the toggle on
ship.Loc.X = 400 '              ship's x coordinate on screen
ship.Loc.Y = 300 '              ship's y coordinate on screen
ship.Heading = 270 '            let's head North for starters
ship.Velocity = 5 '             ship's speed

Screen _NewImage(800, 600, 32) ' graphics screen
_ScreenMove 250, 60 '            centered 0n laptop screen

Do '                             begin main loop
    Cls '                        clear screen
    Print '                      here are instructions to user  cp = Center Print
    cp "Right/Left Arrow keys to turn, Up Arrow key to move forward"
    cp "Spacebar to toggle Compass Off/On"
    DrawShip ship.Loc, ship.Heading
    If showCompass Then ' I like your idea Terry to show turn ticks, here is a nice Compass for you.
        For angle = 0 To 359 Step 15
            PSet (ship.Loc.X + 62 * CosD(angle), ship.Loc.Y + 62 * SinD(angle)) ' draw pixel at 10 degree point
            If angle = 0 Then
                _PrintString (ship.Loc.X + 62 * CosD(angle) + 3, ship.Loc.Y + 62 * SinD(angle) - 7), "E"
            ElseIf angle = 90 Then
                _PrintString (ship.Loc.X + 62 * CosD(angle) - 2, ship.Loc.Y + 62 * SinD(angle) + 1), "S"
            ElseIf angle = 180 Then
                _PrintString (ship.Loc.X + 62 * CosD(angle) - 11, ship.Loc.Y + 62 * SinD(angle) - 7), "W"
            ElseIf angle = 270 Then
                _PrintString (ship.Loc.X + 62 * CosD(angle) - 2, ship.Loc.Y + 62 * SinD(angle) - 16), "N"
            End If
        Next
    End If
    If _KeyDown(18432) Then '                                up arrow key pressed? move it!
        ship.V.X = CosD(ship.Heading) ' very simple formula for normal x component of vector
        ship.V.Y = SinD(ship.Heading) ' very simple formula for normal y component of vector
        ship.Loc.X = ship.Loc.X + ship.V.X * ship.Velocity ' new X location for ship
        ship.Loc.Y = ship.Loc.Y + ship.V.Y * ship.Velocity ' new Y location for ship
        If ship.Loc.X < 0 Then ShipLoc.x = 0 '               keep ship on screen  just stop!
        If ship.Loc.X > _Width Then ship.Loc.X = _Width '    when at border
        If ship.Loc.Y < 0 Then ship.Loc.Y = 0 '              of the screen
        If ship.Loc.Y > _Height Then ShipLoc.y = _Height
    End If
    If _KeyDown(19200) Then ship.Heading = ship.Heading - 1 ' nose heading counter-clockwise to left
    If _KeyDown(19712) Then ship.Heading = ship.Heading + 1 ' nose heading clockwise to right
    If _KeyHit = 32 Then showCompass = Not showCompass '      toggle flag when space bar pressed
    _Display '                                                update screen with changes
    _Limit 60 ' gots to have pause for _keydown release or ship will spin like mad!
Loop Until _KeyDown(27) '                                     leave when ESC pressed
System

Sub DrawShip (place As XYPAIR, DegreeHeading As Single) ' hey we can use this design in another app!!!
    Dim As Single radius
    radius = 60 ' nose and wing tips touch radius around central location = placeXY
    Dim pts(1 To 3) As XYPAIR 'the 3 outer points for triangle ship with 2 wings fit on radius
    pts(1).X = place.X + radius * CosD(0 + DegreeHeading) '   nose at 0 degrees
    pts(1).Y = place.Y + radius * SinD(0 + DegreeHeading)
    pts(2).X = place.X + radius * CosD(135 + DegreeHeading) ' 180 - 45 SW wing tip
    pts(2).Y = place.Y + radius * SinD(135 + DegreeHeading)
    pts(3).X = place.X + radius * CosD(225 + DegreeHeading) ' 180 + 45 NW wing tip
    pts(3).Y = place.Y + radius * SinD(225 + DegreeHeading)
    Line (pts(1).X, pts(1).Y)-(pts(2).X, pts(2).Y)
    Line (pts(2).X, pts(2).Y)-(place.X, place.Y)
    Line (pts(3).X, pts(3).Y)-(place.X, place.Y)
    Line (pts(3).X, pts(3).Y)-(pts(1).X, pts(1).Y)
End Sub

' use angles in degrees units instead of radians (converted inside sub)
Function CosD (degrees)
    ' Note this function uses whatever the default type is, better not be some Integer Type.
    CosD = Cos(_D2R(degrees))
End Function

' use angles in degrees units instead of radians (converted inside sub)
Function SinD (degrees)
    ' Note this function uses whatever the default type is, better not be some Integer Type.
    SinD = Sin(_D2R(degrees))
End Function

Sub cp (s$) ' cp = Center Print string s$ assuming 8 pixel width font on graphics screen
    Print Space$(((_Width / 8) - Len(s$)) / 2); s$
End Sub

   

Here is same exact project in Radians Only for comparison: (I remembered this code was suppose to be a Radian Demo)
Code: (Select All)
_Title "Ship Demo for lesson 17 Radians Only" ' bplus overhaul 2024-10-09

Type XYPAIR '            x,y value definition
    X As Single '        x value
    Y As Single '        y value
End Type

Type SHIP_Type '         ship definition First 2 needed for DrawShip
    Loc As XYPAIR '      where the ship center is on screen
    Heading As Single '  Degree angle the ship is pointed towards
    V As XYPAIR '        Normal vector: V.X = cos(Ship.Heading) V.Y = sin(Ship.Heading)
    Velocity As Single ' mult. Normal Vector by Velocity add to old Loc for new Location
End Type

Dim ship As SHIP_Type '         get our ship started!
Dim angle '                     degrees for the compass
Dim showCompass As Integer '    show Compass toggle flag
showCompass = -1 '              turn the toggle on
ship.Loc.X = 400 '              ship's x coordinate on screen
ship.Loc.Y = 300 '              ship's y coordinate on screen
ship.Heading = _Pi(3 / 2) '     let's head North for starters
ship.Velocity = 5 '             ship's speed

Screen _NewImage(800, 600, 32) ' graphics screen
_ScreenMove 250, 60 '            centered 0n laptop screen

Do '                             begin main loop
    Cls '                        clear screen
    Print '                      here are instructions to user  cp = Center Print
    cp "Right/Left Arrow keys to turn, Up Arrow key to move forward"
    cp "Spacebar to toggle Compass Off/On"
    DrawShip ship.Loc, ship.Heading
    If showCompass Then ' I like your idea Terry to show turn ticks, here is a nice Compass for you.
        For angle = 0 To _Pi(1.99) Step _Pi(2 / 24)
            PSet (ship.Loc.X + 62 * Cos(angle), ship.Loc.Y + 62 * Sin(angle)) ' draw pixel at 10 degree point
            If angle = 0 Then
                _PrintString (ship.Loc.X + 62 * Cos(angle) + 3, ship.Loc.Y + 62 * Sin(angle) - 7), "E"
            ElseIf Abs(angle - _Pi(.5)) < .0001 Then
                _PrintString (ship.Loc.X + 62 * Cos(angle) - 2, ship.Loc.Y + 62 * Sin(angle) + 1), "S"
            ElseIf Abs(angle - _Pi) < .0001 Then
                _PrintString (ship.Loc.X + 62 * Cos(angle) - 11, ship.Loc.Y + 62 * Sin(angle) - 7), "W"
            ElseIf Abs(angle - _Pi(3 / 2)) < .0001 Then
                _PrintString (ship.Loc.X + 62 * Cos(angle) - 2, ship.Loc.Y + 62 * Sin(angle) - 16), "N"
            End If
        Next
    End If
    If _KeyDown(18432) Then '                                up arrow key pressed? move it!
        ship.V.X = Cos(ship.Heading) ' very simple formula for normal x component of vector
        ship.V.Y = Sin(ship.Heading) ' very simple formula for normal y component of vector
        ship.Loc.X = ship.Loc.X + ship.V.X * ship.Velocity ' new X location for ship
        ship.Loc.Y = ship.Loc.Y + ship.V.Y * ship.Velocity ' new Y location for ship
        If ship.Loc.X < 0 Then ShipLoc.x = 0 '               keep ship on screen  just stop!
        If ship.Loc.X > _Width Then ship.Loc.X = _Width '    when at border
        If ship.Loc.Y < 0 Then ship.Loc.Y = 0 '              of the screen
        If ship.Loc.Y > _Height Then ShipLoc.y = _Height
    End If
    If _KeyDown(19200) Then ship.Heading = ship.Heading - _Pi(1 / 180) ' nose counter-clockwise to left
    If _KeyDown(19712) Then ship.Heading = ship.Heading + _Pi(1 / 180) ' nose heading clockwise to right
    If _KeyHit = 32 Then showCompass = Not showCompass '      toggle flag when space bar pressed
    _Display '                                                update screen with changes
    _Limit 60 ' gots to have pause for _keydown release or ship will spin like mad!
Loop Until _KeyDown(27) '                                     leave when ESC pressed
System

Sub DrawShip (place As XYPAIR, DegreeHeading As Single) ' hey we can use this design in another app!!!
    Dim As Single radius
    radius = 60 ' nose and wing tips touch radius around central location = placeXY
    Dim pts(1 To 3) As XYPAIR 'the 3 outer points for triangle ship with 2 wings fit on radius
    pts(1).X = place.X + radius * Cos(0 + DegreeHeading) '   nose at 0 degrees
    pts(1).Y = place.Y + radius * Sin(0 + DegreeHeading)
    pts(2).X = place.X + radius * Cos(_Pi(3 / 4) + DegreeHeading) ' 180 - 45 SW wing tip
    pts(2).Y = place.Y + radius * Sin(_Pi(3 / 4) + DegreeHeading)
    pts(3).X = place.X + radius * Cos(_Pi(5 / 4) + DegreeHeading) ' 180 + 45 NW wing tip
    pts(3).Y = place.Y + radius * Sin(_Pi(5 / 4) + DegreeHeading)
    Line (pts(1).X, pts(1).Y)-(pts(2).X, pts(2).Y)
    Line (pts(2).X, pts(2).Y)-(place.X, place.Y)
    Line (pts(3).X, pts(3).Y)-(place.X, place.Y)
    Line (pts(3).X, pts(3).Y)-(pts(1).X, pts(1).Y)
End Sub

Sub cp (s$) ' cp = Center Print string s$ assuming 8 pixel width font on graphics screen
    Print Space$(((_Width / 8) - Len(s$)) / 2); s$
End Sub
b = b + ...
Reply
#23
Instead of Asteroid making I did a host or regular Polygons to demo Sin and Cos Function with Angles and Movement for lesson 17
Code: (Select All)
_Title "Regular Polygons Demo of Sin and Cos" ' bplus 2024-10-10
Option _Explicit

Type XYPair
    As Single X, Y
End Type

Type PolyType 'first 5 for DrawPoly
    As XYPair Loc '          Location on screen
    As Long NSides '         Number of sides = Number of points
    As Single Radius '       From center to point
    As Single Rotation '     Rotation offset = how much is poly turned
    As _Unsigned Long Colr ' color
    As XYPair V '            Vx, Vy Vector components for movement
    As Single RotAmt '       Rotate Poly this angle amount
End Type
Dim Shared NPoly: NPoly = 20
Dim Shared Poly(1 To NPoly) As PolyType

Screen _NewImage(800, 600, 32)
_ScreenMove 250, 60
Dim As Long i
For i = 1 To NPoly
    NewPoly i
Next
Do
    Cls
    For i = 1 To NPoly 'draw amd update polys
        DrawPoly Poly(i).Loc, Poly(i).NSides, Poly(i).Radius, Poly(i).Rotation, Poly(i).Colr
        ' update poly position and rotation
        Poly(i).Loc.X = Poly(i).Loc.X + Poly(i).V.X
        If Poly(i).Loc.X < 0 Then Poly(i).Loc.X = 0: Poly(i).V.X = -Poly(i).V.X
        If Poly(i).Loc.X > _Width Then Poly(i).Loc.X = _Width: Poly(i).V.X = -Poly(i).V.X
        Poly(i).Loc.Y = Poly(i).Loc.Y + Poly(i).V.Y
        If Poly(i).Loc.Y < 0 Then Poly(i).Loc.Y = 0: Poly(i).V.Y = -Poly(i).V.Y
        If Poly(i).Loc.Y > _Height Then
            Poly(i).Loc.Y = _Height: Poly(i).V.Y = -Poly(i).V.Y
            If Poly(i).NSides < 9 Then Poly(i).NSides = Poly(i).NSides + 1 Else Poly(i).NSides = 3
        End If
        Poly(i).Rotation = Poly(i).Rotation + Poly(i).RotAmt
    Next
    _Display
    _Limit 30
Loop Until _KeyDown(27) ' escape

Sub NewPoly (index) ' for shared array Poly() as PolyType
    Dim r, red, grn, blu
    Poly(index).Radius = Rnd * 60 + 20
    Poly(index).Loc.X = Rnd * (_Width - 2 * Poly(index).Radius) + Poly(index).Radius
    Poly(index).Loc.Y = Rnd * (_Height - 2 * Poly(index).Radius) + Poly(index).Radius
    Poly(index).NSides = 3 + Int(Rnd * 7)
    Poly(index).Rotation = Rnd * _Pi(2)
    red = -Sgn(Rnd < .5) * (76 * Rnd + 180)
    grn = -Sgn(Rnd < .5) * (156 * Rnd + 100)
    blu = -Sgn(Rnd < .5) * (156 * Rnd + 100)
    Poly(index).Colr = _RGB32(red, grn, blu)
    Poly(index).V.X = Rnd * 3 + 1
    If Rnd < .5 Then Poly(index).V.X = -Poly(index).V.X
    Poly(index).V.Y = Rnd * 3 + 1
    If Rnd < .5 Then Poly(index).V.Y = -Poly(index).V.Y
    Poly(index).RotAmt = Rnd * _Pi(1 / 10) - _Pi(1 / 20)
End Sub

Sub DrawPoly (Place As XYPair, NSides As Long, Radius, RadRotation, C As _Unsigned Long)
    Dim pAngle: pAngle = _Pi(2 / NSides) ' angles from center to side points
    Dim a, savex, savey
    For a = 0 To _Pi(1.9999) Step pAngle
        If a = 0 Then
            PSet (Place.X + Radius * Cos(a + RadRotation), Place.Y + Radius * Sin(a + RadRotation)), C
            savex = Place.X + Radius * Cos(a + RadRotation)
            savey = Place.Y + Radius * Sin(a + RadRotation)
        Else
            Line -(Place.X + Radius * Cos(a + RadRotation), Place.Y + Radius * Sin(a + RadRotation)), C
        End If
    Next
    Line -(savex, savey), C
End Sub
b = b + ...
Reply
#24
A Tale of Two Clock Faces
Code: (Select All)
_Title "Tale of Two Clock Faces" ' bplus 2024-10-11

' A tale of woe and miserable confusion between different coordinate systems.

' Well this tale can have a happy ending but everyone needs to understand what is happening.

Screen _NewImage(1200, 600, 32)
_ScreenMove 0, 60
_PrintMode _KeepBackground
a& = _LoadFont("arial.ttf", 32)
_Font a&
Do
    Cls
    clock_EastIsZero_Face 300, 300, 250
    clock_NorthIsZero_Face 900, 300, 250
    _Display
    _Limit 60
Loop Until _KeyDown(27)
Sleep

Sub clock_EastIsZero_Face (x, y, r)
    ' x, y center r = radius

    ' for (x, y) around circle with center (xc, yc)
    ' if 0 degrees is East as it is for all Basic Trig Functions
    '  x = xc + r * cos(a)
    '  y = yc + r * sin(a)
    ' and hour starts at 3 o'clock for 0 Degrees

    hour = 3 ' at a = 0 the first circle for hour will be drawn due East
    For a = 0 To 359 Step 6 ' 360/6 = 60 tick for minutes
        ' mod 30 ? 360/30 = 12 ticks for every hour so make circle big enough to fit 2 digits 16x16
        If a Mod 30 = 0 Then r1 = 0 Else r1 = 1 / 75 * r

        ' !!!!!!!!!!!!!!!!!!!! Regular Formula for x, y around circle center(x, y) !!!!!!!!!!!!!!!
        circX = x + r * Cos(_D2R(a))
        circY = y + r * Sin(_D2R(a))
        ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        If r1 Then Circle (circX, circY), r1, _RGB32(255, 255, 255)
        If r1 Then Paint (circX, circY), _RGB32(255, 255, 255), _RGB32(255, 255, 255)
        If a Mod 30 = 0 Then ' label hour
            hourStr$ = _Trim$(Str$(hour))
            xoffset = _PrintWidth(hourStr$) / 2
            yoffset = 32 / 2
            _PrintString (circX - xoffset, circY - yoffset), _Trim$(Str$(hour))
            hour = hour + 1 ' get ready for next label
            If hour > 12 Then hour = 1 ' cycle back to 1 after label 12
        End If
    Next

    ' the rest of this is based on regular East = 0 degrees
    If Val(Left$(Time$, 2)) + (Val(Mid$(Time$, 4, 2)) / 60) >= 12 Then hrs = Val(Left$(Time$, 2)) + (Val(Mid$(Time$, 4, 2)) / 60) - 12 Else hrs = Val(Left$(Time$, 2)) + (Val(Mid$(Time$, 4, 2)) / 60)
    ftri x + 1 / 15 * r * Cos(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2) + _Pi(1 / 2)), y + 1 / 15 * r * Sin(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2) + _Pi(1 / 2)), x + 1 / 15 * r * Cos(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2) - _Pi(1 / 2)), y + 1 / 15 * r * Sin(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2) - _Pi(1 / 2)), x + r * Cos(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2)), y + r * Sin(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2)), _RGB32(255, 0, 0)
    ftri x + 1 / 10 * r * Cos(hrs * _Pi(1 / 6) - _Pi(1 / 2) + _Pi(1 / 2)), y + 1 / 10 * r * Sin(hrs * _Pi(1 / 6) - _Pi(1 / 2) + _Pi(1 / 2)), x + 1 / 10 * r * Cos(hrs * _Pi(1 / 6) - _Pi(1 / 2) - _Pi(1 / 2)), y + 1 / 10 * r * Sin(hrs * _Pi(1 / 6) - _Pi(1 / 2) - _Pi(1 / 2)), x + 2 / 3 * r * Cos(hrs * _Pi(1 / 6) - _Pi(1 / 2)), y + 2 / 3 * r * Sin(hrs * _Pi(1 / 6) - _Pi(1 / 2)), _RGB32(0, 0, 255)
    Line (x, y)-(x + r * Cos(Val(Right$(Time$, 2)) * _Pi(1 / 30) - _Pi(1 / 2)), y + r * Sin(Val(Right$(Time$, 2)) * _Pi(1 / 30) - _Pi(1 / 2))), _RGB32(255, 255, 0)
    Circle (x, y), 1 / 10 * r, _RGB32(255, 255, 255)
    Paint (x + 1 / 75 * r, y + 1 / 75 * r), _RGB32(100, 100, 100), _RGB32(255, 255, 255)
    Circle (x, y), 1 / 30 * r, _RGB32(0, 0, 0)
End Sub

Sub clock_NorthIsZero_Face (x, y, r)
    ' x, y center r = radius

    ' if 0 degrees is North then Rotate -90 degrees the angles

    ' for (x, y) around circle with center (xc, yc)
    '  x = xc + r * cos(a) BECOMES x = xc + sin(a)  !!!!!!!!!!
    '  y = yc + r * sin(a) BECOMES y = yc + -cos(a) !!!!!!!!!!
    ' and hour starts at 12 o'clock for "0 degrees"

    hour = 12 ' at a = 0 the first circle for hour will be drawn due East
    For a = 0 To 359 Step 6 ' 360/6 = 60 tick for minutes
        ' mod 30 ? 360/30 = 12 ticks for every hour so make circle big enough to fit 2 digits 16x16
        If a Mod 30 = 0 Then r1 = 0 Else r1 = 1 / 75 * r

        ' !!!!!    Formula for (x, y) about circle center(x, y) !!!!!!!!!
        circX = x + r * Sin(_D2R(a))
        circY = y + r * -Cos(_D2R(a))
        ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        If r1 Then Circle (circX, circY), r1, _RGB32(255, 255, 255)
        If r1 Then Paint (circX, circY), _RGB32(255, 255, 255), _RGB32(255, 255, 255)
        If a Mod 30 = 0 Then ' label hour
            hourStr$ = _Trim$(Str$(hour))
            xoffset = _PrintWidth(hourStr$) / 2
            yoffset = 32 / 2
            _PrintString (circX - xoffset, circY - yoffset), _Trim$(Str$(hour))
            hour = hour + 1 ' get ready for next label
            If hour > 12 Then hour = 1 ' cycle back to 1 after label 12
        End If
    Next

    ' the rest of this is based on normal East = 0 degrees
    If Val(Left$(Time$, 2)) + (Val(Mid$(Time$, 4, 2)) / 60) >= 12 Then hrs = Val(Left$(Time$, 2)) + (Val(Mid$(Time$, 4, 2)) / 60) - 12 Else hrs = Val(Left$(Time$, 2)) + (Val(Mid$(Time$, 4, 2)) / 60)
    ftri x + 1 / 15 * r * Cos(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2) + _Pi(1 / 2)), y + 1 / 15 * r * Sin(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2) + _Pi(1 / 2)), x + 1 / 15 * r * Cos(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2) - _Pi(1 / 2)), y + 1 / 15 * r * Sin(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2) - _Pi(1 / 2)), x + r * Cos(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2)), y + r * Sin(Val(Mid$(Time$, 4, 2)) * _Pi(1 / 30) - _Pi(1 / 2)), _RGB32(255, 0, 0)
    ftri x + 1 / 10 * r * Cos(hrs * _Pi(1 / 6) - _Pi(1 / 2) + _Pi(1 / 2)), y + 1 / 10 * r * Sin(hrs * _Pi(1 / 6) - _Pi(1 / 2) + _Pi(1 / 2)), x + 1 / 10 * r * Cos(hrs * _Pi(1 / 6) - _Pi(1 / 2) - _Pi(1 / 2)), y + 1 / 10 * r * Sin(hrs * _Pi(1 / 6) - _Pi(1 / 2) - _Pi(1 / 2)), x + 2 / 3 * r * Cos(hrs * _Pi(1 / 6) - _Pi(1 / 2)), y + 2 / 3 * r * Sin(hrs * _Pi(1 / 6) - _Pi(1 / 2)), _RGB32(0, 0, 255)
    Line (x, y)-(x + r * Cos(Val(Right$(Time$, 2)) * _Pi(1 / 30) - _Pi(1 / 2)), y + r * Sin(Val(Right$(Time$, 2)) * _Pi(1 / 30) - _Pi(1 / 2))), _RGB32(255, 255, 0)
    Circle (x, y), 1 / 10 * r, _RGB32(255, 255, 255)
    Paint (x + 1 / 75 * r, y + 1 / 75 * r), _RGB32(100, 100, 100), _RGB32(255, 255, 255)
    Circle (x, y), 1 / 30 * r, _RGB32(0, 0, 0)
End Sub

Sub ftri (x1, y1, x2, y2, x3, y3, K As _Unsigned Long)
    a& = _NewImage(1, 1, 32)
    _Dest a&
    PSet (0, 0), K
    _Dest 0
    _MapTriangle _Seamless(0, 0)-(0, 0)-(0, 0), a& To(x1, y1)-(x2, y2)-(x3, y3)
    _FreeImage a& '<<< this is important!
End Sub

BTW @TerryRitchie it took me forever to figure out why my Asteroids were upside down to yours.
You didn't follow your own rotation formula:
' for (x, y) around circle with center (xc, yc)
' x = xc + r * cos(a) BECOMES x = xc + sin(a) !!!!!!!!!!
' y = yc + r * sin(a) BECOMES y = yc + -cos(a) !!!!!!!!!!

You used a positive Cos eg, y = yc + r * cos(a)
Probably hacking the code because an unmodified _Atan2 was drawing it upside down with the minus sign.



In case someone doesn't have arial.ttf:


Attached Files
.ttf   arial.ttf (Size: 1,012.29 KB / Downloads: 15)
b = b + ...
Reply
#25
Oh I had it right!

Testing a mod to _ATan2 that will treat North as 0 Dgerees or Radians and go Clockwise around ascending angle value.
Code: (Select All)
Option _Explicit
_Title "Atan4North0 test" ' bplus 2024-10-11

' testing an ATan function that would return 0 for North AND increase going Clockwise around

Screen _NewImage(1200, 600, 32)
_ScreenMove 40, 60
Dim degree30, xc1, xc, yc, xc2, r, a, x1, y1, at, sa$, xoff, yoff, x2, y2
degree30 = _Pi(2 / 12) ' like hours on clock
xc1 = 300: xc2 = 900: yc = 300: r = 200
_PrintString (xc1 - _PrintWidth("Regular East = 0 Deg/Rads Calcs") / 2, 292), "Regular East = 0 Deg/Rads Calcs"
_PrintString (xc2 - _PrintWidth("Terry's North = 0 Deg/Rads Calcs") / 2, 292), "Terry's North = 0 Deg/Rads Calcs"

For a = 0 To _Pi(1.999) Step degree30

    ' Regular East = 0 calcs
    x1 = xc1 + r * Cos(a)
    y1 = yc + r * Sin(a)
    at = Int(_R2D(_Atan2(y1 - yc, x1 - xc1)) + .0001)
    If at < 0 Then at = at + 360
    sa$ = _Trim$(Str$(at))
    xoff = _PrintWidth(sa$) / 2
    yoff = 16 / 2
    _PrintString (x1 - xoff, y1 - yoff), sa$

    ' North = 0 calcs
    x2 = xc2 + r * Sin(a)
    y2 = yc + r * -Cos(a)
    at = Int(_R2D(ATan4North0(y2 - yc, x2 - xc2)) + .0001)
    If at < 0 Then at = at + 360
    sa$ = _Trim$(Str$(at))
    xoff = _PrintWidth(sa$) / 2
    yoff = 16 / 2
    _PrintString (x2 - xoff, y2 - yoff), sa$

    _Limit 1
Next

Function ATan4North0 (dy, dx)
    ATan4North0 = _Pi - _Atan2(dx, dy) ' this was totally unexpected!
End Function


See now it fixes a couple mixups in Lesson 17 Asteroid Demo
Code: (Select All)
_Title "** Asteroid demo using radians fix" ' bplus  2024-10-11

' fix -COS and alternate _ATAN2 for North = 0 calcs  using ATan4North0

' From Lesson 17
'                Vx! = Sin(_D2R(Degree!)) '  calculate the x vector quantity
'                Vy! = -Cos(_D2R(Degree!)) ' calculate the y vector quantity

' Notice the negative sign next to Cos.
' This is a rotation of the coordinate system so _Atan2 is not going to return
' correct radian angle to match North = 0

' I added a modified ATan4North function to use in place of _Atan2 for Asteroid Demo
' to work as Terry intended using those Vx Vy forumlas.


Const FALSE = 0, TRUE = Not FALSE '      truth detectors
Const PI = 3.1415926, PI2 = 2 * PI '     useful PI values
Const SPINRATE = PI2 / 360 '             asteroid spin rate
Const SWIDTH = 640, SHEIGHT = 480 '      screen dimensions
Const MAXASTEROIDS = 20 '                number of asteroids on screen

Type XYPAIR '                            2D point location definition
    x As Single '                        x coordinate
    y As Single '                        y coordinate
End Type

Type OBJECT '                            object definition (points that make up an object)
    Radian As Single '                   direction of point
    Radius As Single '                   distance to point from center
End Type

Type ASTEROID '                          asteroid definition
    Loc As XYPAIR '                      asteroid location
    Dir As Single '                      asteroid radian direction
    Speed As Integer '                   asteroid speed
    Size As Integer '                    asteroid size
End Type

Dim Object(10) As OBJECT '               object point data
Dim Asteroid(MAXASTEROIDS) As ASTEROID ' asteroids array
Dim Vector As XYPAIR '                   vector calculations
Dim Obj As Integer '                     object counter
Dim Ast As Integer '                     asteroid counter
Dim P1 As XYPAIR '                       first object point for PSET
Dim Np As XYPAIR '                       next object point for LINE
Dim Spin As Integer '                    TRUE to activate spin, FALSE otherwise

Randomize Timer '                                                        seed RND generator
For Obj = 1 To 10 '                                                      cycle through object points
    Read Vector.x, Vector.y '                                            get object x,y vector point
    Object(Obj).Radius = _Hypot(Vector.x, Vector.y) '                    calculate radius from vector

    ' _Atan2 takes y's first , x's 2nd
    ' so modified  ATan4North0(Vector.y, Vector.x)
    ' uses the same order
    Object(Obj).Radian = ATan4North0(Vector.y, Vector.x) '              calculate direction from vector
Next Obj
For Ast = 1 To MAXASTEROIDS '                                            cycle through asteroids
    Asteroid(Ast).Loc.x = Int(Rnd * (SWIDTH - 40)) + 20 '                random location
    Asteroid(Ast).Loc.y = Int(Rnd * (SHEIGHT - 40)) + 20
    Asteroid(Ast).Dir = Rnd * PI2 '                                      random direction
    Asteroid(Ast).Speed = Int(Rnd * 6) + 2 '                             random speed
    Asteroid(Ast).Size = 2 ^ Int(Rnd * 3) '                              random size
Next Ast
Screen _NewImage(SWIDTH, SHEIGHT, 32) '                                  graphics screen
Spin = FALSE '                                                           no asteroid spin
Do '                                                                     begin main loop
    Cls '                                                                 clear screen
    _Limit 60 '                                                           60 frames per second
    Locate 2, 19: Print "Press the spacebar to activate asteroid spin" '  print directions
    If _KeyHit = 32 Then Spin = Not Spin '                                flip spin flag if spacebar pressed
    If Spin Then '                                                        spin asteroids?
        For Obj = 1 To 10 '                                               yes, cycle through object points
            Object(Obj).Radian = Object(Obj).Radian + SPINRATE '         move radian location
            If Object(Obj).Radian > PI2 Then Object(Obj).Radian = Object(Obj).Radian - PI2 ' keep within limits
        Next Obj
    End If
    For Ast = 1 To MAXASTEROIDS '                                         cycle through asteroids
        Vector.x = Sin(Object(1).Radian) '                               calculate vector from 1st object point
        Vector.y = -Cos(Object(1).Radian) ' <<<  This should be -Cos
        P1.x = Asteroid(Ast).Loc.x + Vector.x * Object(1).Radius * Asteroid(Ast).Size ' plot location on screen
        P1.y = Asteroid(Ast).Loc.y + Vector.y * Object(1).Radius * Asteroid(Ast).Size
        PSet (P1.x, P1.y) '                                               draw a pixel
        For Obj = 2 To 10 '                                               cycle through remaining points

            ' these assume North = 0 so Vectors are rotated 90 degrees
            Vector.x = Sin(Object(Obj).Radian) '                         calculate vector from object point
            Vector.y = -Cos(Object(Obj).Radian) ' <<<< this should be -Cos
            Np.x = Asteroid(Ast).Loc.x + Vector.x * Object(Obj).Radius * Asteroid(Ast).Size ' plot location
            Np.y = Asteroid(Ast).Loc.y + Vector.y * Object(Obj).Radius * Asteroid(Ast).Size ' on screen
            Line -(Np.x, Np.y) '                                          draw line from previous point
        Next Obj
        Line -(P1.x, P1.y) '                                              draw final line back to start
        Vector.x = Sin(Asteroid(Ast).Dir) '                              get vector from asteroid radian
        Vector.y = -Cos(Asteroid(Ast).Dir) ' <<<  This should be -Cos
        Asteroid(Ast).Loc.x = Asteroid(Ast).Loc.x + Vector.x * Asteroid(Ast).Speed ' plot location on screen
        Asteroid(Ast).Loc.y = Asteroid(Ast).Loc.y + Vector.y * Asteroid(Ast).Speed
        If Asteroid(Ast).Loc.x < -19 Then Asteroid(Ast).Loc.x = SWIDTH + 19 '        keep asteroids on screen
        If Asteroid(Ast).Loc.x > SWIDTH + 19 Then Asteroid(Ast).Loc.x = -19
        If Asteroid(Ast).Loc.y < -19 Then Asteroid(Ast).Loc.y = SHEIGHT + 19
        If Asteroid(Ast).Loc.y > SHEIGHT + 19 Then Asteroid(Ast).Loc.y = -19
    Next Ast
    _Display '                                                            update screen with changes
Loop Until _KeyDown(27) '                                                leave when ESC pressed
System '                                                                 return to operating system
' Asteroid object data (10 coordinate vector points)
Data 0,-5,5,-10,10,-5,7,0,10,5,2,10,-5,10,-10,5,-10,-5,-5,-10

Function ATan4North0 (dy, dx)
    ATan4North0 = _Pi - _Atan2(dx, dy) ' this was totally unexpected!
End Function

BTW I dislike this immensely:
Code: (Select All)
' From Lesson 17
'                Vx! = Sin(_D2R(Degree!)) '  calculate the x vector quantity
'                Vy! = -Cos(_D2R(Degree!)) ' calculate the y vector quantity

So much easier and straight forward to use East = 0 degrees and not have to modify _ATan2.
Then
' Vx = Cos(angle)
' Vy = Sin(angle)
Since sin(a)^2 + cos(a)^2 = 1, you have your Normal Vector

(x, y) around the point (xcenter, ycenter)
x = xcenter + radius*Cos(angle)
y = ycenter + radius*Sin(angle)

x is always associated with Cos
y is always associated with Sin.

But it appears Terry has invested heavily in that formula for Vx, Vy from Lesson 17.
b = b + ...
Reply
#26
Another fix for Asteroids easier than one above but East = 0 degrees
Code: (Select All)
_Title "** Asteroid demo using radians fix 2" ' bplus  2024-10-11

' use forumla
' Vx = cos(a)
' Vy = sin(a)
' and normal _Atan2 but we sacrifice North = 0

Const FALSE = 0, TRUE = Not FALSE '      truth detectors
Const PI = 3.1415926, PI2 = 2 * PI '     useful PI values
Const SPINRATE = PI2 / 360 '             asteroid spin rate
Const SWIDTH = 640, SHEIGHT = 480 '      screen dimensions
Const MAXASTEROIDS = 20 '                number of asteroids on screen

Type XYPAIR '                            2D point location definition
    x As Single '                        x coordinate
    y As Single '                        y coordinate
End Type

Type OBJECT '                            object definition (points that make up an object)
    Radian As Single '                   direction of point
    Radius As Single '                   distance to point from center
End Type

Type ASTEROID '                          asteroid definition
    Loc As XYPAIR '                      asteroid location
    Dir As Single '                      asteroid radian direction
    Speed As Integer '                   asteroid speed
    Size As Integer '                    asteroid size
End Type

Dim Object(10) As OBJECT '               object point data
Dim Asteroid(MAXASTEROIDS) As ASTEROID ' asteroids array
Dim Vector As XYPAIR '                   vector calculations
Dim Obj As Integer '                     object counter
Dim Ast As Integer '                     asteroid counter
Dim P1 As XYPAIR '                       first object point for PSET
Dim Np As XYPAIR '                       next object point for LINE
Dim Spin As Integer '                    TRUE to activate spin, FALSE otherwise

Randomize Timer '                                                        seed RND generator
For Obj = 1 To 10 '                                                      cycle through object points
    Read Vector.x, Vector.y '                                            get object x,y vector point
    Object(Obj).Radius = _Hypot(Vector.x, Vector.y) '                    calculate radius from vector

    ' back to normal _Atan2
    Object(Obj).Radian = _Atan2(Vector.y, Vector.x) '                    calculate direction from vector
Next Obj
For Ast = 1 To MAXASTEROIDS '                                            cycle through asteroids
    Asteroid(Ast).Loc.x = Int(Rnd * (SWIDTH - 40)) + 20 '                random location
    Asteroid(Ast).Loc.y = Int(Rnd * (SHEIGHT - 40)) + 20
    Asteroid(Ast).Dir = Rnd * PI2 '                                      random direction
    Asteroid(Ast).Speed = Int(Rnd * 6) + 2 '                             random speed
    Asteroid(Ast).Size = 2 ^ Int(Rnd * 3) '                              random size
Next Ast
Screen _NewImage(SWIDTH, SHEIGHT, 32) '                                  graphics screen
Spin = FALSE '                                                           no asteroid spin
Do '                                                                     begin main loop
    Cls '                                                                 clear screen
    _Limit 60 '                                                           60 frames per second
    Locate 2, 19: Print "Press the spacebar to activate asteroid spin" '  print directions
    If _KeyHit = 32 Then Spin = Not Spin '                                flip spin flag if spacebar pressed
    If Spin Then '                                                        spin asteroids?
        For Obj = 1 To 10 '                                               yes, cycle through object points
            Object(Obj).Radian = Object(Obj).Radian + SPINRATE '         move radian location
            If Object(Obj).Radian > PI2 Then Object(Obj).Radian = Object(Obj).Radian - PI2 ' keep within limits
        Next Obj
    End If
    For Ast = 1 To MAXASTEROIDS '                                         cycle through asteroids
        Vector.x = Cos(Object(1).Radian) '                               calculate vector from 1st object point
        Vector.y = Sin(Object(1).Radian) ' <<<  fix
        P1.x = Asteroid(Ast).Loc.x + Vector.x * Object(1).Radius * Asteroid(Ast).Size ' plot location on screen
        P1.y = Asteroid(Ast).Loc.y + Vector.y * Object(1).Radius * Asteroid(Ast).Size
        PSet (P1.x, P1.y) '                                               draw a pixel
        For Obj = 2 To 10 '                                               cycle through remaining points

            ' these assume North = 0 so Vectors are rotated 90 degrees
            Vector.x = Cos(Object(Obj).Radian) '                         calculate vector from object point
            Vector.y = Sin(Object(Obj).Radian) ' <<<< this should be -Cos
            Np.x = Asteroid(Ast).Loc.x + Vector.x * Object(Obj).Radius * Asteroid(Ast).Size ' plot location
            Np.y = Asteroid(Ast).Loc.y + Vector.y * Object(Obj).Radius * Asteroid(Ast).Size ' on screen
            Line -(Np.x, Np.y) '                                          draw line from previous point
        Next Obj
        Line -(P1.x, P1.y) '                                              draw final line back to start
        Vector.x = Cos(Asteroid(Ast).Dir) '                              get vector from asteroid radian
        Vector.y = Sin(Asteroid(Ast).Dir) ' <<<  This should be -Cos
        Asteroid(Ast).Loc.x = Asteroid(Ast).Loc.x + Vector.x * Asteroid(Ast).Speed ' plot location on screen
        Asteroid(Ast).Loc.y = Asteroid(Ast).Loc.y + Vector.y * Asteroid(Ast).Speed
        If Asteroid(Ast).Loc.x < -19 Then Asteroid(Ast).Loc.x = SWIDTH + 19 '        keep asteroids on screen
        If Asteroid(Ast).Loc.x > SWIDTH + 19 Then Asteroid(Ast).Loc.x = -19
        If Asteroid(Ast).Loc.y < -19 Then Asteroid(Ast).Loc.y = SHEIGHT + 19
        If Asteroid(Ast).Loc.y > SHEIGHT + 19 Then Asteroid(Ast).Loc.y = -19
    Next Ast
    _Display '                                                            update screen with changes
Loop Until _KeyDown(27) '                                                leave when ESC pressed
System '                                                                 return to operating system
' Asteroid object data (10 coordinate vector points)
Data 0,-5,5,-10,10,-5,7,0,10,5,2,10,-5,10,-10,5,-10,-5,-5,-10
b = b + ...
Reply
#27
Poly Blast Summary Lesson 17: Uses the ship, bullets and regular polygons from lesson 17 for a little shooting game.
Mouse Right Button shifts nose/gun Right likewise Mouse Left Button to the left
Mouse Wheel Rotates nose/guns.

Code: (Select All)
_Title "Poly Blast summary lesson 17" 'bplus 2024-10-10 & 11
Option _Explicit

Type XYPair
    As Single X, Y
End Type

Type SHIP_Type '         ship definition First 2 needed for DrawShip
    Loc As XYPair '      where the ship center is on screen
    Heading As Single '  Degree angle the ship is pointed towards
    V As XYPair '        Normal vector: V.X = cos(Ship.Heading) V.Y = sin(Ship.Heading)
    Speed As Single '    mult. Normal Vector by Speed add to old Loc for new Location
    Lives As Integer '   You have this many lives left in game
End Type

Type PolyType 'first 5 for DrawPoly
    As XYPair Loc '          Location on screen
    As Long NSides '         Number of sides = Number of points
    As Single Radius '       From center to point
    As Single Rotation '     Rotation offset = how much is poly turned
    As _Unsigned Long Colr ' color
    As XYPair V '            Vx, Vy Vector components for movement
    As Single RotAmt '       Rotate Poly this angle amount
    As Integer Live
End Type

Type Bullet '                bullet definition
    Loc As XYPair '          location of bullet
    V As XYPair '            vector of bullet
    Live As Integer '        active status of bullet
End Type

Dim Shared NPoly: NPoly = 10 '                   shared for Sub NewPoly index
Dim Shared Poly(1 To NPoly) As PolyType '        ditto

Screen _NewImage(1280, 740, 32)
_ScreenMove 0, 0
_PrintMode _KeepBackground

Dim ship As SHIP_Type '         get our ship started!
ship.Loc.X = _Width / 2 '       ship's x coordinate on screen
ship.Loc.Y = _Height / 2 '      ship's y coordinate on screen
ship.Heading = _Pi(3 / 2) '     let's head North for starters
ship.Speed = 5 '                ship's speed
ship.Lives = 20 '               the ship can take this many hits before game over

Dim showCompass As Integer '    show Compass toggle flag   use the c key to toggle
Dim As Single angle '           degrees for the compass
showCompass = -1 '              turn the toggle on

Dim MaxBullets: MaxBullets = 50 '        don't need many because slots reused
Dim Bullet(1 To MaxBullets) As Bullet '  setup array
Dim As Integer fire '                    fire flag for shooting bullets
Dim As Long hits '                       how many polygon you hit with bullets
Dim As Single t, lastt '                 control time between bullets

Dim As Long i, j, p '           various counters
Dim f&, s$ '                    add font and general string variable s$

f& = _LoadFont("arial.ttf", 128) ' load font and use later

For i = 1 To NPoly '            get some polys going
    NewPoly i
Next
Do '                            let the shooting begin
    Cls
    DrawShip ship.Loc, ship.Heading
    If showCompass Then ' I like your idea Terry to show turn ticks, here is a nice Compass for you.
        For angle = 0 To _Pi(1.99) Step _Pi(2 / 24)
            PSet (ship.Loc.X + 62 * Cos(angle), ship.Loc.Y + 62 * Sin(angle)) ' draw pixel at 10 degree point
            If angle = 0 Then
                _PrintString (ship.Loc.X + 62 * Cos(angle) + 3, ship.Loc.Y + 62 * Sin(angle) - 7), "E"
            ElseIf Abs(angle - _Pi(.5)) < .0001 Then
                _PrintString (ship.Loc.X + 62 * Cos(angle) - 2, ship.Loc.Y + 62 * Sin(angle) + 1), "S"
            ElseIf Abs(angle - _Pi) < .0001 Then
                _PrintString (ship.Loc.X + 62 * Cos(angle) - 11, ship.Loc.Y + 62 * Sin(angle) - 7), "W"
            ElseIf Abs(angle - _Pi(3 / 2)) < .0001 Then
                _PrintString (ship.Loc.X + 62 * Cos(angle) - 2, ship.Loc.Y + 62 * Sin(angle) - 16), "N"
            End If
        Next
    End If

    For i = 1 To NPoly 'draw amd update polys
        If Poly(i).Live Then
            If Sqr((Poly(i).Loc.X - ship.Loc.X) ^ 2 + (Poly(i).Loc.Y - ship.Loc.Y) ^ 2) < Poly(i).Radius + 60 Then
                'poly hits ship
                For j = 60 To 0 Step -5
                    Circle (ship.Loc.X, ship.Loc.Y), j, &HFFFFAA00
                Next
                _Display
                _Delay .25
                ship.Lives = ship.Lives - 1
                NewPoly i
            Else
                DrawPoly Poly(i).Loc, Poly(i).NSides, Poly(i).Radius, Poly(i).Rotation, Poly(i).Colr
                ' update poly position and rotation and keep in bounds
                Poly(i).Loc.X = Poly(i).Loc.X + Poly(i).V.X
                If Poly(i).Loc.X < 0 Then
                    Poly(i).Loc.X = 0: Poly(i).V.X = -Poly(i).V.X
                    If Poly(i).NSides < 9 Then Poly(i).NSides = Poly(i).NSides + 1 Else Poly(i).NSides = 3
                End If
                If Poly(i).Loc.X > _Width Then
                    Poly(i).Loc.X = _Width: Poly(i).V.X = -Poly(i).V.X
                    If Poly(i).NSides < 9 Then Poly(i).NSides = Poly(i).NSides + 1 Else Poly(i).NSides = 3
                End If
                Poly(i).Loc.Y = Poly(i).Loc.Y + Poly(i).V.Y
                If Poly(i).Loc.Y < 0 Then
                    Poly(i).Loc.Y = 0: Poly(i).V.Y = -Poly(i).V.Y
                    If Poly(i).NSides < 9 Then Poly(i).NSides = Poly(i).NSides + 1 Else Poly(i).NSides = 3
                End If
                If Poly(i).Loc.Y > _Height Then
                    Poly(i).Loc.Y = _Height: Poly(i).V.Y = -Poly(i).V.Y
                    If Poly(i).NSides < 9 Then Poly(i).NSides = Poly(i).NSides + 1 Else Poly(i).NSides = 3
                End If
                Poly(i).Rotation = Poly(i).Rotation + Poly(i).RotAmt
            End If 'poly hits ship
        End If
    Next
    'continuous fire
    fire = 0
    t = Timer(.01)
    If lastt = 0 Or t - lastt > .2 Then fire = 1: lastt = t Else fire = 0
    For i = 1 To MaxBullets 'handle bullets
        If Bullet(i).Live = 0 And fire = 1 Then 'have inactive bullet to use
            Bullet(i).Loc.X = ship.Loc.X + 60 * Cos(ship.Heading)
            Bullet(i).Loc.Y = ship.Loc.Y + 60 * Sin(ship.Heading)
            Bullet(i).V.X = 20 * Cos(ship.Heading)
            Bullet(i).V.Y = 20 * Sin(ship.Heading)
            Bullet(i).Live = -1
            fire = 0
        End If
        If Bullet(i).Live Then 'new location
            Bullet(i).Loc.X = Bullet(i).Loc.X + Bullet(i).V.X
            Bullet(i).Loc.Y = Bullet(i).Loc.Y + Bullet(i).V.Y
            If Bullet(i).Loc.X > 0 And Bullet(i).Loc.X < _Width And Bullet(i).Loc.Y > 0 And Bullet(i).Loc.Y < _Height Then 'in bounds draw it
                For p = 1 To NPoly 'check for collision with rock
                    If Poly(p).Live Then
                        If Sqr((Poly(p).Loc.X - Bullet(i).Loc.X) ^ 2 + (Poly(p).Loc.Y - Bullet(i).Loc.Y) ^ 2) < Poly(p).Radius + 10 Then 'its a hit!
                            'r(r).explodeFrame = 1 'linger with explosion
                            Poly(p).Live = 0
                            For j = Poly(p).Radius To 0 Step -5
                                Circle (Poly(p).Loc.X, Poly(p).Loc.Y), j, &HFFFFAA00
                            Next
                            _Display
                            NewPoly p
                            hits = hits + 1
                            'points = points + ((r(r).speed - 2) * 33.3333 + (50 - (r(r).c - 10)) * 2 + (90 - (r(r).r - 10)) * 1.1111) / 3
                            Bullet(i).Live = 0 'kill bullet
                        End If ' hit rock
                    End If 'rock is there
                Next
                If Bullet(i).Live Then Circle (Bullet(i).Loc.X, Bullet(i).Loc.Y), 10, _RGB32(255, 255, 0) 'draws bullet
            Else
                Bullet(i).Live = 0 'out of bounds
            End If ' bullet is in bounds
        End If ' bullet live
    Next ' bullet
    _Title "Poly Blast:" + Str$(hits) + "   Lives" + Str$(ship.Lives)
    _Display
    While _MouseInput
        ship.Heading = ship.Heading + _MouseWheel * _Pi(1 / 24) ' 22.5  degree changes, Thank Ken for this :)
    Wend 'update ship
    ship.Loc.X = _MouseX: ship.Loc.Y = _MouseY
    If _MouseButton(1) Then ship.Heading = _Pi 'this is new left and right guns
    If _MouseButton(2) Then ship.Heading = 0
    If _KeyHit = 99 Then showCompass = Not showCompass '          toggle flag when c for compass pressed
    _Limit 30
Loop Until _KeyDown(27) Or ship.Lives <= 0 ' escape
_Font f&
s$ = "GAME OVER"
_PrintString ((_Width - _PrintWidth(s$)) / 2, (_Height - 128) / 2), s$
_Display
Sleep
System

Sub NewPoly (index) ' for shared array Poly() as PolyType
    Dim red, grn, blu, r As Single, cx As Single, cy As Single, a As Single
    cx = _Width / 2: cy = _Height / 2
    Poly(index).Radius = Rnd * 60 + 20
    r = Int(Rnd * 4)
    Select Case r
        Case 0 ' from top
            Poly(index).Loc.X = Rnd * (_Width - 2 * Poly(index).Radius) + Poly(index).Radius
            Poly(index).Loc.Y = 0
        Case 1 ' from bottom
            Poly(index).Loc.X = Rnd * (_Width - 2 * Poly(index).Radius) + Poly(index).Radius
            Poly(index).Loc.Y = _Height
        Case 2 ' from left
            Poly(index).Loc.Y = Rnd * (_Height - 2 * Poly(index).Radius) + Poly(index).Radius
            Poly(index).Loc.X = 0
        Case 3 ' from right
            Poly(index).Loc.Y = Rnd * (_Height - 2 * Poly(index).Radius) + Poly(index).Radius
            Poly(index).Loc.X = _Width
    End Select

    ' this points every poly to pass through center screen
    a = _Atan2(cy - Poly(index).Loc.Y, cx - Poly(index).Loc.X)
    r = Rnd * 5 + 1 '                                          random speeds
    Poly(index).V.X = r * Cos(a) ' dx distance moved along x direction each loop
    Poly(index).V.Y = r * Sin(a) ' dy distance moved along y direction each loop
    Poly(index).NSides = 3 '+ Int(Rnd * 7) ' more than 9 looks too much like circle
    Poly(index).Rotation = Rnd * _Pi(2) ' start with some rotation

    red = -Sgn(Rnd < .5) * (56 * Rnd + 200) ' bright primary and 2nd colors setup
    grn = -Sgn(Rnd < .5) * (156 * Rnd + 100)
    blu = -Sgn(Rnd < .5) * (156 * Rnd + 100)
    Poly(index).Colr = _RGB32(red, grn, blu)
    Poly(index).RotAmt = Rnd * _Pi(1 / 10) - _Pi(1 / 20) ' add to rotaion this amount each loop
    Poly(index).Live = 1
End Sub

Sub DrawPoly (Place As XYPair, NSides As Long, Radius, RadRotation, C As _Unsigned Long)
    Dim pAngle: pAngle = _Pi(2 / NSides) ' angles from center to side points
    Dim a, savex, savey
    For a = 0 To _Pi(1.9999) Step pAngle
        If a = 0 Then
            PSet (Place.X + Radius * Cos(a + RadRotation), Place.Y + Radius * Sin(a + RadRotation)), C

            '!!!! this is classic formula for points about a central point !!!!
            savex = Place.X + Radius * Cos(a + RadRotation) ' save first point to tie at end of loop
            savey = Place.Y + Radius * Sin(a + RadRotation)
        Else
            Line -(Place.X + Radius * Cos(a + RadRotation), Place.Y + Radius * Sin(a + RadRotation)), C
        End If
    Next
    Line -(savex, savey), C
End Sub

Sub DrawShip (place As XYPair, DegreeHeading As Single) ' hey we can use this design in another app!!!
    Dim As Single radius
    radius = 60 ' nose and wing tips touch radius around central location = placeXY
    Dim pts(1 To 3) As XYPair 'the 3 outer points for triangle ship with 2 wings fit on radius
    pts(1).X = place.X + radius * Cos(0 + DegreeHeading) '   nose at 0 degrees
    pts(1).Y = place.Y + radius * Sin(0 + DegreeHeading)
    pts(2).X = place.X + radius * Cos(_Pi(3 / 4) + DegreeHeading) ' 180 - 45 SW wing tip
    pts(2).Y = place.Y + radius * Sin(_Pi(3 / 4) + DegreeHeading)
    pts(3).X = place.X + radius * Cos(_Pi(5 / 4) + DegreeHeading) ' 180 + 45 NW wing tip
    pts(3).Y = place.Y + radius * Sin(_Pi(5 / 4) + DegreeHeading)
    Line (pts(1).X, pts(1).Y)-(pts(2).X, pts(2).Y)
    Line (pts(2).X, pts(2).Y)-(place.X, place.Y)
    Line (pts(3).X, pts(3).Y)-(place.X, place.Y)
    Line (pts(3).X, pts(3).Y)-(pts(1).X, pts(1).Y)
End Sub

Probably should add sound, didn't do that Lesson yet Smile
b = b + ...
Reply




Users browsing this thread: 1 Guest(s)