Add tileset loading
This commit is contained in:
@@ -116,6 +116,8 @@ DEF_SYM(pass)
|
||||
DEF_SYM(block)
|
||||
DEF_SYM(ignore)
|
||||
DEF_SYM(call)
|
||||
DEF_SYM(padding)
|
||||
DEF_SYM(offset)
|
||||
DEF_SYM(x)
|
||||
DEF_SYM(y)
|
||||
DEF_SYM(w)
|
||||
|
||||
@@ -98,6 +98,7 @@ public:
|
||||
~Window();
|
||||
|
||||
// Rendering functions
|
||||
std::vector<uint64_t> load_image_set(const char *path, Vec2<float> tile_size, Vec2<float> padding, Vec2<float> offset, bool pixel_art);
|
||||
uint64_t load_image(const char *path, bool pixel_art);
|
||||
uint64_t create_image(Vec2<float> size, bool pixel_art);
|
||||
Vec2<float> get_image_size(uint64_t image_id);
|
||||
|
||||
+8
-1
@@ -7,6 +7,11 @@ default_font = Font.new "assets/fonts/charybdis.ttf", 24, pixel_art: true
|
||||
bg_image1 = Image.load "assets/images/menu_bg.png", pixel_art: true
|
||||
bg_image2 = Image.load "assets/images/game_over_dead_bg.png", pixel_art: true
|
||||
|
||||
tile_set = Image.load_set "assets/images/walls.png", 20, 20, padding: {x: 0, y: 20}, offset: {x: 0, y: 0}, pixel_art: true
|
||||
# tile_set is an array of images, so we can create an animation from it directly or use the images separately
|
||||
pp tile_set, "Tile set size: #{tile_set.size}"
|
||||
tile_animation = Animation.new tile_set, fps: 10
|
||||
|
||||
bg_animation = Animation.new [bg_image1, bg_image2], fps: 5
|
||||
|
||||
bg_image1_a = Animation.from(bg_image1)
|
||||
@@ -18,7 +23,7 @@ text = ElementText.new :btn_text, default_font, 0xFFFF00, {name: "Me"}, position
|
||||
|
||||
rect = ElementRect.new 100, 25, 0xFF0000, position: {x: 50, y: 50}, z: 0, rotation: 60, scale: { x: 1, y: 1 }, alpha: 0.8, click_mode: :block
|
||||
|
||||
image_element = ElementImage.new bg_animation, position: {x: 0, y: 0}, z: -1, click_mode: :block, alpha: 1
|
||||
image_element = ElementImage.new tile_animation, position: {x: 0, y: 0}, scale: { x: 20, y: 20 }, z: -1, click_mode: :block, alpha: 1
|
||||
|
||||
image1 = Image.new 50, 50, pixel_art: true
|
||||
|
||||
@@ -68,6 +73,8 @@ App.update do |delta_time|
|
||||
green_pixel = [0xFF, 0, 255, 0] # ARGB
|
||||
c_p = ((c_c / 10) % 2) == 1 ? red_pixel : green_pixel
|
||||
raw_bytes = (c_p * (50 * 50)).pack('C*')
|
||||
# this is not the most efficient way to create a raw byte array, but it works for demonstration purposes
|
||||
# you can use ` commands to get image data from an external source or generate it procedurally
|
||||
bg_image1.update(0, 0, 50, 50, raw_bytes)
|
||||
image1.update(0, 0, 50, 50, raw_bytes)
|
||||
|
||||
|
||||
+44
-1
@@ -46,6 +46,48 @@ mrb_value image_load(mrb_state *mrb, mrb_value) {
|
||||
return definitions::wrap(definitions::bindings.Image, id);
|
||||
}
|
||||
|
||||
mrb_value image_load_set(mrb_state *mrb, mrb_value) {
|
||||
char *path;
|
||||
mrb_float tile_width, tile_height;
|
||||
mrb_value kwargs;
|
||||
mrb_get_args(mrb, "zff|H", &path, &tile_width, &tile_height, &kwargs);
|
||||
|
||||
bool pixel_art = false;
|
||||
int padding_x = 0, padding_y = 0, offset_x = 0, offset_y = 0;
|
||||
if (!mrb_nil_p(kwargs)) {
|
||||
HASH_BOOL(kwargs, pixel_art, pixel_art);
|
||||
|
||||
mrb_value padding_hash = HASH_GET(kwargs, padding);
|
||||
if (!mrb_nil_p(padding_hash)) {
|
||||
HASH_FLOAT(padding_hash, x, padding_x);
|
||||
HASH_FLOAT(padding_hash, y, padding_y);
|
||||
}
|
||||
|
||||
mrb_value offset_hash = HASH_GET(kwargs, offset);
|
||||
if (!mrb_nil_p(offset_hash)) {
|
||||
HASH_FLOAT(offset_hash, x, offset_x);
|
||||
HASH_FLOAT(offset_hash, y, offset_y);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint64_t> images = window.load_image_set(
|
||||
path,
|
||||
{(float)tile_width, (float)tile_height},
|
||||
{(float)padding_x, (float)padding_y},
|
||||
{(float)offset_x, (float)offset_y},
|
||||
pixel_art
|
||||
);
|
||||
|
||||
mrb_value image_array = mrb_ary_new_capa(mrb, images.size());
|
||||
for (uint64_t image_id : images) {
|
||||
image_pool.use(image_id);
|
||||
mrb_value image_obj = definitions::wrap(definitions::bindings.Image, image_id);
|
||||
mrb_ary_push(mrb, image_array, image_obj);
|
||||
}
|
||||
|
||||
return image_array;
|
||||
}
|
||||
|
||||
mrb_value image_equal(mrb_state *mrb, mrb_value self) {
|
||||
mrb_value other;
|
||||
mrb_get_args(mrb, "o", &other);
|
||||
@@ -104,7 +146,8 @@ mrb_value image_update(mrb_state *mrb, mrb_value self) {
|
||||
namespace definitions {
|
||||
void register_image() {
|
||||
DEF_CLASS(Image, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
|
||||
ADD_CLASS_METHOD(Image, "load", image_load, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
|
||||
ADD_CLASS_METHOD(Image, "load", image_load, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1));
|
||||
ADD_CLASS_METHOD(Image, "load_set", image_load_set, MRB_ARGS_REQ(3) | MRB_ARGS_OPT(1));
|
||||
ADD_METHOD(Image, "==", image_equal, MRB_ARGS_REQ(1));
|
||||
ADD_METHOD(Image, "eql?", image_equal, MRB_ARGS_REQ(1));
|
||||
ADD_METHOD(Image, "hash", image_hash, MRB_ARGS_NONE());
|
||||
|
||||
@@ -113,6 +113,69 @@ uint64_t Window::load_image(const char *path, bool pixel_art) {
|
||||
return id;
|
||||
}
|
||||
|
||||
std::vector<uint64_t> Window::load_image_set(const char *path, Vec2<float> tile_size, Vec2<float> padding, Vec2<float> offset, bool pixel_art) {
|
||||
SDL_Surface *surface = IMG_Load(path);
|
||||
|
||||
if (!surface) {
|
||||
fprintf(stderr, "Failed to load image set: %s\n", SDL_GetError());
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<uint64_t> image_ids;
|
||||
|
||||
int columns = (int)((surface->w - offset.x + padding.x) / (tile_size.x + padding.x));
|
||||
int rows = (int)((surface->h - offset.y + padding.y) / (tile_size.y + padding.y));
|
||||
|
||||
for (int y = 0; y < rows; y++) {
|
||||
for (int x = 0; x < columns; x++) {
|
||||
SDL_Rect src_rect = {
|
||||
(int)(offset.x + x * (tile_size.x + padding.x)),
|
||||
(int)(offset.y + y * (tile_size.y + padding.y)),
|
||||
(int)tile_size.x,
|
||||
(int)tile_size.y
|
||||
};
|
||||
|
||||
SDL_Surface *tile_surface = SDL_CreateSurface(src_rect.w, src_rect.h, SDL_PIXELFORMAT_RGBA8888);
|
||||
SDL_BlitSurface(surface, &src_rect, tile_surface, nullptr);
|
||||
|
||||
SDL_Texture *texture = SDL_CreateTexture(
|
||||
renderer,
|
||||
SDL_PIXELFORMAT_RGBA8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
tile_surface->w,
|
||||
tile_surface->h
|
||||
);
|
||||
|
||||
if (!texture) {
|
||||
fprintf(stderr, "Failed to create texture for tile: %s\n", SDL_GetError());
|
||||
SDL_DestroySurface(tile_surface);
|
||||
continue;
|
||||
}
|
||||
|
||||
SDL_UpdateTexture(
|
||||
texture,
|
||||
nullptr,
|
||||
tile_surface->pixels,
|
||||
tile_surface->pitch
|
||||
);
|
||||
|
||||
if (pixel_art) {
|
||||
SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
|
||||
}
|
||||
|
||||
Image *img = new Image{texture, {(float)tile_surface->w, (float)tile_surface->h}};
|
||||
uint64_t id = image_pool.acquire(img);
|
||||
image_pool.use(id);
|
||||
image_ids.push_back(id);
|
||||
|
||||
SDL_DestroySurface(tile_surface);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_DestroySurface(surface);
|
||||
return image_ids;
|
||||
}
|
||||
|
||||
uint64_t Window::create_image(Vec2<float> size, bool pixel_art) {
|
||||
SDL_Texture *texture = SDL_CreateTexture(
|
||||
renderer,
|
||||
|
||||
@@ -233,10 +233,6 @@ core:
|
||||
- ElementText
|
||||
- ElementRect
|
||||
- ElementImage
|
||||
- ElementScript - uses function to return a pizel buffer each frame, can use frame caching (for stuff liek minimaps)
|
||||
- should not reallocate every frame, can use dirty flag based system, uses a single string \
|
||||
from ruby and maybe keep string alive (add to gc exception) on c++ side too and use the same buffer to send to sdl. \
|
||||
so 2 copies 1 from ruby which can eb directly edited and then 1 a sdl texture object
|
||||
- ElementWorld - (It is a view through a camera)
|
||||
|
||||
- The world has to have an ecs system buitl in it
|
||||
|
||||
Reference in New Issue
Block a user