Created
September 15, 2009 14:41
-
-
Save kthakore/187332 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use strict; | |
use warnings; | |
use Data::Dumper; | |
use Readonly; | |
Readonly my $DIRECTION_UP => 0; #rotates blocks | |
Readonly my $DIRECTION_DOWN => 1; #rotates blocks other way | |
Readonly my $DIRECTION_LEFT => 2; # move left | |
Readonly my $DIRECTION_RIGHT => 3; # move right | |
our $frame_rate = 0; | |
our $time = time; | |
our ( $EDEBUG, $KEYDEBUG, $GDEBUG ) = @ARGV; #Event and key debug | |
#Event Super Class | |
package Event; | |
use Class::XSAccessor accessors => { name => 'name', }; | |
sub new { | |
my $class = shift; | |
my $self = {}; | |
bless $self, $class; | |
$self->name("Generic Event"); | |
return $self; | |
} | |
package Event::Tick; | |
use base 'Event'; | |
sub new { | |
my $class = shift; | |
my $self = $class->SUPER::new(); | |
$self->name('CPU Tick Event'); | |
return $self; | |
} | |
package Event::Quit; | |
use base 'Event'; | |
sub new { | |
my $class = shift; | |
my $self = $class->SUPER::new; | |
$self->name('Program Close Event'); | |
return $self; | |
} | |
package Event::GridBuilt; #Tetris has a grid | |
use base 'Event'; | |
use Class::XSAccessor accessors => { grid => 'grid', }; | |
sub new { | |
my $class = shift; | |
my $self = $class->SUPER::new(); | |
$self->name('Grid Built Event'); | |
return $self; | |
} | |
package Event::GameStart; | |
use base 'Event'; | |
use Class::XSAccessor accessors => { game => 'game', }; | |
sub new { | |
my $class = shift; | |
my $self = $class->SUPER::new; | |
$self->name('Game Start Event'); | |
return $self; | |
} | |
package Request::CharactorMove; | |
use base 'Event'; | |
use Class::XSAccessor accessors => { direction => 'direction', }; | |
sub new { | |
my $class = shift; | |
my $self = $class->SUPER::new; | |
$self->name('Charactor Move Request'); | |
return $self; | |
} | |
package Event::CharactorPlace; | |
use base 'Event'; | |
use Class::XSAccessor accessors => { charactor => 'charactor', }; | |
sub new { | |
my $class = shift; | |
my $self = $class->SUPER::new; | |
$self->name('Charactor Place Event'); | |
return $self; | |
} | |
package Event::CharactorMove; | |
use base 'Event'; | |
use Class::XSAccessor accessors => { charactor => 'charactor', }; | |
sub new { | |
my $class = shift; | |
my $self = $class->SUPER::new; | |
$self->name('Charactor Move Event'); | |
return $self; | |
} | |
#--------------------------- | |
package Event::Manager; | |
use Data::Dumper; | |
sub new { | |
my $class = shift; | |
my $self = { | |
listeners => {}, | |
evt_queue => [], | |
}; | |
bless $self, $class; | |
return $self; | |
} | |
sub listeners : lvalue { | |
return shift->{listeners}; | |
} | |
sub evt_queue : lvalue { | |
return shift->{evt_queue}; | |
} | |
# | |
# so now you can access them like: | |
# $object->listeners->{foo} = 'bar'; | |
# my $listener = $object->listeners->{foo}; # $listener gets 'bar' | |
# | |
# $object->evt_queue->[0] = 'baz'; | |
# I think you can even do: | |
# push @{$object->evt_queue}, 'bla'; | |
# my $event = $objetc->evt_queue->[0]; # $event gets 'baz' | |
# from the code below I see you don't want the user | |
# to interact directly with ->listeners, or do you? | |
sub reg_listener { | |
my ( $self, $listener ) = (@_); | |
$self->listeners->{$listener} = $listener | |
if defined $listener; | |
return $self->listeners->{$listener}; | |
} | |
sub un_reg_listener { | |
my ( $self, $listener ) = (@_); | |
if ( defined $listener ) { | |
return delete $self->listeners->{ \$listener }; | |
} | |
else { | |
return; | |
} | |
} | |
sub post { | |
my $self = shift; | |
my $event = shift if (@_) or die "Post needs a TickEvent"; | |
print 'Event' . $event->name . "notified\n" if $EDEBUG; | |
die "Post needs a TickEvent as parameter" | |
unless $event->isa('Event'); | |
foreach my $listener ( values %{ $self->listeners } ) { | |
$listener->notify($event); | |
} | |
$frame_rate++; | |
my $elapsed_time = time - $time; | |
if ( $elapsed_time > 2 ) { | |
$frame_rate = ($frame_rate/2); | |
print "Frames per second: $frame_rate\n"; | |
$frame_rate = 0; | |
$time = time; | |
} | |
} | |
package Controller::Keyboard; | |
use Class::XSAccessor accessors => | |
{ event => 'event', evt_manager => 'evt_manager' }; | |
use SDL; | |
use SDL::Event; | |
use Scalar::Util qw(weaken); | |
sub new { | |
my ( $class, $event ) = (@_); | |
my $self = {}; | |
bless $self, $class; | |
die 'Expects an Event::Manager' | |
unless defined $event && $event->isa('Event::Manager'); | |
$self->evt_manager($event); | |
my $weak_self = $self; | |
weaken($weak_self); | |
$self->evt_manager->reg_listener($weak_self); | |
return $self; | |
} | |
sub notify { | |
print "Notify in C::KB \n" if $EDEBUG; | |
my ( $self, $event ) = (@_); | |
if ( defined $event and $event->isa('Event::Tick') ) { | |
#if we got a tick event that means we are starting | |
#a new iteration of game loop | |
#so we can check input now | |
my $event_to_process = undef; | |
$self->event( SDL::Event->new ); | |
$self->event->pump; #get events from SDL queue | |
$self->event->poll; #get the first one | |
my $event_type = $self->event->type; | |
$event_to_process = Event::Quit->new if $event_type == SDL_QUIT; | |
if ( $event_type == SDL_KEYDOWN ) { | |
my $key = $self->event->key_name; | |
print $key. " pressed \n" if $KEYDEBUG; | |
#This process the only keys we care about right now | |
#later on we will add more stuff | |
$event_to_process = Event::Quit->new | |
if $key =~ 'escape'; | |
$event_to_process = Request::CharactorMove->new($DIRECTION_UP) | |
if $key =~ 'up'; | |
$event_to_process = Request::CharactorMove->new($DIRECTION_DOWN) | |
if $key =~ 'down'; | |
$event_to_process = Request::CharactorMove->new($DIRECTION_LEFT) | |
if $key =~ 'left'; | |
$event_to_process = Request::CharactorMove->new($DIRECTION_RIGHT) | |
if $key =~ 'right'; | |
} | |
#lets send the new events to be process back the event manager | |
$self->evt_manager->post($event_to_process) | |
if defined $event_to_process; | |
} | |
#if we did not have a tick event then some other controller needs to do | |
#something so game state is still beign process we cannot have new input | |
#now | |
} | |
package Controller::CPUSpinner; | |
use Class::XSAccessor accessors => { evt_manager => 'evt_manager' }; | |
use Scalar::Util qw(weaken); | |
sub new { | |
my ( $class, $event ) = (@_); | |
my $self = {}; | |
bless $self, $class; | |
die 'Expects an Event::Manager' | |
unless defined $event and $event->isa('Event::Manager'); | |
$self->evt_manager($event); | |
my $weak_self = $self; | |
weaken $weak_self; | |
$self->evt_manager->reg_listener($weak_self); | |
$self->{keep_going} = 1; | |
return $self; | |
} | |
sub run { | |
my $self = shift; | |
while ( $self->{keep_going} == 1 ) { | |
my $tick = Event::Tick->new; | |
$self->evt_manager->post($tick); | |
} | |
} | |
sub notify { | |
print "Notify in CPU Spinner \n" if $EDEBUG; | |
my ( $self, $event ) = (@_); | |
if ( defined $event && $event->isa('Event::Quit') ) { | |
print "Stopping to pump ticks \n" if $EDEBUG; | |
#if we got a quit event that means we can stop running the game | |
$self->{keep_going} = 0; | |
} | |
#if we did not have a tick event then some other controller needs to do | |
#something so game state is still beign process we cannot have new input | |
#now | |
} | |
################################################## | |
#Here comes the code for the actual game objects # | |
################################################## | |
package Sprite::Square; | |
use base 'SDL::Surface'; | |
sub new { | |
my $class = shift; | |
my $self = {}; | |
bless $self, $class; | |
$self->init; | |
} | |
sub init { | |
my $self = shift; | |
} | |
package View::Game; | |
use Class::XSAccessor accessors => { evt_manager => 'evt_manager' }; | |
use Scalar::Util qw(weaken); | |
use SDL; | |
use SDL::App; | |
sub new { | |
my ( $class, $event ) = (@_); | |
my $self = {}; | |
bless $self, $class; | |
die 'Expects an Event::Manager' | |
unless defined $event and $event->isa('Event::Manager'); | |
$self->evt_manager($event); | |
my $weak_self = $self; | |
weaken $weak_self; | |
$self->evt_manager->reg_listener($weak_self); | |
$self->init; | |
return $self; | |
} | |
sub init { | |
my $self = shift; | |
$self->{window} = SDL::App->new( | |
-width => 640, | |
-height => 480, | |
-depth => 16, | |
-title => 'SDL Demo', | |
); | |
} | |
sub notify { | |
print "Notify in View Game \n" if $EDEBUG; | |
my ( $self, $event ) = (@_); | |
if ( defined $event ) { | |
if ( $event->isa('Event::Tick') ) { | |
print "Update Game View \n" if $GDEBUG; | |
#if we got a quit event that means we can stop running the game | |
} | |
if ( $event->isa('Event::GridBuilt') ) { | |
print "Showing |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment