/* 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