'eRATication.txt 
' written for Naalaa 6 Windows 1.1.3 by bplus

'2018-07-17 started translate QB64 version over to Naalaa
' setup window and constants, visibles... as needed
' drawShooter, yea polydraw works!
' learn about keydown from sample files, nothing in docs?
' use keydown with arrow keys to rotate shooter
' use keydown with spacebar to shoot bullets
' setup bullets as object, guess need to initialize each and every object and part? no!
'2018-07-18 newRat and handleRats, bullet collisions, 
' fine tune add stats display and add mouse controls
'2018-07-19 today's goal is to eliminate as much float as possible ie do angles in degrees
' Oh a pleasant surprise: when I do pi# = acos(-1),
' it's value is 180.0 or 3.1415.. depending on radians called or not.

'================================ Instructions ==========================
' Up and down arrows for fast rotation of shooter.
' Left and right arrows for more fine tuned rotation of shooter.
' Shooter is connected to mouse, moving mouse moves shooter.
' Left button down for counter-clock wise rotation and
' right button down for clock- wise rotation.
' Spacebar fires bullets.
'========================================================================

'  Bonus Game get to life #3 and see how long you can play dodge rat!

randomize time()
'remove radians 

constant:
'screen 
wW 1200
wH 720

'bullet
nBullets  2000
bSpeed# 20.0

'rats
ratPack 5

'player
maxLife 3

visible:
'aha! when not in radians pi# becomes degrees, 
' that why I didn't have to rewrite all the rat drawing code!!!
pi# = acos#(-1.0)

'shooter 
shooterX = mousex()
shooterY = mousey()

'make this integer
shooterA = 0

fire = false
life = 1
nRats = life * ratPack
maxRats = maxLife * ratPack
gameOn = 1
points = 0

'objects
bullet?[nBullets]
rat?[maxRats]

hidden:
'object initialize
for i = 0 to nBullets - 1
	bullet[i].live = false
next

for i = 0 to nRats - 1
	_newRat i
next

set window 100, 20, wW, wH
set redraw off

'main loop
while gameOn
	fire = false
	shooterX = mousex()
	shooterY = mousey()

	'update for integers pi/60 = 180/60 = 3 180/10 = 18, so use 5 and 15
	if mousebutton(0) then shooterA = (shooterA - 5) % 360 
	if mousebutton(1) then shooterA = (shooterA + 5) % 360
	if keydown(38) then shooterA = (shooterA + 15) % 360
	if keydown(39) then shooterA = (shooterA + 5) % 360
	if keydown(40) then shooterA = (shooterA - 15) % 360
	if keydown(37) then shooterA = (shooterA - 5) % 360
	if keydown(" ") then fire = true

	_rgb 0
	draw rect 0, 0, wW, wH, true
	_drawShooter
	_handleRats
	_handleBullets
	_stats
	redraw
	wait 30
wend
_pause

' ==================== procedures for this app

procedure drawShooter()
	'calculate 3 points of triangle shooter, the 4th is middle of screen, pivot point
  x1 = shooterX + int(60.0 * cos#(float(shooterA))) 
  y1 = shooterY + int(60.0 * sin#(float(shooterA)))
	x2 = shooterX + int(30.0 * cos#(float(shooterA + 240))) 
  y2 = shooterY + int(30.0 * sin#(float(shooterA + 240)))
  x3 = shooterX + int(30.0 * cos#(float(shooterA - 240)))
  y3 = shooterY + int(30.0 * sin#(float(shooterA - 240)))
	_rgb 900
  _fTri shooterX, shooterY, x1, y1, x2, y2
  _fTri shooterX, shooterY, x1, y1, x3, y3
	_rgb 999
  draw line x1, y1, x2, y2
	draw line x1, y1, x3, y3
	draw line x1, y1, shooterX, shooterY
endproc

procedure handleBullets()
	for b = 0 to nBullets - 1
		if bullet[b].live = 0 and fire
			bullet[b].x = shooterX + int(60.0 * cos#(float(shooterA)))
			bullet[b].y = shooterY + int(60.0 * sin#(float(shooterA)))
			bullet[b].dx = int(bSpeed# * cos#(float(shooterA)))
			bullet[b].dy = int(bSpeed# * sin#(float(shooterA)))
			bullet[b].live = true
			fire = false
		endif
		if bullet[b].live = true
			bullet[b].x = bullet[b].x + bullet[b].dx
			bullet[b].y = bullet[b].y + bullet[b].dy
			if bullet[b].x > 0 and bullet[b].x < wW and bullet[b].y > 0 and bullet[b].y < wH
					_rgb 990
					draw ellipse bullet[b].x, bullet[b].y, 2, 2, true

				'here we will check if bullet collides with anything
				for r = 0 to nRats -1
					hit = false
					dx# = float(bullet[b].x - rat[r].x)
					dx# = dx# * dx#
					dy# = float(bullet[b].y - rat[r].y)
					dy# = dy# * dy#
					if int(sqr#(dx# + dy#)) < rat[r].r + 5
						'hit rat r
						if rat[r].dead = 0
							bullet[b].live = false
							rat[r].dead = 1
							points = points + life * life
							hit = true
							break
						endif
					endif
				next
				if hit = false 
					'otherwise draw bullet
					_rgb 990
					draw ellipse bullet[b].x, bullet[b].y, 2, 2, true
				endif
			else
				'out of bounds
				bullet[b].live = false
			endif
		endif
	next
endproc

procedure newRat(j)
		'pick a side to start rat from and set heading towards screen 
		side = rnd(4)
		if side = 0
			rat[j].x = 0
			rat[j].y = rnd(wH)
			rat[j].dx = rand(1, 6)
			rat[j].dy = rand(-4, 4)
		elseif side = 1
			rat[j].x = wW
			rat[j].y = rnd(wH)
			rat[j].dx = rand(-6, -1)
			rat[j].dy = rand(-4, 4)
		elseif side = 2
			rat[j].x = rnd(wW)
			rat[j].y = 0
			rat[j].dx = rand(-6, 6)
			rat[j].dy = rand(1, 4)
		elseif side = 3
			rat[j].x = rnd(wW)
			rat[j].y = wH
			rat[j].dx = rand(-6, 6)
			rat[j].dy = rand(-4, -1)		
    endif
		rat[j].dx = rat[j].dx * life
		rat[j].dy = rat[j].dy * life
		rat[j].r = rnd(60) / life + 10
		rat[j].dead = 0
		red = rnd(7) + 3
		green = red / 2 + rand(0, 2)
		blue = green / 2 + rand(0, 1)
    rat[j].kolor = 100 * red + 10 * green + blue
endproc

procedure handleRats()
	for zz = 0 to nRats - 1
		if rat[zz].dead = 0
			rat[zz].x = rat[zz].x + rat[zz].dx
			rat[zz].y = rat[zz].y + rat[zz].dy
		endif
		'rat collides with shooter?
		dx# = float(rat[zz].x - shooterX)
		dx# = dx# * dx#
		dy# = float(rat[zz].y - shooterY)
		dy# = dy# * dy#
		if int(sqr#(dx#  + dy#)) < rat[zz].r + 20 and rat[zz].dead = 0
			rad = 5
			do
				rad = rad + 5
				set color 255 - rad / 2, 128 - rad / 2, 0
				draw ellipse shooterX, shooterY, rad, rad, true
				redraw
				wait 10
			until rad > 255
			if life < maxLife
 				life = life + 1
				nRats = life * ratPack
				'new set o rats
				for zzz = 0 to nRats - 1
					_newRat zzz
				next  
			else
				gameOn = 0
				break
			endif		
		else 
			'haven't collided with shooter so update rat
			' is the rat inbounds
			if rat[zz].x >= 0 and rat[zz].x <= wW and rat[zz].y >= 0 and rat[zz].y <= wH
				'inbounds, is rat shot? 
				if rat[zz].dead > 0
					'show the burn out until reaches rat radius
					rat[zz].dead = rat[zz].dead + 2
					if rat[zz].dead < rat[zz].r
						set color 255 - rat[zz].dead, 128 - rat[zz].dead, 0
						draw ellipse rat[zz].x, rat[zz].y, rat[zz].r - rat[zz].dead, rat[zz].r - rat[zz].dead, true
					else
						_newRat zz
					endif
				else
					'rat not dead draw a regular rat, 
					'heading is given in degrees same as pi#
					heading# = atan2#(float(rat[zz].dy), float(rat[zz].dx))
					_rgb rat[zz].kolor
					noseX = rat[zz].x + int(2.0 * float(rat[zz].r) * cos#(heading#))
					noseY = rat[zz].y + int(2.0 * float(rat[zz].r) * sin#(heading#))
					neckX = rat[zz].x + int(0.75 * float(rat[zz].r) * cos#(heading#))
					neckY = rat[zz].y + int(0.75 * float(rat[zz].r) * sin#(heading#))
					tailX = rat[zz].x + int(2.0 * float(rat[zz].r) * cos#(heading# + pi#))
					tailY = rat[zz].y + int(2.0 * float(rat[zz].r) * sin#(heading# + pi#))
					earLX = rat[zz].x + int(float(rat[zz].r) * cos#(heading# - pi# / 12.0))
					earLY = rat[zz].y + int(float(rat[zz].r) * sin#(heading# - pi# / 12.0))
					earRX = rat[zz].x + int(float(rat[zz].r) * cos#(heading# + pi# / 12.0))
					earRY = rat[zz].y + int(float(rat[zz].r) * sin#(heading# + pi# / 12.0))
					draw ellipse rat[zz].x, rat[zz].y, int(0.65 * float(rat[zz].r)), int(0.65 * float(rat[zz].r)), true
					draw ellipse neckX, neckY, int(float(rat[zz].r) * 0.3), int(float(rat[zz].r) * 0.3), true
					_fTri noseX, noseY, earLX, earLY, earRX, earRY
					draw ellipse earLX, earLY, int(float(rat[zz].r) * 0.3), int(float(rat[zz].r) * 0.3), true
					draw ellipse earRX, earRY, int(float(rat[zz].r) * 0.3), int(float(rat[zz].r) * 0.3), true
					wX = int(0.5 * float(rat[zz].r) * cos#(heading# - 11.0 * pi# / 18.0))
					wY = int(0.5 * float(rat[zz].r) * sin#(heading# - pi# * 11.0 / 18.0))
					draw line noseX + wX, noseY + wY, noseX - wX, noseY - wY          
					wX =int(0.5 * float(rat[zz].r) * cos#(heading# - pi# * 7.0 / 18.0))
					wY =int(0.5 * float(rat[zz].r) * sin#(heading# - pi# * 7.0 / 18.0))
					draw line noseX + wX, noseY + wY, noseX - wX, noseY - wY
					draw line rat[zz].x, rat[zz].y, tailX, tailY
				endif
			else
				'out of bounds
        _newRat zz
			endif
			'hits shooter
		endif
		'collision with shooter
	next
endproc

procedure stats()
	set color 200, 225, 255
	set caret 1, 1
	s$ = "Life: " + str$(life) + "  Points: " + str$(points)
	wln s$
endproc

'===================== general procedures may or may not use all

procedure pause()
	set color 200, 225, 255
	wln "Click mouse to continue..."
	redraw
	wait mousebutton
endproc

function rand(n1, n2)
	if n1 < n2 then 
		lo = n1 ; hi = n2 
	else 
		lo = n2 ; hi = n1
	endif
	return rnd(hi - lo + 1) + lo
endfunc

procedure fTri(x1, y1, x2, y2, x3, y3)
	draw poly [x1, y1, x2, y2, x3, y3], true
endproc

procedure rgb(d3)
	sn$ = "000" + str$(d3)
	i = len(sn$) - 1
	b = int(mid$(sn$, i, 1)) * 28
	i = i-1
	g = int(mid$(sn$, i, 1)) * 28
	i = i-1
	r = int(mid$(sn$, i, 1)) * 28
	set color r, g, b
endproc