I noticed your "I'm still really new to Perl ..." so I'm guessing a CPAN contribution
wasn't really what you were looking at. This makes the answer to "Is it okay for me to have an empty namespace (Roleplay) and go straight for Roleplay::Player or Roleplay::Goblin?"
a more straightforward YES!
You can have these:
/path/to/perl/mods/Roleplay/Player.pm
/path/to/perl/mods/Roleplay/Goblin.pm
without needing to have this:
/path/to/perl/mods/Roleplay.pm
You may still want a top-level Roleplay class but it's not a requirement of Perl.
In terms of tutorials, I'd suggest going to Perldoc
and looking under GETTING HELP - Tutorials.
perlboot, perltoot, perltooc and perlbot are all
directly related to Perl OO programming.
perlfaq2 - Obtaining and Learning about Perl lists many resources you'll
probably find useful.
Scrolling down a bit further, you'll see Reference Manual which links to a large
amount of documentation including OO topics such as perlmod and perlobj.
I recommend you bookmark Perldoc and refer to it often.
Regarding graphics, take a look at CPAN.
The Graphics and User Interfaces sections should probably be your first
ports of call.
You can post your code to, ask questions of and seek advice from PerlMonks at any time.
Perlmonks FAQ describes how to do these things.
In general, a clearly written question with examples of what you've already tried
(including appropriate output, particularly error messages) will be far better received
than a "it didn't work" or "please write this for me" type posting.
| [reply] [d/l] [select] |
This layout -- Roleplay::Goblin -- will break down very quickly. Consider the Monster Manual, for example. Then the Fiend Folio. Then the Monster Manual 2. Then custom monsters from modules... And you've already got a couple thousand .pm files in a single directory. Not fun to edit or maintain.
You want to abstract it more. MyRPG::NPC or something. Then it can have basic attributes like hit points, damage taken, and alignment; and roles (see Moose for ideas there) for things like "magic (spell list)," "flight," "healing," et cetera. NPCs could then be built from configuration which would be much easier to maintain, write, and generate on the fly.
| [reply] [d/l] [select] |
So you think Roleplay::NPC would be sufficient? I'll do a few characters as objects just to get the game going as well as get used to perl objects- i'll move on afterwards.
| [reply] [d/l] |
I definitely think it could be. It's a design decision, of course, and however you prefer to code is the best way at first.
Here's a what might be a better analogy: file types. You could definitely have a Perl module family for them where you had FileType::Text, FileTypeXML, FileType::Executable::Perl, etc but you'd end up with way too many, obviously, and then you'd also end up stuck trying to accommodate data types that are half-in-half-out of filedom, FileType::ApplicationVnds, FileType::OctectStream...
When you consider that, MIME::Types is obviously superior and a natural partner for whatever specific datastore (file, scalar, stream, db record) or parser.
And since you happened to have hit something I'm interested in, here's a prototype to see one way it could be done. I left out Moose roles and traits as they get kinda hairy. This has some idiomatic Perl in it but also a nice terse tour of some really cool nooks.
# ---------------- path/to/lib/MyRPG.pm
package MyRPG;
our $VERSION = "0.01";
use MyRPG::Die;
use MyRPG::NPC;
# ---------------- path/to/lib/MyRPG/Die.pm
package MyRPG::Die;
use Moose;
use Moose::Util::TypeConstraints;
has "sides" =>
is => "ro",
isa => enum([qw( 4 6 8 12 20 100 )]),
required => 1,
;
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
if ( @_ == 1 && ! ref $_[0] ) {
return $class->$orig(sides => $_[0]);
}
else {
return $class->$orig(@_);
}
};
sub roll {
int(rand(+shift->sides))+1;
}
__PACKAGE__->meta->make_immutable;
1;
# ---------------- path/to/lib/MyRPG/NPC.pm
package MyRPG::NPC;
use Moose;
has [qw( name type )] =>
is => "ro",
isa => "Str",
required => 1,
;
has "hitdice" =>
is => "rw",
isa => "ArrayRef[MyRPG::Die]",
required => 1,
auto_deref => 1,
;
has "hitpoints" =>
is => "ro",
isa => "Int",
default => sub {
my $hitpoints;
$hitpoints += $_->roll for +shift->hitdice;
return $hitpoints;
},
lazy => 1,
;
has "current_hitpoints" =>
is => "rw",
isa => "Int",
default => sub {
+shift->hitpoints;
},
lazy => 1,
;
sub damage { # This would be trait/role/type/armor/alignment influence
+d!
my $self = shift;
my $attack = shift; # Should be an object, we'll just call it raw
+points.
$self->current_hitpoints( $self->current_hitpoints - $attack );
}
sub dump {
my $self = shift;
my $line = "-"x50;
sprintf("%s\n%20s -> %s (%dhp)\n current hitpoints: %d (%s)\n%s\n"
+,
$line,
$self->name, $self->type, $self->hitpoints,
$self->current_hitpoints, $self->status,
$line);
}
sub status {
my $self = shift;
$self->current_hitpoints <= 0 ?
"dead" : ( $self->current_hitpoints < $self->hitpoints * .3 )
+?
"not so hot..." : ( $self->current_hitpoints < $self->hitpoint
+s * .8 ) ?
"s'okay" : $self->current_hitpoints != $self->hitpoints ?
"tip top" : "never better";
}
__PACKAGE__->meta->make_immutable;
1;
# ------------------- some test code in a regular executable
use warnings;
use strict;
use MyRPG;
my $six_sided = MyRPG::Die->new(6);
print "Warming up the bones... test roll $_: ", $six_sided->roll, $/ f
+or 1 .. 3;
my $npc = MyRPG::NPC->new( name => "CmdrTaco",
type => "SwampYankee",
hitdice => [ ( $six_sided ) x 3 ] );
print $npc->dump;
my $dodecahedron = MyRPG::Die->new(12);
print "Take that, ", $npc->name, $/;
$npc->damage( $dodecahedron->roll );
print $npc->dump;
Sample output-
Warming up the bones... test roll 1: 5
Warming up the bones... test roll 2: 2
Warming up the bones... test roll 3: 4
--------------------------------------------------
CmdrTaco -> SwampYankee (16hp)
current hitpoints: 16 (never better)
--------------------------------------------------
Take that, CmdrTaco
--------------------------------------------------
CmdrTaco -> SwampYankee (16hp)
current hitpoints: 6 (s'okay)
--------------------------------------------------
I'm kinda glad I am out of time today. This probably would have eaten up a few hours. :) As it is, that took me almost exactly 30 minutes to put together (I have an RPG background though, obviously). Viva la Perl!
| [reply] [d/l] [select] |