summaryrefslogtreecommitdiff
path: root/src/main.cpp
blob: 75b7894029ba8ec6710b62df482f9df453b2b116 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
 * Copyright 2022 Frederico de Oliveira Linhares
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <chrono>
#include <thread>

#include "core.hpp"
cg_sCore cg_core;

int main(int argc, char *argv[])
{
  using namespace std::chrono;
  using namespace std::this_thread;

  SDL_Event event;

  // Random numbers
  random_number_generator.seed(random_seed());

  cg_core.game_file = argv[1];
  cg_core.mrb = mrb_open();
  if (!cg_core.mrb) throw CommandError{"Failed to initialize mruby."};
  try{ cg_sCore::loader.execute(nullptr); }
  catch(const CommandError &error)
  {
    cg_core.log.message(Log::Level::Fatal, error.what());
    mrb_close(cg_core.mrb);
    return 1;
  }

  mrb_value main_obj{mrb_obj_iv_inspect(cg_core.mrb, cg_core.mrb->top_self)};

  mrb_funcall_id(cg_core.mrb, main_obj, cg_core.sym_init, 0);
  if (cg_core.mrb->exc)
  {
    mrb_print_error(cg_core.mrb);
    cg_sCore::loader.revert(nullptr);
    return 1;
  }

  auto frame_start = steady_clock::now();

  // Game main loop.
  while(!cg_core.quit_game)
  {
    // Get input.
    while(SDL_PollEvent(&event) != 0)
    {
      switch(event.type)
      {
      case SDL_KEYDOWN:
        mrb_funcall_id(
          cg_core.mrb, main_obj, cg_core.sym_key_down, 1,
          mrb_int_value(cg_core.mrb, event.key.keysym.sym));
        break;
      case SDL_KEYUP:
        mrb_funcall_id(
          cg_core.mrb, main_obj, cg_core.sym_key_up, 1,
          mrb_int_value(cg_core.mrb, event.key.keysym.sym));
        break;
      case SDL_MOUSEMOTION:
        break;
      case SDL_MOUSEBUTTONDOWN:
        break;
      case SDL_MOUSEBUTTONUP:
        break;
      case SDL_QUIT:
        mrb_funcall_id(cg_core.mrb, main_obj, cg_core.sym_quit, 0);
        break;
      }
    }

    mrb_funcall_id(cg_core.mrb, main_obj, cg_core.sym_tick, 0);
    if (cg_core.mrb->exc)
    {
      mrb_print_error(cg_core.mrb);
      cg_core.quit_game = true;
    }
    else
    {
      cg_core.vk_renderer->draw();

      // Timer
      {
        auto frame_stop = steady_clock::now();
        auto frame_duration = frame_stop - frame_start;

        // If frame take less time than maximum allowed.
        if(cg_core.max_frame_duration > frame_duration)
          sleep_for(cg_core.max_frame_duration - frame_duration);

        frame_start = frame_stop;
      }
    }
  }

  mrb_close(cg_core.mrb);
  cg_sCore::loader.revert(nullptr);

  return 0;
}