Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - raycrasher

Pages: [1]
1
Graphics / How to draw masked / stenciled graphics?
« on: June 20, 2013, 05:31:28 am »
In my project I have to draw damage sprites (hull breaches, smoldering twisted metal, etc.) over ships depending on where they are hit. The problem is, I want those damage sprites to be drawn only over non-transparent parts of the ship, because drawing a burning piece of bulkhead over empty space looks plain weird.  So I'm asking for help on how should I do this.

Stencil masks? Render to texture? Shaders?

Currently, I'm thinking along the lines of the following:

1. Draw hull(s) normally, but also draw to stencil all pixels which has alpha==255.
2. Draw damage sprites, using stencil mask.
3. Reset stencil so that subsequent draws will not be affected.

But how, OpenGL and code wise? Many thanks in advance!

2
DotNet / Why P/Invoke?
« on: May 14, 2013, 07:28:12 am »
I'm just wondering why SFML.NET uses P/Invoke and not a C++/CLI wrapper?

I have read that a custom C++/CLI wrapper gives better performance that using P/Invoke : manual marshalling, coarse interfaces, etc. Especially when using SFML.NET, since there's an additional layer involved (CSFML). I had previous experience wrapping up the libRocket GUI library for use in .NET, and it works great, so it should work for SFML.

Also, a little background: I have been getting weird errors when using the latest version of the .NET binding, so as a result, I'm creating my own C++/CLI wrapper for use in C#. That took care of the errors, and it runs great, but it still needs some work.

3
Code: [Select]
Failed to set pixel format for device context -- cannot create OpenGL context
SFML.NET (latest version from GitHub) gives this error when creating a RenderWindow. Sample code not given, since the same error occurs with the OpenGL samples (be sure to enable the console window). I would be content to just ignore the error if SFML works regardless, but my program, which worked fine with SFML.NET RC downloaded from the main SFML site, doesn't display fonts/renders sprites as white rectangles with the Github version. I need the latest version in order to use the new Draw overloads for RenderWindow.


OS: Windows 8
Video: Nvidia GeForce GT 220 (driver version 306.14).

I'm currently updating my video card drivers just in case.

Help!

4
SFML wiki / Sprite batching that works with multiple textures
« on: February 10, 2013, 09:29:13 am »
Here's a SpriteBatch class I created that allows you to just put in sf::Sprites without regard for texture. The class automatically constructs sf::VertexArrays for consecutive sprites with the same texture, blend mode, and shader. It's derived from sf::Drawable and sf::Transformable, so you can use it much like a sprite.

Tell me what you think. I'm sure this class still has much room for improvement. Also, feel free to use and modify it for your projects.

EDIT: I haven't posted this to the wiki yet, but I will post if this is useful.

To use:

sf::Sprite spr;

...

SpriteBatch batch;
SpriteBatchItem theSubItem = batch.AddItem(spr); // add a sprite. Differing textures are automatically handled.
SpriteBatchItem theSubItem2 = batch.AddItem(spr, sf::BlendAdd, myShader); // specify different blend mode and shader (this creates a different batch if the previous add is different in texture, blend mode or shader)

theSubItem.setPosition(50.f,50.f); // you can use sf::Transformable methods
theSubItem.setColor(sf::Color::White); // you can set the color of all 4 vertices
theSubItem.setColor(sf::Color::Red,2); // you can set the color of the third vertex (index 2)
theSubItem.UpdateSpriteBatch(); // update the sprite batch (update only if the sprite batch item is transformed

window.draw(batch); // draw the batch

batch.RemoveItem(theSubItem2); // remove a batch item
 

Requires: weak_ptr, shared_ptr, C++11

SpriteBatch.h
#pragma once

#include <list>

class SpriteBatchItem;

class SpriteBatch: public sf::Drawable, public sf::Transformable {
   friend class SpriteBatchItem;

   struct Batch {
      sf::RenderStates states;
      std::vector<sf::Vertex> vertices;
   };

   struct Quad {
      std::list<Batch>::iterator batch;
      std::list<shared_ptr<Quad>>::iterator quadIter;
      int vertexIndex;
      sf::IntRect texCoords;
      SpriteBatch *spriteBatch;
   };



public:

   SpriteBatch();
   ~SpriteBatch();

   SpriteBatchItem AddItem(const sf::Sprite &spr, sf::BlendMode blendMode=sf::BlendAlpha, sf::Shader *shader=nullptr);
   void RemoveItem(SpriteBatchItem &item);
   sf::FloatRect GetLocalBounds();
   sf::FloatRect GetGlobalBounds();
   void Clear();

protected:
   void draw(sf::RenderTarget &target, sf::RenderStates states) const;
private:
   
   sf::FloatRect bounds;
   bool boundsInvalidated;
   std::list<shared_ptr<Quad>> quads;
   std::list<Batch> batches;
};

class SpriteBatchItem: public sf::Transformable {
   friend class SpriteBatch;
public:
   void SetColor(const sf::Color &c, unsigned vtx=4);
   sf::Color GetColor(unsigned vtx=0);
   bool IsValid();
   void UpdateSpriteBatch();
   SpriteBatch &GetSpriteBatch();

   sf::FloatRect GetLocalBounds() const;
   sf::FloatRect GetGlobalBounds() const;

private:
   weak_ptr<SpriteBatch::Quad> quad;
};
 

SpriteBatch.cpp
#include "SpriteBatch.h"

SpriteBatch::SpriteBatch(){}
SpriteBatch::~SpriteBatch(){}

SpriteBatchItem SpriteBatch::AddItem(const sf::Sprite &spr, sf::BlendMode blendMode, sf::Shader *shader) {
   if(batches.empty() || (spr.getTexture() != batches.back().states.texture) || blendMode != batches.back().states.blendMode || shader != batches.back().states.shader) {
      batches.push_back(Batch());
      batches.back().states.texture=spr.getTexture();
      batches.back().states.shader=shader;
      batches.back().states.blendMode=blendMode;
   }

   shared_ptr<Quad> q(new Quad);
   q->batch = (--batches.end());
   q->spriteBatch = this;
   q->vertexIndex = batches.back().vertices.size();
   q->texCoords = spr.getTextureRect();

   batches.back().vertices.resize(batches.back().vertices.size()+4);
   q->batch->vertices[q->vertexIndex].texCoords=sf::Vector2f((float)q->texCoords.left,(float)q->texCoords.top);
   q->batch->vertices[q->vertexIndex+1].texCoords=sf::Vector2f((float)q->texCoords.left,(float)q->texCoords.top+q->texCoords.height);
   q->batch->vertices[q->vertexIndex+2].texCoords=sf::Vector2f((float)q->texCoords.left+q->texCoords.width,(float)q->texCoords.top+q->texCoords.height);
   q->batch->vertices[q->vertexIndex+3].texCoords=sf::Vector2f((float)q->texCoords.left+q->texCoords.width,(float)q->texCoords.top);
   
   

   quads.push_back(q);
   q->quadIter=(--quads.end());

   

   static SpriteBatchItem sbi;
   sbi.quad = q;
   sbi.SetColor(spr.getColor());
   sbi.setOrigin(spr.getOrigin());
   sbi.setPosition(spr.getPosition());
   sbi.setScale(spr.getScale());
   sbi.UpdateSpriteBatch();
   return sbi;
}

void SpriteBatch::RemoveItem(SpriteBatchItem &item) {
   auto q=item.quad.lock();
   if(q && q->spriteBatch==this){
      auto start=q->quadIter;
      start++;
      q->batch->vertices.erase(q->batch->vertices.begin()+q->vertexIndex,q->batch->vertices.begin()+q->vertexIndex+4);
      for(auto iter=start;iter!=quads.end();iter++){
         if(q->batch == (*iter)->batch) {
            (*iter)->vertexIndex-=4;
         }
      }
      if(q->batch->vertices.size()==0) batches.erase(q->batch);
      quads.erase(q->quadIter);
   }
}

void SpriteBatch::draw(sf::RenderTarget &target, sf::RenderStates states) const {
   states.transform*=getTransform();
   for(auto &b : batches){
      states.texture=b.states.texture;
      states.shader=b.states.shader;
      states.blendMode=b.states.blendMode;
      target.draw(&b.vertices[0],b.vertices.size(),sf::Quads,states);
   }
}

void SpriteBatch::Clear() {
   quads.clear();
   batches.clear();
}


void SpriteBatchItem::UpdateSpriteBatch() {
   auto q=quad.lock();
   if(q){
      sf::Vertex *vtx[4] = {
         &q->batch->vertices[q->vertexIndex],
         &q->batch->vertices[q->vertexIndex+1],
         &q->batch->vertices[q->vertexIndex+2],
         &q->batch->vertices[q->vertexIndex+3]
      };

      vtx[0]->position = getTransform().transformPoint(sf::Vector2f(0.f, 0.f));
      vtx[1]->position = getTransform().transformPoint(sf::Vector2f(0.f, (float)q->texCoords.height));
      vtx[2]->position = getTransform().transformPoint(sf::Vector2f((float)q->texCoords.width, (float)q->texCoords.height));
      vtx[3]->position = getTransform().transformPoint(sf::Vector2f((float)q->texCoords.width, 0.f));
   }
}

void SpriteBatchItem::SetColor( const sf::Color &c, unsigned vtx ) {
   auto q=quad.lock();
   if(q){
      if(vtx >= 4){
         q->batch->vertices[q->vertexIndex].color=c;
         q->batch->vertices[q->vertexIndex+1].color=c;
         q->batch->vertices[q->vertexIndex+2].color=c;
         q->batch->vertices[q->vertexIndex+3].color=c;
      } else {
         q->batch->vertices[q->vertexIndex+vtx].color=c;
      }
   }
}

sf::Color SpriteBatchItem::GetColor(unsigned vtx) {
   auto q=quad.lock();
   if(q){
      if(vtx >= 4) vtx=0;
      return q->batch->vertices[q->vertexIndex+vtx].color;
   }
   else return sf::Color(0.f,0.f,0.f,0.f);
}

bool SpriteBatchItem::IsValid() {
   return ((bool) quad.lock());
}

SpriteBatch &SpriteBatchItem::GetSpriteBatch() {
   return *quad.lock()->spriteBatch;
}

sf::FloatRect SpriteBatch::GetLocalBounds()
{
   if(boundsInvalidated)
   {
      sf::Vector2f topleft(0.f,0.f),bottomRight(0.f,0.f);

      for(auto &b : batches){
         for(auto &v : b.vertices){
            topleft.x = std::min(topleft.x,v.position.x);
            topleft.y = std::min(topleft.y,v.position.y);
            bottomRight.x=std::max(bottomRight.x,v.position.x);
            bottomRight.y=std::max(bottomRight.y,v.position.y);
         }
      }
      bounds=sf::FloatRect (topleft,bottomRight-topleft);
      boundsInvalidated=false;
   }
   
   return bounds;
}

sf::FloatRect SpriteBatch::GetGlobalBounds() {
   return getTransform().transformRect(GetLocalBounds());
}

sf::FloatRect SpriteBatchItem::GetLocalBounds() const
{
   auto q=quad.lock();
   if(q){
      return sf::FloatRect(0.f, 0.f, (float) q->texCoords.width, (float) q->texCoords.height);
   }
   else return sf::FloatRect();
}


////////////////////////////////////////////////////////////
sf::FloatRect SpriteBatchItem::GetGlobalBounds() const
{
   return getTransform().transformRect(GetLocalBounds());
}
 

5
SFML projects / Cloud Wars - WIP
« on: July 18, 2012, 02:38:12 pm »
Hello!

I would like to present my pet project, Cloud Wars - a space tactical game in the spirit of Battleships Forever(http://www.wyrdysm.com/games.php), but with significant RPG elements. It is still very much a work in progress - all that is finished are the Ship Editor, the GUI (libRocket), the Lua script bindings (Diluculum and SLB), resource managers, particle systems, Box2d physics, and other bits and pieces. The ship sprites are from community resources from Battleships Forever (I have asked permission), slightly edited. All other resources are made by me or from public domain graphics (such as nebulae)

The reason why I'm posting this unfinished project is that I just want to hear ideas from the community for me to mull over whenever I'm stuck. If you want a look at the code, I can send you the code and data.

Some areas on which I need feedback are on the following:

  • Steering behaviors with Box2d. I already read Steering Behaviors for Autonomous Characters (www.red3d.com/cwr/steer/ ) and I'm basing the code from this. The thing that I'm not sure of is how to apply the resultant steering vector to the ship. Thrusters? Pull the ship by the nose? (I tried the latter, it works, but you get some kind of pendulum effect (can be mitigated), and I can't simulate thrusters.) Also, prioritizing/blending steering vectors.
  • A console-based alternative input system, using a syntax somewhat similar to natural language. For example, typing "Leviathan attack all", or "Grizzly retreat BaseRallyPoint" will give the corresponding orders to the named ships. Of course you can use the mouse/keyboard shortcuts, but you can set advanced orders through a console, like "All ships set DefensivePerimeter at WarpPointAlpha radius 500m until enemy detected at Sector Beta or timeout 5min". Automatic suggestions are also available as you type.
  • Control ANY entity, from small fighters, to large ships, to fleets. Different control systems for fighters, gunships, ships and fleets.

I can also offer working code for sprite batching, particle systems, the libRocket GUI interfaces, and the Lua scripting system if anyone's interested.

Thank you for SFML - it's a really great library!



Screenies:

6
Graphics / infinitely repeating background
« on: January 27, 2012, 05:29:46 am »
Hello,

How do I implement an infinitely repeating background that will work well with parallax and camera movement/zooming?

I was thinking about using a small texture with repeating on, and a scaled sprite with an overly large texture rectangle, but it wouldn't be infinite, wouldn't it? ;) And I'm not sure about the math involved in drawing the backgrounds side by side while accounting for camera location and zoom.

FYI, for the parallax, I used a custom Transform passed to window.Render() in which the position of an object is multiplied by a parallax factor and the scale by the zoom factor; and for the camera I used sf::View. The system works quite perfectly, but I am baffled about how to implement the infinite background.

Thanks in advance!  :D

Pages: [1]