#include #include #include #include #include #include #include #include SDL_Window *mwindow; SDL_Renderer *renderer; struct RClass *cSprite; // class work struct glmrb_sprite { SDL_Surface *surface; SDL_Texture *texture; int width; int height; }; static void glmrb_sprite_free(mrb_state *mrb, void *ptr); static struct mrb_data_type mrb_sprite_type = {"Sprite", glmrb_sprite_free}; struct Timer { Sint64 now, interval; // Uint32 now, wit, lev; } timer; /* Sprite#initialize */ static mrb_value glmrb_sprite_initialize(mrb_state *mrb, mrb_value self) { struct glmrb_sprite *sprite; mrb_value vx, vy; char *s; sprite = (struct glmrb_sprite *)mrb_malloc(mrb, sizeof(struct glmrb_sprite)); if (sprite == NULL) { SDL_Log("Out of memory.\n"); mrb_raise(mrb, E_RUNTIME_ERROR, "out of memory."); } DATA_TYPE(self) = &mrb_sprite_type; DATA_PTR(self) = sprite; sprite->width = 0; sprite->height = 0; sprite->surface = NULL; sprite->texture = NULL; // get paramater, o:Object [mrb_value], z:String [mrb_value] mrb_get_args(mrb, "ooz", &vx, &vy, &s); mrb_iv_set(mrb, self, mrb_intern(mrb, "@x", 2), vx); mrb_iv_set(mrb, self, mrb_intern(mrb, "@y", 2), vy); // load image file sprite->surface = IMG_Load(s); if (sprite->surface == NULL) { SDL_Log("Cannot create SDL_Surface.\n"); mrb_raise(mrb, E_RUNTIME_ERROR, "Cannot create SDL_Surface."); } else { // get image width and height sprite->width = sprite->surface->w; sprite->height = sprite->surface->h; } // create texture sprite->texture = SDL_CreateTextureFromSurface(renderer, sprite->surface); if (sprite->texture == NULL) { SDL_Log("Cannot create SDL_Texture.\n"); mrb_raise(mrb, E_RUNTIME_ERROR, "Cannot create SDL_Texture."); } return self; } /* Sprite#draw */ static mrb_value glmrb_sprite_draw(mrb_state *mrb, mrb_value self) { struct glmrb_sprite *sprite = DATA_PTR(self); SDL_Rect src, dst; src.x = 0; src.y = 0; src.w = sprite->width; src.h = sprite->height; dst.x = mrb_fixnum(mrb_iv_get(mrb, self, mrb_intern(mrb, "@x", 2))); dst.y = mrb_fixnum(mrb_iv_get(mrb, self, mrb_intern(mrb, "@y", 2))); dst.w = src.w; dst.h = src.h; // SDL_BlitSurface(sprite->surface, &src, mwindow, &dst); SDL_RenderCopy(renderer, sprite->texture, &src, &dst); return self; } /* Sprite#width */ static mrb_value glmrb_sprite_width(mrb_state *mrb, mrb_value self) { struct glmrb_sprite *sprite = DATA_PTR(self); return mrb_fixnum_value(sprite->width); } /* Sprite#height */ static mrb_value glmrb_sprite_height(mrb_state *mrb, mrb_value self) { struct glmrb_sprite *sprite = DATA_PTR(self); return mrb_fixnum_value(sprite->height); } static void glmrb_sprite_free(mrb_state *mrb, void *ptr) { struct glmrb_sprite *sprite = ptr; if (sprite->texture != NULL) SDL_DestroyTexture(sprite->texture); if (sprite->surface != NULL) SDL_FreeSurface(sprite->surface); mrb_free(mrb, sprite); } // quit check int quits(void) { SDL_Event events; if (SDL_PollEvent(&events)) { switch (events.type) { case SDL_QUIT: return 0; break; case SDL_KEYDOWN: if (events.key.keysym.sym == SDLK_ESCAPE || events.key.keysym.sym == SDLK_q) return 0; break; default: break; } } return 1; } int main(int argc, char *argv[]) { FILE *fp; mrb_value mrb_obj; // mruby state open mrb_state *mrb = mrb_open(); if (mrb == 0) { SDL_Log("Cannot open mruby state.\n"); return -2; } // define class cSprite = mrb_define_class(mrb, "Sprite", mrb->object_class); MRB_SET_INSTANCE_TT(cSprite, MRB_TT_DATA); // define class method mrb_define_method(mrb, cSprite, "initialize", glmrb_sprite_initialize, MRB_ARGS_REQ(3)); mrb_define_method(mrb, cSprite, "draw", glmrb_sprite_draw, MRB_ARGS_NONE()); mrb_define_method(mrb, cSprite, "width", glmrb_sprite_width, MRB_ARGS_NONE()); mrb_define_method(mrb, cSprite, "height", glmrb_sprite_height, MRB_ARGS_NONE()); // SDL2 init if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { SDL_Log("Failure SDL_INIT()\n"); mrb_close(mrb); return -1; } // mwindow = SDL_SetVideoMode(640, 480, 0, 0); // SDL_WM_SetCaption("glmruby application", NULL); mwindow = SDL_CreateWindow("glmrubysdl2", 100, 100, 640, 480, 0); if (mwindow == NULL) { SDL_Log("Cannot create window.\n"); SDL_Quit(); mrb_raise(mrb, E_RUNTIME_ERROR, "Cannot create window."); exit(-1); } // create renderer renderer = SDL_CreateRenderer(mwindow, -1, SDL_RENDERER_ACCELERATED); if (renderer == NULL) { SDL_Log("Cannot create renderer.\n"); SDL_DestroyWindow(mwindow); SDL_Quit(); mrb_raise(mrb, E_RUNTIME_ERROR, "cannot create renderer."); exit(-1); } // load and run mruby script. execute after create renderer fp = fopen("main.rb", "r"); if (fp == NULL) { SDL_Log("Cannot load main.rb.\n"); mrb_raise(mrb, E_RUNTIME_ERROR, "Cannot load main.rb"); exit(-2); } mrb_obj = mrb_load_file(mrb, fp); fclose(fp); timer.interval = (Sint64)SDL_GetPerformanceFrequency() / 60; timer.now = 0; int framecounter = 0; // main loop while (quits() != 0) { mrb_funcall(mrb, mrb_obj, "update", 0); // clear with background color SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); // SDL_FillRect(mwindow, NULL, SDL_MapRGB(mwindow->format, 0, 0, 0)); mrb_funcall(mrb, mrb_obj, "draw", 0); SDL_RenderPresent(renderer); // timer wait while (SDL_TRUE) { if (((Sint64)SDL_GetPerformanceCounter() - timer.now) >= timer.interval) break; SDL_Delay(0); } timer.now = SDL_GetPerformanceCounter(); // timer.now = SDL_GetTicks(); // timer.wit = timer.now - timer.lev; // if (timer.wit < 16) // SDL_Delay(16 - timer.wit); // timer.lev = SDL_GetTicks(); // SDL_UpdateRect(mwindow, 0, 0, 0, 0); framecounter++; // if (framecounter % 60 == 0) // printf("%d\n", framecounter); } mrb_close(mrb); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(mwindow); SDL_Quit(); return 0; }