Good morning. I have a problem with Spritekit and the Accelerometer of an iPhone. I want to move a Node by tilting the device left or right in portrait mode. Exactly like in the Doodle Jump way.
Now i have this code:
import <CoreMotion/CoreMotion.h>
//Then at the implementation:
_motionManager = [[CMMotionManager alloc] init]; if ([_motionManager isAccelerometerAvailable] == YES) {
[_motionManager startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:^(CMAccelerometerData *data, NSError *error) {
float destX, destY; float currentX = _node.position.x; float currentY = _node.position.y; BOOL shouldMove = NO;
if(data.acceleration.x < -0.25) {
destX = currentX + (data.acceleration.x * kPlayerSpeed);
destY = currentY;
shouldMove = YES; }
else if (data.acceleration.x > 0.25) {
destX = currentX + (data.acceleration.x * kPlayerSpeed);
destY = currentY;
shouldMove = YES;
}
if((destX < 0)||(destX > self.frame.size.width)){shouldMove = NO;}
if(shouldMove) {
SKAction *action = [SKAction moveTo:CGPointMake(destX, destY) duration:0.2];
action.timingMode = SKActionTimingEaseOut;
[_node runAction:action];
}
}];
}
This code works but it`s not good enough. The Node makes huge movements even when i just tap on the device and the overall experience is not very statisfying.
I would like a code that moves the node just by the tilt of the device and not by the x-axis acceleration data. Something like if i tilt the device from 0 to 15 degree nothing happens and after that the node accelerates proportionally in dependency of the devices tilt. And the node should nod make sudden movements but fluent ones. Just like in the Doodle Jump way. I want that exact same behavior. Thanks.
Related
I've been looking around for tutorials on spatial hashing for Objective C or spriteKit. I've found examples in other languages, but I can't Seem to figure it out. I've gotten this far but I'm stuck.
This Loads Enemy Sprites To An NSMutableDictionary, I divide Their x,y positions by 64 to get their cellID (I use cellID as a key for the enemy in NSMutableDictionary).
- (void)loadEnemies {
TMXObjectGroup *enemiesGroup = [self.map groupNamed:#"enemies"];
for (NSDictionary *enemyDict in enemiesGroup.objects) {
NSString *enemyType = enemyDict[#"type"];
NSString *firstFrameName =
[NSString stringWithFormat:#"%#1.png",enemyType];
CGPoint enemyPosition =
CGPointMake([enemyDict[#"x"] floatValue], [enemyDict[#"y"] floatValue]);
CGPoint cellNumber =
CGPointMake(enemyPosition.x / 64, enemyPosition.y / 64);
NSString *CellID =
[NSString stringWithFormat:#"%#",NSStringFromCGPoint(cellNumber)];
SMCEnemy *enemy = [[NSClassFromString(enemyType)alloc]
initEnemyWithImageNamed:firstFrameName Position:enemyPosition];
enemy.position = enemyPosition;
enemy.player = self.cat;
enemy.map = self.map;
enemy.delegate = self;
[self.map addChild:enemy];
enemy.zPosition = 900;
//enemies added to NSMutableDictionary
[self.enemeyDictionary setObject:enemy forKey:CellID];
}
}
Ive added enemies to an NSMutableDictionary using CellID as a key.
This Checks For Collisions with the player, I first check the distance between the player and each enemy; if the distance is less than 1000, then enemy becomes active.
- (void)checkForEnemyCollisions:(SMCEnemy *)enemy {
CGFloat distance = CGPointDistance(enemy.posiiton, self.player.position);
if (distance < 1000){
enemy.isActive = YES;
} else {
enemy.isActive = NO;
}
if (enemy.isActive && enemy.life > 0) {
//cat hurt
if ((CGRectIntersectsRect(self.cat.collisionBoundingBox, enemy.collisionBoundingBox) || CGRectIntersectsRect(self.cat.collisionBoundingBox, enemy.attackBox)) && self.cat.isActive && !enemy.hidden && enemy.canHurtPlayer){
enemy.attackBox = CGRectNull;
if (enemy.position.x < self.cat.position.x) {
[self.cat bounceWithDirection:1];
}else{
[self.cat bounceWithDirection:-1];
}
[self.cat tookHit:self.cat];
[self movementCoolDownForCharacter:self.cat coolDownTime:.5];
}
// enemy hurt
if (CGRectIntersectsRect(enemy.collisionBoundingBox, self.cat.attackBox)&& !enemy.isHurt && enemy.isStun && !enemy.hidden) {
CGRect intersection = CGRectIntersection(enemy.collisionBoundingBox,self.cat.attackBox);
_hit.position = CGPointMake(intersection.origin.x, intersection.origin.y);
_hit.hidden = NO;
SKAction *DoneAction = [SKAction runBlock:(dispatch_block_t)^() {
_hit.hidden = YES;
}];
SKAction *moveLaserActionWithDone = [SKAction sequence:#[enemy.hitAnim,DoneAction]];
[_hit runAction:moveLaserActionWithDone];
enemy.isHurt = YES;
[enemy tookHit:self.cat];
[self movementCoolDownForCharacter:enemy coolDownTime:.5];
}
}
The Update Method
- (void)update:(NSTimeInterval)currentTime {
NSTimeInterval delta = currentTime - self.previousUpdateTime;
self.previousUpdateTime = currentTime;
if (delta > 0.1) {
delta = 0.1;
}
for (SMCEnemy *enemy in self.enemies) {
[self checkForEnemyCollisions:enemy];
}
}
I want to use spatial hashing instead of going through every enemy item in the enemyArray to improve performance.
Im stuck Any Help would be really awesome! :D
I'm using CMDeviceMotion and the attitude's quaternion to obtain the pitch and yaw values, which are then applied to a CC3Camera in a Cocos3D scene to rotate the camera around.
#define RadiansToDegrees(x) ((180 / M_PI) * x)
- (void)initializeScene
{
//...
CC3Camera *cam = [CC3Camera nodeWithName:#"Camera"];
cam.location = cc3v(0, 10, 0.0001);
cam.targetLocation = cc3v(0, 0, 0);
_cameraBoom = [CC3Node nodeWithName:#"CameraBoom"];
_cameraBoom.location = cc3v(0, 0, 0);
[_cameraBoom addChild:cam];
[self addChild:_cameraBoom];
[self setActiveCamera:cam];
_cameraBoom.rotation = cc3v(0, 90, 0);
//...
_motionManager = [[CMMotionManager alloc] init];
_referenceAttitude = nil;
_initialCameraRotation = _cameraBoom.rotation;
[self enableMotion];
}
- (void)enableMotion
{
CMDeviceMotion *deviceMotion = _motionManager.deviceMotion;
_referenceAttitude = deviceMotion.attitude;
_initialCameraRotation = _cameraBoom.rotation;
[_motionManager startDeviceMotionUpdates];
if (!_gyroTimer) {
_gyroTimer = [NSTimer scheduledTimerWithTimeInterval:1 / 30.0
target:self
selector:#selector(doGyroUpdate)
userInfo:nil
repeats:YES];
}
}
- (void)doGyroUpdate
{
CMDeviceMotion *deviceMotion = _motionManager.deviceMotion;
CMAttitude *attitude = deviceMotion.attitude;
if (_referenceAttitude != nil) {
[attitude multiplyByInverseOfAttitude:_referenceAttitude];
}
CMQuaternion quat = attitude.quaternion;
double pitch = RadiansToDegrees(atan2(2 * (quat.x * quat.w + quat.y * quat.z), 1 - 2 * (quat.x * quat.x + quat.z * quat.z)));
double yaw = RadiansToDegrees(asin(2 * (quat.x * quat.y + quat.w * quat.z)));
_cameraBoom.rotation = CC3VectorAdd(_initialCameraRotation, cc3v(pitch, yaw, 0));
}
The pitch is in range [-π, π]. When the device is faced up the pitch = 0 and it becomes π/2 as I take the device from the table and point it to take a picture (portrait mode). The [-π, π] range enables me to rotate the device 360°. When faced down (i.e. device is upside down) the pitch value is π.
The yaw range is only [-π/2, π/2]. It starts at 0 and goes to π/2 when I rotate the device to the left. But if I rotate it beyond π/2, the yaw value starts to decrease.
Can I get the yaw value in range [-π, π], just like the pitch? It would be more useful to be able to rotate the camera sideways by 180° (to the left and to the right, to have a full 360° view) instead of flipping the device vertically to look behind with the camera.
Here's how I did it eventually with the built-in functions:
- (void)doGyroUpdate
{
CMDeviceMotion *deviceMotion = _motionManager.deviceMotion;
CMAttitude *attitude = deviceMotion.attitude;
if (_referenceAttitude != nil) {
[attitude multiplyByInverseOfAttitude:_referenceAttitude];
}
CMQuaternion quat = attitude.quaternion;
CC3Quaternion cc3Quat = CC3QuaternionMake(quat.x, quat.y, quat.z, quat.w);
CC3Vector rot = CC3RotationFromQuaternion(cc3Quat);
_cameraBoom.rotation = cc3v(-rot.x, -rot.z, rot.y);
}
The result:
Rotating the camera like so enables you to look around at the skybox as if you would normally look at the world through the device's back camera. My CC3Camera object is inside a sphere with a HDRi image mapped on to it, on the inside (see this post).
To smoothly rotate the camera:
[_cameraBoom runAction:[CC3ActionRotateTo actionWithDuration:0.15 rotateTo:cc3v(-rot.x, -rot.z, rot.y)]];
Hope this helps someone else too.
Which way is the best for detecting rolling and pitching? I tried to do with this code:
- (void)viewDidLoad {
[super viewDidLoad];
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.accelerometerUpdateInterval = 1/60;
[self.motionManager startAccelerometerUpdatesToQueue:self.queue withHandler:
^(CMAccelerometerData *accelerometerData, NSError *error) {
[(id) self setAcceleration:accelerometerData.acceleration];
[self performSelectorOnMainThread:#selector(update) withObject:nil waitUntilDone:NO];
}];
}
- (void)update {
float accX = atan2f(self.acceleration.x, self.acceleration.z) * 180 /M_PI;
float accY = atan2f(self.acceleration.y, self.acceleration.z) * 180 /M_PI;
//convert to 360 degrees
if (accX < 0) {
accX = 360 + accX;
}
if (accY < 0) {
accY = 360 + accY;
}
NSLog(#"X: %f Y: %f",accX,accY);
}
When the device(iPhone) is on the table, values are X:180 and Y:180 , but when I put device on the right side X is around 90, but Y is chaotic from 0-360.
I would like use it for moving object in 4 directions. It should move like pac-mac, but using accelerometer. When device is in horizontal position, it works ok, but when device is in vertical position, works only in two directions. Is there better way to solve it?
So I have this app Im working on where you can roll the ball around the screen by tilting the device around(accelerometer). How can I alter the code below so that I don't have to hold the phone flat and have that as my neutral balance point. What I want is that whatever tilt you have with the device at the moment when the app loads, that will be the neural balance point. From that current angle your holding the device that is the neutral point. Neutral balance point meaning the point where the ball is pretty much still. Hope thats clear as to what I would like. Also the app is landscapeRight only.
note The code below works 100 percent well just like it need it to work for my app.Just I need to hold the phone flat to roll the ball around...
CGRect screenRect;
CGFloat screenHeight;
CGFloat screenWidth;
double currentMaxAccelX;
double currentMaxAccelY;
#property (strong, nonatomic) CMMotionManager *motionManager;
-(id)initWithSize:(CGSize)size {
//init several sizes used in all scene
screenRect = [[UIScreen mainScreen] bounds];
screenHeight = screenRect.size.height;
screenWidth = screenRect.size.width;
if (self = [super initWithSize:size]) {
self.motionManager = [[CMMotionManager alloc] init];
self.motionManager.accelerometerUpdateInterval = .2;
[self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
[self outputAccelertionData:accelerometerData.acceleration];
if(error)
{
NSLog(#"%#", error);
}
}];
}
return self;
}
-(void)outputAccelertionData:(CMAcceleration)acceleration{
currentMaxAccelX = 0;
currentMaxAccelY = 0;
if(fabs(acceleration.x) > fabs(currentMaxAccelX))
{
currentMaxAccelY = acceleration.x;
}
if(fabs(acceleration.y) > fabs(currentMaxAccelY))
{
currentMaxAccelX = acceleration.y;
}
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
//set min and max bounderies
float maxY = screenHeight - (self.ball.size.width/2);
float minY = 0 + (self.ball.size.width/2);
float maxX = screenWidth - (self.ball.size.height/2);
float minX = 0 + (self.ball.size.height/2);
float newY = 0;
float newX = 0;
//left and right tilt
if(currentMaxAccelX > 0.05){
newX = currentMaxAccelX * -10;
}
else if(currentMaxAccelX < -0.05){
newX = currentMaxAccelX*-10;
}
else{
newX = currentMaxAccelX*-10;
}
//up and down tilt
newY = currentMaxAccelY *10;
newX = MIN(MAX(newX+self.ball.position.x,minY),maxY);
newY = MIN(MAX(newY+self.ball.position.y,minX),maxX);
self.ball.position = CGPointMake(newX, newY);
}
First, Larme's comment gives the correct answer for determining the starting point.
However, if you are trying to determine device tilt (attitude), you want to use the gyroscope, not the accelerometer. The accelerometer tells how fast the device is moving in each direction. That's useful for determining if the user is quickly moving or shaking the device but doesn't help you at all determine whether the device is being tilted. The gyroscope provides the device's current attitude and the rate of rotation.
Since it sounds like you are trying to implement a ball that will "roll" around a table as the user tilts the device, you probably want to get the attitude. To get the attitude, use startDeviceMotionUpdatesToQueue:withHandler:. Then you can use the attitude property of the CMDeviceMotion object to find out how the device is oriented on each axis.
As it was mentioned, we need to catch an initial device position (accelerometer value) and use it as zero reference. We catch reference value once when game starts and subtract this value from every next accelerometer update.
static const double kSensivity = 1000;
#interface ViewController ()
{
CMMotionManager *_motionManager;
double _vx, _vy; // ball velocity
CMAcceleration _referenceAcc; // zero reference
NSTimeInterval _lastUpdateTimeInterval; // see update: method
}
Initially, ball is motionless (velocities = 0). Zero reference is invalid. I set significant value in CMAcceleration to mark it as invalid:
_referenceAcc.x = DBL_MAX;
Accelerometer updates. As the app uses landscape right mode only we map y-acceleration to x-velocity, and x-acceleration to y-velocity. accelerometerUpdateInterval factor is required to make velocity values independent of update rate. We use negative sensitivity value for x-acceleration, because direction of accelerometer X axis is opposite to landscape right orientation.
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
_vx = 0;
_vy = 0;
_referenceAcc.x = DBL_MAX;
_motionManager = [CMMotionManager new];
_motionManager.accelerometerUpdateInterval = 0.1;
[_motionManager
startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
CMAcceleration acc = accelerometerData.acceleration;
if (_referenceAcc.x == DBL_MAX) {
_referenceAcc = acc;
_referenceAcc.x *= -1;
_referenceAcc.y *= -1;
}
_vy += kSensivity * (acc.x+_referenceAcc.x) * _motionManager.accelerometerUpdateInterval;
_vx += -kSensivity * (acc.y+_referenceAcc.y) * _motionManager.accelerometerUpdateInterval;
}];
self.ball = [SKSpriteNode spriteNodeWithImageNamed:#"ball"];
self.ball.position = CGPointMake(self.size.width/2, self.size.height/2);
[self addChild:self.ball];
}
return self;
}
Your update: method does not respect currentTime value. Intervals between update calls can be different. It would be better to update distance according to time interval.
- (void)update:(NSTimeInterval)currentTime {
CFTimeInterval timeSinceLast = currentTime - _lastUpdateTimeInterval;
_lastUpdateTimeInterval = currentTime;
CGSize parentSize = self.size;
CGSize size = self.ball.frame.size;
CGPoint pos = self.ball.position;
pos.x += _vx * timeSinceLast;
pos.y += _vy * timeSinceLast;
// check bounds, reset velocity if collided
if (pos.x < size.width/2) {
pos.x = size.width/2;
_vx = 0;
}
else if (pos.x > parentSize.width-size.width/2) {
pos.x = parentSize.width-size.width/2;
_vx = 0;
}
if (pos.y < size.height/2) {
pos.y = size.height/2;
_vy = 0;
}
else if (pos.y > parentSize.height-size.height/2) {
pos.y = parentSize.height-size.height/2;
_vy = 0;
}
self.ball.position = pos;
}
EDIT: alternative way
By the way, I found an alternative way solve it. If you use SpriteKit, it is possible to configure gravity of physics world in response to accelerometer changes. In that case there's no need to move a ball in update: method.
We need to add physics body to a ball sprite and make it dynamic:
self.physicsWorld.gravity = CGVectorMake(0, 0); // initial gravity
self.ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:self.ball.size.width/2];
self.ball.physicsBody.dynamic = YES;
[self addChild:self.ball];
And set updated gravity in accelerometer handler:
// set zero reference acceleration
...
_vy = kSensivity * (acc.x+_referenceAcc.x) * _motionManager.accelerometerUpdateInterval;
_vx = -kSensivity * (acc.y+_referenceAcc.y) * _motionManager.accelerometerUpdateInterval;
self.physicsWorld.gravity = CGVectorMake(_vx, _vy);
Also we need to set physical bounds of the screen in order to limit ball movement.
Why don't you just take the numbers, at the point of start up, as a baseline and save them as a class property. Any further readings you have you can simply add/subtract the current numbers with your baseline. Unless I am wrong, that should give you the desired results.
In the iOS game flappy bird, there are pipes that generate after a certain distance and they generate at random heights
I am also trying to make flappy bird pipes (I called it a tree branch in my code instead of pipe). Except the pipes are moving vertically instead of horizontally because it is a vertical scrolling game (it scrolls like the game doodle jump)
This is a drawing of what I want it to be: https://docs.google.com/drawings/d/18bxsVsNOlScCvgi1mwuzD2At7R6xKM3QCh6BfAVMuMo/edit?usp=sharing
(The horizontal lines are the branches)
So this is what I have tried to do so far to make the vertical branches (or pipes)...
in my .h
CCSprite *branch;
NSMutableArray *_branches;
CCSprite *obstacle;
CCNode *previousBranch;
CGFloat previousBranchYPosition;
in my .m
#implementation HelloWorldLayer
static const CGFloat firstBranchPosition = 426.f;
static const CGFloat distanceBetweenBranches = 140.f;
#define ARC4RANDOM_MAX 0x100000000
static const CGFloat minimumXPositionRightBranch = 280.f;
static const CGFloat maximumXPositionLeftBranch = 50.f;
static const CGFloat pipeDistance = 100.f;
static const CGFloat maximumXPositionRightBranch = maximumXPositionLeftBranch - pipeDistance;
setBranchInitialPosition method
/* This is where I am setting the initial position of the branches.
So I am specifying the position of the first branch and the other branches after it so it gets placed every time a certain distance is passed. I have a left branch and a right branch*/
-(void) setBranchInitialPosition {
CGFloat random = ((double)arc4random() / ARC4RANDOM_MAX);
CGFloat range = maximumXPositionRightBranch - minimumXPositionRightBranch;
_rightBranch.position = ccp(minimumXPositionRightBranch + (random * range), _rightBranch.position.y);
_leftBranch.position = ccp(_rightBranch.position.x + pipeDistance, _leftBranch.position.y);
}
spawnNewBranches method
// This is how I want the branches to spawn and I want to add them to an array full of branches
- (void)spawnNewBranches {
previousBranch = [_branches lastObject];
previousBranchYPosition = previousBranch.position.y;
if (!previousBranch) {
// this is the first obstacle
previousBranchYPosition = firstBranchPosition;
}
_rightBranch = [CCSprite spriteWithFile:#"branch.png"];
_leftBranch = [CCSprite spriteWithFile:#"branch.png"];
[_leftBranch addChild:_rightBranch];
[self setBranchInitialPosition];
obstacle = [CCSprite node];
[obstacle addChild:_leftBranch];
obstacle.position = ccp(160, previousBranchYPosition + distanceBetweenBranches);
[self addChild:obstacle];
[_branches addObject:obstacle];
}
scroll method
-(void) scroll:(ccTime)dt
{
// moves the bg
background.position = ccp(screenCenter.x, background.position.y + [[NSUserDefaults standardUserDefaults] integerForKey:#"scrollSpeed"]*dt);
bg2.position = ccp(screenCenter.x, background.position.y-background.contentSize.height);
// it adds the new bg's to the screen before the old bg's move off the screen
if (background.position.y >= screenSize.height*1.5)
{
background.position = ccp(screenCenter.x, (screenCenter.y)-(background.size.height/2));
} else if (bg2.position.y >= screenSize.height*1.5) {
bg2.position = ccp(screenCenter.x, (screenCenter.y)-(bg2.size.height/2));
}
// This is where I want them to appear every certain distance and also move with the brackground
obstacle.position = ccp(obstacle.position.x, obstacle.position.y*[[NSUserDefaults standardUserDefaults] integerForKey:#"scrollSpeed"]*dt);
NSMutableArray *offScreenObstacles = nil;
if (obstacle.position.y >= screenSize.height*1.5) {
[offScreenObstacles addObject:obstacle];
}
for (CCNode *obstacleToRemove in offScreenObstacles) {
[obstacleToRemove removeFromParent];
[_branches removeObject:obstacleToRemove];
// for each removed obstacle, add a new one
[self spawnNewBranches];
}
}
Right now, the branches are appearing, but they stay in the bottom left corner and they dont move or spawn at all. I want to make them move with the background and spawn after a certain distance while also being generated in random heights. I provided you with all my code, do you know how I can make this work? Thanks in advance!
You may want to try placement of the pipes based on a trigonometric curve like sine or cosine (https://en.wikipedia.org/wiki/Trigonometric_functions). It seems like you are placing the pipes within a fairly define random range though if you change this range to an offset from the plot of the trigonometric curve it would take into account the ability of the player to transition between the open gaps better. At least that's my feel. I think the code would be easier to follow as well as I'm a bit confused going through it. You can also easily vary the difficulty of the curve by changing the parameters such as increasing the amplitude or frequency.
I created a copy of Flappy Bird just for fun. I used this code to create the pipes:
-(void)createPipes{
//Create Random
int from = 65;
int max = [[UIScreen mainScreen] bounds].size.height - 124;
int delta = max - from - dy;
int y = from + arc4random() % (delta - from);
//Pipe Bottom
UIImageView *pipeBottom = [[UIImageView alloc] init];
[pipeBottom setContentMode:UIViewContentModeTop];
[pipeBottom setImage:[UIImage imageNamed:#"pipeBottom"]];
[pipeBottom setFrame:CGRectMake(320, y+dy, 60, max - y - dy)];
[pipeBottom setClipsToBounds:YES];
//Pipe Top
UIImageView *pipeTop = [[UIImageView alloc] init];
[pipeTop setFrame:CGRectMake(320, 0, 60, y)];
[pipeTop setContentMode:UIViewContentModeBottom];
[pipeTop setImage:[UIImage imageNamed:#"pipeTop"]];
[self.view insertSubview:pipeTop atIndex:1];
[self.view insertSubview:pipeBottom atIndex:1];
if (!self.pipes)
self.pipes = [[NSMutableArray alloc] init];
[self.pipes addObject:pipeBottom];
[self.pipes addObject:pipeTop];
}
and to move them:
-(void)moveArray:(NSMutableArray *)array{
float ds = dv * dt;
NSMutableArray *trash = [NSMutableArray array];
for (UIImageView *obj in array) {
CGRect frame = obj.frame;
frame.origin.x -= ds;
if (frame.origin.x < -frame.size.width) {
[obj removeFromSuperview];
[trash addObject:obj];
}else{
obj.frame = frame;
}
}
[array removeObjectsInArray:trash];
}
-(void)movePipes{
[self moveArray:self.pipes];
}
I call this function every 0.01 seconds, to run the game:
-(void)runGame{
_time += dt;
if (_time >= 180.0/dv) {
_time = 0;
[self createPipes];
}
[self movePipes];
[self moveEnemies];
[self moveYoshi];
[self moveBar];
[self verifyScore];
[self verifyCollision];
[self verifyState];
}
I defined dt = 0.01 and dv = 110.
You can see my parody in youtube: (http://www.youtube.com/watch?v=tTcYdpSIKJg)
I hope this help you.
Best, Rafael Castro.