Sprite: Implement wave effect (RGSS2)
This initial implementation emulates the way RMVX splits the sprite into "chunks" of about 8 pixels, which it then scrolls left/right on a vertical sine wave. It even replicates the weird behavior when wave_amp < 0, namely "shrinking" the src_rect horizontally. As with bush_opacity, this effect in combination with rotation will render differently from RMVX.
This commit is contained in:
		
							parent
							
								
									42b10fd2ee
								
							
						
					
					
						commit
						af9039f58d
					
				
					 6 changed files with 346 additions and 21 deletions
				
			
		| 
						 | 
					@ -69,6 +69,39 @@ DEF_PROP_F(Sprite, Angle)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEF_PROP_B(Sprite, Mirror)
 | 
					DEF_PROP_B(Sprite, Mirror)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RB_METHOD(spriteWidth)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						RB_UNUSED_PARAM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sprite *s = getPrivateData<Sprite>(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int value;
 | 
				
			||||||
 | 
						GUARD_EXC( value = s->getWidth(); )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rb_fix_new(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RB_METHOD(spriteHeight)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						RB_UNUSED_PARAM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sprite *s = getPrivateData<Sprite>(self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int value;
 | 
				
			||||||
 | 
						GUARD_EXC( value = s->getHeight(); )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rb_fix_new(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEF_PROP_I(Sprite, WaveAmp)
 | 
				
			||||||
 | 
					DEF_PROP_I(Sprite, WaveLength)
 | 
				
			||||||
 | 
					DEF_PROP_I(Sprite, WaveSpeed)
 | 
				
			||||||
 | 
					DEF_PROP_F(Sprite, WavePhase)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
spriteBindingInit()
 | 
					spriteBindingInit()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -98,4 +131,14 @@ spriteBindingInit()
 | 
				
			||||||
	INIT_PROP_BIND( Sprite, BlendType, "blend_type" );
 | 
						INIT_PROP_BIND( Sprite, BlendType, "blend_type" );
 | 
				
			||||||
	INIT_PROP_BIND( Sprite, Color,     "color"      );
 | 
						INIT_PROP_BIND( Sprite, Color,     "color"      );
 | 
				
			||||||
	INIT_PROP_BIND( Sprite, Tone,      "tone"       );
 | 
						INIT_PROP_BIND( Sprite, Tone,      "tone"       );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
						_rb_define_method(klass, "width", spriteWidth);
 | 
				
			||||||
 | 
						_rb_define_method(klass, "height", spriteHeight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_PROP_BIND( Sprite, WaveAmp,    "wave_amp"    );
 | 
				
			||||||
 | 
						INIT_PROP_BIND( Sprite, WaveLength, "wave_length" );
 | 
				
			||||||
 | 
						INIT_PROP_BIND( Sprite, WaveSpeed,  "wave_speed"  );
 | 
				
			||||||
 | 
						INIT_PROP_BIND( Sprite, WavePhase,  "wave_phase"  );
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,35 @@ DEF_PROP_F(Sprite, Angle)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEF_PROP_B(Sprite, Mirror)
 | 
					DEF_PROP_B(Sprite, Mirror)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MRB_METHOD(spriteWidth)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Sprite *s = getPrivateData<Sprite>(mrb, self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int value;
 | 
				
			||||||
 | 
						GUARD_EXC( value = s->getWidth(); )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return mrb_fixnum_value(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MRB_METHOD(spriteHeight)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Sprite *s = getPrivateData<Sprite>(mrb, self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int value;
 | 
				
			||||||
 | 
						GUARD_EXC( value = s->getHeight(); )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return mrb_fixnum_value(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEF_PROP_I(Sprite, WaveAmp)
 | 
				
			||||||
 | 
					DEF_PROP_I(Sprite, WaveLength)
 | 
				
			||||||
 | 
					DEF_PROP_I(Sprite, WaveSpeed)
 | 
				
			||||||
 | 
					DEF_PROP_F(Sprite, WavePhase)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
spriteBindingInit(mrb_state *mrb)
 | 
					spriteBindingInit(mrb_state *mrb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -95,5 +124,15 @@ spriteBindingInit(mrb_state *mrb)
 | 
				
			||||||
	INIT_PROP_BIND( Sprite, Color,     "color"      );
 | 
						INIT_PROP_BIND( Sprite, Color,     "color"      );
 | 
				
			||||||
	INIT_PROP_BIND( Sprite, Tone,      "tone"       );
 | 
						INIT_PROP_BIND( Sprite, Tone,      "tone"       );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
						mrb_define_method(mrb, klass, "width",  spriteWidth,  MRB_ARGS_NONE());
 | 
				
			||||||
 | 
						mrb_define_method(mrb, klass, "height", spriteHeight, MRB_ARGS_NONE());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_PROP_BIND( Sprite, WaveAmp,    "wave_amp"    );
 | 
				
			||||||
 | 
						INIT_PROP_BIND( Sprite, WaveLength, "wave_length" );
 | 
				
			||||||
 | 
						INIT_PROP_BIND( Sprite, WaveSpeed,  "wave_speed"  );
 | 
				
			||||||
 | 
						INIT_PROP_BIND( Sprite, WavePhase,  "wave_phase"  );
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mrb_define_method(mrb, klass, "inspect", inspectObject, MRB_ARGS_NONE());
 | 
						mrb_define_method(mrb, klass, "inspect", inspectObject, MRB_ARGS_NONE());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,7 +55,7 @@ public:
 | 
				
			||||||
		flashAlpha = flashColor.w;
 | 
							flashAlpha = flashColor.w;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void update()
 | 
						virtual void update()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!flashing)
 | 
							if (!flashing)
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,17 +34,41 @@
 | 
				
			||||||
typedef uint32_t index_t;
 | 
					typedef uint32_t index_t;
 | 
				
			||||||
#define _GL_INDEX_TYPE GL_UNSIGNED_INT
 | 
					#define _GL_INDEX_TYPE GL_UNSIGNED_INT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ColorQuadArray
 | 
					/* A small hack to get mutable QuadArray constructors */
 | 
				
			||||||
 | 
					inline void initBufferBindings(Vertex *)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	std::vector<Vertex> vertices;
 | 
						glEnableVertexAttribArray(Shader::Color);
 | 
				
			||||||
 | 
						glEnableVertexAttribArray(Shader::Position);
 | 
				
			||||||
 | 
						glEnableVertexAttribArray(Shader::TexCoord);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glVertexAttribPointer(Shader::Color,    4, GL_FLOAT, GL_FALSE, sizeof(Vertex), Vertex::colorOffset());
 | 
				
			||||||
 | 
						glVertexAttribPointer(Shader::Position, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), Vertex::posOffset());
 | 
				
			||||||
 | 
						glVertexAttribPointer(Shader::TexCoord, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), Vertex::texPosOffset());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void initBufferBindings(SVertex *)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						glEnableVertexAttribArray(Shader::Position);
 | 
				
			||||||
 | 
						glEnableVertexAttribArray(Shader::TexCoord);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glVertexAttribPointer(Shader::Position, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), SVertex::posOffset());
 | 
				
			||||||
 | 
						glVertexAttribPointer(Shader::TexCoord, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), SVertex::texPosOffset());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template<class VertexType>
 | 
				
			||||||
 | 
					struct QuadArray
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::vector<VertexType> vertices;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	VBO::ID vbo;
 | 
						VBO::ID vbo;
 | 
				
			||||||
	VAO::ID vao;
 | 
						VAO::ID vao;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int quadCount;
 | 
						int quadCount;
 | 
				
			||||||
 | 
						GLsizeiptr vboSize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ColorQuadArray()
 | 
						QuadArray()
 | 
				
			||||||
	    : quadCount(0)
 | 
						    : quadCount(0),
 | 
				
			||||||
 | 
						      vboSize(-1)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		vbo = VBO::gen();
 | 
							vbo = VBO::gen();
 | 
				
			||||||
		vao = VAO::gen();
 | 
							vao = VAO::gen();
 | 
				
			||||||
| 
						 | 
					@ -53,20 +77,16 @@ struct ColorQuadArray
 | 
				
			||||||
		VBO::bind(vbo);
 | 
							VBO::bind(vbo);
 | 
				
			||||||
		shState->bindQuadIBO();
 | 
							shState->bindQuadIBO();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		glEnableVertexAttribArray(Shader::Color);
 | 
							/* Call correct implementation here via overloading */
 | 
				
			||||||
		glEnableVertexAttribArray(Shader::Position);
 | 
							VertexType *dummy = 0;
 | 
				
			||||||
		glEnableVertexAttribArray(Shader::TexCoord);
 | 
							initBufferBindings(dummy);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		glVertexAttribPointer(Shader::Color,    4, GL_FLOAT, GL_FALSE, sizeof(Vertex), Vertex::colorOffset());
 | 
					 | 
				
			||||||
		glVertexAttribPointer(Shader::Position, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), Vertex::posOffset());
 | 
					 | 
				
			||||||
		glVertexAttribPointer(Shader::TexCoord, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), Vertex::texPosOffset());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		VAO::unbind();
 | 
							VAO::unbind();
 | 
				
			||||||
		IBO::unbind();
 | 
							IBO::unbind();
 | 
				
			||||||
		VBO::unbind();
 | 
							VBO::unbind();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	~ColorQuadArray()
 | 
						~QuadArray()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		VBO::del(vbo);
 | 
							VBO::del(vbo);
 | 
				
			||||||
		VAO::del(vao);
 | 
							VAO::del(vao);
 | 
				
			||||||
| 
						 | 
					@ -78,16 +98,37 @@ struct ColorQuadArray
 | 
				
			||||||
		quadCount = size;
 | 
							quadCount = size;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void clear()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							vertices.clear();
 | 
				
			||||||
 | 
							quadCount = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* This needs to be called after the final 'append()' call
 | 
						/* This needs to be called after the final 'append()' call
 | 
				
			||||||
	 * and previous to the first 'draw()' call. */
 | 
						 * and previous to the first 'draw()' call. */
 | 
				
			||||||
	void commit()
 | 
						void commit()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		VBO::bind(vbo);
 | 
							VBO::bind(vbo);
 | 
				
			||||||
		VBO::uploadData(vertices.size() * sizeof(Vertex), &vertices[0], GL_DYNAMIC_DRAW);
 | 
					
 | 
				
			||||||
		VBO::unbind();
 | 
							GLsizeiptr size = vertices.size() * sizeof(VertexType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (size > vboSize)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* New data exceeds already allocated size.
 | 
				
			||||||
 | 
								 * Reallocate VBO. */
 | 
				
			||||||
 | 
								VBO::uploadData(size, &vertices[0], GL_DYNAMIC_DRAW);
 | 
				
			||||||
 | 
								vboSize = size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			shState->ensureQuadIBO(quadCount);
 | 
								shState->ensureQuadIBO(quadCount);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* New data fits in allocated size */
 | 
				
			||||||
 | 
								VBO::uploadSubData(0, size, &vertices[0]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							VBO::unbind();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void draw(size_t offset, size_t count)
 | 
						void draw(size_t offset, size_t count)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -110,4 +151,7 @@ struct ColorQuadArray
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef QuadArray<Vertex> ColorQuadArray;
 | 
				
			||||||
 | 
					typedef QuadArray<SVertex> SimpleQuadArray;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // QUADARRAY_H
 | 
					#endif // QUADARRAY_H
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										194
									
								
								src/sprite.cpp
									
										
									
									
									
								
							
							
						
						
									
										194
									
								
								src/sprite.cpp
									
										
									
									
									
								
							| 
						 | 
					@ -32,6 +32,9 @@
 | 
				
			||||||
#include "transform.h"
 | 
					#include "transform.h"
 | 
				
			||||||
#include "shader.h"
 | 
					#include "shader.h"
 | 
				
			||||||
#include "glstate.h"
 | 
					#include "glstate.h"
 | 
				
			||||||
 | 
					#include "quadarray.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <math.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <SDL_rect.h>
 | 
					#include <SDL_rect.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,6 +66,22 @@ struct SpritePrivate
 | 
				
			||||||
	Color *color;
 | 
						Color *color;
 | 
				
			||||||
	Tone *tone;
 | 
						Tone *tone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
						struct
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int amp;
 | 
				
			||||||
 | 
							int length;
 | 
				
			||||||
 | 
							int speed;
 | 
				
			||||||
 | 
							float phase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Wave effect is active (amp != 0) */
 | 
				
			||||||
 | 
							bool active;
 | 
				
			||||||
 | 
							/* qArray needs updating */
 | 
				
			||||||
 | 
							bool dirty;
 | 
				
			||||||
 | 
							SimpleQuadArray qArray;
 | 
				
			||||||
 | 
						} wave;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	EtcTemps tmp;
 | 
						EtcTemps tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sigc::connection prepareCon;
 | 
						sigc::connection prepareCon;
 | 
				
			||||||
| 
						 | 
					@ -87,6 +106,13 @@ struct SpritePrivate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		prepareCon = shState->prepareDraw.connect
 | 
							prepareCon = shState->prepareDraw.connect
 | 
				
			||||||
		        (sigc::mem_fun(this, &SpritePrivate::prepare));
 | 
							        (sigc::mem_fun(this, &SpritePrivate::prepare));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
							wave.amp = 0;
 | 
				
			||||||
 | 
							wave.length = 180;
 | 
				
			||||||
 | 
							wave.speed = 360;
 | 
				
			||||||
 | 
							wave.phase = 0.0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	~SpritePrivate()
 | 
						~SpritePrivate()
 | 
				
			||||||
| 
						 | 
					@ -117,6 +143,10 @@ struct SpritePrivate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		quad.setPosRect(IntRect(0, 0, srcRect->width, srcRect->height));
 | 
							quad.setPosRect(IntRect(0, 0, srcRect->width, srcRect->height));
 | 
				
			||||||
		recomputeBushDepth();
 | 
							recomputeBushDepth();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
							wave.dirty = true;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void updateSrcRectCon()
 | 
						void updateSrcRectCon()
 | 
				
			||||||
| 
						 | 
					@ -141,6 +171,16 @@ struct SpritePrivate
 | 
				
			||||||
		if (!opacity)
 | 
							if (!opacity)
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
							if (wave.active)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* Don't do expensive wave bounding box
 | 
				
			||||||
 | 
								 * calculations */
 | 
				
			||||||
 | 
								isVisible = true;
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Compare sprite bounding box against the scene */
 | 
							/* Compare sprite bounding box against the scene */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* If sprite is zoomed/rotated, just opt out for now
 | 
							/* If sprite is zoomed/rotated, just opt out for now
 | 
				
			||||||
| 
						 | 
					@ -161,8 +201,102 @@ struct SpritePrivate
 | 
				
			||||||
		isVisible = SDL_HasIntersection(&self, &sceneRect);
 | 
							isVisible = SDL_HasIntersection(&self, &sceneRect);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
						void emitWaveChunk(SVertex *&vert, float phase, int width,
 | 
				
			||||||
 | 
						                   float zoomY, int chunkY, int chunkLength)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							float wavePos = phase + (chunkY / (float) wave.length) * M_PI * 2;
 | 
				
			||||||
 | 
							float chunkX = sin(wavePos) * wave.amp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							FloatRect tex(0, chunkY / zoomY, width, chunkLength / zoomY);
 | 
				
			||||||
 | 
							FloatRect pos = tex;
 | 
				
			||||||
 | 
							pos.x = chunkX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Quad::setTexPosRect(vert, tex, pos);
 | 
				
			||||||
 | 
							vert += 4;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void updateWave()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (!bitmap)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (wave.amp == 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								wave.active = false;
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							wave.active = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							int width = srcRect->width;
 | 
				
			||||||
 | 
							int height = srcRect->height;
 | 
				
			||||||
 | 
							float zoomY = trans.getScale().y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (wave.amp < -(width / 2))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								wave.qArray.resize(0);
 | 
				
			||||||
 | 
								wave.qArray.commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* RMVX does this, and I have no fucking clue why */
 | 
				
			||||||
 | 
							if (wave.amp < 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								wave.qArray.resize(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								int x = -wave.amp;
 | 
				
			||||||
 | 
								int w = width - x * 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								FloatRect tex(x, srcRect->y, w, srcRect->height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Quad::setTexPosRect(&wave.qArray.vertices[0], tex, tex);
 | 
				
			||||||
 | 
								wave.qArray.commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* The length of the sprite as it appears on screen */
 | 
				
			||||||
 | 
							int visibleLength = height * zoomY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* First chunk length (aligned to 8 pixel boundary */
 | 
				
			||||||
 | 
							int firstLength = ((int) trans.getPosition().y) % 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Amount of full 8 pixel chunks in the middle */
 | 
				
			||||||
 | 
							int chunks = (visibleLength - firstLength) / 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Final chunk length */
 | 
				
			||||||
 | 
							int lastLength = (visibleLength - firstLength) % 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							wave.qArray.resize(!!firstLength + chunks + !!lastLength);
 | 
				
			||||||
 | 
							SVertex *vert = &wave.qArray.vertices[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							float phase = (wave.phase * M_PI) / 180.f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (firstLength > 0)
 | 
				
			||||||
 | 
								emitWaveChunk(vert, phase, width, zoomY, 0, firstLength);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (int i = 0; i < chunks; ++i)
 | 
				
			||||||
 | 
								emitWaveChunk(vert, phase, width, zoomY, firstLength + i * 8, 8);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (lastLength > 0)
 | 
				
			||||||
 | 
								emitWaveChunk(vert, phase, width, zoomY, firstLength + chunks * 8, lastLength);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							wave.qArray.commit();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void prepare()
 | 
						void prepare()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
							if (wave.dirty)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								updateWave();
 | 
				
			||||||
 | 
								wave.dirty = false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		updateVisibility();
 | 
							updateVisibility();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -193,14 +327,21 @@ DEF_ATTR_RD_SIMPLE(Sprite, Angle,     float,   p->trans.getRotation())
 | 
				
			||||||
DEF_ATTR_RD_SIMPLE(Sprite, Mirror,    bool,    p->mirrored)
 | 
					DEF_ATTR_RD_SIMPLE(Sprite, Mirror,    bool,    p->mirrored)
 | 
				
			||||||
DEF_ATTR_RD_SIMPLE(Sprite, BushDepth, int,     p->bushDepth)
 | 
					DEF_ATTR_RD_SIMPLE(Sprite, BushDepth, int,     p->bushDepth)
 | 
				
			||||||
DEF_ATTR_RD_SIMPLE(Sprite, BlendType, int,     p->blendType)
 | 
					DEF_ATTR_RD_SIMPLE(Sprite, BlendType, int,     p->blendType)
 | 
				
			||||||
DEF_ATTR_RD_SIMPLE(Sprite, Width,     int,     p->srcRect->width)
 | 
					 | 
				
			||||||
DEF_ATTR_RD_SIMPLE(Sprite, Height,    int,     p->srcRect->height)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEF_ATTR_SIMPLE(Sprite, BushOpacity, int,    p->bushOpacity)
 | 
					DEF_ATTR_SIMPLE(Sprite, BushOpacity, int,    p->bushOpacity)
 | 
				
			||||||
DEF_ATTR_SIMPLE(Sprite, Opacity,     int,    p->opacity)
 | 
					DEF_ATTR_SIMPLE(Sprite, Opacity,     int,    p->opacity)
 | 
				
			||||||
DEF_ATTR_SIMPLE(Sprite, Color,       Color*, p->color)
 | 
					DEF_ATTR_SIMPLE(Sprite, Color,       Color*, p->color)
 | 
				
			||||||
DEF_ATTR_SIMPLE(Sprite, Tone,        Tone*,  p->tone)
 | 
					DEF_ATTR_SIMPLE(Sprite, Tone,        Tone*,  p->tone)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
					DEF_ATTR_RD_SIMPLE(Sprite, Width,      int,   p->srcRect->width)
 | 
				
			||||||
 | 
					DEF_ATTR_RD_SIMPLE(Sprite, Height,     int,   p->srcRect->height)
 | 
				
			||||||
 | 
					DEF_ATTR_RD_SIMPLE(Sprite, WaveAmp,    int,   p->wave.amp)
 | 
				
			||||||
 | 
					DEF_ATTR_RD_SIMPLE(Sprite, WaveLength, int,   p->wave.length)
 | 
				
			||||||
 | 
					DEF_ATTR_RD_SIMPLE(Sprite, WaveSpeed,  int,   p->wave.speed)
 | 
				
			||||||
 | 
					DEF_ATTR_RD_SIMPLE(Sprite, WavePhase,  float, p->wave.phase)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Sprite::setBitmap(Bitmap *bitmap)
 | 
					void Sprite::setBitmap(Bitmap *bitmap)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	GUARD_DISPOSED
 | 
						GUARD_DISPOSED
 | 
				
			||||||
| 
						 | 
					@ -218,6 +359,10 @@ void Sprite::setBitmap(Bitmap *bitmap)
 | 
				
			||||||
	*p->srcRect = bitmap->rect();
 | 
						*p->srcRect = bitmap->rect();
 | 
				
			||||||
	p->onSrcRectChange();
 | 
						p->onSrcRectChange();
 | 
				
			||||||
	p->quad.setPosRect(p->srcRect->toFloatRect());
 | 
						p->quad.setPosRect(p->srcRect->toFloatRect());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
						p->wave.dirty = true;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Sprite::setSrcRect(Rect *rect)
 | 
					void Sprite::setSrcRect(Rect *rect)
 | 
				
			||||||
| 
						 | 
					@ -252,6 +397,10 @@ void Sprite::setY(int value)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p->trans.setPosition(Vec2(getX(), value));
 | 
						p->trans.setPosition(Vec2(getX(), value));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
						p->wave.dirty = true;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Sprite::setOX(int value)
 | 
					void Sprite::setOX(int value)
 | 
				
			||||||
| 
						 | 
					@ -293,6 +442,10 @@ void Sprite::setZoomY(float value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p->trans.setScale(Vec2(getZoomX(), value));
 | 
						p->trans.setScale(Vec2(getZoomX(), value));
 | 
				
			||||||
	p->recomputeBushDepth();
 | 
						p->recomputeBushDepth();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
						p->wave.dirty = true;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Sprite::setAngle(float value)
 | 
					void Sprite::setAngle(float value)
 | 
				
			||||||
| 
						 | 
					@ -346,6 +499,36 @@ void Sprite::setBlendType(int type)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DEF_WAVE_SETTER(Name, name, type) \
 | 
				
			||||||
 | 
						void Sprite::setWave##Name(type value) \
 | 
				
			||||||
 | 
						{ \
 | 
				
			||||||
 | 
							GUARD_DISPOSED; \
 | 
				
			||||||
 | 
							if (p->wave.name == value) \
 | 
				
			||||||
 | 
								return; \
 | 
				
			||||||
 | 
							p->wave.name = value; \
 | 
				
			||||||
 | 
							p->wave.dirty = true; \
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEF_WAVE_SETTER(Amp,    amp,    int)
 | 
				
			||||||
 | 
					DEF_WAVE_SETTER(Length, length, int)
 | 
				
			||||||
 | 
					DEF_WAVE_SETTER(Speed,  speed,  int)
 | 
				
			||||||
 | 
					DEF_WAVE_SETTER(Phase,  phase,  float)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef DEF_WAVE_SETTER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Flashable */
 | 
				
			||||||
 | 
					void Sprite::update()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Flashable::update();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p->wave.phase += p->wave.speed / 180;
 | 
				
			||||||
 | 
						p->wave.dirty = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Disposable */
 | 
					/* Disposable */
 | 
				
			||||||
void Sprite::releaseResources()
 | 
					void Sprite::releaseResources()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -407,7 +590,14 @@ void Sprite::draw()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p->bitmap->bindTex(*base);
 | 
						p->bitmap->bindTex(*base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
						if (p->wave.active)
 | 
				
			||||||
 | 
							p->wave.qArray.draw();
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
		p->quad.draw();
 | 
							p->quad.draw();
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
						p->quad.draw();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	glState.blendMode.pop();
 | 
						glState.blendMode.pop();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								src/sprite.h
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								src/sprite.h
									
										
									
									
									
								
							| 
						 | 
					@ -41,9 +41,6 @@ public:
 | 
				
			||||||
	Sprite(Viewport *viewport = 0);
 | 
						Sprite(Viewport *viewport = 0);
 | 
				
			||||||
	~Sprite();
 | 
						~Sprite();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int getWidth()  const;
 | 
					 | 
				
			||||||
	int getHeight() const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	DECL_ATTR( Bitmap,      Bitmap* )
 | 
						DECL_ATTR( Bitmap,      Bitmap* )
 | 
				
			||||||
	DECL_ATTR( SrcRect,     Rect*   )
 | 
						DECL_ATTR( SrcRect,     Rect*   )
 | 
				
			||||||
	DECL_ATTR( X,           int     )
 | 
						DECL_ATTR( X,           int     )
 | 
				
			||||||
| 
						 | 
					@ -61,6 +58,18 @@ public:
 | 
				
			||||||
	DECL_ATTR( Color,       Color*  )
 | 
						DECL_ATTR( Color,       Color*  )
 | 
				
			||||||
	DECL_ATTR( Tone,        Tone*   )
 | 
						DECL_ATTR( Tone,        Tone*   )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef RGSS2
 | 
				
			||||||
 | 
						int getWidth()  const;
 | 
				
			||||||
 | 
						int getHeight() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DECL_ATTR( WaveAmp,    int   )
 | 
				
			||||||
 | 
						DECL_ATTR( WaveLength, int   )
 | 
				
			||||||
 | 
						DECL_ATTR( WaveSpeed,  int   )
 | 
				
			||||||
 | 
						DECL_ATTR( WavePhase,  float )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void update();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	SpritePrivate *p;
 | 
						SpritePrivate *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue