520 likes | 621 Views
Topic 07: Interactivity for Games. Overview. Techniques Timer and its events Collision detection and response for loop and Array (review) Main example: Air Raid AirRaid.swf in W drive Release Assignment 2 See Assignment.02 folder. Skeleton Program. AirRaid_skeleton.fla.
E N D
Topic 07: Interactivity for Games SCM-CityU
Overview • Techniques • Timer and its events • Collision detection and response • for loop and Array (review) • Main example: Air Raid • AirRaid.swf in W drive • Release Assignment 2 • See Assignment.02 folder SCM-CityU
Skeleton Program • AirRaid_skeleton.fla Based on an example in book:ActionScript 3.0 Game Programming University, 2nd Edition SCM-CityU
Frame 1 stop(); startButton.addEventListener(MouseEvent.CLICK,clickStart); function clickStart(event:MouseEvent){ startButton.removeEventListener(MouseEvent.CLICK,clickStart); gotoAndStop(2);// go to frame for main game } Name: startButton SCM-CityU
Frame 2 // control the movement of the gun stage.addEventListener(MouseEvent.MOUSE_MOVE, onGunMove); function onGunMove(e:MouseEvent):void{ gun.x = e.stageX;// use mouse to control gun’s translation } // score board initialization var shotsHit:int=0; var timeLeft:int=10; updateGameScore(); functionupdateGameScore():void{ shotsHitTxt.text=String("Score: "+ shotsHit); timeLeftTxt.text=String("Time Left: "+ timeLeft); } Name: shotsHitTxt Name: gun Name: timeLeftTxt SCM-CityU
Frame 3 Name: playAgainButton playAgainButton.addEventListener(MouseEvent.CLICK,clickPlayAgain); function clickPlayAgain(event:MouseEvent){ playAgainButton.removeEventListener( MouseEvent.CLICK,clickPlayAgain); gotoAndStop(2);// go back to main frame to restart game } SCM-CityU
Timer SCM-CityU
Timer (ref) • Usage 1: continuous updating for every user-specified interval(e.g., for programmatic animation) • E.g., rotating second hand per second • timer_events.swf • Updating frequency is specifiedby you, largely independent of Flash’s FPS setting • E.g., for every 1 second • Cf. ENTER_FRAME: animation synchronized with Flash runtime’s frame rate • E.g., Corresponding event listener will be invoked for 30 times per second (due to FPS = 30) SCM-CityU
Timer (ref) • Usage 2: count down • Allowing to perform certain action after a given time period SCM-CityU
Creating Timers • Timer is a complex data type • Syntax of variable definition for complex data type • Number of parameters can be zero, e.g., our SymbolDuck from last class (data type by us) • var duck:SymbolDuck = new SymbolDuck(); • var varName:ComplexType = newComplexType(para1, …, para2); SCM-CityU
Creating Timers • Timer has two parameters (ref) • interval: in milliseconds between timer event • TimerEvent.TIMER event happens whenever a timer reaches the specified interval • E.g., if interval = 1000, there is a TimerEvent.TIMER event for every second • An interval lower than 20 milliseconds is NOT recommended (too fast), which may causes runtime problems • repeatCount: total number of TimerEvent.TIMER needed • E.g., if repeatCount = 10, the timer will stop after 10 TimerEvent.TIMER events are completed;it will then trigger a TimerEvent.TIMER_COMPLETE • If zero (by default), the timer repeats infinitely Timer(interval:Number, repeatCount:int=0) SCM-CityU
Starting/Stopping Timers • Timer instance will not start to invoke events until you call its start()method • If your timer doesn’t work, it is often because you forget to start the timer (common problem)! • To stop the timer, call its stop() method var timer:Timer =new Timer(1000,2); timer.addEventListener(TimerEvent.TIMER, onTimer); timer.start(); var i:int=0; function onTimer(e:TimerEvent):void{ i++; trace("number of repetitions", i); } SCM-CityU
Example var timer:Timer =new Timer(1000); timer.addEventListener(TimerEvent.TIMER, onTimer); timer.start(); function onTimer(evt:TimerEvent):void{ watch.hand.rotation +=5; } SCM-CityU
Class Exercise • New year countdown • Count down from 10 to 1 • Output one number per second • Output “Happy New Year” 1 second after “1” is outputted • I.e., output “Happy New Year” instead of “0” • Hint: we need to output 11messages, one per second SCM-CityU
for Loop vs ENTER_FRAME/Timer • All of them allow repetitive execution of some code • However, unlike ENTER_FRAME or Timer, for loop itself is NOT sufficient for creating animation • Because of no frame refreshing for individual (for) iterations • E.g., NoAnimationWithForLoop.flavs AnimationWithTimer.fla var speed:Number=10; for(var i:uint =0; i <20; i++){ circle.x += speed; circle.y += speed; } Direct jumping SCM-CityU
Back to Main Example • Task: creating multiple planes in a random manner • Random intervals: use Timer • Random side: starting from either left or right • Random speed: random velocity; direction is dependent on which side the plane comes from • Random altitude • Random plane shape: one out of 5 plane models SCM-CityU
Random Intervals • It seems easy to make timer interval random • E.g., var t:Timer = new Timer(100+100*Math.random()); • But such solution still cannot make the delay for creating individual planes random • E.g., waiting for 1 second before creating Plane 1; waiting for 0.78 second before creating Plane 2 • In fact, with such timer, every plane will be created for a fixed interval SCM-CityU
Random Intervals • Solution • setTimer function below initializes a timer with random interval. This function will be repeated at random intervals var t:Timer; setTimer(); function setTimer():void{ t =new Timer(1000+Math.random()*1000,1); t.addEventListener(TimerEvent.TIMER_COMPLETE, timerComplete); t.start(); } function timerComplete(e:TimerEvent):void{ // create a plane // ... // for next timer with random interval setTimer(); } SCM-CityU
Example • TimerWithRandomInterval.fla var t:Timer; setTimer(); functionsetTimer():void{ t =new Timer(1000+Math.random()*1000,1); t.addEventListener(TimerEvent.TIMER_COMPLETE,timerComplete); t.start(); } functiontimerComplete(e:TimerEvent):void{ // create a circle and add it to stage var c:Symbol1 =new Symbol1(); c.x=stage.stageWidth*Math.random(); c.y=stage.stageHeight*Math.random(); addChild(c); // for next timer with random interval setTimer(); } SCM-CityU
Review: Dynamically Creating Display Objects in AS • Create a class name for your symbol • E.g., MySymbol • Create a symbol instance in AS • E.g., var s:MySymbol = newMySymbol(); • Display it to stage • addChild(s); SCM-CityU
Review: Instance Name vs Class Name • Instance name: like variable name in AS • If your AS wants to directly assess some existing symbol instance on stage, assign instance name • Class name: like data type in AS • If your AS wants to dynamically create new symbol instances, create class name for your symbol! • Class naming style is the same asvariable/instance naming style This name has no special usage SCM-CityU
Scope of Variables • Local variables • Defined in function bodies (in-between function {}) • Can be used only within the function where variables are created • Can preventname collision • Global variables • Can be accessedeverywhere var v01:Number=3;// global variable function show1():void{ var v02:Number=4;// local variable var v03:Number=5;// local variable trace(v01);// 3 } function show2():void{ var v02:Number=6;// local variable trace(v02);// 6 trace(v03);// compilation error: local variable in show1 } show1(); show2(); trace(v01);// 3 trace(v02);// compilation error: local variable in show1/show2 trace(v03);// compilation error: local variable in show1 SCM-CityU
Random Speed • Each plane has a random speed • How to store such set of random speed values? • Solution 1: create another array to store speed values • For plane planes[i], its corresponding speed is planeSpeedArray[i] var planeSpeedArray:Array=newArray(); SCM-CityU
Random Speed • Solution 2: associate speed directly with each plane(much simpler!) • Airplane is a complex data type • For complex data type, you can create temporary propertiesby assignment operator • Such temporary properties behave exactly the same as predefined properties like x, y, alpha etc. • You might use any valid variable name as property name, e.g., p.speed =Math.random()* 8 + 3; p.speedX =Math.random()* 8 + 3; SCM-CityU
Random Side • Originally planes are designed for right-to-left flight • Need to flipping shape for planes from left border • By setting scaleX = -1 • Exact transformation will depend on the location of registration point • E.g., example below has registration at top-left corner x x scaleX = -1 Y Y SCM-CityU
Class Exercise • Task: fire a bullet for each mouse click • Create an Array: name bullets • Add event listener for MouseEvent.CLICK • Inside this event listener, create a bullet and add it to stage • In this exercise, don’t bother the movement of bullets SCM-CityU
Make Planes Moving for(declare counter; condition; update counter){ // statement(s) to execute repeatedly // as long as condition is true } for(var i:int=1; i <=100; i++){ trace(i); } • Review: for loop structure • Starting with for keyword • Example Spring 2012 SCM-CityU SCM-CityU 29
Make Planes Moving • Class exercise • Make each plane planes[i] move at speed of planes[i].speed • Hint: use for loop to access every plane in planes array SCM-CityU
Removing Off-Screen Planes • Since we’re keeping inserting new planes, we have to remove planes that are off screen • Otherwise we’ll lead to many unused planes in RAM • But how? • Question 1: how to check? • Depending on flight direction • (p.speed < 0 && p.x < 0) || (p.speed > 0 && p.x > stage.stageWidth) • Question 2: how to remove such planes from stage and planes array? • Removal from stage is easy. Just use removeChild(plane); • How to remove all off-screen planes from the array? • Use Array.pop()? But this removes the last element of the array only. What if the element to be removed has an arbitrary index? SCM-CityU
Removing Off-Screen Planes from Array • Solution: use Array’s splice method (ref) • splice(startIndex:int, deleteCount:uint): Array; • startIndex: where the deletion begins • deleteCount: number of elements to be deleted • Returning an array containing the elements that were removed var vegetables:Array=newArray( "spinach","green pepper","cilantro","onion","avocado"); // remove 2 elements starting at index 2 var spliced:Array= vegetables.splice(2,2); trace(vegetables);// spinach,green pepper,avocado trace(spliced);// cilantro,onion SCM-CityU
Removing Off-Screen Planes from Array • How can we use splice together with for loop? • For example, how to remove all elements that are equal to 3 from an array below? • Above solution is wrong! Why? var a:Array=[3,3,5,6,7,3,3,5,7,3]; for(var i:uint =0; i < a.length; i++){ if(a[i]==3){ a.splice(i,1); trace(a); } } trace("final: ", a); SCM-CityU
Removing Off-Screen Planes from Array • Some 3 cannot be removed successfully! Iteration 0 3 3 3 5 5 6 6 7 7 3 3 3 3 5 5 7 7 3 3 First 3 is sliced and i++ i=0 i=1 Iteration 1 SCM-CityU
Removing Off-Screen Planes from Array • Correct solution: bottom-up iteration var a:Array=[3,3,5,6,7,3,3,5,7,3]; for(var i:int= a.length-1; i >=0; i--){ if(a[i]==3){ a.splice(i,1); trace(a); } } trace("final: ", a); 3 3 3 3 5 5 6 6 7 7 3 3 3 3 5 5 7 7 3 i=9 i=8 Iteration 0 Iteration 1 SCM-CityU
Class Exercise • Task: making bullets moving! • You can get the ideas from movePlanes function SCM-CityU
Next Step • Check if any bullet hitsany plane SCM-CityU
Collision Detection & Response SCM-CityU
Collision Detection (wiki) • Building block for many applications, e.g., games • Detecting if objects intersect with each other • Detection complexity depends on shape complexity SCM-CityU
Collision Detection in AS • Collision against stage borders or other boundaries SCM-CityU
Collision Detection in AS • Collision between complex objects • Use DisplayObject’s hitTestObject method or hitTestPoint method • E.g., bird.hitTestObject(wall); SCM-CityU
hitTestObject Method (ref) • Check if bounding boxes of two display objects intersect with each other • Check if two corresponding rectangles overlap or not • E.g., bird.hitTestObject(wall); • Return true if intersection detected; false otherwise. SCM-CityU
Example • Decrease HP points when collision is detected • Start with skeleton program in W drive wall hp bird bird.hitTestObject(wall) Equivalent testing hill hill.hitTestObject(bird) SCM-CityU
Class Exercise • Task: detect if there is collision between bird and hill bird hill SCM-CityU
Weakness of hitTestObject Method • It is possible that • Display objects do not intersect with each other • But their bounding boxes do intersect SCM-CityU
hitTestPoint Method (ref) • obj.hitTestPoint(x, y, shapeFlag) • Detect if point (x, y) intersects with obj • If shapeFlag == true, detection is done against object shape • If shapeFlag == false, detection is done against bounding box of the object • E.g., hill.hitTestPoint(mouseX, mouseY, true) (x,y) (x,y) shapeFlag == false shapeFlag == true SCM-CityU
Collision Detection in AS • How to detect collision between objects with complex shapes? • Approximate solution • Sample the boundary of one object into a set of points {pi} • For every pi, check if it intersects with another shape • Using shapeA.hitTestPoint(pi.x, pi.y, true); p0 p1 p9 Shape A p2 p8 p3 p5 p7 p4 p6 SCM-CityU
Class Exercise • Check if any bullet hits any plane • Hint: use nested for loop • For every bullet b • For every plane p • Do hit test on the pair of b and p SCM-CityU
Avoid Getting Hit Twice • How to avoid any plane or bullet getting hit twice? • Simply removing bullets/planes from stage and array • Use Array’s splice method • Traverse array in bottom-up manner • If a bullet hits any plane, it is meaningless to compare it with the other plane elements in planes array • We need to immediatelly exit the inner loop if any hit is detected • Use break key word // for each bullet for(var bi:int= bullets.length-1; bi >=0; bi--){ // for each plane for(var ai:int= planes.length-1; ai >=0; ai--){ // splicing elements below } } SCM-CityU
Early Exit of for Loop • Break statement causes inner-most loop to be terminated immediately for(var i:int=0; i <=10; i++){ if(i ==8){ break;// exit the loop }trace(i); } for(var i:int=0; i <=10; i++){ for(var j:int=0; j <=15; j++){ if(j ==8){ break;// exit inner loop only } trace(i, j); } } SCM-CityU