Reputation: 3050
I am looking at Should I use multiple classes for game? - Robert Pitt's answer.
interface Weapons {
public function Fire();
}
class Colt implements Weapons {
function Fire() {
echo 'Fire!';
}
}
abstract class Human implements Colt
{
}
class Sniper extends Human
{
public function __construct()
{
}
}
On the "Human" am I perhaps to implement the "Weapons" rather then Colt, and then on the "Sniper" initialize the Right weapon class?
class Sniper extends Human
{
public $weapon;
public function __construct($weapon)
{
$this->weapon = new $weapon;
}
$this->weapon->fire();
}
Or something like that? I am confused of how it works..
EXAMPLE 1
class A {
public $class;
__construct() {
$this->class = new $class;
}
hello() {
$this->class->hello();
}
}
class B {
public function hello() {
echo 'hi';
}
}
Upvotes: 2
Views: 5007
Reputation: 12244
On my side i would instead use these classes:
Interface iWeapon {}
Interface iAttacker {}
Interface iAttackable {}
Class Human Implements iAttacker, iAttackable {}
Class RangedWeapon Implements iWeapon {}
Class Colt extends RangedWeapon {}
Class M4AA extends RangedWeapon {}
Class Sniper extends RangedWeapon {}
Class Shotgun extends RangedWeapon {}
Let me explain them now:
iWeapon
Describes a weapon, the different getters, setters and a few actions such as DoDamage() or GetRandomAttackDamage(). Its as you wish. This interface allows you to define a weapon'S basics. You could apply this to the Weapon class or any other class that derives it, but i'd keep it to at least one basic class. The goal of the interface is to force all weapons to addopt the same behavior, it has attack damage, range, maybe charges? (Ammo)
iAttacker / iAttackable
Describes something that can attack or be attacked. These interfaces will usually provide functions that determine the ability to attack (is it stunned, immobilized, disabled?) or be attacked (invisible, invincible?) and provide functions to attack the other implementation. Humans or any other creature will implement these to say, HEY, i CAN attack AND be attacked. This interface would also provide getters and setters to control the weapons these creatures carry, maybe armors to prevent damage to them?
About interfaces
Remember always that classes represent something RELATIVELY concrete. If you are naming your class "Attacker" or "Target" you might be missing the point of a class. A class and object representing something tangible. In the other way around Interfaces represent actions or roles that classes may take. They only specify what one can do, they don't provide the implementation per se, they tell what that object will implement and thus DECLARE what they can do.
Hope this helps :)
Regarding the correct implementation of properties here is what i suggest:
class Player implements iAttacker, iAttackable {
protected $playerClass;
protected $race;
protected $weapon;
protected $armor;
public function setClass(playerClass $class){
$this->playerClass = $class;
}
public function getClass(){
return $this->playerClass;
}
public function setRace(race $race){
$this->race = $race;
}
public function getRace(){
return $this->race;
}
public function setWeapon(damagingGear $weapon){
$this->weapon = $weapon;
}
public function getWeapon(){
return $this->weapon;
}
public function setArmor(protectiveGear $armor){
$this->armor = $armor;
}
public function getArmor(){
return $this->armor;
}
public function attack(iAttackable $target){
//Check we can attack
if(!$this->canAttack()){ //Check we are not immobilized or disabled
throw new CannotAttackException($this->getNonAttackingReason());
}elseif(!$this->weapon->canFire()){
throw new CannotAttackException($this->weapon->getNonFireableReason());
}
//We can attack, roll the damage
if($target->isAttackable()){
$target->sufferDamage($this->weapon->rollDamage()+$this->race->getRangedDamageBonus());
}else{
thrown new CannotBeAttackedException($target->getNonAttackableReason());
}
}
}
Upvotes: 5
Reputation: 10529
It's up to you, how will you design your classes.
If I would be a game programmer, I'd probably use something like (it's a working minigame!)
<?php
class Fight {
public $weapon;
public $name;
public function __construct($weapon, $name)
{
$this->name = $name;
$this->weapon = new $weapon;
}
public function fire($person) {
$this->weapon->fire($person);
}
public function changeWeapon($weapon) {
$this->weapon = new $weapon;
}
}
class Sniper extends Fight { }
class Terrorist extends Fight { }
class MauserSniper {
function fire($person) {
echo "Firing $person->name! Miss! Your rifle is damaged<br />";
}
}
class AK47 {
function fire($person) {
echo "Firing $person->name! Hit with AK47!<br />";
}
}
class SteyrSSG {
function fire($person) {
echo "Firing $person->name! Hit!<br />";
}
}
$sniper1 = new Sniper("MauserSniper", "Martin");
$sniper2 = new Sniper("SteyrSSG", "Daniel");
$terrorist = new Terrorist("AK47", "Mike");
$sniper1->fire($sniper2); //we'll miss this one.
$sniper1->changeWeapon("SteyrSSG");
$sniper1->fire($sniper2); //hit!
$terrorist->fire($sniper1);
Upvotes: 5
Reputation: 2042
I would avoid having the Human class implement anything to do with the Weapons. Implementations define which methods a class must define, but don't deal with properties of the class.
Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled. (PHP Documentation: Object Interfaces)
Class Human {}
Class Sniper extends Human{
public $weapon
}
Interface Weapons {
public function fire()
}
Class Colt implements Weapons {}
Class Bazooka implements Weapons {}
Thus a Sniper is a Human (but with a $weapon property), and a Colt, Bazooka etc all implement the Weapons interface (forcing them to define a fire() function.
Upvotes: 2