Bu yazımda PHP, jQuery ve MySQL kullanarak Çok Oyunuculu Online Oyun yapacağız.
Oyunumuzun amacı yukarıdan düşen coinleri toplamak olacak.
Birden fazla oyuncu aynı anda oyunumuzu oynayabilecek ve eğer kayıtlı değilse veritabanımızda bulunan guest kullanıcılarından birine otomatik olarak atanacak. Aynı zamanda oyuncular kayıt olabilecek ve oyunu oynarken giriş yapabilecek.
Tabi ki bu yazımda anlatacağım yöntemler online bir oyun yap
mak için tavsiye edilen yöntemler değildir biz burada örneğin oyuncuların lokasyon verilerini direk veritabanına anlık kaydedip, veritabanı üzerinden anlık okuyoruz fakat normal şartlarda bir online oyunda örnek vermek gerekirse oyuncuların lokasyonunu tutacak bir server yazılımı olur ve o yazılım üzerinden hangi kullanıcı nerede bu veriler aktarılır.
Yapacağımız Oyunun Demosu : DEMO
Kullandığımız Kütüphane Dosyaları ve Oyunun Dosyalarını İndirmek İçin : Github
Şimdi kodlarımıza geçelim, öncelikli olarak kodların tamamını vereceğim daha sonra da parça parça kodların ne işe yaradığını anlatacağım.
Anlatımın sonunda da gerekli olan kütüphane dosyalarını paylaşacağım.
Oyunumuzun Dizin Yapısı :
1.Adım : Veritabanımız üzerinde Tablomuzu oluşturuyoruz :
1 2 3 4 5 6 7 8 9 10 11 |
CREATE TABLE `client` ( `id` int(11) NOT NULL, `gameid` varchar(45) COLLATE utf8_bin DEFAULT NULL, `clix` varchar(45) COLLATE utf8_bin DEFAULT NULL, `cliy` varchar(45) COLLATE utf8_bin DEFAULT NULL, `point` varchar(45) COLLATE utf8_bin DEFAULT NULL, `lastpingtime` int(32) DEFAULT NULL, `username` varchar(16) COLLATE utf8_bin DEFAULT NULL, `password` varchar(64) COLLATE utf8_bin DEFAULT NULL, `usertype` varchar(10) COLLATE utf8_bin DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; |
2.Adım : Tablomuza örnek ve ziyaretçi verilerimizi ekliyoruz.
1 2 3 4 5 6 |
INSERT INTO `client` (`id`, `gameid`, `clix`, `cliy`, `point`, `lastpingtime`, `username`, `password`, `usertype`) VALUES (1, '1', '50', '628', '0', 1, 'Guest1', NULL, 'guest'), (2, '1', '50', '628', '0', 1, 'Guest2', NULL, 'guest'), (3, '1', '50', '628', '0', 1, 'Guest3', NULL, 'guest'), (4, '1', '50', '628', '0', 1, 'Guest4', NULL, 'guest'), (5, '1', '50', '628', '0', 1, 'Guest5', NULL, 'guest'); |
3.Adım : Ana dizinimizde game.html adında bir dosya oluşturuyoruz.
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 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Coin Hunter Game - wwphp.com</title> <link rel="stylesheet" href="assets/css/bootstrap.min.css"> <link rel="stylesheet" href="assets/css/jquery-ui.css"> <link rel="stylesheet" href="assets/css/game.css"> <link rel='shortcut icon' type='image/x-icon' href='favicon.ico' /> </head> <body> <div id="gamecontent"> <div class="MyScoreBoard"> <img src="assets/images/coin.gif" /> <div id="MyScore" class="MyScore">0</div> </div> <img id="MEOBJ" src="assets/images/char1_walk.gif"/> </div> <div class="rightbar"> <div id="score"></div> <div id="login"> <img src="assets/images/login.png" /> <hr /> <div class="form-group"> <input id="username" type="text" class="form-control" placeholder="USERNAME"> </div> <div class="form-group"> <input id="password" type="password" class="form-control" placeholder="PASSWORD"> </div> <button id="loginBtn" type="submit" class="btn btn-default">Login</button> <button id="registerBtn" type="submit" class="btn btn-default">Register</button> </div> <div id="afterlogin"> <img src="assets/images/Welcome.png" /> <div id="usernameDiv"></div> <button id="loginoutBtn" type="submit" class="btn btn-default">Logout</button> </div> <div id="tips"><img src="assets/images/tips1.png" /></div> </div> <div id="wwphp"> Codec By <a href="http://wwphp.com">wwPHP.com</a> </div> </body> <script src="assets/js/jquery.min.js"></script> <script src="assets/js/bootstrap.min.js"></script> <script src="assets/js/jquery-ui.min.js"></script> <script src="assets/js/game.js"></script> </html> |
a. <div id=”gamecontent”> nesnemiz oyunumuzun tabanını oluşturan ve oyunumuza ait arka plan görseli, karakterimiz vb. nesneleri barındıran katmanımız.
b.<div class=”MyScoreBoard”> nesnemiz ise içerisinde karakterimize ait skoru yazdığımız gamecontent nesemiz içerisinde bulunan alan.
c.<img id=”MEOBJ” src=”assets/images/char1_walk.gif”/> nesnemiz ise bizim karakterimiz.
d.<div class=”rightbar”> nesnemiz sağ tarafta bulunan içerisinde Aktif Oyuncular, Giriş vb. kısımların bulunduğu alan.
e.<div id=”score”></div> aktif kullanıcıların ve skorlanının gösterildiği alan.
f.<div id=”login”> ve <div id=”afterlogin”> Kullanıcı girişi ve giriş sonrası ile alakalı alanlar.
4.Adım : /assets/js/ Dizini altında game.js adında bir dosya oluşturuyoruz.
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 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
$(document).ready(function(){ var Players = []; var MECoorX = 0; var MECoorY = 0; var MEID = 0; var ThisGameID = "1"; // USER COOKIE GET FUNCTION function getCookie(cname) { var name = cname + "="; var decodedCookie = decodeURIComponent(document.cookie); var ca = decodedCookie.split(';'); for(var i = 0; i <ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } return ""; } // USER COOKIE SET FUNCTION function setCookie(cname, cvalue, exdays) { var d = new Date(); d.setTime(d.getTime() + (exdays*24*60*60*1000)); var expires = "expires="+ d.toUTCString(); document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; } // USER COOKIE CONTROL var UserCookie = getCookie("wwGameUser"); if(UserCookie != "") // IF Cookie ISSET { var UserCookieDataSplit = UserCookie.split("-"); // SPLIT COOKIE DATA var UserName = UserCookieDataSplit[0]; var Password = UserCookieDataSplit[1]; $.post("process.php?proc=LOGIN", // POST UserName and Password process.php?proc=LOGIN page { username:UserName, password:Password }, function(data,status){ if(data != "0") // Return data if not equals 0 Username and Password correct { var DataSplit = data.split("-"); // Split return User data. MEID = DataSplit[0]; // Update MEID document.getElementById("MyScore").innerHTML = DataSplit[1]; // Show MyScore div in user latest score. document.getElementById("login").style.display = "none"; // Hide User Login Box. document.getElementById("afterlogin").style.display = "block"; // Show Afterlogin Box. document.getElementById("usernameDiv").innerHTML = DataSplit[2]; // Change Afterlogin Username div content. setCookie("wwGameUser", UserName+"-"+Password, 2); }else{ alert("Username or Password Incorrect."); } }); }else{ // IF User not set cookie and not login set guest account this user. $.post("process.php?proc=ME", { GameID:ThisGameID }, function(data,status){ if(data == "FULL") // IF all guest account is used show message user screen "Guest Account FULL !" message and MEOBJ hidden. { alert("Guest Account FULL !"); document.getElementById("MEOBJ").style.display = "none"; }else{ if(MEID == 0) { MEID = data; } } }); } // LOGIN BUTTON CLICK $( "#loginBtn" ).click(function() { var UserName = document.getElementById('username').value; // Username INPUT Value var Password = document.getElementById('password').value; // Password INPUT Value if(UserName != "" && Password != "") // IF NOT EMPTY Username and Password Input { $.post("process.php?proc=LOGIN", // POST User data to process.php?proc=LOGIN page. { username:UserName, password:Password }, function(data,status){ if(data != "0") // IF Username and Password correct return data split. { var DataSplit = data.split("-"); MEID = DataSplit[0]; // UPDATE MEID document.getElementById("MyScore").innerHTML = DataSplit[1]; // Update MyScore latest score. document.getElementById("login").style.display = "none"; // Login box hide. document.getElementById("afterlogin").style.display = "block"; // Show Afterlogin box. document.getElementById("usernameDiv").innerHTML = DataSplit[2]; // Change Afterlogin Username div content. setCookie("wwGameUser", UserName+"-"+Password, 2); // Create Cookie 2 Days }else{ alert("Username or Password Incorrect."); } }); }else{ alert("Username or Password Empty!"); } }); // REGISTER BUTTON CLICK $( "#registerBtn" ).click(function() { var UserName = document.getElementById('username').value; // Username INPUT Value var Password = document.getElementById('password').value; // Password INPUT Value if(UserName != "" && Password != "") // IF NOT EMPTY Username and Password Input { $.post("process.php?proc=REGISTER", // POST Username and Password data process.php?proc=REGISTER page. { username:UserName, password:Password }, function(data,status){ if(data != "0") // IF register return data not equals 0 { MEID = data; // Update MEID. document.getElementById("MyScore").innerHTML = "0"; document.getElementById("login").style.display = "none"; // Login box hide. document.getElementById("afterlogin").style.display = "block"; // Show Afterlogin box. document.getElementById("usernameDiv").innerHTML = UserName; // Change Afterlogin Username div content. setCookie("wwGameUser", UserName+"-"+Password, 2); // Create Cookie 2 Days }else{ alert("Error."); } }); }else{ alert("Username or Password Empty!"); } }); $( "#loginoutBtn" ).click(function() { // LOGOUT Button Click. setCookie("wwGameUser", UserName+"-"+Password, -1); // User Cookie Day -1. location.reload(); // Content Reload. }); // IM HERE // IF I Active Send process.php?proc=IMHERE page. setInterval(function(){ if(MEID > 0) { $.post("process.php?proc=IMHERE", // POST CliID to process.php?proc=IMHERE. { GameID:ThisGameID, CliID:MEID }); } }, 500); // SCORE LIST setInterval(function(){ // Show Dynamic Active User Score List on #score div content. if(MEID > 0) { $.post("process.php?proc=SCORE", { GameID:ThisGameID, CliID:MEID }, function(data,status){ $("#score").html(data); }); } }, 500); //Active Player Check // Check Active Players on 500 Miliseconds setInterval(function(){ if(MEID > 0) { $.post("process.php?proc=ACTIVE", { status:"New", GameID:ThisGameID, CliID:MEID }, function(data,status){ var ClientDetail = data.split("-"); // ACTIVE Players Data. for (ia = 0; ia < ClientDetail.length; ia++) { var ClientCheck = Players.indexOf(ClientDetail[ia]); if(ClientCheck < 0 && ClientDetail[ia] != "") { Players.push(ClientDetail[ia]); // Add Players varibles add Player ID $('#gamecontent').append('<img class="" id="PlayerObj'+ClientDetail[ia]+'" style="top:620px; postion:absolute; background:none; border:0px;" src="assets/images/char1_walk.gif"/>'); // ADD Active player character on #gamecontent. } } }); } }, 500); //InActive Player Check setInterval(function(){ if(MEID > 0) { $.post("process.php?proc=INACTIVE", { status:"New", GameID:ThisGameID, CliID:MEID }, function(data,status){ var ClientDetail = data.split("-"); // Inactive Player Data for (ia = 0; ia < ClientDetail.length; ia++) { var ClientCheck = Players.indexOf(ClientDetail[ia]); if(ClientCheck > -1 && ClientDetail[ia] != "") { Players = Players.filter(function(item) { return item !== ClientDetail[ia]; }); $('#PlayerObj'+ClientDetail[ia]+'').remove(); // Remove InActive Player. } } }); } }, 500); // Check Players Location var LastLocation = 0; setInterval(function(){ if(MEID > 0) { $.post("process.php?proc=PLAYERLOCATION", { CliID:MEID, GameID:ThisGameID }, function(data,status){ var ExpCliDetail = data.split("#"); for (ia = 0; ia < ExpCliDetail.length; ia++) { if(ExpCliDetail[ia] != "") { var ExpCliDetailLoc = ExpCliDetail[ia].split("-"); var ClientCheck = Players.indexOf(ExpCliDetailLoc[0]); if(ClientCheck + 1 > 0 ) { LastLocation = document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.left; if(LastLocation < ExpCliDetailLoc[1]) { document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.transform = "scale(1, 1)"; }else if(LastLocation > ExpCliDetailLoc[1]) { document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.transform = "scale(-1, 1)"; } document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.position = "absolute"; document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.top = ExpCliDetailLoc[2]+"px"; document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.left = ExpCliDetailLoc[1]+"px"; } } } }); } }, 100); // KEYBOARD CONTROL $(document).keydown(function(e){ var offset = $("#MEOBJ").offset(); var xPos = offset.left; // MEOBJ Left Position var yPos = offset.top; // MEOBJ Top Position MECoorX = xPos; MECoorY = yPos; $.post("process.php?proc=UPDATEMELOCATION", // NEW MEOBJ Location Update. { x:xPos, y:yPos, CliID:MEID, GameID:ThisGameID }); switch (e.which){ case 37: // LEFT Arrow Key if(MECoorX > 25) { $("#MEOBJ").finish().animate({ // IF Press Left Arrow Key MEOBJ LEFT : LEFT - 10px left: "-=10" }); } $("#MEOBJ").addClass('mirror'); break; case 39: //RIGHT Array Key if(MECoorX < 700) { $("#MEOBJ").finish().animate({// IF Press Right Arrow Key MEOBJ RIGHT : RIGHT + 10px left: "+=10" }); } $("#MEOBJ").removeClass('mirror'); break; } }); //CREATE AND CONTROL COIN setInterval(function(){ if(MEID > 0) { var CoinPosLeft; $.post("process.php?proc=GETCOIN", // GET Coin Position { CliID:MEID, GameID:ThisGameID }, function(data,status){ CoinPosLeft = data; // Coin Position var CoinID = Math.floor(Math.random() * 700); // Create Random Coin ID var Coin = $('<img id="Coin'+CoinID+'" class="coin" style="left:'+(CoinPosLeft)+'px;" src="assets/images/coin.gif"/>'); Coin.appendTo($('#gamecontent')); // Add NEW Coin on gamecontent. Coin.animate({ top: 650 }, { step: function(now, fx){ var CoinLeft = Coin.offset().left; // Coin Left Position var CoinTop = Coin.offset().top; // Coin Top Position if(CoinLeft + 20 > MECoorX && MECoorX + 20 > CoinLeft) { if(CoinTop + 20 > MECoorY && MECoorY + 20 > CoinTop) { Coin.remove(); // IF Coin Postion cross the Player position Coin Remove $.post("process.php?proc=UPDATEMYSCORE", // Update Player Score. { CliID:MEID, GameID:ThisGameID }); var OldScore = document.getElementById('MyScore').innerHTML; // Old Score document.getElementById('MyScore').innerHTML = parseInt(OldScore)+1; // Update MyScore div content Oldscore + 1 } } }, complete: function(){ Coin.remove(); // Coin finish animate : top position 650 coin remove. CoinLeft = 0; CoinTop = 0; }, duration:4000 }); }); } }, 1000); var e = jQuery.Event("keydown"); e.keyCode = 39; $(document).trigger(e); }); |
Şimdi gelelim game.js içerisinde bulunan kodlarımızın detaylarına ve ne işe yaradıklarına.
a.Global değişkenlerimizi oluşturuyoruz :
1 2 3 4 5 6 7 8 |
var Players = []; // Aktif oyuncuların tutulduğu değişken. var MECoorX = 0; // Bizim karakterimizin X pozisyonu. var MECoorY = 0; // Bizim karakterimizin Y pozisyonu. var MEID = 0; // Bizim karakterimizin ID'si. var ThisGameID = "1"; // Girdiğimiz oyunun ID'si. // Karakterimizin ID'sini ve pozisyonunu aşağıda giriş yapma ve yapmama(ziyaretçi) durumuna göre // güncelleyeceğiz. |
b.Kullanıcının giriş yaptığı zaman her seferinde kullanıcıadı ve şifre sormaması için kullandığımız çerez oluşturma ve çerez bilgisi çağırma fonksiyonları :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
function getCookie(cname) { var name = cname + "="; var decodedCookie = decodeURIComponent(document.cookie); var ca = decodedCookie.split(';'); for(var i = 0; i <ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } return ""; } function setCookie(cname, cvalue, exdays) { var d = new Date(); d.setTime(d.getTime() + (exdays*24*60*60*1000)); var expires = "expires="+ d.toUTCString(); document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; } |
c.Şimdi kullanıcımızın daha önceden giriş yapıp yapmadığını çerezler üzerinden kontolediyoruz ve eğer daha önce giriş yapmış ve çerez oluşturulmuşsa Kullanıcının kendi Kullanıcıadı ve ID sini gerekli değişkenlere atıyoruz eğer giriş yapılmamış ise kullanıcıya daha önceden veritabanında oluşturduğumuz bir ziyaretçi hesabı tanımlıyoruz :
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 |
// USER COOKIE CONTROL var UserCookie = getCookie("wwGameUser"); if(UserCookie != "") // IF Cookie ISSET { var UserCookieDataSplit = UserCookie.split("-"); // SPLIT COOKIE DATA var UserName = UserCookieDataSplit[0]; var Password = UserCookieDataSplit[1]; $.post("process.php?proc=LOGIN", // POST UserName and Password process.php?proc=LOGIN page { username:UserName, password:Password }, function(data,status){ if(data != "0") // Return data if not equals 0 Username and Password correct { var DataSplit = data.split("-"); // Split return User data. MEID = DataSplit[0]; // Update MEID document.getElementById("MyScore").innerHTML = DataSplit[1]; // Show MyScore div in user latest score. document.getElementById("login").style.display = "none"; // Hide User Login Box. document.getElementById("afterlogin").style.display = "block"; // Show Afterlogin Box. document.getElementById("usernameDiv").innerHTML = DataSplit[2]; // Change Afterlogin Username div content. setCookie("wwGameUser", UserName+"-"+Password, 2); }else{ alert("Username or Password Incorrect."); } }); }else{ // IF User not set cookie and not login set guest account this user. $.post("process.php?proc=ME", { GameID:ThisGameID }, function(data,status){ if(data == "FULL") // IF all guest account is used show message user screen "Guest Account FULL !" message and MEOBJ hidden. { alert("Guest Account FULL !"); document.getElementById("MEOBJ").style.display = "none"; }else{ if(MEID == 0) { MEID = data; } } }); } |
d.Ana Sayfamız olan game.html de bulunan Login butonuna basıldığında yapılacak işlemi tanımlayacağız, öncelikli olarak gelen verilerin boş olup olmadığını kontrol edioruz ve daha sonra gelen verileri process.php?proc=LOGIN sayfasına POST metodu ile yolluyoruz. process.php?proc=LOGIN sayfamızdan dönen değere göre işlemlerimizi gerçekleştiriyoruz. Eğer dönen değer 0 değilse gelen veriyi bölüp Oyuncumuzun ID numarası MEID değişkenini güncelliyoruz, daha sonra kullanıcının veritabanında kayıtlı olan skorunu tanımlıyoruz, giriş başarılı olduğu için Login kutumuzu gizleyip Afterlogin kutumuzu açıyoruz, en son ise 2 günlük bir çerez tanımlıyoruz. :
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 |
// LOGIN BUTTON CLICK $( "#loginBtn" ).click(function() { var UserName = document.getElementById('username').value; // Username INPUT Value var Password = document.getElementById('password').value; // Password INPUT Value if(UserName != "" && Password != "") // IF NOT EMPTY Username and Password Input { $.post("process.php?proc=LOGIN", // POST User data to process.php?proc=LOGIN page. { username:UserName, password:Password }, function(data,status){ if(data != "0") // IF Username and Password correct return data split. { var DataSplit = data.split("-"); MEID = DataSplit[0]; // UPDATE MEID document.getElementById("MyScore").innerHTML = DataSplit[1]; // Update MyScore latest score. document.getElementById("login").style.display = "none"; // Login box hide. document.getElementById("afterlogin").style.display = "block"; // Show Afterlogin box. document.getElementById("usernameDiv").innerHTML = DataSplit[2]; // Change Afterlogin Username div content. setCookie("wwGameUser", UserName+"-"+Password, 2); // Create Cookie 2 Days }else{ alert("Username or Password Incorrect."); } }); }else{ alert("Username or Password Empty!"); } }); |
e.Ana Sayfamızda bulunan Register butonuna basıldığında yapılacak işlemleri tanımlayacağız, ilk olarak gelen verilerin boşluk kontrolünü yapıyoruz, daha sonra gelen verileri process.php?proc=REGISTER sayfasına POST metodu ile yolluyoruz.Bu işlemin sonucunda dönen değere göre d. maddesinde ki işlemlerimizin aynısını yapıyoruz. :
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 |
// REGISTER BUTTON CLICK $( "#registerBtn" ).click(function() { var UserName = document.getElementById('username').value; // Username INPUT Value var Password = document.getElementById('password').value; // Password INPUT Value if(UserName != "" && Password != "") // IF NOT EMPTY Username and Password Input { $.post("process.php?proc=REGISTER", // POST Username and Password data process.php?proc=REGISTER page. { username:UserName, password:Password }, function(data,status){ if(data != "0") // IF register return data not equals 0 { MEID = data; // Update MEID. document.getElementById("MyScore").innerHTML = "0"; document.getElementById("login").style.display = "none"; // Login box hide. document.getElementById("afterlogin").style.display = "block"; // Show Afterlogin box. document.getElementById("usernameDiv").innerHTML = UserName; // Change Afterlogin Username div content. setCookie("wwGameUser", UserName+"-"+Password, 2); // Create Cookie 2 Days }else{ alert("Error."); } }); }else{ alert("Username or Password Empty!"); } }); |
f.Ana Sayfamızda bulunan LOGOUT butonuna bastığımız zaman kullanıcımızın çıkış yapması için gerekli işlemleri yazıyoruz, ilk olarak kullanıcımızın çerezini siliyoruz ve sayfa içeriğini yeniden yüklüyoruz. :
1 2 3 4 |
$( "#loginoutBtn" ).click(function() { // LOGOUT Button Click. setCookie("wwGameUser", UserName+"-"+Password, -1); // User Cookie Day -1. location.reload(); // Content Reload. }); |
g.Şimdi oyuncumuz oyunumuzu açtığı zaman her yarım saniyede bir process.php?proc=IMHERE sayfamızı çağırıyoruz, bu sayfada birazdan anlatacağım üzere veritabanına çağırıldığı zamanı saniye cinsinden yazan bir kod bloğu çalışmaktadır.Böylece Oyuncumuzun aktif olduğunu sürekli bildirmiş oluyoruz, eğer kullanıcımız oyundan çıkarsa işlem durmuş olacağı için inaktif olduğunu anlyacağız. :
1 2 3 4 5 6 7 8 9 10 |
setInterval(function(){ if(MEID > 0) { $.post("process.php?proc=IMHERE", // POST CliID to process.php?proc=IMHERE. { GameID:ThisGameID, CliID:MEID }); } }, 500); |
h.Aşağıdaki işlem ile de aktif olan kullanıcıları getireceğimiz ve #score id li divimizde anlık olarak göstereceğimiz kodumuz :
1 2 3 4 5 6 7 8 9 10 11 12 13 |
setInterval(function(){ // Show Dynamic Active User Score List on #score div content. if(MEID > 0) { $.post("process.php?proc=SCORE", { GameID:ThisGameID, CliID:MEID }, function(data,status){ $("#score").html(data); }); } }, 500); |
i.Şimdi ise Aktif olan kullanıcıları her 500 milisaniyede bir kontrol edip #gamecontent divimiz üzerinde o kullanıcıya ait karakteri oluşturmaya geldir. Her yeni kullanıcı giriş yaptığında ve aktif olduğunda bu kullanıcıya ait karakter ekranımıza gelecektir. Bunun için process.php?proc=ACTIVE sayfasını çağırıyoruz ve bu sayfaya POST metodu ile Oyuncumuzun ve Oyunumuzun ID’sini yolluyoruz. Dönen veriye göre #gamecontent divimize ekleyip aynı zamanda yukarıda global değişkenlerde belirttiğimiz Player değişkenine aktif kullanıcıların ID’nini tanımlıyoruz. :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
setInterval(function(){ if(MEID > 0) { $.post("process.php?proc=ACTIVE", { status:"New", GameID:ThisGameID, CliID:MEID }, function(data,status){ var ClientDetail = data.split("-"); // ACTIVE Players Data. for (ia = 0; ia < ClientDetail.length; ia++) { var ClientCheck = Players.indexOf(ClientDetail[ia]); if(ClientCheck < 0 && ClientDetail[ia] != "") { Players.push(ClientDetail[ia]); // Add Players varibles add Player ID $('#gamecontent').append('<img class="" id="PlayerObj'+ClientDetail[ia]+'" style="top:620px; postion:absolute; background:none; border:0px;" src="assets/images/char1_walk.gif"/>'); // ADD Active player character on #gamecontent. } } }); } }, 500); |
j.Yukarıda Aktif oyuncuları kontrol edip aktif olanları eklemiştik şimdi inaktif olanları kontrol edip eğer ekli iseler kaldıracağız :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
setInterval(function(){ if(MEID > 0) { $.post("process.php?proc=INACTIVE", { status:"New", GameID:ThisGameID, CliID:MEID }, function(data,status){ var ClientDetail = data.split("-"); // Inactive Player Data for (ia = 0; ia < ClientDetail.length; ia++) { var ClientCheck = Players.indexOf(ClientDetail[ia]); if(ClientCheck > -1 && ClientDetail[ia] != "") { Players = Players.filter(function(item) { return item !== ClientDetail[ia]; }); $('#PlayerObj'+ClientDetail[ia]+'').remove(); // Remove InActive Player. } } }); } }, 500); |
k.Yukarıda i maddesinde aktif olan kullanıcıları belirleyip nesne olarak eklemiştik. Şimdi ise aktif olan kullanıcıların pozisyonlarını her 100 milisaniyede bir kontrol edip oluşturduğumuz nesleri hareket ettireceğiz yani diğer oyuncular karakterlerini hareket ettirdikçe bizim ekranımızda da hareket edecekler.İlk olarak process.php?proc=PLAYERLOCATION sayfasından aktif kullanıcıların pozisyonları getireceğiz ve gelen veriyi parçalayıp ilgili nesneleri anlık olarak hareket ettireceğiz.Normal şartlar altında bu işlem direk veritabanından okumak yerine ara bir server yazılımı üzerinden kontrol edilir bu sayede oluşabilecek laglar donmaların ve yüksek kaynak kullanımının önüne geçilir.
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 |
var LastLocation = 0; setInterval(function(){ if(MEID > 0) { $.post("process.php?proc=PLAYERLOCATION", { CliID:MEID, GameID:ThisGameID }, function(data,status){ var ExpCliDetail = data.split("#"); for (ia = 0; ia < ExpCliDetail.length; ia++) { if(ExpCliDetail[ia] != "") { var ExpCliDetailLoc = ExpCliDetail[ia].split("-"); var ClientCheck = Players.indexOf(ExpCliDetailLoc[0]); if(ClientCheck + 1 > 0 ) { LastLocation = document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.left; if(LastLocation < ExpCliDetailLoc[1]) { document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.transform = "scale(1, 1)"; }else if(LastLocation > ExpCliDetailLoc[1]) { document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.transform = "scale(-1, 1)"; } document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.position = "absolute"; document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.top = ExpCliDetailLoc[2]+"px"; document.getElementById("PlayerObj"+ExpCliDetailLoc[0]+"").style.left = ExpCliDetailLoc[1]+"px"; } } } }); } }, 100); |
l.Bu adımda kendi karakterimizi sağ ve sol yön tuşları hareket ettirip, anlık olarak pozisyonumuzu process.php?proc=UPDATEMELOCATION sayfasına POST metodu ile yollayarak veritabanına kayıt edeceğiz.Tuşlara her basıldığında veya basılı tutulduğunda anlık olarak sağa veya sola 10px hareket ettireceğiz.
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 |
$(document).keydown(function(e){ var offset = $("#MEOBJ").offset(); var xPos = offset.left; // MEOBJ Left Position var yPos = offset.top; // MEOBJ Top Position MECoorX = xPos; MECoorY = yPos; $.post("process.php?proc=UPDATEMELOCATION", // NEW MEOBJ Location Update. { x:xPos, y:yPos, CliID:MEID, GameID:ThisGameID }); switch (e.which){ case 37: // LEFT Arrow Key if(MECoorX > 25) { $("#MEOBJ").finish().animate({ // IF Press Left Arrow Key MEOBJ LEFT : LEFT - 10px left: "-=10" }); } $("#MEOBJ").addClass('mirror'); break; case 39: //RIGHT Array Key if(MECoorX < 700) { $("#MEOBJ").finish().animate({// IF Press Right Arrow Key MEOBJ RIGHT : RIGHT + 10px left: "+=10" }); } $("#MEOBJ").removeClass('mirror'); break; } }); |
m.Son adımımıza geldik bu adımda Coinlerimizin anlık olarak oluşturulacak pozisyonlarını process.php?proc=GETCOIN sayfamızdan alıp ekranımızda oluşturuyoruz. Ana çerçevemizim yüksekliği 750 olduğu için biz coinlerimizi 650 pozisyonuna geldiği zaman eğer karakterimiz ile denk gelmediyse yok edeceğiz. Bir diğer noktada oluşturduğumuz coinlerin anlık olarak koordinatlarını alıp eğer bizim karakterimizin koordinatı ile çakışıyorsa coin bizim karakterimize denk geldiği zaman yok ediyoruz ve bizim mevcut skorumuza +1 ekliyoruz.
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 |
setInterval(function(){ if(MEID > 0) { var CoinPosLeft; $.post("process.php?proc=GETCOIN", // GET Coin Position { CliID:MEID, GameID:ThisGameID }, function(data,status){ CoinPosLeft = data; // Coin Position var CoinID = Math.floor(Math.random() * 700); // Create Random Coin ID var Coin = $('<img id="Coin'+CoinID+'" class="coin" style="left:'+(CoinPosLeft)+'px;" src="assets/images/coin.gif"/>'); Coin.appendTo($('#gamecontent')); // Add NEW Coin on gamecontent. Coin.animate({ top: 650 }, { step: function(now, fx){ var CoinLeft = Coin.offset().left; // Coin Left Position var CoinTop = Coin.offset().top; // Coin Top Position if(CoinLeft + 20 > MECoorX && MECoorX + 20 > CoinLeft) { if(CoinTop + 20 > MECoorY && MECoorY + 20 > CoinTop) { Coin.remove(); // IF Coin Postion cross the Player position Coin Remove $.post("process.php?proc=UPDATEMYSCORE", // Update Player Score. { CliID:MEID, GameID:ThisGameID }); var OldScore = document.getElementById('MyScore').innerHTML; // Old Score document.getElementById('MyScore').innerHTML = parseInt(OldScore)+1; // Update MyScore div content Oldscore + 1 } } }, complete: function(){ Coin.remove(); // Coin finish animate : top position 650 coin remove. CoinLeft = 0; CoinTop = 0; }, duration:4000 }); }); } }, 1000); |
game.js dosyamız bu kadar.
5.Adım Ana Dizinimizde veritabanı vb. işlemlerimizi yapacağımız process.php isminde bir dosya oluşturuyoruz, bu dosyamızda bulunan işlemler game.js de yaptığımız ve açıkladığımız işlemlerle ilgili veri işleme ve veri getirme görevini yapıyor game.js için olan açıklamaları takip ederek bu sayfada bulunan işlemler hakkında bilgi sahibi olabilirsiniz :
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 |
<?php try { $db = new PDO("mysql:dbname=VT_ADI;host=localhost","KULLANICIADI","ŞİFRE"); if($_GET["proc"] == "ME") { $SqlSorgusu = "SELECT * FROM client WHERE lastpingtime < '".(time()-10)."' and gameid = '".$_POST["GameID"]."' and usertype = 'guest'"; $st = $db->prepare($SqlSorgusu); $st->execute(); $Veriler = $st->fetchAll(PDO::FETCH_ASSOC); if(count($Veriler) > 0) { $stCli = $db->prepare("UPDATE `client` SET `point` = '0' WHERE `id` = '".$Veriler[0]["id"]."'"); $stCli->execute(); ECHO $Veriler[0]["id"]; }else{ ECHO "FULL"; } } if($_GET["proc"] == "LOGIN") { $SqlSorgusu = "SELECT * FROM client WHERE username = '".$_POST["username"]."' and password = '".$_POST["password"]."'"; $st = $db->prepare($SqlSorgusu); $st->execute(); $Veriler = $st->fetchAll(PDO::FETCH_ASSOC); if(count($Veriler) > 0) { ECHO $Veriler[0]["id"]."-".$Veriler[0]["point"]."-".$Veriler[0]["username"]; }else{ ECHO "0"; } } if($_GET["proc"] == "REGISTER") { $SqlSorgusu = "INSERT INTO `client`(`gameid`, `clix`, `cliy`, `point`, `lastpingtime`, `username`, `password`, `usertype`) VALUES ('1', '100', '628', '0', '0', '".$_POST["username"]."', '".$_POST["password"]."','user');"; $st = $db->prepare($SqlSorgusu); $st->execute(); $id = $db->lastInsertId(); if($id > 0) { return $id; }else{ return 0; } } if($_GET["proc"] == "IMHERE") { $SqlSorgusu = "UPDATE `client` SET `lastpingtime` = '".time()."' WHERE `id` = '".$_POST["CliID"]."'"; $st = $db->prepare($SqlSorgusu); $st->execute(); } if($_GET["proc"] == "GETCOIN") { $CoinLeftArray = array("15", "250", "500", "333", "95", "410", "550", "185", "600", "670"); $ArrIndex = time(); $ArrIndex = substr($ArrIndex, -1); ECHO $CoinLeftArray[$ArrIndex]; } if($_GET["proc"] == "SCORE") { $SqlSorgusu = "SELECT * FROM client WHERE lastpingtime > '".(time()-10)."'"; $st = $db->prepare($SqlSorgusu); $st->execute(); $Veriler = $st->fetchAll(PDO::FETCH_ASSOC); $VeriR = "<div class='col-sm-12'><img src='assets/images/active-users.png'></div><br /><hr />"; foreach($Veriler as $Veri) { if($_POST["CliID"] == $Veri["id"]) { $VeriR .= "<div class='row' style='padding-top:5px;'><div class='col-sm-3' style='padding-top:5px;'> <img src='assets/images/char1.png'; /> </div> <div class='col-sm-5'> <font style='color:green;'>YOU</font> </div> <div class='col-sm-4'>".$Veri["point"]."</div></div>"; }else{ $VeriR .= "<div class='row' style='padding-top:5px;'><div class='col-sm-3'> <img src='assets/images/char1.png'; /> </div> <div class='col-sm-5'> ".$Veri["username"]." </div> <div class='col-sm-4'>".$Veri["point"]."</div></div>"; } } ECHO $VeriR; } if($_GET["proc"] == "ACTIVE") { $SqlSorgusu = "SELECT * FROM client WHERE NOT (`id` = ".$_POST["CliID"].") and lastpingtime > '".(time()-10)."' and gameid = '".$_POST["GameID"]."'"; $st = $db->prepare($SqlSorgusu); $st->execute(); $Veriler = $st->fetchAll(PDO::FETCH_ASSOC); $VeriR = ""; foreach($Veriler as $Veri) { $VeriR .= $Veri["id"]."-"; } ECHO $VeriR; } if($_GET["proc"] == "INACTIVE") { $SqlSorgusu = "SELECT * FROM client WHERE NOT (`id` = ".$_POST["CliID"].") and lastpingtime < '".(time()-10)."' and gameid = '".$_POST["GameID"]."'"; $st = $db->prepare($SqlSorgusu); $st->execute(); $Veriler = $st->fetchAll(PDO::FETCH_ASSOC); $VeriR = ""; foreach($Veriler as $Veri) { $VeriR .= $Veri["id"]."-"; } ECHO $VeriR; } if($_GET["proc"] == "PLAYERLOCATION") { $SqlSorgusu = "SELECT * FROM client WHERE NOT (`id` = ".$_POST["CliID"].")"; $st = $db->prepare($SqlSorgusu); $st->execute(); $Veriler = $st->fetchAll(PDO::FETCH_ASSOC); $DonecekVeri = ""; foreach($Veriler as $Veri) { $DonecekVeri .= $Veri["id"]."-".$Veri["clix"]."-".$Veri["cliy"]."#"; } ECHO $DonecekVeri; } if($_GET["proc"] == "UPDATEMELOCATION") { $SqlSorgusu = "UPDATE `client` SET `clix` = '".$_POST["x"]."', `cliy` = '".$_POST["y"]."' WHERE `id` = '".$_POST["CliID"]."'"; $st = $db->prepare($SqlSorgusu); $st->execute(); } if($_GET["proc"] == "UPDATEMYSCORE") { $SqlSorgusu = "UPDATE `client` SET `point` = `point` + 1 WHERE `id` = '".$_POST["CliID"]."'"; $st = $db->prepare($SqlSorgusu); $st->execute(); } $db = null; }catch (PDOException $e) { "Error!: " . $e->getMessage() . "<br/>"; die(); } ?> |
6.Adım son olarak game.css dosyamızı /assets/css/ dizini altında oluşturuyoruz. Bu dosya içerisinde oyunumuzla ilgili çeşitli nesnelerin stil kodları bulunmaktadır.
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 |
#gamecontent{ width:750px; height:750px; border:1pxsolidwhite; background-image:url("../images/background.png"); float:left; } #MEOBJ { top:628px; left:50px; border:0px; position:absolute; } .rightbar { width:235px; height:750px; float:left; } #score{ height:400px; padding-top:10px; padding-left:15px; } #login{ height:250px; padding-top:10px; padding-left:15px; text-align:center; } #login>button { width:49%; } #afterlogin { height:250px; padding-top:10px; padding-left:15px; text-align:center; display:none; } #tips{ height:90px; padding-top:10px; padding-left:15px; } #wwphp{ width:750px; height:50px; font-size:25px; color:blue; text-align:center; float:none; padding:5px; } .mirror{ -moz-transform:scale(-1,1); -webkit-transform:scale(-1,1); transform:scale(-1,1); } .coin{ width:32px; height:32px; margin:0auto; position:absolute; top:0; } .MyScoreBoard { width:150px; height:30px; background-image:url('../images/score.png'); background-repeat:no-repeat; position:absolute; left:305px; top:15px; z-index:100; } .MyScoreBoard>img { position:absolute; top:-3px; left:10px; } .MyScoreBoard>.MyScore { position:absolute; left:40px; top:-1px; font-size:19px; font-weight:bold; color:yellow; font-family:monospace; } |
Dosyalarımız bu kadar. Diğer gerekli jQuery, Bootstrap vb. kütüphaneleri yazının başında verdiğim Github linki üzerinden indirebilirsiniz.
Soru, görüş ve sorunlarını yorum olarak yazarsanız cevaplarım.
tesekkurler guzel anlatim
Ben teşekkür ederim (:
güzel anlatımınız için teşekkürler peki şunu sormak istiyorum özel proje geliştirebilir misiniz oyun ile ilgili mail ile dönüşlerinizi bekliyorum
Merhaba,
Öncelikli olarak yorumunuz için teşekkür ederim.
Mail ile size geri dönüş sağladım.