Added obscured/scratched window puzzle

This commit is contained in:
Mathew Velasquez 2016-01-28 23:32:29 -05:00
parent 71b2187e50
commit ba0203169e
22 changed files with 324 additions and 28 deletions

View file

@ -26,6 +26,19 @@ RB_METHOD(oneshotMsgBox)
return rb_bool_new(shState->oneshot().msgbox(type, body, title));
}
RB_METHOD(oneshotResetObscured)
{
RB_UNUSED_PARAM;
shState->oneshot().resetObscured();
return Qnil;
}
RB_METHOD(oneshotObscuredCleared)
{
RB_UNUSED_PARAM;
return shState->oneshot().obscuredCleared() ? Qtrue : Qfalse;
}
void oneshotBindingInit()
{
VALUE module = rb_define_module("Oneshot");
@ -43,4 +56,6 @@ void oneshotBindingInit()
//Functions
_rb_define_module_function(module, "set_yes_no", oneshotSetYesNo);
_rb_define_module_function(module, "msgbox", oneshotMsgBox);
_rb_define_module_function(module, "reset_obscured", oneshotResetObscured);
_rb_define_module_function(module, "obscured_cleared?", oneshotObscuredCleared);
}

View file

@ -69,6 +69,7 @@ DEF_PROP_F(Sprite, Angle)
DEF_PROP_F(Sprite, WavePhase)
DEF_PROP_B(Sprite, Mirror)
DEF_PROP_B(Sprite, Obscured)
RB_METHOD(spriteWidth)
{
@ -121,6 +122,7 @@ spriteBindingInit()
INIT_PROP_BIND( Sprite, BlendType, "blend_type" );
INIT_PROP_BIND( Sprite, Color, "color" );
INIT_PROP_BIND( Sprite, Tone, "tone" );
INIT_PROP_BIND( Sprite, Obscured, "obscured" );
if (rgssVer >= 2)
{

View file

@ -242,6 +242,7 @@ EMBED = \
shader/simpleAlpha.frag \
shader/simpleAlphaUni.frag \
shader/flashMap.frag \
shader/obscured.frag \
shader/minimal.vert \
shader/simple.vert \
shader/simpleColor.vert \

View file

@ -7,8 +7,8 @@ class Ed_Message
def initialize
@viewport = Viewport.new(0, 0, 640, 480)
@sprite_bg = Sprite.new(@viewport)
@sprite_bg.bitmap = RPG::Cache.menu('ed')
@sprite_bg.blend_type = 2
@sprite_bg.bitmap = Bitmap.new(640, 480)
@sprite_bg.bitmap.fill_rect(0, 0, 640, 480, Color.new(0, 0, 0, 128))
@sprite_text = Sprite.new(@viewport)
@contents = Bitmap.new(640, HEIGHT)
@sprite_text.bitmap = @contents

View file

@ -23,10 +23,13 @@ class Game_Map
attr_accessor :battleback_name # battleback file name
attr_accessor :display_x # display x-coordinate * 128
attr_accessor :display_y # display y-coordinate * 128
attr_accessor :wrap_x # display x-coordinate * 128 for wrap
attr_accessor :wrap_y # display y-coordinate * 128 for wrap
attr_accessor :need_refresh # refresh request flag
attr_accessor :bg_name # bg file name
attr_accessor :particles_type # particles name
attr_accessor :clamped_panorama # panorama is clamped?
attr_accessor :clamped_x # panorama is horizontally clamped?
attr_accessor :clamped_y # panorama is vertically clamped?
attr_accessor :wrapping # map is wrapping?
attr_accessor :ambient # ambient light
attr_reader :passages # passage table
@ -39,10 +42,15 @@ class Game_Map
#--------------------------------------------------------------------------
# * List of clamped panorama images
#--------------------------------------------------------------------------
CLAMPED_PANORAMAS = [
CLAMPED = [
'red',
'red_distort',
]
CLAMPED_X = [
]
CLAMPED_Y = [
'red_obsdesk',
]
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
@ -85,6 +93,8 @@ class Game_Map
# Initialize displayed coordinates
@display_x = 0
@display_y = 0
@wrap_x = 0
@wrap_y = 0
# Clear refresh request flag
@need_refresh = false
# Set map event data
@ -114,7 +124,19 @@ class Game_Map
# Clear particles
@particles_type = nil
# Unclamp panorama
@clamped_panorama = CLAMPED_PANORAMAS.include? @panorama_name
if CLAMPED.include? @panorama_name
@clamped_x = true
@clamped_y = true
elsif CLAMPED_X.include? @panorama_name
@clamped_x = true
@clamped_y = false
elsif CLAMPED_Y.include? @panorama_name
@clamped_x = false
@clamped_y = true
else
@clamped_x = false
@clamped_y = false
end
# Unwrap map
@wrapping = false
# Full bright ambient light

View file

@ -54,6 +54,7 @@ class Game_Temp
attr_accessor :debug_top_row # debug screen: for saving conditions
attr_accessor :debug_index # debug screen: for saving conditions
attr_accessor :footstep_sfx # current footstep sfx array
attr_accessor :filmsprite # film puzzle sprite
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
@ -104,5 +105,6 @@ class Game_Temp
@debug_top_row = 0
@debug_index = 0
@footstep_sfx = nil
@filmsprite = nil
end
end

View file

@ -6,6 +6,7 @@
#==============================================================================
class Interpreter
@@chill_pill = false
#--------------------------------------------------------------------------
# * Object Initialization
# depth : nest depth
@ -129,6 +130,11 @@ class Interpreter
Graphics.update
@loop_count = 0
end
# Chill pill
if @@chill_pill
@@chill_pill = false
return
end
# If map is different than event startup time
if $game_map.map_id != @map_id
# Change event ID to 0
@ -306,4 +312,8 @@ class Interpreter
end
end
end
# Chill out
def self.take_a_chill_pill
@@chill_pill = true
end
end

14
scripts/Puzzle_Film.rb Normal file
View file

@ -0,0 +1,14 @@
def film_puzzle_begin
Oneshot.reset_obscured
$game_temp.filmsprite.dispose if $game_temp.filmsprite
filmsprite = Sprite.new
filmsprite.bitmap = RPG::Cache.picture('numbersheet')
filmsprite.z = 9999
filmsprite.obscured = true
$game_temp.filmsprite = filmsprite
end
def film_puzzle_end
$game_temp.filmsprite.dispose if $game_temp.filmsprite
$game_temp.filmsprite = nil
end

View file

@ -50,6 +50,13 @@ def has_lightbulb?
$game_party.item_number(1) > 0
end
def button_pressed?
(1..18).each do |i|
return true if Input.trigger?(i)
end
return false
end
def enter_name
$game_temp.name_calling = true
end
@ -100,10 +107,6 @@ def clear_lights
#$scene.clear_lights
end
def clamp_panorama
$game_map.clamped_panorama = true
end
def wrap_map
$game_map.wrapping = true
end
@ -134,3 +137,7 @@ end
def plight_update_timer
Script.tmp_v1 = ((Time.now - $game_oneshot.plight_timer) / 60).to_i
end
def quit
$scene = nil
end

View file

@ -195,13 +195,16 @@ class Spriteset_Map
@tilemap.oy = $game_map.display_y / 4
@tilemap.update
# Update panorama plane
if $game_map.clamped_panorama
if $game_map.clamped_x
x = ($game_player.real_x.to_f / (($game_map.width - 1) * 128)) * (@panorama.bitmap.width - 640)
y = ($game_player.real_y.to_f / (($game_map.height - 1) * 128)) * (@panorama.bitmap.height - 480)
@panorama.ox = x < 0.0 ? 0.0 : x
@panorama.oy = y < 0.0 ? 0.0 : y
else
@panorama.ox = $game_map.display_x / 8
end
if $game_map.clamped_y
y = ($game_player.real_y.to_f / (($game_map.height - 1) * 128)) * (@panorama.bitmap.height - 480)
@panorama.oy = y < 0.0 ? 0.0 : y
else
@panorama.oy = $game_map.display_y / 8
end
# Update fog plane

View file

@ -139,6 +139,17 @@ class Window_Item < Window_Selectable
$game_system.se_play($data_system.buzzer_se)
return
end
# Run common event of item if valid
item = @data[@index]
if item.common_event_id > 0
$game_temp.common_event_id = item.common_event_id
$game_system.se_play($data_system.decision_se)
@fade_out = true
return
end
# Select or combine items
item_a = $game_variables[1]
item_b = @data[@index].id
if item_a == item_b

View file

@ -194,7 +194,7 @@ class Window_Message < Window_Selectable
@text.sub!(/\[([0-9]+)\]/, "")
color = $1.to_i
if color >= 0 and color <= 7
self.contents.font.color = text_color(color)
self.contents.font.color = Window_Base.text_color(color)
end
# go to next text
next

12
shader/obscured.frag Normal file
View file

@ -0,0 +1,12 @@
uniform sampler2D texture;
uniform sampler2D obscured;
varying vec2 v_texCoord;
void main()
{
vec4 color = texture2D(texture, v_texCoord);
color.a *= texture2D(obscured, v_texCoord).r;
gl_FragColor = color;
}

View file

@ -38,6 +38,8 @@
#include "al-util.h"
#include "debugwriter.h"
#include "oneshot.h"
#include <string.h>
#include <map>
@ -546,6 +548,19 @@ int EventThread::eventFilter(void *data, SDL_Event *event)
Debug() << "SDL_APP_LOWMEMORY";
return 0;
/* Workaround for Windows pausing on drag */
case SDL_WINDOWEVENT:
if (event->window.event == SDL_WINDOWEVENT_MOVED)
{
if (shState->rgssVersion > 0)
{
shState->oneshot().setWindowPos(event->window.data1, event->window.data2);
shState->graphics().update(false);
}
return 0;
}
return 1;
// case SDL_RENDER_TARGETS_RESET :
// Debug() << "****** SDL_RENDER_TARGETS_RESET";
// return 0;

View file

@ -37,6 +37,7 @@
#include "intrulist.h"
#include "binding.h"
#include "debugwriter.h"
#include "oneshot.h"
#include <SDL_video.h>
#include <SDL_timer.h>
@ -484,6 +485,8 @@ struct GraphicsPrivate
* (disposed on reset) */
IntruList<Disposable> dispList;
TEX::ID obscuredTex;
GraphicsPrivate(RGSSThreadData *rtData)
: scRes(DEF_SCREEN_W, DEF_SCREEN_H),
scSize(scRes),
@ -516,6 +519,12 @@ struct GraphicsPrivate
TEXFBO::linkFBO(transBuffer);
fpsLimiter.resetFrameAdjust();
obscuredTex = TEX::gen();
TEX::bind(obscuredTex);
TEX::setRepeat(false);
TEX::setSmooth(false);
gl.TexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE8, 640, 480, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
}
~GraphicsPrivate()
@ -612,6 +621,12 @@ struct GraphicsPrivate
void redrawScreen()
{
if (shState->oneshot().obscuredDirty)
{
TEX::bind(obscuredTex);
TEX::uploadSubImage(0, 0, 640, 480, shState->oneshot().obscuredMap().data(), GL_LUMINANCE);
shState->oneshot().obscuredDirty = false;
}
screen.composite();
GLMeta::blitBeginScreen(winSize);
@ -665,7 +680,7 @@ Graphics::~Graphics()
delete p;
}
void Graphics::update()
void Graphics::update(bool limitFps)
{
p->checkShutDownReset();
p->checkSyncLock();
@ -673,23 +688,33 @@ void Graphics::update()
if (p->frozen)
return;
if (p->fpsLimiter.frameSkipRequired())
if (limitFps)
{
if (p->threadData->config.frameSkip)
if (p->fpsLimiter.frameSkipRequired())
{
/* Skip frame */
p->fpsLimiter.delay();
++p->frameCount;
p->threadData->ethread->notifyFrame();
if (p->threadData->config.frameSkip)
{
/* Skip frame */
p->fpsLimiter.delay();
++p->frameCount;
p->threadData->ethread->notifyFrame();
return;
}
else
{
/* Just reset frame adjust counter */
p->fpsLimiter.resetFrameAdjust();
return;
}
else
{
/* Just reset frame adjust counter */
p->fpsLimiter.resetFrameAdjust();
}
}
}
else
{
if (!p->fpsLimiter.frameSkipRequired())
return;
}
shState->oneshot().update();
p->checkResize();
p->redrawScreen();
@ -1062,3 +1087,8 @@ void Graphics::remDisposable(Disposable *d)
{
p->dispList.remove(d->link);
}
const TEX::ID &Graphics::obscuredTex() const
{
return p->obscuredTex;
}

View file

@ -23,6 +23,7 @@
#define GRAPHICS_H
#include "util.h"
#include "gl-util.h"
class Scene;
class Bitmap;
@ -34,7 +35,7 @@ struct AtomicFlag;
class Graphics
{
public:
void update();
void update(bool limitFps = true);
void freeze();
void transition(int duration = 8,
const char *filename = "",
@ -70,6 +71,8 @@ public:
void repaintWait(const AtomicFlag &exitCond,
bool checkReset = true);
const TEX::ID &obscuredTex() const;
private:
Graphics(RGSSThreadData *data);
~Graphics();

View file

@ -80,6 +80,12 @@ struct OneshotPrivate
std::string txtYes;
std::string txtNo;
//Alpha texture data for portions of window obscured by screen edges
int winX, winY;
bool winPosChanged;
std::vector<uint8_t> obscuredMap;
bool obscuredCleared;
#if defined OS_LINUX
//GTK+
void *libgtk;
@ -205,6 +211,11 @@ Oneshot::Oneshot(const RGSSThreadData &threadData)
p = new OneshotPrivate();
p->window = threadData.window;
p->savePath = threadData.config.commonDataPath.substr(0, threadData.config.commonDataPath.size() - 1);
p->obscuredMap.resize(640 * 480, 255);
obscuredDirty = true;
p->winX = 0;
p->winY = 0;
p->winPosChanged = false;
/********************
* USERNAME/SAVE PATH
@ -337,6 +348,69 @@ Oneshot::~Oneshot()
delete p;
}
void Oneshot::update()
{
if (p->winPosChanged)
{
p->winPosChanged = false;
//Map of unobscured pixels in this frame
static std::vector<bool> obscuredFrame(p->obscuredMap.size());
std::fill(obscuredFrame.begin(), obscuredFrame.end(), true);
SDL_Rect screenRect;
screenRect.x = p->winX;
screenRect.y = p->winY;
screenRect.w = 640;
screenRect.h = 480;
//Update obscured map and texture for window portion offscreen
for (int i = 0, max = SDL_GetNumVideoDisplays(); i < max; ++i)
{
SDL_Rect bounds;
SDL_GetDisplayBounds(i, &bounds);
//If it's fully within the monitor, it's completely unobscured
//and no texture update is necessary
if (p->winX >= bounds.x && p->winY >= bounds.y && p->winX + 640 <= bounds.x + bounds.w && p->winY + 480 <= bounds.y + bounds.h)
return;
//Update obscuredFrame otherwise
SDL_Rect intersect;
if (!SDL_IntersectRect(&screenRect, &bounds, &intersect))
continue;
intersect.x -= p->winX;
intersect.y -= p->winY;
for (int y = intersect.y; y < intersect.y + intersect.h; ++y)
{
int start = y * 640 + intersect.x;
std::fill(obscuredFrame.begin() + start, obscuredFrame.begin() + (start + intersect.w), false);
}
}
//Update the obscured map, and return prematurely if we don't have any changes
//to make to the texture
bool needsUpdate = false;
bool cleared = true;
for (size_t i = 0; i < obscuredFrame.size(); ++i)
{
if (obscuredFrame[i])
{
p->obscuredMap[i] = 0;
needsUpdate = true;
}
if (p->obscuredMap[i] == 255)
cleared = false;
}
p->obscuredCleared = cleared;
if (!needsUpdate)
return;
//Flag as dirty
obscuredDirty = true;
}
}
const std::string &Oneshot::lang() const
{
return p->lang;
@ -352,6 +426,16 @@ const std::string &Oneshot::savePath() const
return p->savePath;
}
const std::vector<uint8_t> &Oneshot::obscuredMap() const
{
return p->obscuredMap;
}
bool Oneshot::obscuredCleared() const
{
return p->obscuredCleared;
}
void Oneshot::setYesNo(const char *yes, const char *no)
{
p->txtYes = yes;
@ -458,3 +542,16 @@ bool Oneshot::msgbox(int type, const char *body, const char *title)
return button ? true : false;
#endif
}
void Oneshot::setWindowPos(int x, int y)
{
p->winX = x;
p->winY = y;
p->winPosChanged = true;
}
void Oneshot::resetObscured()
{
std::fill(p->obscuredMap.begin(), p->obscuredMap.end(), 255);
obscuredDirty = true;
}

View file

@ -42,17 +42,26 @@ public:
GRADIENT_VERTICAL,
};
void update();
//Accessors
const std::string &lang() const;
const std::string &userName() const;
const std::string &savePath() const;
const std::vector<uint8_t> &obscuredMap() const;
bool obscuredCleared() const;
//Mutators
void setYesNo(const char *yes, const char *no);
void setWindowPos(int x, int y);
void resetObscured();
//Functions
bool msgbox(int type, const char *body, const char *title);
//Dirty flag for obscured texture
bool obscuredDirty;
private:
OneshotPrivate *p;
};

View file

@ -52,6 +52,7 @@
#include "blurH.vert.xxd"
#include "blurV.vert.xxd"
#include "tilemapvx.vert.xxd"
#include "obscured.frag.xxd"
#define INIT_SHADER(vert, frag, name) \
@ -641,3 +642,17 @@ void BltShader::setOpacity(float value)
{
gl.Uniform1f(u_opacity, value);
}
ObscuredShader::ObscuredShader()
{
INIT_SHADER(simple, obscured, ObscuredShader);
ShaderBase::init();
GET_U(obscured);
}
void ObscuredShader::setObscured(const TEX::ID value)
{
setTexUniform(u_obscured, 1, value);
}

View file

@ -304,6 +304,18 @@ private:
GLint u_source, u_destination, u_subRect, u_opacity;
};
/* Obscured graphic */
class ObscuredShader : public ShaderBase
{
public:
ObscuredShader();
void setObscured(const TEX::ID value);
private:
GLint u_obscured;
};
/* Global object containing all available shaders */
struct ShaderSet
{
@ -325,6 +337,7 @@ struct ShaderSet
SimpleMatrixShader simpleMatrix;
BlurShader blur;
TilemapVXShader tilemapVX;
ObscuredShader obscured;
};
#endif // SHADER_H

View file

@ -33,6 +33,8 @@
#include "shader.h"
#include "glstate.h"
#include "quadarray.h"
#include "config.h"
#include "debugwriter.h"
#include <math.h>
@ -64,6 +66,8 @@ struct SpritePrivate
* the screen if drawn? */
bool isVisible;
bool obscured;
Color *color;
Tone *tone;
@ -95,6 +99,7 @@ struct SpritePrivate
opacity(255),
blendType(BlendNormal),
isVisible(false),
obscured(false),
color(&tmp.color),
tone(&tmp.tone)
@ -322,6 +327,7 @@ DEF_ATTR_SIMPLE(Sprite, Opacity, int, p->opacity)
DEF_ATTR_SIMPLE(Sprite, SrcRect, Rect&, *p->srcRect)
DEF_ATTR_SIMPLE(Sprite, Color, Color&, *p->color)
DEF_ATTR_SIMPLE(Sprite, Tone, Tone&, *p->tone)
DEF_ATTR_SIMPLE(Sprite, Obscured, bool, p->obscured)
void Sprite::setBitmap(Bitmap *bitmap)
{
@ -518,7 +524,15 @@ void Sprite::draw()
flashing ||
p->bushDepth != 0;
if (renderEffect)
if (p->obscured)
{
ObscuredShader &shader = shState->shaders().obscured;
shader.bind();
shader.applyViewportProj();
shader.setObscured(shState->graphics().obscuredTex());
base = &shader;
}
else if (renderEffect)
{
SpriteShader &shader = shState->shaders().sprite;

View file

@ -66,6 +66,7 @@ public:
DECL_ATTR( WaveLength, int )
DECL_ATTR( WaveSpeed, int )
DECL_ATTR( WavePhase, float )
DECL_ATTR( Obscured, bool )
void initDynAttribs();