Had a further tinker and opted to use nested objects for the overlay images -
As they sit within an associative array of the parent MAPBUILD object, they are only instantiated once. When instantiated they are assembled as an array[x-pos][y-pos] = array(RR, GG, BB, AA); of non transparent pixels.
Each object is then draw over the map by iterating its pixel array - should (and does) speed the process somewhat.
If you wanted to go astep further, I'd advise using the .gd2 file format rather than png (just slightly faster as more native to gd)
Anyway,
http://www.teckis.com/testing/overlay/ovre.php uses five nested objects (images) to create the map shown....
Code: Select all
<?php
class MAPBUILD {
var $images; // array of images used
var $path; // path to images used
function MAPBUILD($img='', $colour='CCCCCC', $width=360, $height=240) {
$this->flush();
$this->path = '/home/teckisc/public_html/testing/overlay/imgs/';
$this->images['background'] = new MAKEIMAGE($this->path.$img.'.png', $colour, $width, $height);
return $this->images['background'];
}
function mergeImage($merge_img="", $x_left=0, $y_top=0, $trans_colour="0000FF", $altitude=0, $xplus=0, $yplus=0) {
if(!isset($this->images[$merge_img])) {
// image not yet created
$this->images[$merge_img] = new MAKEIMAGE($this->path.$merge_img.'.png');
$this->images[$merge_img]->tc = array(
'red'=> hexdec(substr($trans_colour,0,2)),
'green'=> hexdec(substr($trans_colour,2,2)),
'blue'=> hexdec(substr($trans_colour,4,2))
);
//
// we now have an overlay image stored in GD format as $this->images['img_name']->img
// with width $this->images['img_name']->w and height $this->images['img_name']->h
// iterate that image a pixel at a time to build array
// $this->images['img_name']->pxs[left][top] = array('red','green','blue')
//
for($this->ypo = 0; $this->ypo < $this->images[$merge_img]->h; $this->ypo++) {
for($this->xpo = 0; $this->xpo < $this->images[$merge_img]->w; $this->xpo++) {
$this->indx_rgb = imagecolorsforindex($this->images[$merge_img]->img, imagecolorat($this->images[$merge_img]->img, $this->xpo, $this->ypo));
if(
($this->indx_rgb['red'] != $this->images[$merge_img]->tc['red']) ||
($this->indx_rgb['green'] != $this->images[$merge_img]->tc['green']) ||
($this->indx_rgb['blue'] != $this->images[$merge_img]->tc['blue'])) {
// not transparent colour, so set as array index
$this->images[$merge_img]->pxs[$this->ypo][$this->xpo] = $this->indx_rgb;
}
}
}
}
$altitude = (substr($merge_img,0,1) == 'h') ? 7: 0;
if($this->images[$merge_img] == true) {
foreach($this->images[$merge_img]->pxs AS $ypos=>$vals) {
foreach($vals AS $xpos=>$pxc) {
imagesetpixel($this->images['background']->img, $x_left+$xpos+$xplus, $y_top+$ypos-$yplus-$altitude, imagecolorallocate($this->images['background']->img, $pxc['red'], $pxc['green'], $pxc['blue']));
}
}
return true;
} else {
return false;
}
}
function destroyAll() {
foreach($this->images AS $image) {
$image->destroyImage();
}
}
function showMap($savename='') {
if(strlen($savename) > 0) {
imagepng($this->images['background']->img, $savename);
} else {
header('Content-type: image/png');
imagepng($this->images['background']->img);
}
}
function flush() {
$this->images = array();
$this->path = '';
}
}
class MAKEIMAGE {
var $img; // the image itself
var $w; // width of image
var $h; // height of image
var $t; // type of image
var $tc; // rgb array of transparent colour for overlays
var $pxs; // rgba array of non transparent pixels - array[y-pos][x-pos] = rgba
function MAKEIMAGE($img='', $colour='CCCCCC', $width=32, $height=22) {
$this->flush();
$this->img = Null;
if(strlen($img) > 0 && file_exists($img)) {
// img reference sent - create from that
$this->giz = getimagesize($img);
$this->w = $this->giz[0];
$this->h = $this->giz[1];
$this->t = $this->giz[2];
$this->img = ($this->t < 4) ? ($this->t < 3) ? ($this->t < 2) ? ($this->t < 1) ? Null : imagecreatefromgif($img) : imagecreatefromjpeg($img) : imagecreatefrompng($img) : Null;
} else {
// no img reference, create blank image
$this->img = imagecreatetruecolor($width, $height);
$bgcolour = imagecolorallocate($this->img, hexdec(substr($colour,0,2)), hexdec(substr($colour,2,2)), hexdec(substr($colour,4,2)));
imagefill($this->img, 0, 0, $bgcolour);
$this->w = $width;
$this->h = $height;
}
return (is_null($this->img)) ? false : true;
}
function destroyImage() {
imagedestroy($this->img);
}
function flush() {
$this->h = 0;
$this->w = 0;
$this->img = Null;
$this->t = 3;
$this->tc = array();
$this->pxs = array();
}
}
/*********** SAMPLE UNDYNAMIC CALL */
$landscape = array(
0 => array('w1', 'w1', 'w1','w1','w1', 'w1', 'w1','g1','h1'),
1 => array(Null, 'w1', 'w1','w1','w1', 'w1', 'w1','g1','h1'),
2 => array(Null, Null, 'w1','w1','g1', 'g1', 'g1','g1','h1'),
3 => array(Null, Null, 'g1','g1','g1', 'g1', 'g1','g1','h2'),
4 => array(Null, 'g1', 'g1', 'g1', 'g1', 'g1', 'g1','g1','g1'),
5 => array('g1', 'g1', 'g1', 'g1', 'g1', 'g1', 'g1','g1','g1'),
6 => array('g1', 'g1', 'g1', Null, Null, Null, 'g1', 'g1', 'g1')
);
$rows = count($landscape);
$cols = count($landscape[0]);
$mapwidth = (($cols + $rows) * 16) + 4;
$mapheight = (($rows + $cols) * + 18;
$a = new MAPBUILD('', 'DDDDDD', $mapwidth, $mapheight);
$offsetleft = -14;
$offsettop = 10;
for($rowcnt = 0; $rowcnt < $rows; $rowcnt++) {
$offsetleft += ($cols / 2)*32;
for($colcnt = $cols-1; $colcnt > -1; $colcnt--) {
if($landscape[$rowcnt][$colcnt] != Null) {
$a->mergeImage($landscape[$rowcnt][$colcnt], $offsetleft, $offsettop);
}
$offsettop += 8;
$offsetleft -= 16;
}
$offsettop -= ($cols-1) * 8;
$offsetleft += 16;
}
$a->mergeImage('library', 146, 43);
$a->showMap();
$a->destroyAll();
// ***********************************/
?>
Quite a bit of work to get that running nice from a database - perhaps
MAPS
`id` AUTO_INCREMENT
`name` VARCHAR
`desc` VARCHAR
`rows` SMALLINT 2
`cols` SMALLINT 2
MAP_ITEMS
`id` AUTO_INCREMENT
`map_id` MEDIUMINT 8
`type` SMALLINT 2 // eg 1=terrain, 2=groundItems, 3=aerial stuff
`image` VARCHAR
`row` SMALLINT 2
`col` SMALLINT 2
`altitude` SMALLINT 2
`x_offset` SMALLINT 2
`y_offset` SMALLINT 2
then you could store the terrain and items in the same table and order by row, col, type ASC.
That would also facilitate referencing any item to a grid rather than full x,y from top left.
Feel free to hack that around any way you want.
Have a major project at work and am moving house to a non-net-connected abode, so will not have much time to domuch more to this coding. Will try to keep an eye on things during my lunchbreaks , so if you meet a brickwall, just holler and wait.