/* This program shows how to move a gun turret and track shots. The physics that
is covered is traslating between vector (Magnitude & Angle) and standard
artesian (x & y) notation to simplify the process of adding gravity.(Currently not activated)
Advanced computer concepts are use of:
Input.KeyDown
*/
View.Set ("graphics:max,max")
/*------------------------------------------------------------------
VECTORTOXY - XYTOVECTOR
~~~~~~~~~~
The key to this program are these two procedures. A vector is just a
magnitude in a direction. For Example 10 km NE is a vector. To keep
track of things and draw them on the screen we break the vector into
it's x and y components. Basically the vector is the hypotenuse of the
triangle, the angle is well the angle, x is the adjacent side and y is
the opposite side.
----------------------------------------------------------------------- */
proc level1 (level1map:int)
Pic.Draw (level1map,0,0,picCopy)
end level1
%level 2 %%ball bounce%%
proc level2 (level3 : int)
Pic.Draw (level3, 0, 0, picCopy)
end level2
proc vectorToXY (mag, ang : real, var x, y : real)
x := cosd (ang) * mag
y := sind (ang) * mag
end vectorToXY
proc xyToVector (x, y : real, var mag, ang : real)
mag := sqrt (x ** 2 + y ** 2)
if mag > 0 then
if x >= 0 then
ang := arcsind (y / mag)
else
ang := 180 - arcsind (y / mag)
end if
else
ang := 0
end if
end xyToVector
proc trackInput (var mag, ang : real, var shotFired : boolean)
shotFired := false
var chars : array char of boolean
Input.KeyDown (chars)
if chars (KEY_UP_ARROW) then
mag := min (mag + .2, 100)
end if
if chars (KEY_RIGHT_ARROW) then
ang := (ang - 1) mod 360
end if
if chars (KEY_LEFT_ARROW) then
ang := (ang + 1) mod 360
end if
if chars (KEY_DOWN_ARROW) then
mag := max (1, mag - .2)
end if
if chars (' ') then %Fire a shot
shotFired := true
end if
end trackInput
/* -----------------------------------------------------------------------
ADDSHOT
~~~~~~~
The shot is maintained in 5 variables. One of the variables
is whether the shot is alive or not. i.e. is the shot still on the screen.
----------------------------------------------------------------------- */
proc addShot (mag, ang : real, var shotvx, shotvy, shotx, shoty : real, var shotlive : boolean)
if not shotlive then
shotlive := true
vectorToXY (mag, ang, shotvx, shotvy)
vectorToXY (20, ang, shotx, shoty)
shotvx /= 10 % this will be the number of pixels the shot moves each time around the loop
shotvy /= 10
shotx += 100 % This is so the shots come out of the barrel
shoty += 300
end if
end addShot
/* -----------------------------------------------------------------------
TRACKSHOTS
~~~~~~~~~~
Trackshots does not draw anything. It is best to place ALL of your drawing
of the scene in the same place. TrackShots just adjusts the values in
the shots variabes so they can be drawn properly.
----------------------------------------------------------------------- */
proc trackShots (var shotvx, shotvy, shotx, shoty, lives : real, var shotlive : boolean, var level : int, level3 : int,var level1map :int)
if shotlive then
if shotx < 0 then %%%%%%or shotx > maxx or
shotlive := false % so we can recycle the shot
lives -= 1
elsif shoty < 0 then
shotlive := false
lives -= 1
elsif shoty > maxy then
shotlive := false
lives -= 1
else
if level = 1 then
level1(level1map)
elsif level = 2 then
level2 (level3)
end if
%shotvy -= .01 % This is the effect of gravity. Don't worry about
% using 9.8 m/s/s Just play with it 'till it looks good
shotx += shotvx
shoty += shotvy
for i : 1 .. 10 % top of ball
if whatdotcolour (round (shotx - 10 + i), round (shoty + 11)) = black then
shotvy := - (shotvy) %top
exit
elsif whatdotcolour (round (shotx - 10 + i), round (shoty - 11)) = black then
shotvy := - (shotvy) % bottom
exit
elsif whatdotcolour (round (shotx + 11), round (shoty - 10 + i)) = black then
shotvx := - (shotvx)
exit
elsif whatdotcolour (round (shotx - 11), round (shoty - 10 + i)) = black then
shotvx := - (shotvx) % left
exit
elsif whatdotcolour (round (shotx - 10 + i), round (shoty + 11)) = red then
shotlive := false
lives -= 1
exit
elsif whatdotcolour (round (shotx - 10 + i), round (shoty - 11)) = red then
shotlive := false
lives -= 1
exit
elsif whatdotcolour (round (shotx + 11), round (shoty - 10 + i)) = red then
shotlive := false
lives -= 1
exit
elsif whatdotcolour (round (shotx - 11), round (shoty - 10 + i)) = red then
shotlive := false
lives -= 1 % left
exit
end if
end for
if shotx >= maxx then
level += 1
cls
delay (500)
shotlive := false
% elsif shoty >= maxy then % top wall - ball will travel down after it gets to the edge of the screen
% shotvy := - (shotvy)
% elsif shotx <= 0 then % left wall- ball will travel right after it gets to the edge of the screen
% shotvx := - (shotvx)
% elsif shoty <= 0 then % bottom of screen --Life is lost
% shotvy := - (shotvy)
end if
end if
end if
end trackShots
/* -----------------------------------------------------------------------
DRAWSCENE
~~~~~~~~~
It is common to have one procedure that draws the entire scene. It
might call a number of other custom made procedures to do the job.
You will notice that all of the parameters are call by value. If I am
just drawing the scene I shouldn't be changing anything.
----------------------------------------------------------------------- */
proc drawScene (mag, ang : real, shotx, shoty : real, shotlive : boolean, lives : real, level : int, level3 : int,var level1map : int)
var linex, liney : real
var dx, dy : real
vectorToXY (mag, ang, dx, dy)
vectorToXY (20, ang, linex, liney)
if level = 1 then
level1(level1map)
elsif level = 2 then
level2 (level3)
end if
drawfilloval (100, 300, 2, 2, 4)
drawline (100, 300, round (100 + linex), round (300 + liney), 1)
drawfilloval (round (100 + linex), round (300 + liney), 2, 2, 2)
if shotlive then
drawfilloval (round (shotx), round (shoty), 10, 10, 7)
end if
locate (1, 1)
put "MAG:", round (mag) : 3, " ==> X:", round (dx) : 3, " Y:", round (dy) : 3
locate (2, 1)
put " lives ", lives
end drawScene
/* -----------------------------------------------------------------------
MAINLINE
~~~~~~~~
The mainline contains a very standard MAIN GAME LOOP. You check the input,
adjust everything in the game world based on input, passage of time and
interactions between other things in the game world. Finaly you draw the
scene.
----------------------------------------------------------------------- */
% clear the shots array to allow for new shots
var shotx : real := 0
var shoty : real := 0
var shotvx : real
var shotvy : real
var shotlive : boolean := false
var lives : real := 5
var shotFired : boolean := false % Did the user try to shoot (won't shoot if gun is "hot"
var ang : real := 0 % current angle of the big gun
var mag : real := 100 % Amount of power being used for the shots
var font : int := Font.New ("sans serif:14:bold")
var font2 : int := Font.New ("sans serif:24:bold")
var name : string
var midx : int := maxx div 2
var midy : int := maxy div 2
var mx, my, mb : int
var current_tool : string := "no tool"
var ch : string (1) := "p"
var level : int := 1
var level3 : int := Pic.FileNew ("Level 3.jpg")
var level1map : int := Pic.FileNew ("level 1.jpg")
Font.Draw ("Welcome to Ball Bounce", midx - 200, midy + 50, font2, brightgreen)
locate (22, 51)
put "What is your name?"
locate (23, 51)
get name
drawfillbox (0, 0, 9999, 9999, black)
Font.Draw (name, midx - 150, midy - 70, font, brightgreen)
Font.Draw ("Ball Bounce", midx - 200, midy - 30, font2, brightgreen)
drawfillbox (350, 170, 540, 245, grey) %start
setscreen ("nocursor")
Font.Draw ("The aim of the game is to get the ball to the other side of the level. The ball can bounce off dark grey squares ", 10, 600, font, brightgreen)
Font.Draw (". But must not hit the light grey squares. Use the left arrow key and the right one to aim the ball. Have Fun", 10, 500, font, brightgreen)
Font.Draw ("Hit enter to Start", 360, 200, font, red)
loop
getch (ch)
exit when ord (ch) = 10
end loop
setscreen ("offscreenonly")
loop
exit when lives = 0
cls
trackInput (mag, ang, shotFired)
if shotFired then
addShot (mag, ang, shotvx, shotvy, shotx, shoty, shotlive)
end if
trackShots (shotvx, shotvy, shotx, shoty, lives, shotlive, level, level3,level1map)
drawScene (mag, ang, shotx, shoty, shotlive, lives, level, level3,level1map)
View.Update
delay (0)
end loop