sexta-feira, 4 de novembro de 2011

Vector Editor - Progress update

Uploaded a couple more videos:


This one shows the grid of points created inside the shape to later do tesselation (decompose the inside of the shape into polygons), which will be shaded using vertex colors, smoothly interpolating the colors between each vertex.

The shape is built using Java's GeneralPath, the control point coordinates are converted from Catmull-Rom to Bezier using a matrix.



This shows color interpolation for those inner points, using an algorithm that I created. Works nicely for any points in any position, even for points inside the shape (which in the literature I managed to find, presented a problem for most interpolation algorithms when dealing with polygons). I'm quite happy with the solution! :)

domingo, 30 de outubro de 2011

Vector Editor (Video)

I've been working on a vector editor program that uses control points to define shapes and colors. Here's an initial video of it in action, in a very early state (I liked the color effects :))

I'm doing the editor in Java using Netbeans as development environment, and using Processing for many things (love it), and maths from all over the internet.

I move, add and delete some points.


Music is from "The Hybrid Front", Sega Genesis/Mega Drive game, 1994.
Composed by Naofumi Hataya.

Other than that, been working hard on some flash action games, but not quite ready to show them yet!

terça-feira, 24 de maio de 2011

An easier BitmapData.draw

After lots of struggling with ActionScript's BitmapData "draw" function, with trying to render a tileset using a zoom factor (by applying a scale, and selecting the area inside a larger tileset image to draw from), I decided to create a couple of helper functions, so that I never have to figure out again what the variables do in the "draw" call.

Here, I present to you a couple of functions. The first, "DrawImageAreaScaled", basically draws an upscaled rectangular sub-area of a picture wherever on another image (or on the screen). The second, "DrawImageScaledAndRotated", draws a rotated and scaled picture on the screen.
Transparency is respected (if the image contains alpha information, transparent pixels are drawn correctly).

This can easily be applied to, say, Flixel, by passing as the first parameter "FlxG.buffer" as the destination image, and "your_FlxSprite.pixels" as source (see example below).

Below is the class, and under it, an example on how to use it using Flixel.

P.S.: don't expect too great a performance, since BitmapData.draw is a somewhat slow function, specially when called several times a second to display, say, a tileset.

Class "Render.as" in folder "Utils":

package Utils
{
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;

/**
* Contains helper Renderer functions.
* @author PJMendes aka TurboLento
*/
public class Render
{
// helper variables - initialized once, reused at every function called
private static var DrawClipRect:Rectangle = new Rectangle(0, 0, 0, 0); // area on screen to draw (sort of a mask)
private static var DrawMatrix:Matrix = new Matrix();

/**
* Helper for a simpler BitmapData.draw. Draws a rectangular area of an image on the screen, using syntax similar to copyPixels.
* Useful for drawing scaled tiles (performance isn't great though, due to "draw" being slow).
* @param imgSource The image to draw from.
* @param imgDestination The image to draw to
* @param areaSource The area in the source image to draw from.
* @param positionDestination The x,y position on the destination to draw to.
* @param scale The scaling to apply to the drawn image (areaSource will be multiplied by this dimension in the final drawing).
*/
public static function DrawImageAreaScaled(imgSource:BitmapData, imgDestination:BitmapData, areaSource:Rectangle, positionDestination:Point, scale:Point = null, rotationRadians:Number = 0): void
{
DrawMatrix.identity();
DrawMatrix.rotate(rotationRadians);

if (scale != null)
{
DrawMatrix.scale(scale.x, scale.y);

DrawClipRect.width = areaSource.width * scale.x; // i think this is it
DrawClipRect.height = areaSource.height * scale.y;

DrawClipRect.x = positionDestination.x; // i think this is it - making clipRect sort of a "window" on the destination where source will appear
DrawClipRect.y = positionDestination.y;

DrawMatrix.translate(positionDestination.x - areaSource.x * scale.x, positionDestination.y - areaSource.y * scale.y);
}
else
{
DrawClipRect.width = areaSource.width; // i think this is it
DrawClipRect.height = areaSource.height;

DrawClipRect.x = positionDestination.x; // i think this is it - making clipRect sort of a "window" on the destination where source will appear
DrawClipRect.y = positionDestination.y;

DrawMatrix.translate(positionDestination.x - areaSource.x, positionDestination.y - areaSource.y);
}

imgDestination.draw(imgSource, DrawMatrix, null, null, DrawClipRect);
}

/**
* Helper for a simpler BitmapData.draw. Draws an image on the screen, scaled and rotated, using syntax similar to copyPixels.
* Useful for drawing scaled tiles (performance isn't great though, due to "draw" being slow).
* @param imgSource The image to draw from.
* @param imgDestination The image to draw to
* @param positionDestination The x,y position on the destination to draw to.
* @param scale The scaling to apply to the drawn image (areaSource will be multiplied by this dimension in the final drawing).
* @param rotationRadians The rotation in radians to apply to the drawn image. Axis for rotation is the top left of the source image.
*/
public static function DrawImageScaledAndRotated(imgSource:BitmapData, imgDestination:BitmapData, positionDestination:Point, scale:Point = null, rotationRadians:Number = 0): void
{
DrawMatrix.identity();

DrawMatrix.rotate(rotationRadians);

if (scale != null)
{
DrawMatrix.scale(scale.x, scale.y);

DrawMatrix.translate(positionDestination.x, positionDestination.y);
}
else
{
DrawMatrix.translate(positionDestination.x, positionDestination.y);
}

imgDestination.draw(imgSource, DrawMatrix, null, null, null);
}
}
}


Example class:

package
{
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import org.flixel.FlxSprite;
import org.flixel.FlxState;
import org.flixel.FlxG;
import Utils.Render;

/**
* ...
* @author
*/
public class TestState extends FlxState
{
[Embed(source = "/../data/test.png")] protected var ImgTileset:Class;
[Embed(source = "/../data/player_sprite.png")] protected var ImgPlayer:Class;

private var img:FlxSprite;
private var img2:FlxSprite;

override public function create():void
{
super.create();
img = new FlxSprite(0, 0, ImgTileset);
img2 = new FlxSprite(0, 0, ImgPlayer);
}


override public function update():void
{
//trace("update");
super.update();
}

override public function render():void
{
//trace("render; DataManagerHasLoaded "+ DataManagerHasLoaded +" TilemapHasLoaded "+ TilemapHasLoaded);


// render method 1
var srcRect:Rectangle = new Rectangle(0, 0, img.width, img.height);
var destPoint:Point = new Point(320, 0);
FlxG.buffer.copyPixels(img.pixels, srcRect, destPoint);


// render method 2
var scale:Point = null;
var destPoint:Point = null;
var rectSource:Rectangle = null;

//rectSource = new Rectangle(0, 0, img.width, img.height);
//rectSource = new Rectangle(0, 0, 32, 32);

rectSource = new Rectangle(64, 32, 32, 32);
destPoint = new Point(FlxG.mouse.x, FlxG.mouse.y);

scale = new Point(2, 2);

Render.DrawImageAreaScaled(img.pixels, FlxG.buffer, rectSource, destPoint, scale);
//Render.DrawImageScaledAndRotated(img.pixels, FlxG.buffer, destPoint, scale, 0.2);


// test with img with transparency
rectSource = new Rectangle(0, 0, img2.width, img2.height);
//Render.DrawImageAreaScaled(img2.pixels, FlxG.buffer, rectSource, destPoint, scale);
Render.DrawImageScaledAndRotated(img2.pixels, FlxG.buffer, destPoint, scale, 0.2);

super.render();
}
}
}


Hope this is helpful!

quarta-feira, 23 de fevereiro de 2011

Trying to Keep it Simpler, doing more with less (effort)

- Going through the continuous process of learning, doing, and learning from doing.
- Reducing the scope for what I want to do, and go through the process of starting, developing and finishing my projects.
- Dealing with demotivation and boredom, by cycling projects - start project A, reach a point where I'm bored/tired/demotivated, get interested in project B, reach that same point, and go back to project A, now with a fresh outlook on it, and breaking through the point where I got stuck previously.

- having lots of fun with ActionScript, can't recommend it enough for simpler games (unfortunately current Flash performance is weak, allows the creation of games similar to the Super Nintendo, on a technology/performance level)

- creating a few games for Flash, using ActionScript, Flixel and FlashDevelop as the Integrated Development Environment. Reading stuff about business, game business and flash game business, how to monetize the games I'm making.

- swore off C/C++, due to annoyingly complicated and unnecessary stuff like includes, defining/using static classes (as enums), errors due to having to manually manage memory, compilation, using other libraries, and language complexity in general. I want to develop fun games, not become a C++ pro, and I feel I waste lots of time dealing with the "low level" part of the language.

Trying out doing stuff in Java using the "Slick" library, for projects more advanced than Flash allows (hardware accelerated drawing, heavy processing, etc). Java pretty much skips/solves all of these problems, and if I need performance, I can always learn how to invoke dlls from Java and code heavier functions in C (although Java's bad reputation on performance is something that isn't always true, if some care is taken when coding).