Jump to content
  • 0

[Resolved] Sprite positions in relation to body


Kenpachi

Question


  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  764
  • Reputation:   220
  • Joined:  11/14/11
  • Last Seen:  

Hi.

Can someone share a list with the position of sprites in relation to the body? (For example: head, hair, headgear, weapon, and so on...)

I hope you understand what I'm asking for.... otherwise ask for details please. smile.png

Link to comment
Share on other sites

7 answers to this question

Recommended Posts

  • 0

  • Group:  Members
  • Topic Count:  1
  • Topics Per Day:  0.00
  • Content Count:  186
  • Reputation:   51
  • Joined:  11/14/11
  • Last Seen:  

Hi.

Can someone share a list with the position of sprites in relation to the body? (For example: head, hair, headgear, weapon, and so on...)

I hope you understand what I'm asking for.... otherwise ask for details please. :)

My PHP sprite class draws them some sort of dynamic:

   	 public function drawPart($pallette, $data, $sizeX, $sizeY, $offX, $offY, $round) {
		$i = 0;
		$x = (self::$IMAGE_WIDTH / 2);
		$x -= ($round == true ? round($sizeX / 2) : $sizeX / 2);
		$y = self::$IMAGE_BASEOFF;
		if ($this->charOption == 32) {
			$y += 10;
		}
		if ($this->charOption == 16) {
			$y += 30;
		}
		$y -= ($round == true ? round($sizeY / 2) : $sizeY / 2);

		while ($i < strlen($data)) {
			$entry = $pallette[hexdec(substr($data, $i, 2))];
			$pal = imageColorAllocateAlpha($this->ImageObj, $entry['r'], $entry['g'], $entry['b'], $entry['a']);
	   	 imageSetPixel($this->ImageObj, $offX + $x, $offY + $y, $pal);
			$i += 2;
			$x++;
			if (($i / 2) % $sizeX == 0) {
				$y++;
				$x = (self::$IMAGE_WIDTH / 2);
				$x -= ($round == true ? round($sizeX / 2) : $sizeX / 2);
			}
		}
	}

While the parameter/arguments are something screwed up.. i never had time to clean this up, but her is a the whole drawing:

   	 public function drawHead($internal = false, $bodyextraX = 0, $bodyextraY = 0) {
		if ($internal == false) {
			$this->ImageObj = ImageCreateTrueColor(self::$IMAGE_WIDTH, self::$IMAGE_HEIGHT);
			ImageSaveAlpha($this->ImageObj, true);
			ImageFill($this->ImageObj, 0, 0, ImageColorAllocateAlpha($this->ImageObj, 255, 0, 255, 127));
		}

		// Head
		$this->HEAD_ACT = RagnarokActionFormat::structFromFile(self::$DATA_FOLDER . 'sprite/Àΰ£Á·/¸Ó¸®Åë/'.$this->getSpriteSex().'/'.self::$HAIR_IDS[$this->charSex][$this->charHair].'_'.$this->getSpriteSex() . '.act');
		$this->HEAD_SPR = RagnarokSpriteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/Àΰ£Á·/¸Ó¸®Åë/'.$this->getSpriteSex().'/'.self::$HAIR_IDS[$this->charSex][$this->charHair].'_'.$this->getSpriteSex() . '.spr');
		if (isset($this->charHair_color) && $this->charHair_color != 0) {
			$this->HEAD_PAL = RagnarokPaletteFormat::structFromFile(self::$DATA_FOLDER . 'palette/¸Ó¸®/¸Ó¸®'.self::$HAIR_IDS[$this->charSex][$this->charHair].'_'.$this->getSpriteSex().'_'.$this->charHair_color.'.pal');
		} else {
			$this->HEAD_PAL = RagnarokPaletteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/Àΰ£Á·/¸Ó¸®Åë/'.$this->getSpriteSex().'/'.self::$HAIR_IDS[$this->charSex][$this->charHair].'_'.$this->getSpriteSex().'.spr');
		}

		$headoffsetX = $this->HEAD_ACT['animations'][$this->getFrameNo()]['frames'][1]['subframes'][1]['offsetX'];
		$headoffsetY = $this->HEAD_ACT['animations'][$this->getFrameNo()]['frames'][1]['subframes'][1]['offsetY'];
		$headextraX = $this->HEAD_ACT['animations'][$this->getFrameNo()]['frames'][1]['extraX'];
		$headextraY = $this->HEAD_ACT['animations'][$this->getFrameNo()]['frames'][1]['extraY'];

		$newheadoffsetX = $headoffsetX + $bodyextraX - $headextraX;
		$newheadoffsetY = $headoffsetY + $bodyextraY - $headextraY;

		// draw head
		$this->drawPart($this->HEAD_PAL, $this->getHeadSpr('Extracted_Data'), $this->getHeadSpr('Size_X'), $this->getHeadSpr('Size_Y'), $newheadoffsetX, $newheadoffsetY, false);

		// Headgear
		if ($this->charHead_top != 0) {
			$this->HEADT_ACT = RagnarokActionFormat::structFromFile(self::$DATA_FOLDER . 'sprite/¾Ç¼¼»Ç¸®/'.$this->getSpriteSex().'/'.$this->getSpriteSex().'_'.$this->getSpriteHeadName($this->charHead_top) . '.act');
			$this->HEADT_SPR = RagnarokSpriteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/¾Ç¼¼»Ç¸®/'.$this->getSpriteSex().'/'.$this->getSpriteSex().'_'.$this->getSpriteHeadName($this->charHead_top) . '.spr');
			$this->HEADT_PAL = RagnarokPaletteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/¾Ç¼¼»Ç¸®/'.$this->getSpriteSex().'/'.$this->getSpriteSex().'_'.$this->getSpriteHeadName($this->charHead_top) . '.spr');
			$head_topoffsetX = $this->HEADT_ACT['animations'][$this->getFrameNo()]['frames'][1]['subframes'][1]['offsetX'];
			$head_topoffsetY = $this->HEADT_ACT['animations'][$this->getFrameNo()]['frames'][1]['subframes'][1]['offsetY'];
			$head_topextraX = $this->HEADT_ACT['animations'][$this->getFrameNo()]['frames'][1]['extraX'];
			$head_topextraY = $this->HEADT_ACT['animations'][$this->getFrameNo()]['frames'][1]['extraY'];
			$newhead_topoffsetX = $head_topoffsetX + $bodyextraX - $head_topextraX;
			$newhead_topoffsetY = $head_topoffsetY + $bodyextraY - $head_topextraY;
		}
		if ($this->charHead_mid != 0) {
			$this->HEADM_ACT = RagnarokActionFormat::structFromFile(self::$DATA_FOLDER . 'sprite/¾Ç¼¼»Ç¸®/'.$this->getSpriteSex().'/'.$this->getSpriteSex().'_'.$this->getSpriteHeadName($this->charHead_mid) . '.act');
			$this->HEADM_SPR = RagnarokSpriteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/¾Ç¼¼»Ç¸®/'.$this->getSpriteSex().'/'.$this->getSpriteSex().'_'.$this->getSpriteHeadName($this->charHead_mid) . '.spr');
			$this->HEADM_PAL = RagnarokPaletteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/¾Ç¼¼»Ç¸®/'.$this->getSpriteSex().'/'.$this->getSpriteSex().'_'.$this->getSpriteHeadName($this->charHead_mid) . '.spr');
			$head_midoffsetX = $this->HEADM_ACT['animations'][$this->getFrameNo()]['frames'][1]['subframes'][1]['offsetX'];
			$head_midoffsetY = $this->HEADM_ACT['animations'][$this->getFrameNo()]['frames'][1]['subframes'][1]['offsetY'];
			$head_midextraX = $this->HEADM_ACT['animations'][$this->getFrameNo()]['frames'][1]['extraX'];
			$head_midextraY = $this->HEADM_ACT['animations'][$this->getFrameNo()]['frames'][1]['extraY'];
			$newhead_midoffsetX = $head_midoffsetX + $bodyextraX - $head_midextraX;
			$newhead_midoffsetY = $head_midoffsetY + $bodyextraY - $head_midextraY;
		}
		if ($this->charHead_bottom != 0) {
			$this->HEADB_ACT = RagnarokActionFormat::structFromFile(self::$DATA_FOLDER . 'sprite/¾Ç¼¼»Ç¸®/'.$this->getSpriteSex().'/'.$this->getSpriteSex().'_'.$this->getSpriteHeadName($this->charHead_bottom) . '.act');
			$this->HEADB_SPR = RagnarokSpriteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/¾Ç¼¼»Ç¸®/'.$this->getSpriteSex().'/'.$this->getSpriteSex().'_'.$this->getSpriteHeadName($this->charHead_bottom) . '.spr');
			$this->HEADB_PAL = RagnarokPaletteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/¾Ç¼¼»Ç¸®/'.$this->getSpriteSex().'/'.$this->getSpriteSex().'_'.$this->getSpriteHeadName($this->charHead_bottom) . '.spr');
			$head_bottomoffsetX = $this->HEADB_ACT['animations'][$this->getFrameNo()]['frames'][1]['subframes'][1]['offsetX'];
			$head_bottomoffsetY = $this->HEADB_ACT['animations'][$this->getFrameNo()]['frames'][1]['subframes'][1]['offsetY'];
			$head_bottomextraX = $this->HEADB_ACT['animations'][$this->getFrameNo()]['frames'][1]['extraX'];
			$head_bottomextraY = $this->HEADB_ACT['animations'][$this->getFrameNo()]['frames'][1]['extraY'];
			$newhead_bottomoffsetX = $head_bottomoffsetX + $bodyextraX - $head_bottomextraX;
			$newhead_bottomoffsetY = $head_bottomoffsetY + $bodyextraY - $head_bottomextraY;
		}

		// draw head bottom
		if ($this->charHead_bottom != 0) {
			$this->drawPart($this->HEADB_PAL, $this->getHeadBSpr('Extracted_Data'), $this->getHeadBSpr('Size_X'), $this->getHeadBSpr('Size_Y'), $newhead_bottomoffsetX, $newhead_bottomoffsetY, true);
		}
		// draw head middle
		if ($this->charHead_mid != 0) {
			$this->drawPart($this->HEADM_PAL, $this->getHeadMSpr('Extracted_Data'), $this->getHeadMSpr('Size_X'), $this->getHeadMSpr('Size_Y'), $newhead_midoffsetX, $newhead_midoffsetY, true);
		}
		// draw head top
		if ($this->charHead_top != 0) {
			$this->drawPart($this->HEADT_PAL, $this->getHeadTSpr('Extracted_Data'), $this->getHeadTSpr('Size_X'), $this->getHeadTSpr('Size_Y'), $newhead_topoffsetX, $newhead_topoffsetY, false);
		}


		if ($internal == false) {
			self::Trim($this->ImageObj);
		}
	}

	public function drawCharacter() {
		$this->ImageObj = ImageCreateTrueColor(self::$IMAGE_WIDTH, self::$IMAGE_HEIGHT);
		ImageSaveAlpha($this->ImageObj, true);
		ImageFill($this->ImageObj, 0, 0, ImageColorAllocateAlpha($this->ImageObj, 255, 0, 255, 127));


		// Body
		$this->BODY_ACT = RagnarokActionFormat::structFromFile(self::$DATA_FOLDER . 'sprite/Àΰ£Á·/¸öÅë/'.$this->getSpriteSex().'/'.$this->getSpriteBodyName().'_'.$this->getSpriteSex() . '.act');
		$this->BODY_SPR = RagnarokSpriteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/Àΰ£Á·/¸öÅë/'.$this->getSpriteSex().'/'.$this->getSpriteBodyName().'_'.$this->getSpriteSex() . '.spr');

		// Shadow
		$this->SHADOW_ACT = RagnarokActionFormat::structFromFile(self::$DATA_FOLDER . 'sprite/shadow.act');
		$this->SHADOW_SPR = RagnarokSpriteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/shadow.spr');

		$classpal_tab = array(
			4011 => 10,
			4009 => 8
		);
		if (isset($classpal_tab[$this->charClass]) && isset($this->charClothes_color) && $this->charClothes_color != 0) {
			$this->BODY_PAL = RagnarokPaletteFormat::structFromFile(self::$DATA_FOLDER . 'palette/¸ö/'.$CLASS_SPRITES[$classpal_tab[$this->charClass]].'_'.$this->getSpriteSex().'_'.$this->charClothes_color.'.pal');
		} else {
			$this->BODY_PAL = RagnarokPaletteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/Àΰ£Á·/¸öÅë/'.$this->getSpriteSex().'/'.$this->getSpriteBodyName().'_'.$this->getSpriteSex().'.spr');
		}
		$this->SHADOW_PAL = RagnarokPaletteFormat::structFromFile(self::$DATA_FOLDER . 'sprite/shadow.spr', true);

		$bodyoffsetX = $this->BODY_ACT['animations'][$this->getFrameNo()]['frames'][1]['subframes'][1]['offsetX'];
		$bodyoffsetY = $this->BODY_ACT['animations'][$this->getFrameNo()]['frames'][1]['subframes'][1]['offsetY'];
		$bodyextraX = $this->BODY_ACT['animations'][$this->getFrameNo()]['frames'][1]['extraX'];
		$bodyextraY = $this->BODY_ACT['animations'][$this->getFrameNo()]['frames'][1]['extraY'];
		$shadowoffsetX = $this->SHADOW_ACT['animations'][1]['frames'][1]['subframes'][1]['offsetX'];
		$shadowoffsetY = $this->SHADOW_ACT['animations'][1]['frames'][1]['subframes'][1]['offsetY'];

		$newshadowoffsetX = $shadowoffsetX;
		$newshadowoffsetY = $shadowoffsetY;
		$newbodyoffsetX = $bodyoffsetX;
		$newbodyoffsetY = $bodyoffsetY;

		// draw shadow
		$this->drawPart($this->SHADOW_PAL, $this->getShadowSpr('Extracted_Data'), $this->getShadowSpr('Size_X'), $this->getShadowSpr('Size_Y'), $newshadowoffsetX, $newshadowoffsetY, true);
		// draw body
		$this->drawPart($this->BODY_PAL, $this->getBodySpr('Extracted_Data'), $this->getBodySpr('Size_X'), $this->getBodySpr('Size_Y'), $newbodyoffsetX, $newbodyoffsetY, true);
		// draw head
		$this->drawHead(true, $bodyextraX, $bodyextraY);


		self::Trim($this->ImageObj);
	}

Its working for me but i dont know if there are some better ways for calulcating the positions.

It assums that the offsetX and offsetY in action files are based on the image's center. As GDI draws based on the top-left corner, i subtract the half of width and height to get the top-left corner.

The extraX and extraY in the body action file is used to offset the head sprite. This was just a test because i never read something about these 2 coordinates and after frustrating about a dynamic way for drawing a full character sprite, i tried them and yay, it worked!

Hope it helps, even if its rly unclean :S

€dit: spoiled x.x

Edited by GodLesZ
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  764
  • Reputation:   220
  • Joined:  11/14/11
  • Last Seen:  

PHP makes me cry!

But well, I'll give it a chance. Thanks. :)

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  9
  • Topics Per Day:  0.00
  • Content Count:  379
  • Reputation:   304
  • Joined:  11/10/11
  • Last Seen:  

It's something like this :

vec2 pos = size.xy*0.5 + off.xy + ( body_off2.xy - off2.xy );

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  1
  • Topics Per Day:  0.00
  • Content Count:  186
  • Reputation:   51
  • Joined:  11/14/11
  • Last Seen:  

It's something like this :

vec2 pos = size.xy*0.5 + off.xy + ( body_off2.xy - off2.xy );

Without the explanation of the variable names i dont think this helps alot xD

I assume size is the head sprite size after apply the scale from the action, right?

off may be the world offset used to draw the sprite on a specified position.

body_off2 seems to hold either the offset from the body action or another world offset/position. Or maybe the extraX/extraY in the action file?

off2 had to be advised. :)

Just to test some generic algorithms (i hate pseudocode) ..

// assume the image is draw from the top-left corner
// -- Input --
// Contains the world position
Vector2 worldPos;
// Offset taken from the boady action file, most named as "extraX/extraY"
Vector2 bodyExtraOffset;
// Offset taken from the head action file
Vector2 headOffset;
// Offset taken from the head action file, most named as "extraX/extraY"
Vector2 headExtraOffset;
// Head image size, after apply mirror, rotation & scale modifer from action file
Vector2 headImageSize;

// --- Drawing ---
// Calculate the final offset for drawing
Vector2 finalHeadOffset = (worldPos + headOffset + bodyExtraOffset - headExtraOffset);
// The offset in action files are relative to the image center, so normalize this to the top-left corner
finalHeadOffset -= headImageSize * 0.5f;
// Draw the image
Draw(<headImage>, finalHeadOffset); 

Hope it helps ôo

Edited by GodLesZ
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  9
  • Topics Per Day:  0.00
  • Content Count:  379
  • Reputation:   304
  • Joined:  11/10/11
  • Last Seen:  

Yeah off2 seems to be your extraX-extraY (and body_off2 -> body_extraX/body_extraY).

Size is the sprite size store in action after apply in the order : mirror -> rotation -> scale.

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  1
  • Topics Per Day:  0.00
  • Content Count:  186
  • Reputation:   51
  • Joined:  11/14/11
  • Last Seen:  

Yeah off2 seems to be your extraX-extraY (and body_off2 -> body_extraX/body_extraY).

Size is the sprite size store in action after apply in the order : mirror -> rotation -> scale.

Thanks for pointing that out. :)

I think my pseudocode should be correct now.

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  22
  • Topics Per Day:  0.00
  • Content Count:  764
  • Reputation:   220
  • Joined:  11/14/11
  • Last Seen:  

Thank you guys. I think this will help me a lot. :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...