SM1205 Interactivity Topic 10: Motion Tracking Part II Spring 2012SCM-CityU1.
SM1205 Interactivity Topic 07: Interactivity for Games Spring 2012SCM-CityU1.
-
Upload
kerry-nichols -
Category
Documents
-
view
234 -
download
2
Transcript of SM1205 Interactivity Topic 07: Interactivity for Games Spring 2012SCM-CityU1.
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
Spring 2012 SCM-CityU 2
Skeleton Program• AirRaid_skeleton.fla
Spring 2012 SCM-CityU 3
Based on an example in book: ActionScript 3.0 Game Programming University, 2nd EditionBased on an example in book: ActionScript 3.0 Game Programming University, 2nd Edition
Frame 1
Spring 2012 SCM-CityU 4
stop();
startButton.addEventListener(MouseEvent.CLICK,clickStart); function clickStart(event:MouseEvent) {
startButton.removeEventListener(MouseEvent.CLICK,clickStart); gotoAndStop(2); // go to frame for main game
}
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 Name: startButton
Frame 2
Spring 2012 SCM-CityU 5
Name: timeLeftTxtName: timeLeftTxt
// 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();
function updateGameScore(): void { shotsHitTxt.text = String("Score: " + shotsHit); timeLeftTxt.text = String("Time Left: " + timeLeft);
}
// 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();
function updateGameScore(): void { shotsHitTxt.text = String("Score: " + shotsHit); timeLeftTxt.text = String("Time Left: " + timeLeft);
}
Name: shotsHitTxtName: shotsHitTxt Name: gunName: gun
Frame 3
Spring 2012 SCM-CityU 6
Name: playAgainButton
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 }
playAgainButton.addEventListener(MouseEvent.CLICK,clickPlayAgain);
function clickPlayAgain(event:MouseEvent) {
playAgainButton.removeEventListener(MouseEvent.CLICK,clickPlayAgain);
gotoAndStop(2); // go back to main frame to restart game }
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)
Spring 2012 SCM-CityU 8
Timer (ref)• Usage 2: count down – Allowing to perform certain action after a given time period
Spring 2012 SCM-CityU 9
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();
Spring 2012 SCM-CityU 10
var varName:ComplexType = new ComplexType(para1, …, para2);
var varName:ComplexType = new ComplexType(para1, …, para2);
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
Spring 2012 SCM-CityU 11
Timer(interval:Number, repeatCount:int = 0)Timer(interval:Number, repeatCount:int = 0)
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
Spring 2012 SCM-CityU 12
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);
}
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);
}
Example
Spring 20112 SCM-CityU 13
var timer:Timer = new Timer(1000); timer.addEventListener(TimerEvent.TIMER, onTimer); timer.start();
function onTimer(evt:TimerEvent):void { watch.hand.rotation +=5; }
var timer:Timer = new Timer(1000); timer.addEventListener(TimerEvent.TIMER, onTimer); timer.start();
function onTimer(evt:TimerEvent):void { watch.hand.rotation +=5; }
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 11 messages, one per second
Spring 2012 SCM-CityU 14
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.fla vs AnimationWithTimer.fla
Spring 2012 SCM-CityU 15
var speed:Number = 10; for (var i:uint = 0; i < 20; i++) {
circle.x += speed; circle.y += speed;
}
var speed:Number = 10; for (var i:uint = 0; i < 20; i++) {
circle.x += speed; circle.y += speed;
}Direct jumpingDirect jumping
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
Spring 2012 SCM-CityU 16
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
Spring 2012 SCM-CityU 17
Random Intervals • Solution
– setTimer function below initializes a timer with random interval. This function will be repeated at random intervals
Spring 2012 SCM-CityU 18
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();
}
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();
}
Review: Dynamically Creating Display Objects in AS
1. Create a class name for your symbol – E.g., MySymbol
2. Create a symbol instance in AS– E.g., var s:MySymbol = new MySymbol();
3. Display it to stage – addChild(s);
Spring 2012 SCM-CityU 20
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 as
variable/instance naming style
Spring 2012 SCM-CityU 21
This name has no special usageThis name has
no special usage
Scope of Variables • Local variables
– Defined in function bodies (in-between function {})– Can be used only within the function where variables are
created– Can prevent
name collision
• Global variables– Can be
accessedeverywhere
Spring 2012 SCM-CityU 23
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); // 3trace(v02); // compilation error: local variable in show1/show2trace(v03); // compilation error: local variable in show1
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); // 3trace(v02); // compilation error: local variable in show1/show2trace(v03); // compilation error: local variable in show1
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]
Spring 2012 SCM-CityU 24
var planeSpeedArray:Array = new Array();
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 properties
by 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.,
Spring 2012 SCM-CityU 25
p.speed = Math.random() * 8 + 3; p.speed = Math.random() * 8 + 3;
p.speedX = Math.random() * 8 + 3; p.speedX = Math.random() * 8 + 3;
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
Spring 2012 SCM-CityU 26
x
Y
x
Y
scaleX = -1
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 bulletsSpring 2012 SCM-CityU 28
Make Planes Moving
• Review: for loop structure– Starting with for keyword
– Example
Spring 2012 SCM-CityU 29
for (declare counter; condition; update counter) { // statement(s) to execute repeatedly // as long as condition is true
}
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);}
for (var i:int = 1; i <= 100; i++) { trace(i);}
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
Spring 2012 SCM-CityU 30
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?
Spring 2012 SCM-CityU 31
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
Spring 2012 SCM-CityU 32
var vegetables:Array = new Array("spinach", "green pepper", "cilantro", "onion",
"avocado");
// remove 2 elements starting at index 2var spliced:Array = vegetables.splice(2, 2);
trace(vegetables); // spinach,green pepper,avocado trace(spliced); // cilantro,onion
var vegetables:Array = new Array("spinach", "green pepper", "cilantro", "onion",
"avocado");
// remove 2 elements starting at index 2var spliced:Array = vegetables.splice(2, 2);
trace(vegetables); // spinach,green pepper,avocado trace(spliced); // cilantro,onion
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?
Spring 2012 SCM-CityU 33
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);
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);
Removing Off-Screen Planes from Array
• Some 3 cannot be removed successfully!
Spring 2012 SCM-CityU 34
3 3 5 6 7 3 3 5 7 3
i=0
3 5 6 7 3 3 5 7 3
i=1
First 3 is sliced and i++
Iteration 0
Iteration 1
Removing Off-Screen Planes from Array
• Correct solution: bottom-up iteration
Spring 2012 SCM-CityU 35
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);
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 5 6 7 3 3 5 7 3
i=9
i=8
Iteration 0
Iteration 1 3 3 5 6 7 3 3 5 7
Class Exercise
• Task: making bullets moving! – You can get the ideas from movePlanes function
Spring 2012 SCM-CityU 36
Collision Detection (wiki)• Building block for many applications, e.g., games– Detecting if objects intersect with each other
• Detection complexity depends on shape complexity
Spring 2012 SCM-CityU 39
Collision Detection in AS• Collision against stage borders or other boundaries
Spring 2012 SCM-CityU 40
Collision Detection in AS
• Collision between complex objects
• Use DisplayObject’s hitTestObject method or hitTestPoint method
• E.g., bird.hitTestObject(wall);
Spring 2012 SCM-CityU 41
• 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.
hitTestObject Method (ref)
Spring 2012 SCM-CityU 42
Example • Decrease HP points when collision is detected– Start with
skeleton program in W drive
Spring 2012 SCM-CityU 43
hp
hill
wall
bird
bird.hitTestObject(wall)
hill.hitTestObject(bird)
Equivalent testing
Class Exercise • Task: detect if there is collision between bird and hill
Spring 2012 SCM-CityU 44
bird
hill
Weakness of hitTestObject Method
• It is possible that – Display objects do not intersect with each other– But their bounding boxes do intersect
Spring 2012 SCM-CityU 45
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)
Spring 2012 SCM-CityU 46
(x,y)(x,y)
shapeFlag == trueshapeFlag == false
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);
Spring 2012 SCM-CityU 47
p0
p1
p2
p3
p4
p5
p6
p7
p8
p9Shape A
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
Spring 2012 SCM-CityU 48
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
Spring 2012 SCM-CityU 49
// for each bulletfor (var bi:int = bullets.length-1; bi >= 0; bi--) {
// for each planefor (var ai:int = planes.length-1; ai >= 0; ai--)
{// splicing elements below
}}
// for each bulletfor (var bi:int = bullets.length-1; bi >= 0; bi--) {
// for each planefor (var ai:int = planes.length-1; ai >= 0; ai--)
{// splicing elements below
}}
Early Exit of for Loop• Break statement causes inner-most loop to be
terminated immediately
Spring 2012 SCM-CityU 50
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++) { 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);
} }
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);
} }
Plane Explosion Effect• What if we want to play some animation for plane
explosion? – We cannot immediately remove the hit plane from
stage/array
• How can we still avoid getting hit twice?– Solution
• Marking hit planes alive = false – By introducing a temporary property
• Hit test will not be done for planes with alive = false• Such hit planes will be automatically removed from stage/array
when they are off screen Spring 2012 SCM-CityU 51
Class Exercise • Add time constraint to the game
– E.g., shot as many planes as possible within 30 seconds
• Hints– Add another timer – Update timeLeftTxt text field with the time left
• Listening for TimerEvent.TIMER
– Jump to game over frame when the timer is completed • Listening for TimerEvent.TIMER_COMPLETE • Be aware to stop timers and remove event listeners at current frame
before jumping • Remove remaining planes and bullets as well
Spring 2012 SCM-CityU 52