Skip to content
17 changes: 17 additions & 0 deletions ext/ruby2d/gl.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,23 @@ void R2D_GL_DrawSprite(R2D_Sprite *spr) {
}


/*
* Draw a tile
*/
void R2D_GL_DrawTile(R2D_Image *img, int x, int y, int tw, int th, GLfloat tx1, GLfloat ty1, GLfloat tx2,
GLfloat ty2, GLfloat tx3, GLfloat ty3, GLfloat tx4, GLfloat ty4) {
#if GLES
R2D_GLES_DrawTile(img, x, y, tw, th, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
#else
if (R2D_GL2) {
R2D_GL2_DrawTile(img, x, y, tw, th, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
} else {
R2D_GL3_DrawTile(img, x, y, tw, th, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
}
#endif
}


/*
* Draw text
*/
Expand Down
15 changes: 15 additions & 0 deletions ext/ruby2d/gl2.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,21 @@ void R2D_GL2_DrawSprite(R2D_Sprite *spr) {
}


/*
* Draw a tile
*/
void R2D_GL2_DrawTile(R2D_Image *img, int x, int y, int tw, int th, GLfloat tx1, GLfloat ty1, GLfloat tx2,
GLfloat ty2, GLfloat tx3, GLfloat ty3, GLfloat tx4, GLfloat ty4) {
R2D_GL2_DrawTexture(
x, y, tw, th,
img->rotate, img->rx, img->ry,
img->color.r, img->color.g, img->color.b, img->color.a,
tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4,
img->texture_id
);
}


/*
* Draw text
*/
Expand Down
15 changes: 15 additions & 0 deletions ext/ruby2d/gl3.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,21 @@ void R2D_GL3_DrawSprite(R2D_Sprite *spr) {
}


/*
* Draw a tile
*/
void R2D_GL3_DrawTile(R2D_Image *img, int x, int y, int tw, int th, GLfloat tx1, GLfloat ty1, GLfloat tx2,
GLfloat ty2, GLfloat tx3, GLfloat ty3, GLfloat tx4, GLfloat ty4) {
R2D_GL3_DrawTexture(
x, y, tw, th,
img->rotate, img->rx, img->ry,
img->color.r, img->color.g, img->color.b, img->color.a,
tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4,
img->texture_id
);
}


/*
* Draw text
*/
Expand Down
15 changes: 15 additions & 0 deletions ext/ruby2d/gles.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,21 @@ void R2D_GLES_DrawSprite(R2D_Sprite *spr) {
}


/*
* Draw a tile
*/
void R2D_GLES_DrawTile(R2D_Image *img, int x, int y, int tw, int th, GLfloat tx1, GLfloat ty1, GLfloat tx2,
GLfloat ty2, GLfloat tx3, GLfloat ty3, GLfloat tx4, GLfloat ty4) {
R2D_GLES_DrawTexture(
x, y, tw, th,
img->rotate, img->rx, img->ry,
img->color.r, img->color.g, img->color.b, img->color.a,
tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4,
img->texture_id
);
}


/*
* Draw text
*/
Expand Down
53 changes: 53 additions & 0 deletions ext/ruby2d/ruby2d.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,50 @@ static void free_sprite(R2D_Sprite *spr) {
}


/*
* Ruby2D::Tileset#ext_init
* Initialize tileset data
*/
static R_VAL ruby2d_tileset_ext_init(R_VAL self, R_VAL path) {
R2D_Image *img = R2D_CreateImage(RSTRING_PTR(path));
if (!img) return R_FALSE;

// Get width and height from Ruby class. If set, use it, else choose the
// native dimensions of the image.
R_VAL w = r_iv_get(self, "@width");
R_VAL h = r_iv_get(self, "@height");
r_iv_set(self, "@width" , r_test(w) ? w : INT2NUM(img->width));
r_iv_set(self, "@height", r_test(h) ? h : INT2NUM(img->height));
r_iv_set(self, "@data", r_data_wrap_struct(image, img));

return R_TRUE;
}


/*
* Ruby2D::Tileset#ext_draw
* Draws a single tile, will be called once per individual tile to draw
*/
static R_VAL ruby2d_tileset_ext_draw(R_VAL self, R_VAL a) {
// `a` is the array representing the tileset

R2D_Image *img;
r_data_get_struct(r_ary_entry(a, 0), "@data", &image_data_type, R2D_Image, img);

int tw = NUM2INT(r_ary_entry(a, 1));
int th = NUM2INT(r_ary_entry(a, 2));
int padding = NUM2INT(r_ary_entry(a, 3));
int spacing = NUM2INT(r_ary_entry(a, 4));
int tx = NUM2INT(r_ary_entry(a, 5));
int ty = NUM2INT(r_ary_entry(a, 6));
int x = NUM2INT(r_ary_entry(a, 7));
int y = NUM2INT(r_ary_entry(a, 8));

R2D_DrawTile(img, tw, th, padding, spacing, tx, ty, x, y);
return R_NIL;
}


/*
* Ruby2D::Text#ext_init
* Initialize text structure data
Expand Down Expand Up @@ -1246,6 +1290,15 @@ void Init_ruby2d() {
// Ruby2D::Sprite#self.ext_draw
r_define_class_method(ruby2d_sprite_class, "ext_draw", ruby2d_sprite_ext_draw, r_args_req(1));

// Ruby2D::Tileset
R_CLASS ruby2d_tileset_class = r_define_class(ruby2d_module, "Tileset");

// Ruby2D::Tileset#ext_init
r_define_method(ruby2d_tileset_class, "ext_init", ruby2d_tileset_ext_init, r_args_req(1));

// Ruby2D::Tileset#self.ext_draw
r_define_class_method(ruby2d_tileset_class, "ext_draw", ruby2d_tileset_ext_draw, r_args_req(1));

// Ruby2D::Text
R_CLASS ruby2d_text_class = r_define_class(ruby2d_module, "Text");

Expand Down
21 changes: 21 additions & 0 deletions ext/ruby2d/ruby2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,13 @@ void R2D_DrawSprite(R2D_Sprite *spr);
*/
void R2D_FreeSprite(R2D_Sprite *spr);

// Tile ////////////////////////////////////////////////////////////////////////

/*
* Draw a tile
*/
void R2D_DrawTile(R2D_Image *img, int tw, int th, int padding, int spacing, int tx, int ty, int x, int y);

// Text ////////////////////////////////////////////////////////////////////////

/*
Expand Down Expand Up @@ -715,6 +722,8 @@ void R2D_GL_DrawTriangle(
GLfloat r3, GLfloat g3, GLfloat b3, GLfloat a3);
void R2D_GL_DrawImage(R2D_Image *img);
void R2D_GL_DrawSprite(R2D_Sprite *spr);
void R2D_GL_DrawTile(R2D_Image *img, int x, int y, int tw, int th, GLfloat tx1, GLfloat ty1, GLfloat tx2,
GLfloat ty2, GLfloat tx3, GLfloat ty3, GLfloat tx4, GLfloat ty4);
void R2D_GL_DrawText(R2D_Text *txt);
void R2D_GL_FreeTexture(GLuint *id);
void R2D_GL_Clear(R2D_Color clr);
Expand All @@ -734,6 +743,10 @@ void R2D_GL_FlushBuffers();
GLfloat r3, GLfloat g3, GLfloat b3, GLfloat a3);
void R2D_GLES_DrawImage(R2D_Image *img);
void R2D_GLES_DrawSprite(R2D_Sprite *spr);
void R2D_GLES_DrawTile(R2D_Image *img, int x, int y,
int tw, int th,
GLfloat tx1, GLfloat ty1, GLfloat tx2, GLfloat ty2,
GLfloat tx3, GLfloat ty3, GLfloat tx4, GLfloat ty4);
void R2D_GLES_DrawText(R2D_Text *txt);
#else
int R2D_GL2_Init();
Expand All @@ -758,6 +771,14 @@ void R2D_GL_FlushBuffers();
void R2D_GL3_DrawImage(R2D_Image *img);
void R2D_GL2_DrawSprite(R2D_Sprite *spr);
void R2D_GL3_DrawSprite(R2D_Sprite *spr);
void R2D_GL2_DrawTile(R2D_Image *img, int x, int y,
int tw, int th,
GLfloat tx1, GLfloat ty1, GLfloat tx2, GLfloat ty2,
GLfloat tx3, GLfloat ty3, GLfloat tx4, GLfloat ty4);
void R2D_GL3_DrawTile(R2D_Image *img, int x, int y,
int tw, int th,
GLfloat tx1, GLfloat ty1, GLfloat tx2, GLfloat ty2,
GLfloat tx3, GLfloat ty3, GLfloat tx4, GLfloat ty4);
void R2D_GL2_DrawText(R2D_Text *txt);
void R2D_GL3_DrawText(R2D_Text *txt);
void R2D_GL3_FlushBuffers();
Expand Down
30 changes: 30 additions & 0 deletions ext/ruby2d/tileset.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// tileset.c

#include "ruby2d.h"


/*
* Draw a tile
*/
void R2D_DrawTile(R2D_Image *img, int tw, int th, int padding, int spacing, int tx, int ty, int x, int y) {
if (!img) return;

if (img->texture_id == 0) {
R2D_GL_CreateTexture(&img->texture_id, img->format,
img->width, img->height,
img->surface->pixels, GL_NEAREST);
SDL_FreeSurface(img->surface);
}

GLfloat tx1 = (double)(padding + ((spacing + tw) * tx)) / (double) img->width ;
GLfloat tx2 = tx1 + ((double)tw / (double) img->width);
GLfloat tx3 = tx2;
GLfloat tx4 = tx1;

GLfloat ty1 = (double)(padding + ((spacing + th) * ty)) / (double) img ->height;
GLfloat ty2 = ty1;
GLfloat ty3 = ty1 + ((double)th / (double) img->height);
GLfloat ty4 = ty3;

R2D_GL_DrawTile(img, x, y, tw, th, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
}
1 change: 1 addition & 0 deletions lib/ruby2d.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
require 'ruby2d/pixel'
require 'ruby2d/image'
require 'ruby2d/sprite'
require 'ruby2d/tileset'
require 'ruby2d/font'
require 'ruby2d/text'
require 'ruby2d/sound'
Expand Down
69 changes: 69 additions & 0 deletions lib/ruby2d/tileset.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Ruby2D::Tileset

module Ruby2D
class Tileset
include Renderable

def initialize(path, opts = {})
unless File.exist? path
raise Error, "Cannot find tileset image file `#{path}`"
end
@path = path
@tiles = []
@defined_tiles = {}
@padding = opts[:padding] || 0
@spacing = opts[:spacing] || 0
@tile_width = opts[:tile_width]
@tile_height = opts[:tile_height]

unless ext_init(@path)
raise Error, "Tileset `#{@path}` cannot be created"
end

unless opts[:show] == false then add end
end

def define_tile(name, x, y)
@defined_tiles[name] = { x: x, y: y }
end

def set_tile(name, coordinates)
tile = @defined_tiles.fetch(name)

coordinates.each do |coordinate|
@tiles.push({
tile_x: tile.fetch(:x),
tile_y: tile.fetch(:y),
x: coordinate.fetch(:x),
y: coordinate.fetch(:y)
})
end
end

def clear_tiles
@tiles = []
end
end

def draw(opts = {})
render(opts)
end

private

def render(opts = {})
opts[:tile_width] = opts[:tile_width] || @tile_width
opts[:tile_height] = opts[:tile_height] || @tile_height
opts[:padding] = opts[:padding] || @padding
opts[:spacing] = opts[:spacing] || @spacing

@tiles.each do |tile|
self.class.ext_draw(
[
self, opts[:tile_width], opts[:tile_height], opts[:padding], opts[:spacing],
tile.fetch(:tile_x), tile.fetch(:tile_y), tile.fetch(:x),
tile.fetch(:y)
])
end
end
end
46 changes: 46 additions & 0 deletions test/tileset.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'ruby2d'

class GameWindow < Ruby2D::Window
TILE_WIDTH = 36
TILE_HEIGHT = 45

def initialize
super
set width: 108
set height: 135
set background: 'white'
@tileset = Tileset.new('media/texture_atlas.png', tile_width: TILE_WIDTH, tile_height: TILE_HEIGHT)
end

def update
@tileset.clear_tiles

@tileset.define_tile('num-1', 0, 0)
@tileset.define_tile('num-2', 1, 1)
@tileset.define_tile('num-3', 2, 0)

@tileset.set_tile('num-1', [
{x: TILE_WIDTH * 0, y: TILE_HEIGHT * 0},
{x: TILE_WIDTH * 1, y: TILE_HEIGHT * 1},
{x: TILE_WIDTH * 2, y: TILE_HEIGHT * 2}
])

@tileset.set_tile('num-2', [
{x: TILE_WIDTH * 0, y: TILE_HEIGHT * 1},
{x: TILE_WIDTH * 1, y: TILE_HEIGHT * 2},
{x: TILE_WIDTH * 2, y: TILE_HEIGHT * 0},
])

@tileset.set_tile('num-3', [
{x: TILE_WIDTH * 0, y: TILE_HEIGHT * 2},
{x: TILE_WIDTH * 1, y: TILE_HEIGHT * 0},
{x: TILE_WIDTH * 2, y: TILE_HEIGHT * 1},
])
end

def render
@tileset.draw
end
end

GameWindow.new.show