Tworzenie gry przeglądarkowej – #8 Ekwipunek

W tej części poradnika pt. „Tworzenie gry przeglądarkowej” dodamy możliwość kupowania, zakładania i zdejmowania różnych przedmiotów. Zaczynajmy 🙂

Na początku przejdźmy do bazy danych i stwórzmy tabelę o nazwie items, która będzie przechowywała wszystkie przedmioty.

tabela items

Tabela składa się z sześciu kolumn. Są to:

  • id – unikalny identyfikator przedmiotu
  • uid – identyfikator właściciela przedmiotu
  • name – nazwa przedmiotu
  • defense – ilość obrony dodawanej przez przedmiot
  • attack – ilość ataku dodawanego przez przedmiot
  • is_equipped – przyjmuje wartość 0 dla przedmiotu aktualnie nie używanego lub 1 dla używanego

Tabela jest już gotowa. Możemy teraz przejść do klasy ModuleLoader i dodać nową metodę – loadItemsShop, która wyświetli przedmioty, które będą do kupienia w sklepie.

Pod zamykającą klamrą metody load dodaj następujący kod:

static public function loadItemsShop($item, $cena) {
            echo '
                <div class="item">
                                        
                <div class="col-xs-1 col-sm-2 col-md-3 col-lg-3">
                                        
                </div>
                                        
                                        
                <div class="col-xs-5 col-sm-4 col-md-3 col-lg-3">
                    <img src="images/sklep_'.$item.'.png" class="img-responsive">
                </div>
                                        
                <div class="col-xs-5 col-sm-4 col-md-3 col-lg-3">
                    <button class="sklep_'.$item.'">Kup <i>'.$item.' ('.$cena.')</i></button>
                </div>
                                                                        
                                        
                <div class="col-xs-1 col-sm-2 col-md-3 col-lg-3">
                                        
                </div>
                                        
                </div>
            ';      
}

Ta metoda przyjmuje w parametrach nazwę i cenę przedmiotu. Następnie wyświetla przedmiot w oparciu o te parametry. Wykorzystajmy od razu tą metodę w tej samej klasie i uzupełnijmy case sklep.

case 'sklep':
            
            echo '
                <section class="content sklep" id="u_'.$_SESSION['uid'].'">  	
                    <div class="container">        
                    	 <h2>Sklep:</h2>         
                         <div class="row">';
                            
            			   ModuleLoader::loadItemsShop('miecz', 75);   
                           ModuleLoader::loadItemsShop('tarcza', 50); 
            
                    	 echo '</div>
                  
                    </div>   
                </section>
            ';
            
break;

Korzystamy tutaj z wcześniej napisanej metody, aby wyświetlić przedmioty – miecz i tarczę.

Przejdźmy teraz do pliku style.css i dodajmy kilka nowych reguł:

.item {
    height: 100px;
    border: 1px #ccc solid;
    margin-bottom: 30px;
    margin-top: 10px;
}

.item img {
    float: right;
    margin-right: 20px;
}

.item button {
    width: 70%;
    height: 50px;
    border-radius: 5px;
    text-align: center;
    border: none;
    background: rgba(153,0,51,1);
    color: #fff;
    font-size: 18px; 
    float: left;
    margin-top: 25px;
}

Skoro mamy już strukturę HTML CSS to możemy przejść do napisania kodu PHP, który obsłuży kupowanie przedmiotów. Przejdźmy do klasy GameManager i dodajmy metodę o nazwie buyItem, która obsłuży kupowanie przedmiotów. Zamykającym znacznikiem metody checkWorkStatus dodajmy następujący kod:

public function buyItem($UID, $NAME, $PRICE, $DEFENSE, $ATTACK) {
        
     
                $select = DatabaseManager::selectBySQL("SELECT * FROM stats WHERE id={$UID} AND gold>{$PRICE}"); //sprawdzenie czy użytkownik ma wystarczająco złota
                
                
                
                if($select) { //ma wystarczająco
                       
                    foreach($select as $arr) {
                        $stats = $arr;
                    }
                        
                    $update_gold = $stats['gold'] - $PRICE; //obliczenie złota po kupieniu przedmiotu
                     
                    DatabaseManager::updateTable("stats", Array('gold' => ''.$update_gold.''), Array('id' => ''.$UID.'')); //odjęcie złota z konta gracza
                        
                    $res = DatabaseManager::insertInto("items", Array('uid' => ''.$UID.'',
                                                                        'name' => ''.$NAME.'',
                                                                        'defense' => ''.$DEFENSE.'',
                                                                        'attack' => ''.$ATTACK.'',
                                                                        'is_equipped' => '0'      
                                                                        )); //dodanie przedmiotu do tabeli items
                    if($res) {
                        return true;                                                  
                    }
                        
                    else {
                        return false;
                    }
                  
                } //brakuje złota
                
                else {
                    return false;
                    exit;
                }                                                                       
    }

Cała metoda jest dosyć prosta. Dodałem kilka komentarzy, aby wszystko było bardziej zrozumiałe.

Przejdźmy teraz do pliku wlasny.js i dodajmy kod, który wyśle żądanie:

 zmienna3 = $('.sklep').attr('id'); //pobranie id
 
 function buyItem(UID, NAME, PRICE, DEFENSE, ATTACK){
        $('.sklep_' + NAME).on('click', function() {
        var element = $(this);
       
        var posting = $.post( 'buyItem/', { user: UID, name: NAME, price: PRICE, defense: DEFENSE, attack: ATTACK } ); //wysłanie żądania
       
        posting.done(function( data ) { //po zakończeniu żądania
            if(data != false){  //kupiono przedmiot
                $.smkAlert({text: 'Kupiono przedmiot.', type:'success'}); //wyświetlenie komunikatu o powodzeniu
            }
            else {
                
                $.smkAlert({text: 'Nie masz wystarczająco złota.', type:'danger'}); //wyświetlenie komunikatu o niepowodzeniu
            }
      });   
     });
 }
 
 buyItem(zmienna3, 'miecz', 75, 0, 10);
 buyItem(zmienna3, 'tarcza', 50, 5, 0);

Żądanie zostaje przesłane do pliku buyItem.library.php.  Utwórzmy go teraz wewnątrz folderu LIBRARY.

Plik buyItem.library.php:

<?php

if(isset($_POST['user']) && isset($_POST['name']) && isset($_POST['price']) && isset($_POST['defense']) && isset($_POST['attack'])) {
    
   $um = new GameManager;
      
      $id = ltrim($_POST['user'], 'u_'); 
      
      $res = $um->buyItem($id, $_POST['name'], $_POST['price'], $_POST['defense'], $_POST['attack']); 
      
      if($res) {
          echo "success";
          exit;
      } else {     
          return 0;    
      }
 
    
} else {
   return false;
}

?>

Pamiętajmy jeszcze o dodaniu kolejnego case wewnątrz klasy MainPage:

case 'buyItem':
      require_once $this->active_page.".library.php";
break;

Gracz ma już możliwość kupowania przedmiotu 🙂

Powinniśmy teraz pomyśleć nad miejscem gdzie gracz będzie mógł przejrzeć zdobyte przedmioty i z nich korzystać. Moglibyśmy np. dodać nową stronę o nazwie Ekwipunek i tam wyświetlić przedmioty gracza. Możesz tak zrobić. Ja po prostu zrobię to na stronie ze statystykami.

Przejdźmy do klasy ModuleLoader i dodajmy kolejną metodę, która wyświetli listę posiadanych przedmiotów. Zaraz pod wcześniej napisaną metodą, dodaj kolejną:

static public function loadItemsEquipment($item, $defense, $attack, $is_equipped, $item_id) {
            echo '
                <div class="item">
                                        
                <div class="col-xs-1 col-sm-2 col-md-3 col-lg-3">
                                        
                </div>
                                        
                                        
                <div class="col-xs-5 col-sm-4 col-md-3 col-lg-3">
                    <img src="images/sklep_'.$item.'.png" class="img-responsive">
                </div>
                                        
                <div class="col-xs-5 col-sm-4 col-md-3 col-lg-3">';
                
                if($is_equipped == 0) {
                    echo '<button name="'.$item_id.'" class="equip_'.$item.'">Załóż <i>'.$item.' ('.$attack.' AT, '.$defense.' OB)</i></button>';
                }    
                else {    
                    echo '<button name="'.$item_id.'" class="takeoff_'.$item.'">Zdejmij <i>'.$item.' ('.$attack.'AT, '.$defense.'OB)</i></button>';
                }

                echo '</div>
                      
                <div class="col-xs-1 col-sm-2 col-md-3 col-lg-3">
                                        
                </div>
                                        
                </div>
            ';      
}

Metoda loadItemsEquipment różni się trochę od loadItemsShop. Posiada ona parametry, które ułatwią wyświetlenia informacji o przedmiocie. Użyjmy jej teraz wewnątrz case statystyki:

case 'statystyki':
             $select = DatabaseManager::selectBySQL("SELECT * FROM stats WHERE id={$_SESSION['uid']}");
             foreach($select as $arr) {
                $stats = $arr;
             }

            echo '
                <section class="content statystyki">  	
                    <div class="container">        
                    	 <h2>Statystyki:</h2>         
                         
                         <div class="row">
                            
                            <ul class="ul" id="u_'.$_SESSION['uid'].'">
                                <li><img src="images/punkty.png">Punkty: <span>'.$stats['points'].'</span></li>
                                <li><img src="images/serce.png">Życie: <span>'.$stats['hp'].'</span> <button class="add" name="hp" type="button"><img src="images/dodaj.png"></button></li>
                                <li><img src="images/miecz.png">Atak: <span>'.$stats['attack'].'</span> <button class="add" name="attack" type="button"><img src="images/dodaj.png"></button></li>
                                <li><img src="images/tarcza.png">Obrona: <span>'.$stats['defense'].'</span> <button class="add" name="defense" type="button"><img src="images/dodaj.png"></button></li>
                                <li><img src="images/zloto.png">Złoto: <span id="zloto">'.$stats['gold'].'</span> </li>
                            </ul>
                            <div id="result"></div>
                    	 </div>
                         
                         <div class="row">
                            <h2>Ekwipunek:</h2>';
                            $select2 = DatabaseManager::selectBySQL("SELECT * FROM items WHERE uid={$_SESSION['uid']}");
                            
                            if($select2) {
                                foreach($select2 as $item) {                      
                                 ModuleLoader::loadItemsEquipment($item['name'], $item['defense'], $item['attack'], $item['is_equipped'], $item['id']);
                                }
                            }
                             else {
                                echo '<h3>Nie masz żadnych przedmiotów.</h3>';
                             }
                               
                    	echo '</div>
                  
                    </div>   
                </section>
            ';
break;

Został dodany tylko jeden div o klasie rowWewnątrz niego korzystamy z napisanej wcześniej metody i wyświetlamy posiadane przez gracza przedmioty.

Wróćmy teraz do klasy GameManager i dodajmy dwie nowe metody, odpowiadające za ubieranie i ściąganie ekwipunku.

public function equipItem($UID, $ITEM_ID, $NAME) {
        
     
                $select = DatabaseManager::selectBySQL("SELECT * FROM items WHERE is_equipped=1 AND name='".$NAME."' AND uid={$UID}"); //sprawdzenie czy przedmiot tego typu nie jest już założony
                
                
                
                if(!$select) { //można założyć
                 
                    
                         
                  $res = DatabaseManager::updateTable("items", Array('is_equipped' => '1'), Array('id' => ''.$ITEM_ID.'')); //założenie przedmiotu
                        
   
                    if($res) {
                        return true;                                                  
                    }
                        
                    else {
                        return false;
                    }
                  
                }
                
                else {
                    return false;
                    exit;
                }                                                                       
}
    
public function takeOffItem($UID, $ITEM_ID, $NAME) {
        
     
                $select = DatabaseManager::selectBySQL("SELECT * FROM items WHERE is_equipped=1 AND name='".$NAME."' AND uid={$UID}"); //sprawdzenie czy przedmiot jest założony
                
                
                
                if($select) { //można zdjąć
                 
                    
                         
                  $res = DatabaseManager::updateTable("items", Array('is_equipped' => '0'), Array('id' => ''.$ITEM_ID.'')); //zdjęcie przedmiotu
                        
   
                    if($res) {
                        return true;                                                  
                    }
                        
                    else {
                        return false;
                    }
                  
                }
                
                else {
                    return false;
                    exit;
                }                                                                       
}

Całość została opisana komentarzami. Pierwsza metoda sprawdza czy nie jest już ubrany podobny przedmiot (bo przecież nie chcemy aby gracz mógł ubrać kilka mieczy). Druga metoda odpowiada za ściągnięcie przedmiotu.

Dodajmy teraz w pliku wlasny.js instrukcje odpowiedzialne za wysłanie żądania założenia/zdjęcia przedmiotu:

function manageItem(UID, NAME, ACTION){
        $('.' + ACTION + '_' + NAME).on('click', function() {
        var element = $(this);
        var ITEM_ID = element.attr('name');
        var posting = $.post( 'ekwipunek/', { user: UID, name: NAME, action: ACTION, id: ITEM_ID } ); //wysłanie żądania z parametrami
       
        posting.done(function( data ) { //po zakończeniu żądania
            if(data != false){  //powodzenie
                location.reload();
            }
            else {
                
                $.smkAlert({text: 'Nie możesz tego teraz zrobić.', type:'danger'}); //wyświetlenie komunikatu o niepowodzeniu

    
            }
      });   
     });
 }
 
  manageItem(zmienna, 'miecz', 'equip');
  manageItem(zmienna, 'tarcza', 'equip');
 
  manageItem(zmienna, 'miecz', 'takeoff');
  manageItem(zmienna, 'tarcza', 'takeoff');

Funkcja manageItem realizuje jednocześnie zakładanie i zdejmowanie przedmiotów. Utwórzmy teraz plik ekwipunek.library.php, w którym obsłużymy wysłane z poziomu Javascriptu żądanie.

Plik ekwipunek.library.php:

<?php

if(isset($_POST['user']) && isset($_POST['name']) && isset($_POST['action']) && isset($_POST['id'])) {
    
   $um = new GameManager;
      
      $id = ltrim($_POST['user'], 'u_'); 
      
      
      if($_POST['action'] == 'equip') {
        $res = $um->equipItem($id, $_POST['id'], $_POST['name']); 
      }
      elseif($_POST['action'] == 'takeoff') {
        $res = $um->takeOffItem($id, $_POST['id'], $_POST['name']);
      }
      
      
      if($res) {
          echo "success";
          exit;
      } else {     
          return 0;    
      }
 
    
} else {
   return false;
}

?>

W zależności od parametru ACTION z funkcji manageItem odwołujemy się do odpowiednich metod. Dodajmy jeszcze kolejny case w klasie MainPage:

case 'ekwipunek':
     require_once $this->active_page.".library.php";
break;

I to wszystko. Gracz może już kupować, zakładać i zdejmować przedmioty.

Przykład możesz zobaczyć tutaj.

Paczkę możesz pobrać tutaj.

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

10 przydatnych bibliotek PHP – luty 2017 Jak zrobić chat Jak zbudować chatbota dla Messengera w PHP #2 – Nawiązanie komunikacji
View Comments
Bądź pierwszą osobą, która skomentuje ten wpis.