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.
Probably should add sound, didn't do that Lesson yet
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
b = b + ...