Advertisement
  1. Code
  2. Games

Bermain-main dengan Tumbukan Elastis

Scroll to top
Read Time: 17 min
This post is part of a series called You Do The Math.
Creating Generative Art with HYPE
Euclidean Vectors in Flash

Indonesian (Bahasa Indonesia) translation by Sap (you can also view the original English article)

Dalam tutorial ini kita akan membuat game di mana tujuannya adalah untuk mencegah benda lain bertabrakan dengan kursor Anda. Kita tidak akan menggunakan metode hitTestObject() bawaan Flash; alih-alih kita akan menulis rutinitas deteksi tabrakan kita sendiri.

Tutorial yang diterbitkan Ulang

Setiap beberapa minggu, kami mengunjungi kembali beberapa posting favorit pembaca dari sepanjang sejarah situs. Tutorial ini pertama kali diterbitkan pada bulan Februari 2011.


Pratinjau Hasil Akhir

Mari kita lihat hasil akhir yang akan kita upayakan:


Langkah 1: Memulai

Buat file Flash baru (ActionScript 3.0)

Flash collision game tutorial

Atur dimensi panggung ke 500x500px dan FPS ke 32.

Flash collision game tutorialFlash collision game tutorialFlash collision game tutorial

Langkah 2: Kelas Bola

Kelas ini akan berisi semua data yang terkait dengan satu bola. Sebuah bola memiliki _mass, _radius, sebuah _xSpeed dan _ySpeed. Jadi kita akan membuat properti untuk masing-masing. Di konstruktor, kita melewati massa, sudut dan kecepatan bola. Karena kelas akan ditautkan ke objek tampilan, kita dapat mengambil jari-jari bola kita dengan membagi lebar objek tampilan dengan 2. _xSpeed dan _ySpeed dapat dihitung dengan menggunakan fungsi sinus dan cosinus sederhana.

1
2
package
3
{
4
  import flash.display.Stage
5
  import flash.display.Sprite
6
  import flash.events.Event
7
8
  public class Ball extends Sprite
9
  {
10
    private var _radius:Number = 0
11
    private var _mass:Number = 0
12
    private var _xSpeed:Number = 0
13
    private var _ySpeed:Number = 0
14
15
    public function Ball(mass:Number = 10.0, angle:Number = Math.PI, speed:Number = 10.0):void
16
    {
17
      this.mass = mass
18
      this._radius = this.width/2
19
      this.xSpeed = speed*Math.sin(angle)
20
      this.ySpeed = speed*Math.cos(angle)
21
    }
22
  }
23
}

Untuk informasi lebih lanjut tentang fungsi trigonometrik Math.sin() dan Math.cos() ini, lihat Tips Cepat ini.


Langkah 3: Menyediakan Getters dan Setter

Di kelas Ball, kita menyediakan getter dan setter untuk properti.

1
2
public function get radius():Number
3
{
4
  return this._radius
5
}
6
7
public function set mass(mass:Number):void
8
{
9
  this._mass = mass
10
}
11
12
public function get mass():Number
13
{
14
  return this._mass
15
}
16
17
public function set xSpeed(xSpeed:Number):void
18
{
19
  this._xSpeed = xSpeed
20
}
21
22
public function get xSpeed():Number
23
{
24
  return this._xSpeed
25
}
26
27
public function set ySpeed(ySpeed:Number):void
28
{
29
  this._ySpeed = ySpeed
30
}
31
32
public function get ySpeed():Number
33
{
34
  return this._ySpeed
35
}

Langkah 4: Fungsi Update

Fungsi ini memperbarui properti x dan y bola kita sesuai dengan _xSpeed dan _ySpeed. Kita akan menerapkan fungsi ini di kelas Ball.

1
2
public function update():void
3
{
4
  this.x += _xSpeed
5
  this.y += _ySpeed
6
}

Langkah 5: Kelas yang Selesai

Kita akan menyelesaikan kelas Ball di langkah ini.

1
2
package
3
{
4
  import flash.display.Stage
5
  import flash.display.Sprite
6
  import flash.events.Event
7
8
  public class Ball extends Sprite
9
  {
10
    private var _radius:Number = 0
11
    private var _mass:Number = 0
12
    private var _xSpeed:Number = 0
13
    private var _ySpeed:Number = 0
14
15
    public function Ball(mass:Number = 10.0, angle:Number = Math.PI, speed:Number = 10.0):void
16
    {
17
      this.mass = mass
18
      this._radius = this.width/2
19
      this.xSpeed = speed*Math.sin(angle)
20
      this.ySpeed = speed*Math.cos(angle)
21
    }
22
23
    public function get radius():Number
24
    {
25
      return this._radius
26
    }
27
28
    public function set mass(mass:Number):void
29
    {
30
      this._mass = mass
31
    }
32
33
    public function get mass():Number
34
    {
35
      return this._mass
36
    }
37
38
    public function set xSpeed(xSpeed:Number):void
39
    {
40
      this._xSpeed = xSpeed
41
    }
42
43
    public function get xSpeed():Number
44
    {
45
      return this._xSpeed
46
    }
47
48
    public function set ySpeed(ySpeed:Number):void
49
    {
50
      this._ySpeed = ySpeed
51
    }
52
53
    public function get ySpeed():Number
54
    {
55
      return this._ySpeed
56
    }
57
58
    public function update():void
59
    {
60
      this.x += _xSpeed
61
      this.y += _ySpeed
62
    }
63
  }
64
}

Langkah 6: Tampilkan Objek untuk Kelas Bola

Di file sumber saya menyertakan FLA awal yang berisi semua item perpustakaan yang dibutuhkan. Anda dapat menggambarnya sendiri jika Anda mau, tentu saja. Pastikan FLA Anda memiliki objek tampilan berikut:

Flash collision game tutorial

(Ed. Note: itu salah ketik: "ennemyball" seharusnya mengatakan "ballball".)


Langkah 7: Menghubungkan Objek Perpustakaan

Kelas Ball yang baru kita buat harus dikaitkan dengan Sprite enemyball di perpustakaan.

Flash collision game tutorialFlash collision game tutorialFlash collision game tutorial

playerball Sprite harus memiliki Ball sebagai kelas dasar dan PlayerBall sebagai kelas.

Flash collision game tutorialFlash collision game tutorialFlash collision game tutorial

Klip video score harus memiliki kelas Score.

Flash collision game tutorialFlash collision game tutorialFlash collision game tutorial

Langkah 8: Kelas Aplikasi (Kelas Dokumen)

Kelas Application akan berisi semua logika game. Kita mengimpor semua kelas yang dibutuhkan. Seperti yang Anda lihat, kita akan menggunakan TweenMax.

Selanjutnya kita mendefinisikan variabel bidang kita. Variabel bidang pertama adalah ballPlayer.

Karena kelas dasar dari Sprite playerball adalah Ball, kita dapat menyimpan Kelas ini dalam variabel ballPlayer. Ini membuatnya lebih mudah nanti untuk memeriksa tabrakan antara ballPlayer dan bola musuh.

Variabel bidang kedua adalah array yang akan berisi semua bola musuh kita. Variabel ketiga adalah timer yang akan digunakan untuk melakukan loop permainan utama. Bidang keempat dan terakhir adalah turunan dari objek perpustakaan Score kita yang akan digunakan untuk menampilkan waktu permainan yang telah berlalu. Dalam konstruktor kita memanggil fungsi init() yang akan saya jelaskan pada langkah selanjutnya.

1
2
package
3
{
4
  import flash.display.Sprite
5
  import flash.display.Graphics
6
  import flash.events.Event
7
  import flash.events.TimerEvent
8
  import flash.events.MouseEvent
9
  import flash.geom.Matrix
10
  import flash.utils.Timer
11
  import flash.ui.Mouse
12
  import com.greensock.TweenMax
13
  import com.greensock.easing.*
14
15
  public class Application extends Sprite
16
  {
17
18
    private var ballPlayer:Ball
19
    private var eballs:Array
20
    private var tmr:Timer
21
    private var score:Score
22
23
    public function Application():void
24
    {
25
      init()
26
    }
27
  }
28
}

Jangan lupa untuk menautkan kelas dokumen!.

Flash collision game tutorial

Langkah 9: Fungsi init()

Perhatikan kode ini:

1
2
private function init():void
3
{
4
  ballPlayer = new PlayerBall()
5
  eballs = new Array()
6
  tmr = new Timer(10)
7
  score = new Score()
8
9
  stage.align = "TL"
10
  stage.scaleMode = "noScale"
11
  Mouse.hide()
12
13
  setBackground()
14
15
  score.x = stage.stageWidth/2
16
  score.y = stage.stageHeight/2
17
  stage.addChild(score)
18
19
  stage.addEventListener(MouseEvent.MOUSE_MOVE, updatePlayerBall)
20
  stage.addChild(ballPlayer)
21
22
        tmr.addEventListener(TimerEvent.TIMER, updateTime)
23
24
  stage.addEventListener(MouseEvent.CLICK, startGame)
25
}

Di empat baris pertama kita menginisialisasi variabel bidang.

Selanjutnya kita pastikan panggung kita sejajar dengan sudut kiri atas dan tidak skala.

Kita menyembunyikan kursor mouse. Kursor kita akan diganti dengan playerball Sprite. Selanjutnya kita memanggil fungsi setBackground (dijelaskan pada langkah berikutnya).

Kita memusatkan score di layar dan menambahkannya ke daftar tampilan. Untuk memperbarui posisi ballPlayer, kita lampirkan acara MouseEvent.MOUSE MOVE ke atas panggung.

Fungsi updatePlayerBall (dijelaskan pada langkah 11) akan menangani MouseEvent ini. Selanjutnya kita menambahkan ballPlayer ke daftar tampilan.

Timer akan digunakan untuk menampilkan waktu permainan. Kita melampirkan pendengar TimerEvent.TIMER ke timer, yang akan memicu fungsi updateTime() (dijelaskan pada Langkah 12) setiap 10 milidetik.

Akhirnya, kita menambahkan MouseEvent. KLIK ke panggung. Fungsi startGame (dijelaskan pada langkah 13) kemudian akan memulai permainan kita.


Langkah 10: setBackground() Fungsi

Fungsi ini menambahkan background gradien radial ke daftar tampilan. Untuk menggambar gradien pada Sprite Anda harus menentukan jenis gradien, warna yang ingin Anda gunakan, nilai alpha warna, rasio (ini menentukan distribusi warna) dan metode penyebaran.

Untuk informasi lebih lanjut, lihat Tips Cepat ini tentang gradien.

1
2
private function setBackground():void
3
{
4
  var type:String = "radial"
5
  var colors:Array = [0xffffff,0xcccccc]
6
  var alphas:Array = [ 1, 1 ]
7
  var ratios:Array = [ 0, 255 ]
8
  var matr:Matrix = new Matrix()
9
  matr.createGradientBox(stage.stageWidth, stage.stageHeight, Math.PI / 2, 0, 0 )
10
  //SpreadMethod will define how the gradient is spread. Note!!! Flash uses CONSTANTS to represent String literals

11
  var sprMethod:String = "pad"
12
  //Start the Gradietn and pass our variables to it

13
  var sprite:Sprite = new Sprite()
14
  //Save typing + increase performance through local reference to a Graphics object

15
  var g:Graphics = sprite.graphics
16
  g.beginGradientFill( type, colors, alphas, ratios, matr, sprMethod )
17
  g.drawRect(0,0,stage.stageWidth,stage.stageHeight)
18
19
  stage.addChild(sprite)
20
}

Langkah 11: Fungsi updatePlayerBall()

Fungsi ini memperbarui posisi ballPlayer sesuai dengan posisi mouse Anda.

1
2
private function updatePlayerBall(e:MouseEvent):void
3
{
4
  ballPlayer.x = mouseX
5
  ballPlayer.y = mouseY
6
}

Langkah 12: Fungsi updateTime()

Kita menghitung waktu dalam detik dan memasukkannya ke dalam kotak teks Sprite score kita. Setiap 5000ms (lima detik) kita menambahkan bola baru ke permainan.

1
2
private function updateTime(e:TimerEvent):void
3
{
4
  score.txtScore.text = String(((tmr.currentCount*tmr.delay)/1000).toFixed(2));
5
  if((tmr.currentCount*tmr.delay) % 5000 == 0)
6
  {
7
    addBall();
8
  }
9
}

Langkah 13: Fungsi startGame()

Game dimulai dengan mengklik panggung. Pertama-tama kita menghapus pendengar untuk klik panggung, sehingga kita tidak dapat memulai waktu server game. Kita menambahkan tiga bola ke permainan dengan memanggil fungsi addBall() (dijelaskan pada langkah berikutnya) tiga kali. Kita memulai timer yang akan memperbarui waktu permainan kita.

Akhirnya kita menambahkan acara ENTER_FRAME ke stage. Fungsi gameLoop() (dijelaskan pada Langkah 15) akan memperbarui posisi bola musuh kita.

1
2
private function startGame(e:MouseEvent):void
3
{
4
  stage.removeEventListener(MouseEvent.CLICK, startGame)
5
  addBall()
6
  addBall()
7
  addBall()
8
  tmr.start()
9
  stage.addEventListener(Event.ENTER_FRAME, gameLoop)
10
}

Langkah 14: Fungsi addBall()

Pertama, kita membuat instance baru dari kelas Ball. Kita memposisikan ball secara acak di atas panggung dengan alfa 0 dan menambahkannya ke daftar tampilan.

Selanjutnya kita tween alpha kembali ke 1. (Saya menggunakan TweenMax, itu termasuk dalam file sumber. Anda juga dapat menggunakan mesin tween Flash built-in.) Tween kedua sebenarnya bukan tween. Itu hanya menunggu sebentar dan fungsi onComplete mendorong ball ke array eballs kita. Dengan cara ini fungsi gameLoop() (dijelaskan pada langkah berikutnya) dapat menangani sisanya.

1
2
private function addBall():void
3
{
4
  var ball:Ball = new Ball(10, Math.random()*Math.PI*2, 5)
5
  ball.x = Math.random()*stage.stageWidth
6
  ball.y = Math.random()*stage.stageHeight
7
  ball.alpha = 0
8
  stage.addChild(ball)
9
  TweenMax.to(ball, 0.5, {alpha:1})
10
  TweenMax.to(ball, 0, {delay: 1, onComplete:function():void{eballs.push(ball)}})
11
}

Langkah 15: Fungsi gameLoop()

Setiap frame akan melalui fungsi ini.

1
2
private function gameLoop(e:Event):void
3
{
4
  for (var i:uint = 0; i < eballs.length; i++)
5
  {
6
    for (var j:uint = i + 1; j < eballs.length; j++)
7
    {
8
      if (collision(eballs[i], eballs[j]))
9
      {
10
        doCollision(eballs[i], eballs[j])
11
      }
12
    }
13
14
    if(collision(eballs[i], ballPlayer))
15
    {
16
      endOfGame()
17
      break
18
    }
19
20
    eballs[i].update()
21
    checkBounds(eballs[i])
22
  }
23
}

Kita mulai dengan mengulangi semua bola musuh kita.

Cekungan kedua untuk tabrakan antara bola musuh. Loop dimulai pada 'i + 1'. Dengan cara ini kita tidak mengecek tabrakan.

Selanjutnya kita periksa apakah ballPlayer menyentuh bola musuh. Jika demikian, game sudah selesai. Kemudian kita memperbarui posisi bola musuh.

Kita memastikan bola tetap berada di layar game dengan memanggil fungsi checkBounds() (dijelaskan nanti).


Langkah 16: Fungsi collision()

Fungsi ini memeriksa apakah ada pasangan bola yang bertabrakan.

Pertama kita menghitung jarak x dan jarak y antara kedua bola. Menggunakan Teorema Pythagoras (lihat diagram berikut) kita menghitung jarak absolut di antara mereka. Jika jaraknya kurang atau sama dengan jumlah jari-jari bola kita memiliki tabrakan.

Flash collision game tutorial
1
2
private function collision(ball1:Ball, ball2:Ball):Boolean
3
{
4
  var xDist:Number = ball1.x - ball2.x
5
  var yDist:Number = ball1.y - ball2.y
6
  var Dist:Number = Math.sqrt(xDist * xDist + yDist * yDist)
7
8
  return Dist <= ball1.radius + ball2.radius
9
}

Langkah 17: Funsi doCollision()

Fungsi ini akan menghitung kecepatan x dan y baru bola sesuai dengan kecepatan dan sudut tumbukan. Peringatan: matematika;)

Pertama kita menghitung jarak horizontal antara kedua bola dan kemudian jarak vertikal antara bola. Dengan jarak ini (dan lebih banyak trigonometri) kita dapat menghitung sudut antara bola (lihat diagram).

Flash collision game tutorial

Selanjutnya kita menghitung apa yang saya sebut magnitude setiap bola. (Kita memiliki vektor xspeed dan vektor yspeed; besarnya adalah jumlah vektor dari mereka.) Kemudian kita menghitung sudut setiap bola (mirip dengan perhitungan sudut sebelumnya).

Selanjutnya kita memutar kecepatan x dan y baru dari setiap bola. Apa yang sebenarnya kita lakukan adalah memutar sistem koordinat. Dengan memutar sumbu kita, kita memiliki tabrakan 1D. (Lihat diagram berikut).

Flash collision game tutorial

Newton mengatakan bahwa jumlah total energi kinetik dalam sistem tertutup adalah konstan. Sekarang kita menggunakan rumus ini:

  • v1 = (u1*(m1-m2) + 2*m2*u2)/(m1+m2)
  • V2 = (u2*(m2-m1) + 2*m1*u1)/(m1+m2)

dimana:

v1 = final xSpeedBall 1

v2 = final xSpeedBall 2

m1 = mass ball 1

m2 = mass ball 2

u1 = initial speed ball 1

u2 = initial speed ball 2

Kecepatan-y tidak berubah karena merupakan tabrakan 1D.

Dengan rumus ini kita bisa menghitung xSpeed dan ySpeed dari setiap bola.

Sekarang ketika memiliki kecepatan x dan y baru dalam sistem koordinat yang diputar. Langkah terakhir adalah mengubah semuanya kembali ke sistem koordinat normal. Kita menggunakan Math.PI/2 karena sudut antara xSpeed dan ySpeed harus selalu 90 derajat (pi/2 radian).

1
2
private function doCollision(ball1:Ball, ball2:Ball):void
3
{
4
  var xDist:Number = ball1.x - ball2.x
5
  var yDist:Number = ball1.y - ball2.y
6
  var collisionAngle:Number = Math.atan2(yDist, xDist)
7
8
  var magBall1:Number = Math.sqrt(ball1.xSpeed*ball1.xSpeed+ball1.ySpeed*ball1.ySpeed)
9
  var magBall2:Number = Math.sqrt(ball2.xSpeed*ball2.xSpeed+ball2.ySpeed*ball2.ySpeed)
10
11
  var angleBall1:Number = Math.atan2(ball1.ySpeed, ball1.xSpeed)
12
  var angleBall2:Number = Math.atan2(ball2.ySpeed, ball2.xSpeed)
13
14
  var xSpeedBall1:Number = magBall1 * Math.cos(angleBall1-collisionAngle)
15
  var ySpeedBall1:Number = magBall1 * Math.sin(angleBall1-collisionAngle)
16
  var xSpeedBall2:Number = magBall2 * Math.cos(angleBall2-collisionAngle)
17
  var ySpeedBall2:Number = magBall2 * Math.sin(angleBall2-collisionAngle)
18
19
  var finalxSpeedBall1:Number = ((ball1.mass-ball2.mass)*xSpeedBall1+(ball2.mass+ball2.mass)*xSpeedBall2)/(ball1.mass+ball2.mass)
20
  var finalxSpeedBall2:Number = ((ball1.mass+ball1.mass)*xSpeedBall1+(ball2.mass-ball1.mass)*xSpeedBall2)/(ball1.mass+ball2.mass)
21
  var finalySpeedBall1:Number = ySpeedBall1
22
  var finalySpeedBall2:Number = ySpeedBall2
23
24
  ball1.xSpeed = Math.cos(collisionAngle)*finalxSpeedBall1+Math.cos(collisionAngle+Math.PI/2)*finalySpeedBall1
25
  ball1.ySpeed = Math.sin(collisionAngle)*finalxSpeedBall1+Math.sin(collisionAngle+Math.PI/2)*finalySpeedBall1
26
  ball2.xSpeed = Math.cos(collisionAngle)*finalxSpeedBall2+Math.cos(collisionAngle+Math.PI/2)*finalySpeedBall2
27
  ball2.ySpeed = Math.sin(collisionAngle)*finalxSpeedBall2+Math.sin(collisionAngle+Math.PI/2)*finalySpeedBall2
28
}

Untuk menemukan informasi lebih lanjut tentang tumbukan elastis, lihat di hoomanr.com.


Langkah 18: Fungsi endOfGame()

Ini dijalankan saat game berakhir.

1
2
private function endOfGame():void
3
{
4
  tmr.stop()
5
  Mouse.show()
6
  stage.removeEventListener(MouseEvent.MOUSE_MOVE, updatePlayerBall)
7
  stage.removeEventListener(Event.ENTER_FRAME, gameLoop)
8
9
  while(eballs.length > 0)
10
  {
11
    TweenMax.to(eballs[0], 0.5, {scaleX:0, scaleY:0, ease:Bounce.easeOut})
12
    eballs.splice(0,1)
13
  }
14
15
  TweenMax.to(ballPlayer, 0.5, {scaleX:0, scaleY:0, ease:Bounce.easeOut})
16
}

Pertama-tama kita menghentikan timer. Kita menunjukkan mouse lagi. Selanjutnya kita menghapus pendengar acara MOUSE_MOVE dan ENTER_FRAME. Akhirnya kita membuat semua bola di atas panggung tidak terlihat.


Langkah 19: Fungsi checkBounds ()

Fungsi ini memastikan bola tetap berada di dalam layar game. Jadi, jika bola mengenai sisi atas atau bawah, kita membalikkan ySpeed. jika bola menyentuh sisi kiri atau kanan layar, kita membalikkan xSpeed. Ini menggunakan logika yang mirip dengan fungsi deteksi tabrakan bola untuk memeriksa apakah tepi bola menyentuh tepi layar.

1
2
private function checkBounds(ball:Ball):void
3
{
4
  if((ball.x + ball.radius) > stage.stageWidth)
5
  {
6
    ball.x = stage.stageWidth - ball.radius
7
    ball.xSpeed *= -1
8
  }
9
  if((ball.x - ball.radius) < 0)
10
  {
11
    ball.x = 0 + ball.radius
12
    ball.xSpeed *= -1
13
  }
14
  if((ball.y + ball.radius) > stage.stageHeight)
15
  {
16
    ball.y = stage.stageHeight - ball.radius
17
    ball.ySpeed *= - 1
18
  }
19
  if((ball.y - ball.radius) < 0)
20
  {
21
    ball.y = 0 + ball.radius
22
    ball.ySpeed *= - 1
23
  }
24
}

Langkah 20: Kelas Aplikasi Lengkap

Kita telah menyelesaikan kelas Aplikasi. Kita sekarang memiliki game yang berfungsi!!!

1
2
package
3
{
4
  import flash.display.Sprite;
5
  import flash.display.Graphics;
6
  import flash.events.Event;
7
  import flash.events.TimerEvent;
8
  import flash.events.MouseEvent;
9
  import flash.geom.Matrix;
10
  import flash.utils.Timer;
11
  import flash.ui.Mouse;
12
  import com.greensock.TweenMax;
13
  import com.greensock.easing.*;
14
  public class Application extends Sprite
15
  {
16
17
    private var ballPlayer:Ball;
18
    private var eballs:Array;
19
    private var tmr:Timer;
20
    private var score:Score;
21
    public function Application():void
22
    {
23
      init();
24
    }
25
26
    private function init():void
27
    {
28
      ballPlayer = new PlayerBall();
29
      eballs = new Array();
30
      tmr = new Timer(10);
31
      score = new Score();
32
33
      stage.align = "TL";
34
      stage.scaleMode = "noScale";
35
      Mouse.hide();
36
37
      setBackground();
38
39
      score.x = stage.stageWidth / 2;
40
      score.y = stage.stageHeight / 2;
41
      stage.addChild(score);
42
43
      stage.addEventListener(MouseEvent.MOUSE_MOVE, updatePlayerBall);
44
      stage.addChild(ballPlayer);
45
46
      tmr.addEventListener(TimerEvent.TIMER, updateTime);
47
48
      stage.addEventListener(MouseEvent.CLICK, startGame);
49
    }
50
51
    private function setBackground():void
52
    {
53
      var type:String = "radial";
54
      var colors:Array = [0xffffff,0xcccccc];
55
      var alphas:Array = [1,1];
56
      var ratios:Array = [0,255];
57
      var matr:Matrix = new Matrix();
58
      matr.createGradientBox(stage.stageWidth, stage.stageHeight, Math.PI / 2, 0, 0 );
59
      //SpreadMethod will define how the gradient is spread. Note!!! Flash uses CONSTANTS to represent String literals

60
      var sprMethod:String = "pad";
61
      //Start the Gradietn and pass our variables to it

62
      var sprite:Sprite = new Sprite();
63
      //Save typing + increase performance through local reference to a Graphics object

64
      var g:Graphics = sprite.graphics;
65
      g.beginGradientFill( type, colors, alphas, ratios, matr, sprMethod );
66
      g.drawRect(0,0,stage.stageWidth,stage.stageHeight);
67
      stage.addChild(sprite);
68
    }
69
70
    private function updatePlayerBall(e:MouseEvent):void
71
    {
72
      ballPlayer.x = mouseX;
73
      ballPlayer.y = mouseY;
74
    }
75
76
    private function updateTime(e:TimerEvent):void
77
    {
78
      score.txtScore.text = String(((tmr.currentCount*tmr.delay)/1000).toFixed(2));
79
      if ((tmr.currentCount*tmr.delay) % 5000 == 0)
80
      {
81
        addBall();
82
      }
83
    }
84
85
    private function startGame(e:MouseEvent):void
86
    {
87
      stage.removeEventListener(MouseEvent.CLICK, startGame);
88
      addBall();
89
      addBall();
90
      addBall();
91
      tmr.start();
92
      stage.addEventListener(Event.ENTER_FRAME, gameLoop);
93
    }
94
95
    private function addBall():void
96
    {
97
      var ball:Ball = new Ball(10,Math.random() * Math.PI * 2,5);
98
      ball.x = Math.random() * stage.stageWidth;
99
      ball.y = Math.random() * stage.stageHeight;
100
      ball.alpha = 0;
101
      stage.addChild(ball);
102
      TweenMax.to(ball, 0.5, {alpha:1});
103
      TweenMax.to(ball, 0, {delay: 1, onComplete:function():void{eballs.push(ball)}});
104
    }
105
106
    private function gameLoop(e:Event):void
107
    {
108
      for (var i:uint = 0; i < eballs.length; i++)
109
      {
110
        for (var j:uint = i + 1; j < eballs.length; j++)
111
        {
112
          if (collision(eballs[i],eballs[j]))
113
          {
114
            doCollision(eballs[i], eballs[j]);
115
          }
116
        }
117
118
        if (collision(eballs[i],ballPlayer))
119
        {
120
          endOfGame();
121
          break;
122
        }
123
124
        eballs[i].update();
125
        checkBounds(eballs[i]);
126
      }
127
    }
128
129
    private function collision(ball1:Ball, ball2:Ball):Boolean
130
    {
131
      var xDist:Number = ball1.x - ball2.x;
132
      var yDist:Number = ball1.y - ball2.y;
133
      var Dist:Number = Math.sqrt(xDist * xDist + yDist * yDist);
134
135
      if (Dist <= ball1.radius + ball2.radius)
136
      {
137
        if (ball1.x < ball2.x)
138
        {
139
          ball1.x -=  2;
140
          ball2.x +=  2;
141
        }
142
        else
143
        {
144
          ball1.x +=  2;
145
          ball2.x -=  2;
146
        }
147
148
        if (ball1.y < ball2.y)
149
        {
150
          ball1.y -=  2;
151
          ball2.y +=  2;
152
        }
153
        else
154
        {
155
          ball1.y +=  2;
156
          ball2.y -=  2;
157
        }
158
      }
159
160
161
      return Dist <= ball1.radius + ball2.radius;
162
    }
163
164
    private function doCollision(ball1:Ball, ball2:Ball):void
165
    {
166
      var xDist:Number = ball1.x - ball2.x;
167
      var yDist:Number = ball1.y - ball2.y;
168
      var collisionAngle:Number = Math.atan2(yDist,xDist);
169
      var magBall1:Number = Math.sqrt(ball1.xSpeed * ball1.xSpeed + ball1.ySpeed * ball1.ySpeed);
170
      var magBall2:Number = Math.sqrt(ball2.xSpeed * ball2.xSpeed + ball2.ySpeed * ball2.ySpeed);
171
      var angleBall1:Number = Math.atan2(ball1.ySpeed,ball1.xSpeed);
172
      var angleBall2:Number = Math.atan2(ball2.ySpeed,ball2.xSpeed);
173
      var xSpeedBall1:Number = magBall1 * Math.cos(angleBall1 - collisionAngle);
174
      var ySpeedBall1:Number = magBall1 * Math.sin(angleBall1 - collisionAngle);
175
      var xSpeedBall2:Number = magBall2 * Math.cos(angleBall2 - collisionAngle);
176
      var ySpeedBall2:Number = magBall2 * Math.sin(angleBall2 - collisionAngle);
177
      var finalxSpeedBall1:Number = ((ball1.mass-ball2.mass)*xSpeedBall1+(ball2.mass+ball2.mass)*xSpeedBall2)/(ball1.mass+ball2.mass);
178
      var finalxSpeedBall2:Number = ((ball1.mass+ball1.mass)*xSpeedBall1+(ball2.mass-ball1.mass)*xSpeedBall2)/(ball1.mass+ball2.mass);
179
      var finalySpeedBall1:Number = ySpeedBall1;
180
      var finalySpeedBall2:Number = ySpeedBall2;
181
      ball1.xSpeed = Math.cos(collisionAngle) * finalxSpeedBall1 + Math.cos(collisionAngle + Math.PI / 2) * finalySpeedBall1;
182
      ball1.ySpeed = Math.sin(collisionAngle) * finalxSpeedBall1 + Math.sin(collisionAngle + Math.PI / 2) * finalySpeedBall1;
183
      ball2.xSpeed = Math.cos(collisionAngle) * finalxSpeedBall2 + Math.cos(collisionAngle + Math.PI / 2) * finalySpeedBall2;
184
      ball2.ySpeed = Math.sin(collisionAngle) * finalxSpeedBall2 + Math.sin(collisionAngle + Math.PI / 2) * finalySpeedBall2;
185
    }
186
187
    private function endOfGame():void
188
    {
189
      tmr.stop();
190
      Mouse.show();
191
      stage.removeEventListener(MouseEvent.MOUSE_MOVE, updatePlayerBall);
192
      stage.removeEventListener(Event.ENTER_FRAME, gameLoop);
193
194
      while (eballs.length > 0)
195
      {
196
        TweenMax.to(eballs[0], 0.5, {scaleX:0, scaleY:0, ease:Bounce.easeOut});
197
        eballs.splice(0,1);
198
      }
199
200
      TweenMax.to(ballPlayer, 0.5, {scaleX:0, scaleY:0, ease:Bounce.easeOut});
201
    }
202
203
    private function checkBounds(ball:Ball):void
204
    {
205
      if ((ball.x + ball.radius) > stage.stageWidth)
206
      {
207
        ball.x = stage.stageWidth - ball.radius;
208
        ball.xSpeed *=  -1;
209
      }
210
      if ((ball.x - ball.radius) < 0)
211
      {
212
        ball.x = 0 + ball.radius;
213
        ball.xSpeed *=  -1;
214
      }
215
      if ((ball.y + ball.radius) > stage.stageHeight)
216
      {
217
        ball.y = stage.stageHeight - ball.radius;
218
        ball.ySpeed *=  -1;
219
      }
220
      if ((ball.y - ball.radius) < 0)
221
      {
222
        ball.y = 0 + ball.radius;
223
        ball.ySpeed *=  -1;
224
      }
225
    }
226
  }
227
}

Kesimpulan

Itu saja untuk tutorial ini. Tentu saja Anda dapat menambahkan kemungkinan untuk memulai kembali permainan, tetapi itu tidak terlalu sulit. Contoh dasar tabrakan elastis ini dapat digunakan untuk game yang lebih besar seperti game biliar atau sejenisnya.

Saya harap Anda menyukai tutorial ini, terima kasih sudah membaca!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.