W tej części kursu napiszemy system pracy, dzięki któremu gracz będzie mógł zarobić złoto aby móc je później wydać np. na podniesienie statystyk. Zaczynajmy 🙂
Na początku przejdźmy do bazy danych i stwórzmy nową tabelę o nazwie work.
Tabela work:
Możesz kliknąć na powyższy obrazek aby go powiększyć.
Tabela składa się z:
- id – unikalny identyfikator pracy
- uid – identyfikator pracującego użytkownika
- finish_date – czas zakończenia pracy podany w sekundach
- reward – nagroda w złocie
Jak będzie działał system pracy?
Gracz będzie wybierał na ile godzin chce iść do pracy (1-8). Jeśli podane w formularzu dane będą prawidłowe to do tabeli work zostanie dodany rekord zawierający id gracza, czas zakończenia zlecenia (aktualny czas uniksowy + ilość godzin pracy * 3600) oraz nagroda, która będzie zależna od ilości przepracowanych godzin. W tym samym momencie na stronie praca pojawi się licznik, który będzie odliczał pozostały czas pracy. Gracz otrzyma nagrodę gdy licznik dojdzie do zera. Jednocześnie zostanie skasowany rekord w tabeli work.
Przejdźmy teraz do pliku ModuleLoader.class.php i uzupełnijmy case praca oraz dodajmy nowy case – timer, który wyświetli wspomniany licznik.
Case praca:
case 'praca':
$select = DatabaseManager::selectBySQL("SELECT * FROM work WHERE uid={$_SESSION['uid']}");
if(!$select){
$form = '
<form>
<input type="number" name="hours" class="hours"
min="1" max="8" step="1" value="1"> <br />
<button type="button" id="u_'.$_SESSION['uid'].'">Pracuj</button>
</form>';
}
else {
$form = '';
}
echo '
<section class="content praca">
<div class="container">
<h2>Praca:</h2>
<div class="row">
'.$form.'
';
ModuleLoader::load('timer');
echo '
</div>
</div>
</section>
';
break;
Na początku wybieramy z tabeli work rekord, w którym id użytkownika jest równe numerowi id, który jest przechowywany w sesji. Jeśli nie zostanie znaleziony taki rekord to zmienna $select będzie przechowywała false. Tylko w tym przypadku możemy wyświetlić formularz odpowiedzialny za wysłanie do pracy, ponieważ można wykonywać tylko jedną pracę w tym samym czasie. Jeśli rekord zostałby znaleziony to za pomocą case timer wyświetlamy licznik.
Case timer:
case 'timer':
$select = DatabaseManager::selectBySQL("SELECT * FROM work WHERE uid={$_SESSION['uid']}");
if($select) {
foreach($select as $arr) {
$work = $arr;
}
$akt = time();
$finish = $work['finish_date'];
$wynik = $finish - $akt;
echo '<script>
var seconds = '.$wynik.';
function timer() {
var days = Math.floor(seconds/24/60/60);
var hoursLeft = Math.floor((seconds) - (days*86400));
var hours = Math.floor(hoursLeft/3600);
var minutesLeft = Math.floor((hoursLeft) - (hours*3600));
var minutes = Math.floor(minutesLeft/60);
var remainingSeconds = seconds % 60;
if (remainingSeconds < 10) {
remainingSeconds = "0" + remainingSeconds;
}
if (minutes < 10) {
minutes = "0" + minutes;
}
document.getElementById("countdown").innerHTML = hours + ":" + minutes + ":" + remainingSeconds;
if (seconds == 0) {
clearInterval(countdownTimer);
document.getElementById("countdown").innerHTML = "Zakończono! Odśwież stronę.";
} else {
seconds--;
}
}
var countdownTimer = setInterval("timer()", 1000);
</script>
<span id="countdown" class="timer"></span>
';
}
else {
echo '';
}
break;
Jeżeli gracz pracuje to obliczany jest czas do końca pracy. Następni wyświetlany jest kod javascript, który ten czas w sekundach konwertuje do godzin, minut i sekund oraz rozpoczyna odliczanie.
Dodajmy też kilka reguł CSS w pliku style.css:
#countdown {
font-size: 50px;
}
.hours {
width: 100px;
background: silver;
border-radius: 5px;
text-align: center;
}
.praca button {
width: 70px;
border-radius: 5px;
margin-top: 10px;
}
Możemy teraz przejść do stworzonej w poprzedniej części klasy GameManager i dodać metodę, która umieści w tabeli work rekord. Przed kończącym klasę znakiem } dodaj nową metodę:
public function sendToWork($UID, $TIME) {
if(isset($UID) && isset($TIME)) {
$select = DatabaseManager::selectBySQL("SELECT * FROM work WHERE uid={$UID}");
if($select) { //znaleziono już pracę
return false;
exit;
}
else {
$seconds = time() + ($TIME * 3600); //obliczenie czasu końca pracy
$reward = ($seconds / 1000000) * $TIME; //obliczenie nagrody
$res = DatabaseManager::insertInto("work", Array('uid' => ''.$UID.'',
'finish_date' => ''.$seconds.'',
'reward' => ''.$reward.''));
if($res) {
return true;
} else {
return false; //niepowodzenie, zwracamy false
}
}
} else {
return false; // zwracamy false
}
}
Ta metoda doda nowy rekord w tabeli work, pod warunkiem, że już go tam nie ma.
Stwórzmy teraz nowy plik w folderze LIBRARY o nazwie toWork.library.php. Będzie on odpowiadał za sprawdzenie przesyłanych przez użytkownika danych i wysłanie ich do metody sendToWork.
Plik toWork.library.php:
<?php
if((isset($_POST['user'])) && ($_POST['time'] >= 1 && $_POST['time'] <= 8)) { //walidacja przesłanych danych
$um = new GameManager;
$id = ltrim($_POST['user'], 'u_');
$time = intval($_POST['time']);
$res = $um->sendToWork($id, $time); //przesłanie tablicy do metody CreateUser w klasie UserManager
if($res) {
echo "success";
exit;
} else {
return 0;
}
} else {
return false;
}
?>
Plik jest bardzo podobny do pliku updateStats.library.php, który napisaliśmy w poprzedniej części. Jak zwykle musimy jeszcze dodać case do klasy MainPage:
case 'toWork':
require_once $this->active_page.".library.php";
break;
Przejdźmy teraz do pliku wlasny.js i dodajmy kod odpowiedzialny za obsłużenie formularza:
zmienna2 = $('.praca button').attr('id'); //pobranie id
$('.praca button').on('click', function() {
var element = $(this);
var uid = zmienna2; //przekazanie do zmiennej uid id użytkownika
var hours = $('.hours').val();
var posting = $.post( 'toWork/', { user: uid, time: hours } ); //wysłanie żądania z parametrami uid i time
posting.done(function( data ) { //po zakończeniu żądania
if(data != false){ //wysłano do pracy
location.reload(); //odświeżenie strony
}
else {
$.smkAlert({text: 'Możesz pracować od 1 do 8 godzin.', type:'danger'}); //wyświetlenie komunikatu o niepowodzeniu
}
});
});
Mamy już prawie wszystko. Pozostało nam jeszcze napisać metodę, która sprawdzi czy praca została zakończona, doda nagrodę i usunie rekord. Wróćmy do klasy GameManager i dodajmy kolejną metodę:
public function checkWorkStatus($UID) {
$akt = time();
$select = DatabaseManager::selectBySQL("SELECT * FROM work WHERE uid={$UID} AND finish_date<{$akt}"); //wybieramy tylko zakończone prace
if($select) {
$select2 = DatabaseManager::selectBySQL("SELECT * FROM stats WHERE id={$UID}");
foreach($select2 as $arr) {
$stats = $arr;
}
foreach($select as $arr){
$reward = $arr;
}
$update_gold = $stats['gold'] + $reward['reward']; //obliczenie dodanego złota
DatabaseManager::updateTable("stats", Array('gold' => ''.$update_gold.''), Array('id' => ''.$UID.'')); //dodanie złota
DatabaseManager::deleteFrom("work", array('uid' => ''.$UID.'')); //usunięcie rekordu
}
else {
return false;
exit;
}
}
Wywołajmy teraz tą metodę na stronach statystyki, praca, sklep, walka oraz ranking. Na tych podstronach zaraz pod instrukcją die dodaj poniższy kod.
$um = new GameManager;
$res = $um->checkWorkStatus($_SESSION['uid']);
Dzięki temu status pracy będzie aktualizowany.
I to tyle. Wszystko już działa 🙂
Paczkę możesz pobrać tutaj.
Zobacz przykład klikając tutaj.