【100sites #007】Pong,使用P5.js建構的復古遊戲

Posted by Eason Chang on 2016-03-19

Pong,使用P5.js建構的復古遊戲

點我遊玩

我想看看程式碼

螢幕快照 2016-03-20 上午1.23.09.png

一句話摘要:使用P5.js這個JavaScript繪圖框架,重建Pong這個復古遊戲,並重新開動100sites專案

因為一直很忙加上懶惰加上拖延,已經快一個月沒有持續我的100sites專案了,然現在我終於忙完了,是時候該重拾行囊,繼續走完這段成為專業全端工程師的修行之路了!

這次的#007成品是Pong,一個很經典遊戲,左右兩位玩家操縱著各自的棒棒將球反彈給對方,漏球最多的一方輸。

前些日子在SITCON年有講者分享P5.js這個框架,他算是我在#006 Snack裡面使用的Processing.js的兄弟,Processing.js使用Processing語言,但P5.js使用JavaScript來達到相同的功能,對於現在JS大熱門的趨勢來看,P5.js也是一個很值得學起來的框架之一呀!

以下附上本次的程式碼:

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Pong!</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.23/p5.js"></script>
<script src="pong.js"></script>
<style> body{padding:0; margin:0; overflow:hidden;} </style>
</head>

<body>
</body>
</html>
pong.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
var BAR_MOVE_SPEED = 15;
var BALL_SIZE = 20;
var BALL_SPEED = 10;

var MAP_WIDTH = 800;
var MAP_HEIGHT = 500;

var BAR_WIDTH = 10;
var BAR_HEIGHT = 120;

var p1_y;
var p2_y;
var p1_score;
var p2_score;

var ball_x;
var ball_y;
var ball_velocity_x;
var ball_velocity_y;

var gamePaused = false;
var gameStarted = false;

function setup() {
MAP_WIDTH = windowWidth;
MAP_HEIGHT = windowHeight;
createCanvas(MAP_WIDTH, MAP_HEIGHT);

ellipseMode(CENTER);
rectMode(CENTER);

p1_y = MAP_HEIGHT/2;
p2_y = MAP_HEIGHT/2;
p1_score = 0;
p2_score = 0;
ball_x = MAP_WIDTH/2;
ball_y = MAP_HEIGHT/2;
ball_velocity_x = BALL_SPEED;
ball_velocity_y = BALL_SPEED;
}

function draw() {

if(!gamePaused && gameStarted) {
pleyerControl();
ballMove();
ballCollide();
checkBallOutside();
}
displayGame();
displayGUI();

}


function keyPressed() {
if(keyCode === ENTER) {
if(!gameStarted) {
gameStarted = true;
} else {
gamePaused = !gamePaused;
}
}
}


function pleyerControl() {
if(keyIsDown(87) || keyIsDown(119)) { // W
if(p1_y-BAR_HEIGHT/2 > 0) {
p1_y -= BAR_MOVE_SPEED;
}
} else if (keyIsDown(83) || keyIsDown(115)) { // S
if(p1_y+BAR_HEIGHT/2 < MAP_HEIGHT) {
p1_y += BAR_MOVE_SPEED;
}
}

if(keyIsDown(UP_ARROW)) { // UP
if(p2_y-BAR_HEIGHT/2 > 0) {
p2_y -= BAR_MOVE_SPEED;
}
} else if (keyIsDown(DOWN_ARROW)) { // DOWN
if(p2_y+BAR_HEIGHT/2 < MAP_HEIGHT) {
p2_y += BAR_MOVE_SPEED;
}
}
}


function ballMove() {
ball_x += ball_velocity_x;
ball_y += ball_velocity_y;
}


function ballCollide() {
if(ball_y+BALL_SIZE/2 > MAP_HEIGHT || ball_y-BALL_SIZE/2 < 0) { // collide with upper and lower walls
ball_velocity_y = -ball_velocity_y;
}

if(ball_x <= 30+BAR_WIDTH/2 // collide with player1
&& ball_x >= 30-BAR_WIDTH/2
&& ball_y >= p1_y-BAR_HEIGHT/2
&& ball_y <= p1_y+BAR_HEIGHT/2) {
ball_velocity_x = -ball_velocity_x;
// slightly change ball y speed according to the position ball hit on the bar
ball_velocity_y += (ball_y-p1_y)*10/(BAR_HEIGHT/2);
if(ball_velocity_y > BALL_SPEED) // strict the ball speed not exceed max speed
ball_velocity_y = BALL_SPEED;
else if(ball_velocity_y < -BALL_SPEED)
ball_velocity_y = -BALL_SPEED;
}

if(ball_x >= MAP_WIDTH-30-BAR_WIDTH/2 // collide with player2
&& ball_x <= MAP_WIDTH-30+BAR_WIDTH/2
&& ball_y >= p2_y-BAR_HEIGHT/2
&& ball_y <= p2_y+BAR_HEIGHT/2) {
ball_velocity_x = -ball_velocity_x;
// slightly change ball y speed according to the position ball hit on the bar
ball_velocity_y += (ball_y-p2_y)*10/(BAR_HEIGHT/2);
if(ball_velocity_y > BALL_SPEED) // strict the ball speed not exceed max speed
ball_velocity_y = BALL_SPEED;
else if(ball_velocity_y < -BALL_SPEED)
ball_velocity_y = -BALL_SPEED;
}
}


function checkBallOutside() {
if(ball_x > MAP_WIDTH) {
ball_x = MAP_WIDTH/2;
ball_y = MAP_HEIGHT/2;
++p1_score;
} else if(ball_x < 0) {
ball_x = MAP_WIDTH/2;
ball_y = MAP_HEIGHT/2;
++p2_score;
}
}


function displayGame() {
background(0);
fill(255); // white
rect(30, p1_y, BAR_WIDTH, BAR_HEIGHT); // player1 bar
rect(MAP_WIDTH-30, p2_y, BAR_WIDTH, BAR_HEIGHT); // player2 bar
fill(0,255,255);
ellipse(ball_x, ball_y, BALL_SIZE, BALL_SIZE); // ball
}


function displayGUI() {

if(gamePaused) {
textSize(100);
fill(255);
textAlign(CENTER);
text("PAUSED", MAP_WIDTH/2, MAP_HEIGHT/2);
}
if(!gameStarted) {
textAlign(CENTER);
textSize(100);
fill(0, 255, 255);
text("Pong!", MAP_WIDTH/2, 150);
fill(255);
textSize(80);
text("Press ENTER to Start", MAP_WIDTH/2, MAP_HEIGHT/2);
textSize(40);
text("Left player: W, S to move\nRight player: UP, DOWN to move\nPress ENTER to pause", MAP_WIDTH/2, MAP_HEIGHT/2+150);
}
textSize(30);
textAlign(LEFT);
text(p1_score, 30, 30);
textAlign(RIGHT);
text(p2_score, MAP_WIDTH-30, 30);
}