Tworzenie gry przeglądarkowej – #7 Praca

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:

work table

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 statystykipracasklepwalka 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.

Spodobał Ci się artykuł? Dzięki naciśnięciu serduszka poniżej będę wiedział jakie treści tworzyć. Dzięki! :)

Jak zrobić chat Umbrella JS jako alternatywa dla jQuery? Jak zbudować chatbota dla Messengera w PHP #3 – Zaawansowane wiadomości
View Comments
Bądź pierwszą osobą, która skomentuje ten wpis.