Encapsulating Movement
Any sane person would abandon PHP for JavaScript, Ajax, jQuery or some other client-side language that would work directly with Web-based SVG graphic elements and attributes. In doing so, though, it would give up on both the OOP capacity of PHP (lacking in these other languages) and low cost (no open socket server) inter-internet games (i.e., remote multiplayer games.)
Ironically (for some), the easiest part of creating action games is the game physics. You just need to take a formula from physics (e.g., deceleration, acceleration) and turn it into an algorithm. Eventually, we’ll get to that luxury, but first we need to work out the mechanics of changing the position of a SVG graphic on a grid. Before getting into that discussion, click the Play button to see the end results (goal) and the Download button to see the code:
As you will see, there’s not a lot to play with, but it does deal with two velocity issues; velocity itself and capacity. It’s like comparing the velocity of a 2014 Rolls-Royce Wraith with that of a 1988 Trabant 601. Both cars can attain speeds of 100 km/hr (62 mph), but the Wraith can do it much faster and go far above that speed because it has a more powerful engine. It has greater capacity.
The Space Grid
In the previous post on using SVG graphics in making games, you can see the grid setup, and in that grid you can determine distance and collision using simple geometry. If you’ve spend any time with SVG graphics, you will find a animation system to move graphics along paths. The problem with that system (for now at least) is working out position and collision detection. Movement along paths has grid-like parameters in defining X and Y locations on a grid, but paths can also be defined in terms of curves, and knowing the position of an object at any given time can be problematic. Further, movement is a function of timing using the SVG animateMotion element. For example, consider the following path:
It moves an SVG object from 0,0 to 100,150 in a half a second (0.5 seconds). There is no checking along the way for collision. Using a Bézier curve the following movement goes from 0,0 to 300,0 in two seconds (2s) but it curves downward before reaching its destination.
Again, what it may have collided with is unknown given both the timing of the motion and the curve. This is not to say that every point could not somehow be tracked, but at this point I’d rather take a more familiar route to movement and collision detection.
Moving SVG objects involves changing their X and Y values. I’m calling the frequency with which the X and Y values are updated, “capacity” and the amount of change “velocity.” Rather than using the animateMotion SVG element, this example changes the object’s X value through timed updates and variable values in the number of pixels each timed update generates. For example, an update of every 50 milliseconds is faster than one of every 100 milliseconds—there’s less time between each update pause. Likewise, an X increment of 10 pixels will cause faster movement than an update of 5 pixels.
A timed loop fires a function that changes the ship’s position:
function moveShip() { // Change the ship's position shipX += $this->velocity; shipX = shipX % 500; oopz.setAttribute("x", shipX); } |
As you can see the code is JavaScript using a PHP variable ($this->velocity) to set the speed. I would have preferred to do it using all PHP, but needed to use the JavaScript setAttribute method for moving the ship’s X position without having to create a new object. Changing the speed using capacity (loop timing) and velocity (amount of variable increment) requires PHP to create another SVG object, and for demonstration purposes, that’s fine. In an action game, though, it’d eat up a lot of resources.
The “ship” (rectangle) only moves from left to right at this time, and when it leaves “the galaxy” it loops around and comes in the other end. Using the modulus of 500 (% 500), the value will always be calculated correctly when moving from left to right (in both JavaScript and PHP); however, moving from right to left, as soon as the X position is 0, it fails. (See this post on game algorithms for a detailed explanation and comparison of how the modulus operator works differently in Python than PHP and JavaScript). It’s an easy fix using conditional statements, but that’s so…I don’t know…inelegant? See what you can do. For now, continue on to see how the Move class is created and used.
The Move Class
The first class to examine is Move. It has a single responsibility: set the velocity and capacity of the ship. It does this by wrapping an XML SGV document inside an HTML5 document and putting the whole thing into a string using HEREDOC.
class Move
{
private $velocity;
private $capacity;
public function setVelocity($speed,$ship)
{
$this->velocity=$speed;
$this->capacity=$ship;
$ship =<<
|
The Move class’ return value is the package of code with the values being updated by a little JavaScript engine (timed loop) with the values for speed and capacity set by PHP. In any event, the whole thing is encapsulated in a class with access provided for specifying capacity and speed through the setVelocity() method.
The Client Class
Originally, I used a little trigger script to fire up the Move class but decided to better encapsulate the process using a Client class with a private method to handle the superglobal variables. Superglobals are available in all scopes, but by designating private variables for the velocity and capacity and passing the values inside of a private method, I’d have their values nicely encapsulated with no concerns about those variables being changed in any scope outside of the Client class.
ERROR_REPORTING( E_ALL | E_STRICT );
ini_set("display_errors", 1);
function __autoload($class_name)
{
include $class_name . '.php';
}
class Client
{
private $speed;
private $ship;
public function __construct()
{
$this->engage();
}
private function engage()
{
$trigger=$_POST["doit"];
if(isset($trigger))
{
$this->speed= intval($_POST["speed"]);
$this->ship= intval($_POST["ship"]);
$launcher=new Move();
echo $launcher->setVelocity($this->speed,$this->ship);
unset($trigger);
}
}
}
$worker = new Client();
?>
|
The engage() method assigns the superglobal values ($_POST) to private variables and used them in creating an instance of the Move class and then calling the object’s setVelocity() method with the two private variables values used as arguments.
To make everything easy, the HTML document has a two-part form: the first part has a set of radio buttons for the capacity and the second part is for a set of radio buttons for the velocity values. Both must be used or the PHP to correctly work. (If you want, your can add a verification system or start with checked radio buttons for each set.) You can see the HTML code detail in the following listing:
|
The CSS that accompanies the HTML can be seen in the following listing:
@charset "UTF-8"; /* CSS Document */ /* 003159 (dk blue) f5cc04 (lt yellow orange) f2b608 (med yellow orange) f3732d (singed orange) f4383d (rubbed red) palette name : flash */ body { font-family: fantasy; color: #003159; background-color: #F5CC04; } h3 { background-color:#F4383D; font-family: Impact, Haettenschweiler, "Franklin Gothic Bold", "Arial Black", sans-serif; color: #DBDEE7; width: 500px; padding: 5px; } h4 { background-color:#003159; font-family: Impact, Haettenschweiler, "Franklin Gothic Bold", "Arial Black", sans-serif; color: #f3732d; width: 250px; padding-left: 1em; } iframe { background-color:#DBDEE7; width: 520px; height: 400px; margin: 5px; padding: 5px; } |
What Next?
The arcade game project using SVG graphics with PHP is proceeding, and eventually, I’d like to make a two-player arcade game using PHP. However, this blog is advertised as and dedicated to PHP Design Patterns. Once all of the kinks are worked out I think that we can see a two-player game with design pattern structure. However, making arcade games using SVG graphics, a little JavaScript and HTML5 wrapped in PHP OOP will have to proceed a gradual pace. This will give readers a change to chime in with ideas and OOP code to move it along.
In the meantime, though, I’d like to move ahead with some more PHP design patterns than have not yet been discussed on this blog. Not to worry, though, we’ll return to the game projects and even see some game work in sample design patterns.
Copyright © 2013 William Sanders. All Rights Reserved.
0 Responses to “PHP Game Coding: SVG Movement”