320 likes | 410 Views
14 – Functions and Modules. Questions: Parameters. Consider the following code: Sub Move(ByRef obj, ByVal dist) obj.style.posLeft = obj.style.posLeft + dist obj.style.posTop = obj.style.posTop + dist End Sub Move imgShip, 25 Name a formal parameter Name an actual parameter.
E N D
Questions: Parameters • Consider the following code:Sub Move(ByRef obj, ByVal dist) obj.style.posLeft = obj.style.posLeft + dist obj.style.posTop = obj.style.posTop + dist End SubMove imgShip, 25 • Name a formal parameter • Name an actual parameter objdist imgShip 25
Session Aims & Objectives • Aims, to introduce: • the idea of a function as a way to make code shorter and easier to understand • the idea of modules as a way to split up large programs and share code between pages • Objectives,by end of this week’s sessions, you should be able to: • create your own functiondefinitions • call these functions • appropriately split a program into multiple modules • reuse modules in several pages/programs
Example: Interceptor (analysis) • SPECIFICATION • User Requirements • to be entertained • Software Requirements • Functional: • display image of space ship, which can be moved using the left and right arrow keys • display images of asteroids, which the user must block using the space ship (thereby gaining points) • Non-functionalshould be playable in real time
Example: Interceptor (design) • Computer games & simulations work like board games:
Problem Solving: Collision Detection • 2 types of problem: • familiar (seen before – remember solution) • novel (work out solution) • generate algorithm: • solve it on paper • draw diagrams • work through possibilities • ask how did I do that • what steps did I take?
Example: Interceptor v1 (code) Option Explicit Dim xInc Dim score Sub window_onLoad() Randomize imgShip.style.posTop = document.body.clientHeight - imgShip.height imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) xInc = 0 score = 0 window.setInterval "Main", 20 End Sub Sub document_OnKeyDown() Select Case window.event.keyCode Case 37 xInc = xInc + 2 Case 39 xInc = xInc - 2 End Select End Sub Sub Main Dim nxt nxt = imgShip.style.posLeft - xInc If nxt < 0 Or nxt > document.body.clientWidth - imgShip.width Then xInc = -xInc Else imgShip.style.posLeft = nxt End If imgAst1.style.posTop = imgAst1.style.posTop + 4 If (imgAst1.style.posTop + imgAst1.height) > document.body.clientHeight Then imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If If imgAst1.style.posTop + imgAst1.height > imgShip.style.posTop Then If imgAst1.style.posLeft + imgAst1.width > imgShip.style.posLeft Then If imgAst1.style.posLeft < imgShip.style.posLeft + imgShip.width Then score = score + 1 parScore.innerText = "Score: " & score imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If End If End If End Sub Sub window_onLoad() Randomize imgShip.style.posTop = document.body.clientHeight - imgShip.height imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) xInc = 0 score = 0 window.setInterval "Main", 20 End Sub
Example: Interceptor v1 (code) Option Explicit Dim xInc Dim score Sub window_onLoad() Randomize imgShip.style.posTop = document.body.clientHeight - imgShip.height imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) xInc = 0 score = 0 window.setInterval "Main", 20 End Sub Sub document_OnKeyDown() Select Case window.event.keyCode Case 37 xInc = xInc + 2 Case 39 xInc = xInc - 2 End Select End Sub Sub Main Dim nxt nxt = imgShip.style.posLeft - xInc If nxt < 0 Or nxt > document.body.clientWidth - imgShip.width Then xInc = -xInc Else imgShip.style.posLeft = nxt End If imgAst1.style.posTop = imgAst1.style.posTop + 4 If (imgAst1.style.posTop + imgAst1.height) > document.body.clientHeight Then imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If If imgAst1.style.posTop + imgAst1.height > imgShip.style.posTop Then If imgAst1.style.posLeft + imgAst1.width > imgShip.style.posLeft Then If imgAst1.style.posLeft < imgShip.style.posLeft + imgShip.width Then score = score + 1 parScore.innerText = "Score: " & score imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If End If End If End Sub Sub document_OnKeyDown() Select Case window.event.keyCode Case 37 xInc = xInc + 2 Case 39 xInc = xInc - 2 End Select End Sub
Example: Interceptor v1 (code) Sub Main Dim nxt nxt = imgShip.style.posLeft - xInc If nxt < 0 Or nxt > document.body.clientWidth - imgShip.width Then xInc = -xInc Else imgShip.style.posLeft = nxt End If imgAst1.style.posTop = imgAst1.style.posTop + 4 If (imgAst1.style.posTop + imgAst1.height) > document.body.clientHeight Then imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If If imgAst1.style.posTop + imgAst1.height > imgShip.style.posTop Then If imgAst1.style.posLeft + imgAst1.width > imgShip.style.posLeft Then If imgAst1.style.posLeft < imgShip.style.posLeft + imgShip.width Then score = score + 1 parScore.innerText = "Score: " & score imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If End If End If End Sub Option Explicit Dim xInc Dim score Sub window_onLoad() Randomize imgShip.style.posTop = document.body.clientHeight - imgShip.height imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) xInc = 0 score = 0 window.setInterval "Main", 20 End Sub Sub document_OnKeyDown() Select Case window.event.keyCode Case 37 xInc = xInc + 2 Case 39 xInc = xInc - 2 End Select End Sub Sub Main Dim nxt nxt = imgShip.style.posLeft - xInc If nxt < 0 Or nxt > document.body.clientWidth - imgShip.width Then xInc = -xInc Else imgShip.style.posLeft = nxt End If imgAst1.style.posTop = imgAst1.style.posTop + 4 If (imgAst1.style.posTop + imgAst1.height) > document.body.clientHeight Then imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If If imgAst1.style.posTop + imgAst1.height > imgShip.style.posTop Then If imgAst1.style.posLeft + imgAst1.width > imgShip.style.posLeft Then If imgAst1.style.posLeft < imgShip.style.posLeft + imgShip.width Then score = score + 1 parScore.innerText = "Score: " & score imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If End If End If End Sub
Problem: Repeated Calculations • implementation (code) • more complicated than algorithm • technical detail (how) e.g. right = left + width If imgAst1.style.posTop + imgAst1.height > imgShip.style.posTop Then If imgAst1.style.posLeft + imgAst1.width > imgShip.style.posLeft Then If imgAst1.style.posLeft < imgShip.style.posLeft + imgShip.width Then score = score + 1 parScore.innerText = "Score: " & score imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If End If End If
Procedures and Functions • Both Procedures and Functions • Group of statements • Identified by uniquename • mirror real life activities • Procedures – just do something • Functions – return a value • used to perform calculations
Built in Functions • Sqr – gives square root of a number: Sqr(16) returns 4 Sqr(9) returns 3 Sqr(4) returns 2 • Rnd() – generates random numbers between 0 and 0.99999999… • Right, Mid, Left …
User Defined Functions (how) • Syntax very similar to procedure definition:Functionname(parameters) Statementblock name =valueEndFunction • where • name represents function’s name (you choose) • parameters represent information needed • value represent the return value
Functions: FtoC • The declaration: Function FtoC(F) FtoC = ((f-32) * 5) / 9 End Function • The call: parRes.innerText = FtoC(50)
Functions: Largest • What will first and second contain?
Questions: Functions • Consider the following function definition: Function Twice(num) Twice = num * 2 End Function • What do the following return: Twice(6) Dim b b = 12 Twice(b) 12 24
Example: Interceptor v2 • Function makes code easier to read (closer to pseudo-code / algorithm): If imgAst1.style.posTop + imgAst1.height > imgShip.style.posTop Then If posRight(imgAst1) > imgShip.style.posLeft Then If imgAst1.style.posLeft < posRight(imgShip) Then score = score + 1 parScore.innerText = "Score: " & score imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If End If End If End Sub Function posRight(obj) posRight = obj.style.posLeft + obj.width End Function
Question: Function Headers • Write the first line of a function definition to convert pounds to euros: • Write the first line of a function definition to convert minutes and hours to minutes: Function Euros(Pounds) Function Minutes(Mins, Hours)
Example: Interceptor v3 If ShipCollide(imgAst1) Then score = score + 1 parScore.innerText = "Score: " & score imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If Function ShipCollide(obj1) ShipCollide = False If obj1.style.posTop + obj1.height > imgShip.style.posTop Then If posRight(obj1) > imgShip.style.posLeft Then If obj1.style.posLeft < posRight(imgShip) Then ShipCollide = True End If End If End If End Function Function posRight(obj) posRight = obj.style.posLeft + obj.width End Function
Question: Functions • Write a function that converts kilometres to miles (divide the number of kilometres by 1.6 to get miles): Function Miles(km) Miles = km / 1.6 End Function
Problem: Interceptor Option Explicit Dim xInc Dim score Sub window_onLoad() Randomize imgShip.style.posTop = document.body.clientHeight - imgShip.height imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) xInc = 0 score = 0 window.setInterval "Main", 20 End Sub Sub document_OnKeyDown() Select Case window.event.keyCode Case 37 xInc = xInc + 2 Case 39 xInc = xInc - 2 End Select End Sub Sub Main Dim nxt nxt = imgShip.style.posLeft - xInc If nxt < 0 Or nxt > document.body.clientWidth - imgShip.width Then xInc = -xInc Else imgShip.style.posLeft = nxt End If imgAst1.style.posTop = imgAst1.style.posTop + 4 If (imgAst1.style.posTop + imgAst1.height) > document.body.clientHeight Then imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If If imgAst1.style.posTop + imgAst1.height > imgShip.style.posTop Then If imgAst1.style.posLeft + imgAst1.width > imgShip.style.posLeft Then If imgAst1.style.posLeft < imgShip.style.posLeft + imgShip.width Then score = score + 1 parScore.innerText = "Score: " & score imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If End If End If End Sub Option Explicit Dim xInc Dim score Sub window_onLoad() Randomize imgShip.style.posTop = document.body.clientHeight - imgShip.height imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) xInc = 0 score = 0 window.setInterval "Main", 20 End Sub Sub document_OnKeyDown() Select Case window.event.keyCode Case 37 xInc = xInc + 2 Case 39 xInc = xInc - 2 End Select End Sub Sub Main Dim nxt nxt = imgShip.style.posLeft - xInc If nxt < 0 Or nxt > document.body.clientWidth - imgShip.width Then xInc = -xInc Else imgShip.style.posLeft = nxt End If imgAst1.style.posTop = imgAst1.style.posTop + 4 If (imgAst1.style.posTop + imgAst1.height) > document.body.clientHeight Then imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If If ShipCollide(imgAst1) Then score = score + 1 parScore.innerText = "Score: " & score imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If End Sub Function ShipCollide(obj1) ShipCollide = False If obj1.style.posTop + obj1.height > imgShip.style.posTop Then If posRight(obj1) > imgShip.style.posLeft Then If obj1.style.posLeft < posRight(imgShip) Then ShipCollide = True End If End If End If End Function Function posRight(obj) posRight = obj.style.posLeft + obj.width End Function • Code is longer(but easier to read)
Modules • Projects can contain many modules/units • web pages (*.htm) • vb script file (*.vbs) • Modules • divide your code into separate parts • available to other pages and modules, using:<script language="vbscript"src="Interceptor.vbs"></script>
Example: Interceptor v4 Interceptor.htm • vb script file (module) holds functions and general procedures <script language="vbscript" src="Interceptor.vbs"></script> <script language=vbscript> Option Explicit Dim xInc Dim score Sub window_onLoad() Randomize imgShip.style.posTop = document.body.clientHeight - imgShip.height imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) xInc = 0 score = 0 window.setInterval "Main", 20 End Sub Sub document_OnKeyDown() Select Case window.event.keyCode Case 37 xInc = xInc + 2 Case 39 xInc = xInc - 2 End Select End Sub Sub Main Dim nxt nxt = imgShip.style.posLeft - xInc If nxt < 0 Or nxt > document.body.clientWidth - imgShip.width Then xInc = -xInc Else imgShip.style.posLeft = nxt End If imgAst1.style.posTop = imgAst1.style.posTop + 4 If (imgAst1.style.posTop + imgAst1.height) > document.body.clientHeight Then imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If If ShipCollide(imgAst1) Then score = score + 1 parScore.innerText = "Score: " & score imgAst1.style.posTop = 0 imgAst1.style.posLeft = Rnd() * (document.body.clientWidth - imgAst1.width) End If End Sub </script> Interceptor.vbs Function ShipCollide(obj1) ShipCollide = False If obj1.style.posTop + obj1.height > imgShip.style.posTop Then If posRight(obj1) > imgShip.style.posLeft Then If obj1.style.posLeft < posRight(imgShip) Then ShipCollide = True End If End If End If End Function Function posRight(obj) posRight = obj.style.posLeft + obj.width End Function
Example: Interceptor v5 <script language="vbscript" src="Interceptor.vbs"></script> <script language="vbscript"> Option Explicit Dim xInc Dim score Sub window_onLoad() Randomize MoveToBottom imgShip MoveRndHor imgAst1 xInc = 0 score = 0 window.setInterval "Main", 20 End Sub Sub document_OnKeyDown() Select Case window.event.keyCode Case 37 xInc = xInc + 2 Case 39 xInc = xInc - 2 End Select End Sub Sub Main MoveShip MoveDown imgAst1, 4 If AtBottom(imgAst1) Then MoveRndHor imgAst1 End If If HitShip(imgAst1) Then IncreaseScore MoveRndHor imgAst1 End If End Sub </script> Sub MoveToBottom(obj) obj.style.posTop = document.body.clientHeight - obj.height End Sub Sub MoveRndHor(obj) obj.style.posTop = 0 obj.style.posLeft = Rnd() * (document.body.clientWidth - obj.width) End Sub Sub MoveDown(obj, dist) obj.style.posTop = obj.style.posTop + dist End Sub Function HitShip(obj) HitShip = False If obj.style.posTop + obj.height > imgShip.style.posTop Then If posRight(obj) > imgShip.style.posLeft Then If obj.style.posLeft < posRight(imgShip) Then HitShip = True End If End If End If End Function Function posRight(obj) posRight = obj.style.posLeft + obj.width End Function Function AtBottom(obj) AtBottom = (obj.style.posTop + obj.height) > document.body.clientHeight End Function Sub IncreaseScore() score = score + 1 parScore.innerText = "Score: " & score End Sub Sub MoveShip() Dim nxt nxt = imgShip.style.posLeft - xInc If nxt < 0 Or nxt > document.body.clientWidth - imgShip.width Then xInc = -xInc Else imgShip.style.posLeft = nxt End If End Sub
Example: Interceptor v5 • Main code reads almost like algorithm: Sub Main MoveShip MoveDown imgAst1, 2 If AtBottom(imgAst1) Then MoveRndHor imgAst1 End If If HitShip(imgAst1) Then IncreaseScore MoveRndHor imgAst1 End If End Sub Sub Main MoveShip MoveDown imgAst1, 4 If AtBottom(imgAst1) Then MoveRndHor imgAst1 End If If HitShip(imgAst1) Then IncreaseScore MoveRndHor imgAst1 End If End Sub
Example: Interceptor v6 • Functions and Procedures • benefits when code gets larger • easy to add extra asteroid
Sharing Modules Clock Orbit Sub window_onLoad() Dim ang Dim s Dim i s = "" For i = 1 To 12 s = s & "<div id=div" & i & " style=""position: absolute;"">" & i & "</div>" Next s = s & "<img id=imgMid style=""position: absolute;"" src=dot.gif />" For i = 1 To 18 s = s & "<img id=imgSec" & i & " style=""position: absolute;"" src=dot.gif />" Next document.body.innerHTML = s imgMid.style.posleft = document.body.clientWidth / 2 imgMid.style.postop = document.body.clientHeight / 2 ang = 6.2 / 12 For i = 1 To 12 Position document.body.children("div" & i), 200, ang * i Next window.setinterval "ShowHands", 500 End Sub Sub ShowHands() Dim ang Dim s Dim i ang = 6.2 / 60 s = Second(Now()) For i = 1 To 18 Position document.body.children("imgSec" & i), i * 10, ang * s Next End Sub Sub Position(objO, o, a) objO.style.posleft = imgMid.style.posleft + Sin(a) * o objO.style.postop = imgMid.style.postop - Cos(a) * o End Sub Option Explicit Const orbit = 150 Dim ang Dim angInc Dim earthLft Dim earthTop Dim ang2 Sub Window_onLoad() earthLft = imgEarth.style.posleft earthTop = imgEarth.style.postop imgMoon.Style.posLeft = earthLft imgMoon.Style.posTop = earthTop + orbit window.setInterval "MoonRotate", 50 ang = 0 angInc = 0.025 ang2 = 0 End Sub Sub MoonRotate() ang = ang + angInc imgMoon.Style.posLeft = earthLft + (Sin(ang) * orbit) imgMoon.Style.posTop = earthTop + (Cos(ang) * orbit) ang2 = ang2 - (angInc * 3) imgAstr.Style.posLeft = imgMoon.style.posleft + (Sin(ang2) * 50) imgAstr.Style.posTop = imgMoon.style.postop + (Cos(ang2) * 50) End Sub • 2 pages can use same module:
Tutorial Exercises: Interceptor • LEARNING OBJECTIVE: • use functions to shorten your code and make it easier to modify • Task 1: Get the Interceptor example (from the lecture) working. • Task 2: Modify your page to play a suitable sound when the asteroid collides with the ship. • Task 3: Modify your page to have 4 asteroids • Task 4: Modify your page so that the player must avoid the asteroids. Give your player 5 lives (lose a life each time the space craft hits an asteroid). • Task 5: Add an escape pod which the player must pick up (hit) to increase their score.
Tutorial Exercises: Position • LEARNING OBJECTIVE: • use a module file to share code between pages • Task 1: Create a web site that contains copies of your orbit and clock examples. • Task 2: Create a module file containing shared code between the modules for the position procedure.