📜 ⬆️ ⬇️

We will throw the puck in iOS eight

Before creating a casual game for iOS, it would be good to answer the question: - Why?
Three options:


image

I think in the coming years, the correct answer is the third.
And, I will not argue and teach - I will tell you how I make applications.
The development gurus silently press the plus and go to the side. The rest follow me to remember the school and table hockey.
And yes, the uniqueness of the topic, that in each sentence the words begin with different letters.
The article has nine pictures and half a minute of funny animation.

1. The idea


It depends on the choice of tools. My ideas as smartphone users are straightforward. Therefore - no extra tools for development, except for the library of playing sounds. Resources borrowed from the network. Melodies, design, images, code samples. Everything has been created before us. Copyright - as in hockey or football. Suppose Messi came up with a new trick. You can copy it without deducting the author of money.
Okay. As an example of the game, I chose table hockey.
Very personal
80s. On the fur-mate this fun was popular. We played the FDS-6 wash. Boasting a high point - a crowd of people competed in the night. I entered, waited in line, won the local champion 10-0 and modestly withdrew. To be honest - I have two brothers and sixteen years of gambling practice.

')

2. Beginning of the project


image
Figure 2. I'm getting a new project in Xcode.

By the way, I have fat fingers. It means that only iPad mode is suitable for the game. This greatly facilitates the work. In addition, I prohibit the rotation of the screen, allowing only portrait orientation. Long live the portrait, here you hockey, not ballet.
There are no difficulties with the choice of the application name - Hockey 2015 . Names of sports are profitable. As for the money, I, of course, was deceitful. It would be desirable, that the future opus brought satisfaction both sincere and material. I already wrote here about my game Biathlon 2014. Every year - almost a thousand dollars profit. Buy in the days of the World Cup, Olympiad, cup stages. Who! Norwegians, Germans, Czechs, French, Russians, Italians.
I think my future hockey is waiting for something similar just because of the name.

I choose an icon. Not as important as the name. The main thing - to like it yourself.
image
Figure 3. Who can guess what kind of hockey player, the prize is $ 1.

As a result, it turns out the preparation of the future game, which displays a bright gray screen. The project has two main files that I can edit.

And I will not, bad form. A good tone is not to be lazy and create another class of view ViewController. For example, with the name PlayViewController.

image
Figure 4. Add a new PlayViewController controller.

The project has two new files that I can always edit.


3. Static images


I place still images using the editor in the PlayViewController.xib file.
First, the pictures must be created, stolen or borrowed. Images of the ice field, hockey players, as well as goalkeepers I made Milfgard . In Mosigre they are. For which, without asking, I placed the Mosigra name label in the center of the field. Washer - from the network. Photos of players' faces - nhl.com. Buttons - from designers Zeptolab. Hockey sounds - from the Ice Rage application.
Now you can place the images in the editor xib-files. It's simple - all the images are displayed by the UIImageView element.

image
Figure 5. Hockey field and scoreboard in Xcode editor.

If you later need to animate statically defined elements - it does not matter. Name the element. Now you can programmatically move, extinguish, rotate, mock as you please.

Example, declare the scoreBoard element (black board in the picture) in the file PlayViewController.m
IBOutlet UIImageView *scoreBoard; 

The IBOutlet keyword means that in the XIB editor any element can be assigned the identifier scoreBoard.
I assign it with the mouse in the editor.

Now I can move the picture up deep so that it does not block the hockey field.
  scoreBoard.center = CGPointMake(384, -1000); 

I remind you that 384 is the width of the iPad screen center, -1000 is something outside the device. After the command is executed, the display will fly up beyond the screen.

If you want to move a group of pictures - they need to be combined. Add an element of type UIView to move a group of pictures and inscriptions into it.
image
Figure 6. So, unnecessary items are removed from the ice.

Now we will place hockey players here to teach them how to move.


4. Transformable images


We place one hockey player programmatically in the PlayViewController.m file
  UIImageView *player = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"player_1.png"]]; float rPlayer = 150.0; player.frame = CGRectMake(0, 0, rPlayer, rPlayer); player.center = CGPointMake(100, 500); [self.view addSubview:player]; 


image
Figure 7. A hockey player appeared on the court.

In the future I will move and rotate it. Like this.
  player.center = CGPointMake(xnew, ynew); //    (xnew=100, ynew=440) player.transform = CGAffineTransformMakeRotation(alpha); //     (alpha=2.0)   


image
Figure 8. Hockey player left for another place and turned around.

There are many hockey players, and I am alone. Place all 12 players using the array.
  NSMutableArray *players; players = [[NSMutableArray alloc] init]; shadows = [[NSMutableArray alloc] init]; for (int k=0; k<12; k++) { UIImageView *p = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"player_1"]]; p.frame = CGRectMake(0, 0, cellDx, cellDx); float x = xp[k]; float y = yp[k]; p.center = CGPointMake(x, y); p.transform = CGAffineTransformMakeRotation(ap[k]); [players addObject:p]; p = [players objectAtIndex:k]; //        12  [self.view addSubview:p]; } 


5. Numerical methods in hockey


Hockey, like life, depends on time.
It is necessary to start the time counter. The event that the program will trigger 3000 times per minute.

  NSTimer *pauseTimer; time = 0; deltaTime = 1.0/50.0; pauseTimer = [NSTimer scheduledTimerWithTimeInterval:deltaTime target:self selector:@selector(timerFunction) userInfo:nil repeats:YES]; - (void) timerFunction { //    50    time = time + deltaTime; [self renderPuck]; [self renderPlayers]; [self puckMoving:deltaTime]; } 


So, all I have to do is to paint the puckMoving function. In it I will check collision of a washer and hockey players. Mathematically, the puck is defined by a circle with a radius of 21 pixels. Each hockey player has two circles - a larger (radius 25 pixels) body. Smaller (5 pixel radius) - stick.

Function below, comments inside.
puckMoving
  for (int k=1; k<33; k++) { if ( [self checkCollision:i With:k] ) { [self resolve:i With:k]; } } -(int) checkCollision:(int) k1 With:(int) k2 { float d2 = [self distance2:k1 With:k2]; float dr = rp2[k1] + rp2[k2]; return ( d2 < dr*dr ? 1 : 0); } -(float) distance2:(int) k1 With:(int) k2 { float dxx = xp2[k1] - xp2[k2]; float dyy = yp2[k1] - yp2[k2]; return dxx*dxx + dyy*dyy; } -(void) resolve:(int) k1 With:(int) k2 { float x1 = xp2[k1]; float y1 = yp2[k1]; float x2 = xp2[k2]; float y2 = yp2[k2]; float u2 = up2[k2]; float v2 = vp2[k2]; float u1 = up2[k1]; float v1 = vp2[k1]; Vector *b1Velocity = [Vector alloc]; [b1Velocity initX:u1 initY:v1]; Vector *b2Velocity = [Vector alloc]; [b2Velocity initX:u2 initY:v2 ]; float b1Mass = mp2[k1]; float b2Mass = mp2[k2]; Vector *vv = [Vector alloc]; [vv initX:x1-x2 initY:y1-y2]; float distance = [vv magnitude]; float min_distance = rp2[k1] + rp2[k2]; if (distance < min_distance) { [vv mulScalar: ((0.1+min_distance-distance)/(distance)) ]; x1 += vv.x; y1 += vv.y; xp2[k1] = x1; yp2[k1] = y1; } Vector *lineOfSight = [Vector alloc]; [lineOfSight initX:x1-x2 initY:y1-y2]; Vector *v1Prime = [b1Velocity vectorProjectionOnto:lineOfSight]; Vector *v2Prime = [b2Velocity vectorProjectionOnto:lineOfSight]; Vector *v1Prime2 = [Vector alloc]; [v1Prime2 copyVector:v2Prime]; [v1Prime2 mulScalar:(2*b2Mass)]; [v1Prime2 addVector:[v1Prime getMulScalar:(b1Mass - b2Mass)] ]; [v1Prime2 mulScalar:(1.0/(b1Mass + b2Mass))]; Vector *v2Prime2 = [Vector alloc]; [v2Prime2 copyVector:v1Prime]; [v2Prime2 mulScalar:(2*b1Mass)]; [v2Prime2 subVector: [v2Prime getMulScalar:(b1Mass - b2Mass)] ]; [v2Prime2 mulScalar:(1.0/(b1Mass + b2Mass))]; [v1Prime2 subVector:(v1Prime)]; [v2Prime2 subVector:(v2Prime)]; [b1Velocity addVector:v1Prime2]; [b2Velocity addVector:v2Prime2]; float a = 0.999; up2[k1] = a*b1Velocity.x + (1.0-a)*b2Velocity.x; vp2[k1] = a*b1Velocity.y + (1.0-a)*b2Velocity.y; a = 1.0 - a; // NSLog(@"new speed %f", hypotf(u, v)) ); } 


Inside the function, the Vector class is used.
Vector class
 #import "Vector.h" @implementation Vector @synthesize x,y; -(void) initX:(float) setX initY:(float) setY { x = setX; y = setY; } -(void) copyVector:(Vector*) v{ x = vx; y = vy; } -(void) addVector:(Vector*) v { x += vx; y += vy; } -(void) subVector:(Vector*) v { x -= vx; y -= vy; } -(void) mulScalar:(float) f { x *= f; y *= f; } -(float) magnitude { return sqrt( x*x + y*y ); } -(float) magnitude2 { return x*x + y*y; } -(Vector *)getMulScalar:(float) f { Vector *v = [Vector alloc]; [v initX:x*f initY:y*f]; return v; } -(float) scalarProjectionOnto:(Vector*) v { return (x* vx + y*vy)/ [v magnitude]; } -(Vector *) vectorProjectionOnto:(Vector*) v { Vector *res = [v getUnitVector]; [res mulScalar: [self scalarProjectionOnto:v]]; return res; } -(Vector *) getUnitVector { float len = [ self magnitude]; Vector *res = [Vector alloc]; [res initX:x initY:y]; if (len>0) { len = 1.0/len; [res mulScalar:len]; } return res; } @end 



In numerical simulation of the movement of the puck, there is one trick. 50 times per second is not enough for modeling accuracy. I use an elementary trick - I double the number of puckMoving function calls, thus dividing the time step into ten.

 - (void) timerFunction { //    50    time = time + deltaTime; [self renderPuck]; [self renderPlayers]; for (int k=0; k<10; k++) [self puckMoving:deltaTime/10.0]; } 


We look what happened



6. Statistics knows everything


Russians and Americans love statistics. Therefore, I organized a tournament of the six best teams in the world.
Real players from nhl.com, goals, pucks, points, all stars of the tournament.

7. Testing


Apple admits 1000 testers at the application revision stage.

Do not go advertising
At night, the application was approved in the Apple store. A week the game will be paid, then I will tell you about the number of downloads.


Thank you for reading.

Source: https://habr.com/ru/post/253423/


All Articles