Wiley.Games.on.Symbian.OS.A.Handbook.for.Mobile.Development.Apr.2008 (779888), страница 48
Текст из файла (страница 48)
In fact, in the console andPC game industry, there has been a growing trend towards the use ofhaptic interface technologies (tactile feedback such as vibration), andsuch interactions are equally relevant for mobile games.Haptic technologies interface to the player through their sense of touchby applying vibration and/or motion through the game controller.
In mostcases, this interface creates the illusion of forces acting on the player, as inreality, true force feedback would involve the feedback of an actual resisting force to the player. A common example of this type of haptic feedbackis in driving games, where, by the simulated revolution of the engine,the imaginary bumps on the road are transferred to the user throughvibrations of the controller, to enable greater immersion within the game.Thus far, the use of vibration in mobile games has been limited, butthere are products appearing that may expand its use and make it easierfor developers to create more sophisticated uses for it.
Most notableis VibeTonz from Immersion, which offers a combined software andhardware solution in the form of a dedicated player and amplifier design,which has been licensed by Samsung and Nokia with commercial gamesalready appearing.6.5.1 Using Vibration on Symbian OSControlling the vibration motor in phones via Symbian OS was nota supported feature for third-party developers in the early releases ofthe different Symbian OS-based UI platforms.
The APIs were privatecomponents, meaning that they were restricted to the licensees of SymbianOS and their partner companies. The reason for this was, most likely, thatvibration consumes a lot of battery power, and manufacturers wanted tolimit excessive demands on this constrained resource.Advances in hardware and power supply technologies meant that,from Symbian OS v7.0, these APIs became public. However, they werenot always consistent and they were sometimes missing from different firmware builds of the same phone model. In addition, there werebackward-compatibility issues, even between different platforms from thesame manufacturer, which caused portability problems for developers.For example, applications developed for S60 2nd Edition Feature Pack 2(FP2) devices (such as the Nokia 6630) that implemented the vibration feature used to crash at run time on S60 2nd Edition FP1 phones (such as theNokia 3230).
Consequently, the use of vibration was not recommendedwhen developing applications that were targeted to run on handsets spanning several platform versions. This limitation has since been resolvedin recent releases of the S60 3rd Edition SDK, because Nokia has deprecated the old vibration APIs CVibraControl (the interface to controlVIBRATION209the vibration motor) and VibraFactory (which created instances ofCVibraControl). Nokia is in the process of phasing those classes outentirely and replacing them with a new API CHWRMVibra, which is whatyou should now use for S60 3rd Edition devices.The following example shows the usage of CHWRMVibra for the NokiaS60 3rd Edition platform, as it is the one to be supported in future phonesby Nokia, and it does not introduce any compatibility breaks.Vibration API OverviewLibrary to link againstHWRMVibraClient.libHeader to includehwrmvibra.hRequired platform security capabilities NoneClasses to implementMHWRMVibraObserver(dependent)Classes to useCHWRMVibraAs a simple example, we have created the VibraPool game shown inFigure 6.16.
The application demonstrates how vibration could be usedas part of a pool game where collisions of the ball on the sides of thepool table are indicated by short vibrations, while longer ones indicatethe ball has gone into a pocket.Figure 6.16 Screenshots of VibraPoolUsing the vibration feature in S60 is a fairly straightforward task andsimply requires the instantiation of an object of class CHWRMVibra usingthe static factory function CHWRMVibra::NewL().
It is important tonote that the NewL() function may leave with KErrNotSupported if210EXPLOITING THE PHONE HARDWAREthe phone does not support the vibration feature, or KErrNoMemory ifinsufficient memory is available to instantiate the CHWRMVibra object.The vibration is started by calling the function CHWRMVibra::StartVibraL(), passing in a specific duration measured in milliseconds.
A value of 0 specifies that the vibration should continue indefinitelyuntil it is stopped by a call to CHWRMVibra::StopVibraL(). Note thatthe duration can alternatively have a maximum value of KHWRMVibraMaxDuration (=2147482).StartVibraL() has another overload that takes intensity as a secondparameter (a value between 100 and −100) to represent the percentage ofthe rotation speed of the vibration motor. Note that the device might havehardware imposed limits on the supported vibration intensity values, soactual effects might vary between different hardware. A negative valuefor intensity rotates the vibration motor in one direction, while a positivevalue rotates it in the opposite direction – each feels different to the touch.Value 0 stops the vibration altogether.Either of the StartVibraL() overloads may leave with one of thefollowing error codes as documented in the S60 SDK:• KErrNotSupported if the device doesn’t support user-definedvibration intensity (specific only to the second overload of StartVibraL()• KErrArgument if the duration and/or intensity are out of range• KErrAccessDenied if the vibration setting in the user profile is notenabled• KErrBadHandle if the vibration session has been invalidated (seeSDK documentation)• KErrLocked if vibration is prevented by a lock down because of toomuch continuous use, or if it is explicity blocked by, for example,some vibration sensitive accessory• KErrTimedOut if a timeout occurred in controlling the vibration• KErrInUse if using vibration is not reserved to this client but it isreserved to some other client• KErrNoMemory if there is a memory allocation failure• KErrGeneral if there is a hardware error.As the vibration feature on the phone can also be adjusted by theuser, the different mode settings and status values can be queried by calling CHWRMVibra::VibraSettings() and CHWRMVibra::VibraStatus() respectively.
The modes are specific to the vibration settings inVIBRATION211the user profile and they are enumerated in the class TVibraModeStatewith the following possible values:• EVibraModeON if the vibration setting in the user profile is on• EVibraModeOFF if the vibration setting in the user profile is off• EVibraModeUnknown if the vibration is not initialized yet or thereis an error condition.The vibration status is responsible for querying the current status setfor the vibration by this application or another client. It is defined by theTVibraStatus class and can be:• EVibraStatusUnknown if the vibration is not initialized or becauseof an uncertain error condition• EVibraStatusNotAllowed if the vibration is not enabled in theuser profile, or some application is specifically blocking it• EVibraStatusStopped if the vibration is stopped• EVibraStatusOn if the vibration is turned on.Changes to the phone’s vibration mode or status generate notificationsto implementers of the mixin class MHWRMVibraObserver.
It providestwo pure virtual functions, VibraModeChanged() and VibraStatusChanged(), that must be implemented by any class wishing toreceive change notifications. The programmer should implement thisobserver class if handling the vibration state events matters for theapplication (but it is not mandatory to do so). To receive change notifications, use the second overload of NewL(), which takes a reference toMHWRMVibraObserver as a parameter.There are additional features available, relating to priorities and suspensions, although these are generally only required by very sophisticatedapplications and are unlikely to be required for games. The mechanismguarantees a certain client to have a higher priority to use the vibrationcontrol over other applications by reserving it using the CHWRMVibra::ReserveVibraL() function.
As a result, other clients with lowerpriorities are forced to suspend their use of the resource temporarily untilit is released by CHWRMVibra::ReleaseVibra().Having provided an overview of the API we can apply it to our examplestarting from our CVibraPoolView. We start with VibraPoolView.hand perform the following actions in the subsequent code:• include hwrmvibra.h. It requires linking against HWRMVibraClient.lib in the MMP file212EXPLOITING THE PHONE HARDWARE• declare the vibration instance iVibra• declare iMove to animate the ball• declare the controlling functions of the game.#include <hwrmvibra.h>// Vibration APIclass CVibraPoolView : public CCoeControl{public:// Construction, destruction omitted for claritypublic:void ReStartGame();// Restarts ball animationvoid StopGame();// Stops ball animationprivate:// Game action functionsvoid WallsDetection();TBool HolesDetection();void UpdateScreen();// Updates new ball// position on screenprivate:CHWRMVibra* iVibra;CMoveBall* iMove;// Ball positioning variables omitted for clarity};The construction of iVibra and iMove is performed in CVibraPoolView::ConstructL(), which also initializes the values forthe ball position and movement on the table.
The logic behind movingthe ball and detecting walls and holes is not the main aim of the example,and, therefore, we will cover only the vibration implementation details;please download the full sample code for the application from the Symbian Developer Network (developer.symbian.com/gamesbook ) for moredetails.void CVibraPoolAppView::ConstructL( const TRect& aRect ){// Constructing the vibration controliVibra = CHWRMVibra::NewL(); // No callbacks// Initial ball location on screen (set randomly)iBallLoc.iX = Math::Random()%( aRect.Width()-(TABLE_BORDER*2)BALL_DIAMETER-(THRESHOLD*2) )+( THRESHOLD+TABLE_BORDER );iBallLoc.iY = Math::Random()%( aRect.Height()- (TABLE_BORDER*2)BALL_DIAMETER-(THRESHOLD*2) )+( THRESHOLD+TABLE_BORDER );// Number of pixels to step each time the ball moves.iMoveX = iMoveY = STEP;// Ball not in a hole so it is drawniDrawBall = ETrue;// Construct and start our asynchronous timer to move the ball.VIBRATION213iMove = CMoveBall::NewL(*this);iMove->StartMovingBall();}Up to this point, we have created the framework such that the vibrationcontrol is ready to use and now we just need to start or stop it as required.Function WallsDetection() uses vibration in two different scenarios.It first checks if the ball has hit the edge of the pool table, which it doesby calculating the distance between the upper-left corner of the rectanglesurrounding the ball, and any of the table edges.
If it is less than thediameter of the ball (25) plus the width of the table edge (30) then it is a hitand WallsDetection() will generate a short vibration effect. The effectis generated by the function, calling CHWRMVibra::StartVibraL()to run the vibration motor for an interval of 100 milliseconds and anintensity of 20 %. The second scenario is applied when the ball falls intoany of the holes.
The effect for this scenario is longer than the bordercollision; it has two interruption intervals that switch the direction ofrotation, and two intensities to form a rhythm-like vibration effect.The following code illustrates WallsDetection() implementationfor these vibration effects. Note that the function keeps checking for themode of the vibration setting in the user profile.