2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #include <boost/any.hpp>
25 #include <boost/function.hpp>
26 #include <dali/dali.h>
27 #include <dali-toolkit/dali-toolkit.h>
28 #include "../shared/view.h"
32 using namespace Dali::Toolkit;
33 using namespace DemoHelper;
37 const char* BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-blocks.jpg" );
38 const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
39 const char* APPLICATION_TITLE( "DALi Blocks" );
40 const char* BALL_IMAGE = DALI_IMAGE_DIR "blocks-ball.png";
41 const char* PADDLE_IMAGE = DALI_IMAGE_DIR "blocks-paddle.png";
42 const char* PADDLE_HANDLE_IMAGE = DALI_IMAGE_DIR "blocks-paddle-handle.png";
44 const char* BRICK_IMAGE_PATH[] = { DALI_IMAGE_DIR "blocks-brick-1.png",
45 DALI_IMAGE_DIR "blocks-brick-2.png",
46 DALI_IMAGE_DIR "blocks-brick-3.png",
47 DALI_IMAGE_DIR "blocks-brick-4.png" };
49 const int TOTAL_BRICKS(4); ///< Total bricks in game.
50 const Vector3 ICON_SIZE(100.0f, 100.0f, 0.0f);
52 const float SCREEN_MARGIN = 10.0f; ///< Margin indentation around screen
53 const Vector3 MENU_BUTTON_SIZE = Vector3(0.15f, 0.05f, 1.0f); ///< Standard Menu Buttons.
55 const float MAX_ANIMATION_DURATION = 60.0f; ///< 60 seconds animations. Long enough for ball to hit an obstacle.
56 const float BALL_VELOCITY = 300.0f; ///< Ball velocity in pixels/second.
57 const float MAX_VELOCITY = 500.0f; ///< Max. velocity in pixels/second.
58 const Vector3 PADDLE_COLLISION_MARGIN(0.0f, 0.0f, 0.0f); ///< Collision margin for ball-paddle detection.
59 const Vector3 BRICK_COLLISION_MARGIN(0.0f, 0.0f, 0.0f); ///< Collision margin for ball-brick detection.
60 const Vector3 INITIAL_BALL_DIRECTION(1.0f, 1.0f, 0.0f); ///< Initial ball direction.
62 const std::string WOBBLE_PROPERTY_NAME("wobble-property"); ///< Wobble property name.
63 const std::string COLLISION_PROPERTY_NAME("collision-property"); ///< Collision property name.
65 const Vector2 BRICK_SIZE(0.1f, 0.05f ); ///< Brick size relative to width of stage.
66 const Vector2 BALL_SIZE( 0.05f, 0.05f ); ///< Ball size relative to width of stage.
67 const Vector2 PADDLE_SIZE( 0.2f, 0.05f ); ///< Paddle size relative to width of stage.
68 const Vector2 PADDLE_HANDLE_SIZE( 0.3f, 0.3f ); ///< Paddle handle size relative to width of stage.
69 const Vector2 BALL_START_POSITION(0.5f, 0.8f); ///< Ball start position relative to stage size.
70 const Vector2 PADDLE_START_POSITION(0.5f, 0.9f); ///< Paddler start position relative to stage size.
71 const Vector2 PADDLE_HIT_MARGIN( 0.1, 0.15f ); ///< Extra hit Area for Paddle when touching.
73 const int TOTAL_LIVES(3); ///< Total lives in game before it's game over!
74 const int TOTAL_LEVELS(3); ///< 3 Levels total, then repeats.
76 // constraints ////////////////////////////////////////////////////////////////
79 * CollisionConstraint generates a collision vector
80 * between two actors a and b, assuming they're rectangular
81 * based on their size.
83 struct CollisionConstraint
86 * Collision Constraint constructor
87 * The adjust (optional) parameter can be used to add a margin
88 * to the actors. A +ve size will result in larger collisions,
89 * while a -ve size will result in tighter collisions.
91 * @param[in] adjust (optional) Adjusts the rectangular size detection
93 CollisionConstraint(Vector3 adjust = Vector3::ZERO)
99 * Generates collision vector indicating whether Actor's A and B
100 * have overlapped eachother, and the relative position of Actor B to A.
102 * @param[in] current The current collision-property (ignored)
103 * @param[in] propertyA Actor A's Position property.
104 * @param[in] propertyB Actor B's Position property.
105 * @param[in] propertySizeA Actor A's Size property.
106 * @param[in] propertySizeB Actor B's Size property.
107 * @return The collision vector is returned.
109 Vector3 operator()(const Vector3& current,
110 const PropertyInput& propertyA,
111 const PropertyInput& propertyB,
112 const PropertyInput& propertySizeA,
113 const PropertyInput& propertySizeB)
115 const Vector3& a = propertyA.GetVector3();
116 const Vector3& b = propertyB.GetVector3();
117 const Vector3& sizeA = propertySizeA.GetVector3();
118 const Vector3& sizeB = propertySizeB.GetVector3();
119 const Vector3 sizeComb = (sizeA + sizeB + mAdjust) * 0.5f;
121 // get collision relative to a.
122 Vector3 delta = b - a;
124 // Check if not overlapping Actors.
125 if( (fabsf(delta.x) > sizeComb.width) ||
126 (fabsf(delta.y) > sizeComb.height) )
128 delta = Vector3::ZERO; // not overlapping
131 return delta; // overlapping, return overlap vector relative to actor a.
134 const Vector3 mAdjust; ///< Size Adjustment value
138 * CollisionCircleRectangleConstraint generates a collision vector
139 * between two actors a (circle) and b (rectangle)
141 struct CollisionCircleRectangleConstraint
144 * Collision Constraint constructor
145 * The adjust (optional) parameter can be used to add a margin
146 * to the actors. A +ve size will result in larger collisions,
147 * while a -ve size will result in tighter collisions.
149 * @param[in] adjustPosition (optional) Adjusts the position offset of detection
150 * @param[in] adjustSize (optional) Adjusts the rectangular size of detection
152 CollisionCircleRectangleConstraint(Vector3 adjustPosition = Vector3::ZERO,
153 Vector3 adjustSize = Vector3::ZERO)
154 : mAdjustPosition(adjustPosition),
155 mAdjustSize(adjustSize)
160 * Generates collision vector indicating whether Actor's A and B
161 * have overlapped eachother, and the relative position of Actor B to A.
163 * @param[in] current The current collision-property (ignored)
164 * @param[in] propertyA Actor A's Position property.
165 * @param[in] propertyB Actor B's Position property.
166 * @param[in] propertySizeA Actor A's Size property.
167 * @param[in] propertySizeB Actor B's Size property.
168 * @return The collision vector is returned.
170 Vector3 operator()(const Vector3& current,
171 const PropertyInput& propertyA,
172 const PropertyInput& propertyB,
173 const PropertyInput& propertySizeA,
174 const PropertyInput& propertySizeB)
176 const Vector3& a = propertyA.GetVector3();
177 const Vector3 b = propertyB.GetVector3() + mAdjustPosition;
178 const Vector3& sizeA = propertySizeA.GetVector3();
179 const Vector3& sizeB = propertySizeB.GetVector3();
180 const Vector3 sizeA2 = sizeA * 0.5f; // circle radius
181 const Vector3 sizeB2 = (sizeB + mAdjustSize) * 0.5f; // rectangle half rectangle.
183 // get collision relative to a (rectangle).
184 Vector3 delta = a - b;
186 // reduce rectangle to 0.
187 if (delta.x > sizeB2.x)
191 else if (delta.x < -sizeB2.x)
200 if (delta.y > sizeB2.y)
204 else if (delta.y < -sizeB2.y)
213 // now calculate collision vector vs origin. (assume A is a circle, not ellipse)
214 if(delta.Length() < sizeA2.x)
220 return Vector3::ZERO;
223 const Vector3 mAdjustPosition; ///< Position Adjustment value
224 const Vector3 mAdjustSize; ///< Size Adjustment value
228 * WobbleConstraint generates a decaying sinusoidial rotation.
229 * The result when applied to an Actor, is the Actor rotating left/right
230 * initially a large amount (deviation degrees, when wobble property is 0.0f)
231 * then eventually coming to a stop (once wobble property reaches 1.0f)
233 struct WobbleConstraint
236 * Wobble Constraint constructor
237 * Generates a sinusoidial rotation that starts with
238 * high amplitude (deviation), and then decays to zero over input 0.0f to 1.0f
240 * @param[in] deviation The max. deviation of wobble effect in degrees.
242 WobbleConstraint(float deviation)
243 : mDeviation(Radian(Degree(deviation)))
249 * @param[in] current The current rotation property (ignored)
250 * @param[in] propertyWobble The wobble property (value from 0.0f to 1.0f)
251 * @return The rotation (quaternion) is generated.
253 Quaternion operator()(const Quaternion& current,
254 const PropertyInput& propertyWobble)
256 const float& wobble = propertyWobble.GetFloat();
258 float f = sinf(wobble * 10.0f) * (1.0f-wobble);
260 Quaternion q(mDeviation * f, Vector3::ZAXIS);
265 const float mDeviation; ///< Deviation factor in radians.
268 } // unnamed namespace
271 * This example shows how to use PropertyNotifications
273 class ExampleController : public ConnectionTracker
279 * @param application Application class, stored as reference
281 ExampleController( Application& application )
282 : mApplication( application ),
285 // Connect to the Application's Init and orientation changed signal
286 mApplication.InitSignal().Connect(this, &ExampleController::Create);
290 * This method gets called once the main loop of application is up and running
291 * @param[in] application Reference to the application instance
293 void Create(Application& application)
295 Stage::GetCurrent().KeyEventSignal().Connect(this, &ExampleController::OnKeyEvent);
297 // Creates a default view with a default tool bar.
298 // The view is added to the stage.
299 Toolkit::ToolBar toolBar;
300 mContentLayer = DemoHelper::CreateView( application,
307 // Add an extra space on the right to center the title text.
308 toolBar.AddControl( Actor::New(), DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight );
310 // Create the content layer, which is where game actors appear.
317 * Adds a new layer to the stage, containing game actors.
319 void AddContentLayer()
321 Stage stage = Stage::GetCurrent();
322 const Vector3 stageSize(stage.GetSize());
325 mBallStartPosition = stageSize * Vector3( BALL_START_POSITION );
326 mBall = CreateImage(BALL_IMAGE);
327 mBall.SetPosition( mBallStartPosition );
328 mBall.SetSize( BALL_SIZE * stageSize.width );
329 mContentLayer.Add(mBall);
330 mBallVelocity = Vector3::ZERO;
333 mPaddleHitMargin = Vector2(stageSize) * PADDLE_HIT_MARGIN;
334 mPaddle = Actor::New();
335 mPaddleHandle = CreateImage(PADDLE_HANDLE_IMAGE);
336 mPaddleImage = CreateImage(PADDLE_IMAGE);
337 mPaddle.Add( mPaddleHandle );
338 mPaddle.Add( mPaddleImage );
339 mPaddleHandle.SetParentOrigin( ParentOrigin::TOP_CENTER );
340 mPaddleHandle.SetAnchorPoint( AnchorPoint::TOP_CENTER );
341 mPaddleHandle.SetPosition( 0.0f, stageSize.width * 0.0125f );
342 mPaddleImage.SetParentOrigin( ParentOrigin::TOP_CENTER );
343 mPaddleImage.SetAnchorPoint( AnchorPoint::TOP_CENTER );
344 mPaddle.SetParentOrigin( ParentOrigin::TOP_LEFT );
345 mPaddle.SetAnchorPoint( AnchorPoint::CENTER );
346 mPaddleFullSize = PADDLE_SIZE * stageSize.width;
347 mPaddle.SetSize( mPaddleFullSize + mPaddleHitMargin );
348 mPaddleHandle.SetSize( PADDLE_HANDLE_SIZE * stageSize.width );
349 mPaddleImage.SetSize( mPaddleFullSize );
351 mWobbleProperty = mPaddle.RegisterProperty(WOBBLE_PROPERTY_NAME, 0.0f);
352 Constraint wobbleConstraint = Constraint::New<Quaternion>( Actor::ROTATION,
353 LocalSource(mWobbleProperty),
354 WobbleConstraint(10.0f));
355 mPaddle.ApplyConstraint(wobbleConstraint);
357 mPaddle.SetPosition( stageSize * Vector3( PADDLE_START_POSITION ) );
358 mContentLayer.Add(mPaddle);
359 mPaddle.TouchedSignal().Connect(this, &ExampleController::OnTouchPaddle);
360 mContentLayer.TouchedSignal().Connect(this, &ExampleController::OnTouchLayer);
362 const float margin(BALL_SIZE.width * stageSize.width * 0.5f);
364 // Set up notifications for ball's collisions against walls.
365 PropertyNotification leftNotification = mBall.AddPropertyNotification( Actor::POSITION_X, LessThanCondition(margin) );
366 leftNotification.NotifySignal().Connect( this, &ExampleController::OnHitLeftWall );
368 PropertyNotification rightNotification = mBall.AddPropertyNotification( Actor::POSITION_X, GreaterThanCondition(stageSize.width - margin) );
369 rightNotification.NotifySignal().Connect( this, &ExampleController::OnHitRightWall );
371 PropertyNotification topNotification = mBall.AddPropertyNotification( Actor::POSITION_Y, LessThanCondition(margin) );
372 topNotification.NotifySignal().Connect( this, &ExampleController::OnHitTopWall );
374 PropertyNotification bottomNotification = mBall.AddPropertyNotification( Actor::POSITION_Y, GreaterThanCondition(stageSize.height + margin) );
375 bottomNotification.NotifySignal().Connect( this, &ExampleController::OnHitBottomWall );
377 // Set up notification for ball colliding against paddle.
378 Actor delegate = Actor::New();
380 Property::Index property = delegate.RegisterProperty(COLLISION_PROPERTY_NAME, Vector3::ZERO);
381 Constraint constraint = Constraint::New<Vector3>( property,
382 Source(mBall, Actor::POSITION),
383 Source(mPaddle, Actor::POSITION),
384 Source(mBall, Actor::SIZE),
385 Source(mPaddle, Actor::SIZE),
386 CollisionCircleRectangleConstraint( -Vector3(0.0f, mPaddleHitMargin.height * 0.575f, 0.0f),-Vector3(mPaddleHitMargin) ));
387 delegate.ApplyConstraint(constraint);
389 PropertyNotification paddleNotification = delegate.AddPropertyNotification( property, GreaterThanCondition(0.0f) );
390 paddleNotification.NotifySignal().Connect( this, &ExampleController::OnHitPaddle );
397 * Resets Lives count and other stats, and loads level
401 mLives = TOTAL_LIVES;
403 mBall.SetPosition( mBallStartPosition );
404 mBallVelocity = Vector3::ZERO;
405 mPaddle.SetSize( mPaddleFullSize + mPaddleHitMargin );
406 mPaddleImage.SetSize( mPaddleFullSize );
413 * All existing level content is removed, and new bricks
415 * @param[in] level Level index to load.
417 void LoadLevel(int level)
419 if(mLevelContainer && mLevelContainer.GetParent() == mContentLayer)
421 mContentLayer.Remove( mLevelContainer );
424 mLevelContainer = Actor::New();
425 mLevelContainer.SetAnchorPoint( AnchorPoint::CENTER );
426 mLevelContainer.SetParentOrigin( ParentOrigin::CENTER );
427 mLevelContainer.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
428 mContentLayer.Add( mLevelContainer );
432 switch(level%TOTAL_LEVELS)
459 void GenerateLevel0()
461 Vector2 stageSize(Stage::GetCurrent().GetSize());
462 const Vector2 brickSize(BRICK_SIZE * stageSize.width);
464 const int columns = (0.85f * stageSize.width) / brickSize.width; // 85 percent of the width of the screen covered with bricks.
465 const int rows = (0.3f * stageSize.height) / brickSize.height; // 30 percent of the height of the screen covered with bricks.
466 const Vector2 offset( (stageSize.x - (columns * brickSize.width)) * 0.5f,
467 stageSize.y * 0.125f );
469 for(int j = 0; j < rows; j++)
471 for(int i = 0; i < columns; i++)
473 Actor brick = CreateBrick(Vector2(i * brickSize.width + offset.x, j * brickSize.height + offset.y) + (brickSize * 0.5f), j % TOTAL_BRICKS );
474 mLevelContainer.Add(brick);
483 void GenerateLevel1()
485 Vector2 stageSize(Stage::GetCurrent().GetSize());
486 const Vector2 brickSize(BRICK_SIZE * stageSize.width);
488 const int columns = (0.85f * stageSize.width) / brickSize.width; // 85 percent of the width of the screen covered with bricks.
489 const int rows = (0.3f * stageSize.height) / brickSize.height; // 30 percent of the height of the screen covered with bricks.
490 const Vector2 offset( (stageSize.x - (columns * brickSize.width)) * 0.5f,
491 stageSize.y * 0.125f );
493 for(int j = 0; j < rows; j++)
495 for(int i = 0; i < columns; i++)
497 int i2 = columns - i - 1;
498 int j2 = rows - j - 1;
499 int brickIndex = std::min( std::min(i, j), std::min(i2, j2) ) % TOTAL_BRICKS;
501 Actor brick = CreateBrick(Vector2(i * brickSize.width + offset.x, j * brickSize.height + offset.y) + (brickSize * 0.5f), brickIndex );
503 mLevelContainer.Add(brick);
512 void GenerateLevel2()
514 Vector2 stageSize(Stage::GetCurrent().GetSize());
515 const Vector2 brickSize(BRICK_SIZE * stageSize.width);
517 const int columns = (0.85f * stageSize.width) / brickSize.width; // 85 percent of the width of the screen covered with bricks.
518 const int rows = (0.3f * stageSize.height) / brickSize.height; // 30 percent of the height of the screen covered with bricks.
519 const Vector2 offset( (stageSize.x - (columns * brickSize.width)) * 0.5f,
520 stageSize.y * 0.125f );
522 // lays down bricks in a spiral formation starting at i,j = (0,0) top left corner
523 // travelling right di,dj = (1,0) initially
529 // contracting boundaries
531 int right = columns - 1;
533 int bottom = rows - 1;
535 // length of current line. we stop laying down bricks when the length is 1 brick or less.
539 Actor brick = CreateBrick(Vector2(i * brickSize.width + offset.x, j * brickSize.height + offset.y) + (brickSize * 0.5f), 0 );
540 mLevelContainer.Add(brick);
544 if((i==right) && (di==1))
549 if((j==bottom) && (dj==1))
554 if((i==left) && (di==-1))
559 if((j==top) && (dj==-1))
566 // turn 90 degrees clockwise.
582 * Creates a brick at a specified position on the stage
583 * @param[in] position the position for the brick
584 * @param[in] type the type of brick
585 * @return The Brick Actor is returned.
587 Actor CreateBrick( const Vector2& position, int type )
589 Vector2 stageSize(Stage::GetCurrent().GetSize());
590 const Vector2 brickSize(BRICK_SIZE * Vector2(stageSize.x, stageSize.x));
592 ImageAttributes attr;
593 attr.SetSize( 128, 64 );
594 attr.SetScalingMode( ImageAttributes::ScaleToFill );
595 Image img = Image::New(BRICK_IMAGE_PATH[type], attr);
596 ImageActor brick = ImageActor::New(img);
597 brick.SetParentOrigin(ParentOrigin::TOP_LEFT);
598 brick.SetAnchorPoint(AnchorPoint::CENTER);
599 brick.SetSize( brickSize );
600 brick.SetPosition( Vector3( position ) );
602 // Add a constraint on the brick between it and the ball generating a collision-property
603 Property::Index property = brick.RegisterProperty(COLLISION_PROPERTY_NAME, Vector3::ZERO);
604 Constraint constraint = Constraint::New<Vector3>( property,
605 Source(mBall, Actor::POSITION),
606 Source(brick, Actor::POSITION),
607 Source(mBall, Actor::SIZE),
608 Source(brick, Actor::SIZE),
609 CollisionCircleRectangleConstraint(BRICK_COLLISION_MARGIN));
610 brick.ApplyConstraint(constraint);
612 // Now add a notification on this collision-property
614 PropertyNotification brickNotification = brick.AddPropertyNotification( property, GreaterThanCondition(0.0f) );
615 brickNotification.NotifySignal().Connect( this, &ExampleController::OnHitBrick );
621 * Creates an Image (Helper)
623 * @param[in] filename the path of the image.
625 ImageActor CreateImage(const std::string& filename)
627 Image img = Image::New(filename);
628 ImageActor actor = ImageActor::New(img);
629 actor.SetParentOrigin(ParentOrigin::TOP_LEFT);
630 actor.SetAnchorPoint(AnchorPoint::CENTER);
635 * Continue animation (based on current velocity)
637 void ContinueAnimation()
641 mBallAnimation.Clear();
644 mBallAnimation = Animation::New(MAX_ANIMATION_DURATION);
645 mBallAnimation.AnimateBy( Property( mBall, Actor::POSITION ), mBallVelocity * MAX_ANIMATION_DURATION);
646 mBallAnimation.Play();
650 * Signal invoked whenever user touches the Paddle.
651 * @param[in] actor The actor touched
652 * @param[in] event The touch event
654 bool OnTouchPaddle(Actor actor, const TouchEvent& event)
656 if(event.GetPointCount()>0)
658 const TouchPoint& point = event.GetPoint(0);
659 if(point.state==TouchPoint::Down) // Commence dragging
661 // Get point where user touched paddle (relative to paddle's center)
662 mRelativeDragPoint = Vector3(point.screen.x, point.screen.y, 0.0f);
663 mRelativeDragPoint -= actor.GetCurrentPosition();
666 mDragAnimation = Animation::New(0.25f);
667 mDragAnimation.AnimateTo( Property(mDragActor, Actor::SCALE), Vector3(1.1f, 1.1f, 1.0f), AlphaFunctions::EaseOut);
668 mDragAnimation.AnimateTo( Property(mPaddleHandle, Actor::COLOR), Vector4(1.0f, 1.0f, 1.0f, 0.0f), AlphaFunctions::EaseOut);
669 mDragAnimation.Play();
676 * Signal invoked whenever user touches anywhere on the screen.
677 * @param[in] actor The actor touched
678 * @param[in] event The touch event
680 bool OnTouchLayer(Actor actor, const TouchEvent& event)
682 if(event.GetPointCount()>0)
684 const TouchPoint& point = event.GetPoint(0);
687 Vector3 position(point.screen.x, point.screen.y, 0.0f);
688 mPaddle.SetPosition( position - mRelativeDragPoint );
690 if(point.state==TouchPoint::Up) // Stop dragging
692 mDragAnimation = Animation::New(0.25f);
693 mDragAnimation.AnimateTo( Property(mDragActor, Actor::SCALE), Vector3(1.0f, 1.0f, 1.0f), AlphaFunctions::EaseIn);
694 mDragAnimation.AnimateTo( Property(mPaddleHandle, Actor::COLOR), Vector4(1.0f, 1.0f, 1.0f, 1.0f), AlphaFunctions::EaseOut);
695 mDragAnimation.Play();
704 * Notification: Ball hit left wall
705 * @param source The notification
707 void OnHitLeftWall(PropertyNotification& source)
709 mBallVelocity.x = fabsf(mBallVelocity.x);
714 * Notification: Ball hit right wall
715 * @param source The notification
717 void OnHitRightWall(PropertyNotification& source)
719 mBallVelocity.x = -fabsf(mBallVelocity.x);
724 * Notification: Ball hit top wall
725 * @param source The notification
727 void OnHitTopWall(PropertyNotification& source)
729 mBallVelocity.y = fabsf(mBallVelocity.y);
734 * Notification: Ball hit bottom wall
735 * @param source The notification
737 void OnHitBottomWall(PropertyNotification& source)
741 mBallAnimation.Clear();
747 const float f(static_cast<float>(mLives) / TOTAL_LIVES);
748 mBallVelocity = Vector3::ZERO;
750 Animation shrink = Animation::New(0.5f);
751 shrink.AnimateTo( Property(mPaddle, Actor::SIZE_WIDTH), mPaddleFullSize.x * f + mPaddleHitMargin.x);
752 shrink.AnimateTo( Property(mPaddleImage, Actor::SIZE_WIDTH), mPaddleFullSize.x * f );
754 shrink.FinishedSignal().Connect( this, &ExampleController::OnPaddleShrunk );
760 * Paddle Shrink Animation complete.
761 * @param[in] source The animation responsible for shrinking the paddle.
763 void OnPaddleShrunk( Animation &source )
765 // Reposition Ball in start position, and make ball appear.
766 mBall.SetPosition( mBallStartPosition );
767 mBall.SetColor( Vector4(1.0f, 1.0f, 1.0f, 0.1f) );
768 Animation appear = Animation::New(0.5f);
769 appear.AnimateTo( Property(mBall, Actor::COLOR), Vector4(1.0f, 1.0f, 1.0f, 1.0f) );
779 * Notification: Ball hit paddle
780 * @param source The notification
782 void OnHitPaddle(PropertyNotification& source)
784 Actor delegate = Actor::DownCast(source.GetTarget());
785 Vector3 collisionVector = delegate.GetProperty<Vector3>(source.GetTargetProperty());
786 Vector3 ballRelativePosition(mBall.GetCurrentPosition() - mPaddle.GetCurrentPosition());
787 ballRelativePosition.Normalize();
789 collisionVector.x += ballRelativePosition.x * 0.5f;
791 if(mBallVelocity.LengthSquared() < Math::MACHINE_EPSILON_1)
793 mBallVelocity += collisionVector * BALL_VELOCITY;
797 const float normalVelocity = fabsf(mBallVelocity.Dot(collisionVector));
798 mBallVelocity += collisionVector * normalVelocity * 2.0f;
799 const float currentSpeed = mBallVelocity.Length();
800 const float limitedSpeed = std::min( currentSpeed, MAX_VELOCITY );
801 mBallVelocity = mBallVelocity * limitedSpeed / currentSpeed;
807 mWobbleAnimation = Animation::New(0.5f);
808 mWobbleAnimation.AnimateTo( Property( mPaddle, mWobbleProperty ), 1.0f );
809 mWobbleAnimation.Play();
810 mPaddle.SetProperty(mWobbleProperty, 0.0f);
814 * Notification: Ball hit brick
815 * @param source The notification
817 void OnHitBrick(PropertyNotification& source)
819 Actor brick = Actor::DownCast(source.GetTarget());
820 Vector3 collisionVector = brick.GetProperty<Vector3>(source.GetTargetProperty());
822 const float normalVelocity = fabsf(mBallVelocity.Dot(collisionVector));
823 mBallVelocity += collisionVector * normalVelocity * 2.0f;
824 const float currentSpeed = mBallVelocity.Length();
825 const float limitedSpeed = std::min( currentSpeed, MAX_VELOCITY );
826 mBallVelocity = mBallVelocity * limitedSpeed / currentSpeed;
830 // remove collision-constraint and notification.
831 brick.RemovePropertyNotification(source);
832 brick.RemoveConstraints();
834 // fade brick (destroy)
835 Animation destroyAnimation = Animation::New(0.5f);
836 destroyAnimation.AnimateTo( Property( brick, Actor::COLOR_ALPHA ), 0.0f, AlphaFunctions::EaseIn );
837 destroyAnimation.Play();
838 destroyAnimation.FinishedSignal().Connect( this, &ExampleController::OnBrickDestroyed );
839 mDestroyAnimationMap[destroyAnimation] = brick;
843 * Brick Destruction Animation complete.
844 * @param[in] source The animation responsible for destroying the brick
846 void OnBrickDestroyed( Animation& source )
848 // Remove brick from stage, it's constraint and property notification should also remove themselves.
849 Actor brick = mDestroyAnimationMap[source];
850 mDestroyAnimationMap.erase(source);
851 brick.GetParent().Remove(brick);
862 * Main key event handler
864 void OnKeyEvent(const KeyEvent& event)
866 if(event.state == KeyEvent::Down)
868 if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
877 Application& mApplication; ///< Application instance
878 Toolkit::View mView; ///< The View instance.
879 Layer mContentLayer; ///< The content layer (contains game actors)
880 ImageActor mBall; ///< The Moving ball image.
881 Vector3 mBallStartPosition; ///< Ball Start position
882 Vector3 mBallVelocity; ///< Ball's current direction.
883 Animation mBallAnimation; ///< Ball's animation
884 Actor mPaddle; ///< The paddle including hit area.
885 ImageActor mPaddleImage; ///< The paddle's image.
886 ImageActor mPaddleHandle; ///< The paddle's handle (where the user touches)
887 Vector2 mPaddleHitMargin; ///< The paddle hit margin.
888 Animation mWobbleAnimation; ///< Paddle's animation when hit (wobbles)
889 Property::Index mWobbleProperty; ///< The wobble property (generated from animation)
890 Actor mLevelContainer; ///< The level container (contains bricks)
892 // actor - dragging functionality
894 Animation mDragAnimation; ///< Animation for dragging. (grows - affects ACTOR::SCALE)
895 Actor mDragActor; ///< The actor which is being dragged (if any)
896 Vector3 mRelativeDragPoint; ///< The point the user touched, relative to the actor.
897 std::map<Animation, Actor> mDestroyAnimationMap; ///< Keep track of which actors are to be destroyed.
898 Vector2 mPaddleFullSize; ///< Initial 100% size of the paddle.
899 int mLevel; ///< Current level
900 int mLives; ///< Total lives.
901 int mBrickCount; ///< Total bricks on screen.
904 void RunTest(Application& app)
906 ExampleController test(app);
911 int main(int argc, char **argv)
913 Application app = Application::New(&argc, &argv);