Exemplo n.º 1
0
void
init(void)
{
	CORE->palette.colors[PC_TRANSPARENT] = color_make(0x00, 0x00, 0x00, 0x00);
	CORE->palette.colors[PC_TRUE_BLACK]  = color_make(0x00, 0x00, 0x00, 0xff);
	set_palette_set(PS_WHITE); // IMPORTANT NOTE(bill): This must be white as the spritesheet is white

	CORE->palette.colors_count = PC_COUNT;
	canvas_clear(1);

	bitmap_load_resource(&spritesheet, "spritesheet.png");
	bitmap_load_resource(&title_screen, "title_screen.png");

	bitmap_load_resource(&font.bitmap, "font.png");
	font.char_width = 4;
	font.char_height = 7;


	CORE->font = &font;

	init_game();

#if 0
	set_palette_set(PS_WHITE);
#endif
}
Exemplo n.º 2
0
void
step()
{
    canvas_clear(1);

    if (key_down(KEY_ESCAPE)) {
        CORE->running = 0;
    }

    if (key_pressed(KEY_RETURN)) {
        window_fullscreen_toggle();
    }

    player_step(&GAME->player,
                key_down(KEY_LEFT), key_down(KEY_RIGHT), key_pressed(KEY_UP));

    tilemap_draw(GAME->scene.tilemap);

    char buf[256];
    sprintf(buf, "%.3fms %.3f", CORE->perf_step * 1e3, CORE->time_delta);
    text_draw(buf, 0, 0, 2);
}
Exemplo n.º 3
0
int32_t main(int32_t argc, char *argv[]) {
    printf("<<watchlist//>>\n");

    if( init_sdl2() ) {
        return 1;
    }

    uint32_t width = 1280;
    uint32_t height = 720;

    SDL_Window* window;
    sdl2_window("test-canvas", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, &window);

    SDL_GLContext* context;
    sdl2_glcontext(3, 2, window, &context);

    if( init_shader() ) {
        return 1;
    }

    if( init_canvas() ) {
        return 1;
    }

    printf("sizeof(struct Canvas): %zu\n", sizeof(struct Canvas));
    printf("MAX_OGL_PRIMITIVES: %d\n", MAX_OGL_PRIMITIVES);

    struct Arcball arcball = {0};
    arcball_create(width, height, (Vec4f){1.0,2.0,8.0,1.0}, (Vec4f){0.0,0.0,0.0,1.0}, 0.01, 1000.0, &arcball);

    struct Character symbols[256] = {0};
    default_font_create(symbols);

    struct Shader shader = {0};
    shader_create(&shader);
    shader_attach(&shader, GL_VERTEX_SHADER, "prefix.vert", 1, "volumetric_lines.vert");
    shader_attach(&shader, GL_FRAGMENT_SHADER, "prefix.frag", 1, "volumetric_lines.frag");
    shader_make_program(&shader, SHADER_DEFAULT_NAMES, "lines_shader");

    struct Font font = {0};
    font_create_from_characters(L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,:;", 256, symbols, 9, 3, global_default_font_palette, &font);

    struct Canvas text_canvas = {0};
    canvas_create("text_canvas", &text_canvas);
    canvas_add_attribute(&text_canvas, SHADER_ATTRIBUTE_VERTEX, 3, GL_FLOAT);
    canvas_add_attribute(&text_canvas, SHADER_ATTRIBUTE_VERTEX_COLOR, 4, GL_UNSIGNED_BYTE);
    canvas_add_attribute(&text_canvas, SHADER_ATTRIBUTE_VERTEX_TEXCOORD, 2, GL_FLOAT);
    log_assert( canvas_add_shader(&text_canvas, shader.name, &shader) < MAX_CANVAS_SHADER );
    log_assert( canvas_add_font(&text_canvas, "other_font", &font) < MAX_CANVAS_FONTS );

    struct GameTime time = {0};
    gametime_create(1.0f / 60.0f, &time);

    SDL_SetEventFilter(event_filter, NULL);
    while (true) {
        SDL_Event event;
        while( sdl2_poll_event(&event) ) {
            if( sdl2_handle_quit(event) ) {
                goto done;
            }
            sdl2_handle_resize(event);

            arcball_handle_resize(&arcball, event);
            arcball_handle_mouse(&arcball, event);
        }

        gametime_advance(&time, sdl2_time_delta());

        sdl2_debug( SDL_GL_SetSwapInterval(1) );

        ogl_debug( glClearDepth(1.0f);
                   glClearColor(.0f, .0f, .0f, 1.0f);
                   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); );

        draw_grid(&text_canvas, 0, (Mat)IDENTITY_MAT, (Color){20, 180, 240, 255}, 0.02f, 12.0f, 12.0f, 12);

        draw_basis(&text_canvas, 1, (Mat)IDENTITY_MAT, 0.02f, 1.0f);

        Mat text_matrix = {0};
        Quat text_rotation = {0};
        quat_from_axis_angle((Vec4f){1.0, 0.0, 0.0, 1.0}, PI/2, text_rotation);
        mat_rotate(NULL, text_rotation, text_matrix);
        mat_translate(text_matrix, (Vec4f){-3.5, -1.0, 6.25, 1.0}, text_matrix);

        Vec4f world_cursor = {0,0,0,1};
        text_put_world(&text_canvas, 0, world_cursor, text_matrix, (Color){0, 255, 255, 255}, 0.5f, "other_font", L"Dies ist ein Test\n");
        text_put_world(&text_canvas, 0, world_cursor, text_matrix, (Color){255, 255, 0, 255}, 0.5f, "other_font", L"fuer einen Text");

        gametime_integrate(&time);
        Vec4f screen_cursor = {0,0,0,1};
        double fps = text_show_fps(&global_dynamic_canvas, 0, screen_cursor, 0, 0, (Color){255, 255, 255, 255}, 20.0f, "default_font", time.frame);

        /* text_show_time(&text_canvas, screen_cursor, 0, "default_font", 20.0, (Color){255, 255, 255, 255}, 0, 0, time.t); */

        /* text_put_screen(&text_canvas, screen_cursor, 0, "default_font", 20.0, (Color){255, 210, 255, 255}, 0, 0, L"LALA singt das Meerschweinchen\n"); */
        /* text_put_screen(&text_canvas, screen_cursor, 0, "default_font", 20.0, (Color){0, 210, 255, 255}, 0, 0, L"FICKEN immer und ueberall\n"); */
        /* text_put_screen(&text_canvas, screen_cursor, 0, "default_font", 20.0, (Color){20, 210, 110, 255}, 0, 0, L"FUMMELN den ganzen Tag lang\n"); */

        /* text_printf(&text_canvas, screen_cursor, 0, "default_font", 20.0, (Color){255, 40, 60, 255}, 0, 0, L"PRINTF %d Luftballons\n", 99); */

        canvas_render_layers(&text_canvas, 0, MAX_CANVAS_LAYERS, &arcball.camera, (Mat)IDENTITY_MAT);
        canvas_clear(&text_canvas);

        canvas_render_layers(&global_dynamic_canvas, 0, MAX_CANVAS_LAYERS, &arcball.camera, (Mat)IDENTITY_MAT);
        canvas_clear(&global_dynamic_canvas);

        sdl2_debug( SDL_GL_SwapWindow(window) );
    }
Exemplo n.º 4
0
void
hand_pai_advice_info_display (global_t *gp)
{
  integer_t i, j, k;
  widget_t canvas = hand_pai_advice_info;
  canvas_clear ();
  widget_configure (canvas, resource_pixmapstart, HANDPAISTART);

  collect_reveal_pai_info (gp);

  for (i = 0; i < hand[vself].closed_num; i++)
    {
      integer_t pai = P_KIND (hand[vself].closed[i]);
      integer_t reveal = pai_reveal[pai];
      integer_t margin;
      gpixmap2_t pm;
      if (i == hand[vself].closed_num - 1)
        margin = HANDPAIMARGIN;
      else
        margin = 0;
      if (reveal < 0 || reveal > 4)
        reveal = 4;

      if (flag_advicedigit)
        {
          pm = &pm_tiny_digit[4 - reveal];
        }
      else
        {
          pm = &pm_tiny_space;
        }
      print_colorpixmap2_withmargin (pm, margin);

      if (flag_advicepai)
        {
          for (j = 0; j < 4; j++)
            {
              if (j != vself)
                {
                  if (pai_genbutu[j][pai])
                    {
                      print_colorpixmap (pm_tiny_home[j]);
                    }
                  else
                    {
                      print_colorpixmap (pm_tiny_space);
                    }
                }
              else
                {
                  print_colorpixmap (pm_tiny_space);
                }
            }
        }
      else
        {
          for (j = 0; j < 4; j++)
            {
              print_colorpixmap (pm_tiny_space);
            }
        }
    }
}
Exemplo n.º 5
0
int32_t main(int32_t argc, char *argv[]) {
    if( init_sdl2() ) {
        return 1;
    }

    uint32_t width = 1280;
    uint32_t height = 720;

    SDL_Window* window = NULL;
    sdl2_window("cute3d: " __FILE__, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, &window);

    SDL_GLContext* context = NULL;
    sdl2_glcontext(3, 2, window, &context);

    if( init_shader() ) {
        return 1;
    }

    if( init_vbo() ) {
        return 1;
    }

    if( init_canvas(width, height) ) {
        return 1;
    }

    struct Arcball arcball = {};
    arcball_create(width, height, (Vec4f){1.0,2.0,6.0,1.0}, (Vec4f){0.0,0.0,0.0,1.0}, 0.001f, 100.0, &arcball);

    struct GameTime time = {};
    gametime_create(1.0f / 60.0f, &time);

    while(true) {
        SDL_Event event = {};
        while( sdl2_poll_event(&event) ) {
            if( sdl2_handle_quit(event) ) {
                goto done;
            }
            sdl2_handle_resize(event);

            arcball_handle_resize(&arcball, event);
            arcball_handle_mouse(&arcball, event);
        }

        sdl2_gl_set_swap_interval(1);
        sdl2_clear((Color){0, 0, 0, 255}, 1.0f, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        gametime_advance(&time, sdl2_time_delta());
        gametime_integrate(&time);

        Mat identity = {};
        mat_identity(identity);
        draw_grid(&global_dynamic_canvas, 0, identity, (Color){120, 120, 120, 255}, 0.01f, 12.0f, 12.0f, 12);

        Vec4f screen_cursor = {0,0,0,1};
        text_show_fps(&global_dynamic_canvas, 0, screen_cursor, 0, 0, (Color){255, 255, 255, 255}, 20.0f, "default_font", time.frame);

        canvas_render_layers(&global_static_canvas, 0, MAX_CANVAS_LAYERS, &arcball.camera, (Mat)IDENTITY_MAT);
        canvas_render_layers(&global_dynamic_canvas, 0, MAX_CANVAS_LAYERS, &arcball.camera, (Mat)IDENTITY_MAT);
        canvas_clear(&global_dynamic_canvas);

        sdl2_gl_swap_window(window);
    }

done:
    return 0;
}
Exemplo n.º 6
0
void
step(void)
{


	if (key_pressed(KEY_ESCAPE)) {
		CORE->running = 0;
		return;
	}

	     if (key_pressed(KEY_1)) set_palette_set(PS_WHITE);
	else if (key_pressed(KEY_2)) set_palette_set(PS_GREEN);
	else if (key_pressed(KEY_3)) set_palette_set(PS_BEIGE);
	else if (key_pressed(KEY_4)) set_palette_set(PS_BLUE);
	else if (key_pressed(KEY_5)) set_palette_set(PS_RED);
	else if (key_pressed(KEY_6)) set_palette_set(PS_PASTEL_MIX);
	else if (key_pressed(KEY_7)) set_palette_set(PS_RED_GREEN);




	switch (game.mode) {
	case GAME_MODE_TITLE: {
		if (game.intro_cooldown --> 0) {
			canvas_clear(PC_TRANSPARENT);
			bitmap_draw(0, 0, 0, 0, &title_screen, NULL, 0, 0);
		} else {
			game.mode = GAME_MODE_MAP;
		}
	} break;

	case GAME_MODE_MAP: {
		Map *map = &game.maps[game.curr_map_index];
		i32 i, j, x, y;
		gbVec2 old_player_pos = game.player.pos;
		b32 render_doctor_text = false;


		canvas_clear(PC_TRANSPARENT);

		game.player.vel = gb_vec2_zero();
		if (key_down(KEY_UP))    { game.player.vel.y -= 1.0f; }
		if (key_down(KEY_DOWN))  { game.player.vel.y += 1.0f; }
		if (key_down(KEY_LEFT))  { game.player.vel.x -= 1.0f; }
		if (key_down(KEY_RIGHT)) { game.player.vel.x += 1.0f; }
		gb_vec2_norm0(&game.player.vel, game.player.vel);
		gb_vec2_muleq(&game.player.vel, game.player.in_grass ? 2.5f : 3.5f);
		gb_vec2_addeq(&game.player.pos, game.player.vel);
		game.player.in_grass = false;

		game.player.is_moving = (gb_vec2_mag(game.player.vel) > 0);

		if (game.player.vel.x < 0) game.player.orientation = 2;
		if (game.player.vel.x > 0) game.player.orientation = 3;
		if (game.player.vel.y > 0) game.player.orientation = 0;
		if (game.player.vel.y < 0) game.player.orientation = 1;

		game.player.pos.x = gb_clamp(game.player.pos.x, 0, (map->width-1) *TILE_SIZE);
		game.player.pos.y = gb_clamp(game.player.pos.y, 0, (map->height-1)*TILE_SIZE);


		game.grass_event_cooldown--;
		if (game.grass_event_cooldown < 0)
			game.grass_event_cooldown = 0;

		draw_tooltip = false;
		gb_zero_array(tooltip_messages, gb_count_of(tooltip_messages));


		{ // Handle Interactions
			Rect player_rect = rect_make_size(game.player.pos.x+2, game.player.pos.y+12,
			                                  12, 4);
			for (j = 0; j < map->height; j++) {
				y = j*TILE_SIZE;
				for (i = 0; i < map->width; i++) {
					Rect tile_rect;
					char t = map->tiles[j][i];
					x = i*TILE_SIZE;
					tile_rect = rect_make_size(x, y, TILE_SIZE, TILE_SIZE);

					if (gb_char_is_digit(t)) {
						if (rect_collides(player_rect, tile_rect, NULL)) {
							change_map_to(t-'0');
							return;
						}
					}
					if ((t != ' ' && t != '.' && t != 'g')) {
						Rect inter;
						b32 do_collision = true;
						if (t == 'L') { // NOTE(bill): Lab Chemicals Top
							tile_rect = rect_make_size(x, y+7, TILE_SIZE, TILE_SIZE-7);
						}

						if (t == 'Q' && game.has_chosen_transmog) {
							do_collision = false;
						}
						if (do_collision && rect_collides(player_rect, tile_rect, &inter)) {
							game.player.pos = old_player_pos;
							game.player.is_moving = false;
						}

					}


					if (t == 'g' && game.player.is_moving && rect_collides(player_rect, tile_rect, NULL)) {
						i32 random = gb_random_range_int(0, 100);
						game.player.in_grass = true;
						if ((random < 7) && (game.grass_event_cooldown <= 0)) {
							game.grass_event_cooldown = 50;
#if 1
							change_to_battle_mode(BATTLE_TYPE_GRASS);
#endif
							return;
						}
					}

					if (t == 'D') {
						f32 dx = game.player.pos.x - (x + TILE_SIZE/2);
						f32 dy = game.player.pos.y - (y + TILE_SIZE/2);
						if (dx*dx+dy*dy < square(2*TILE_SIZE)) render_doctor_text = true;
					}

					if (t == 'Y') {
						set_tooltip(x, y, 1.5f,
						            "Hello! I'm your worst nightmare!",
						            "My name is Yugi the Boss.",
						            "Want to battle [z]?");

						if (key_pressed(KEY_Z)) {
							change_to_battle_mode(BATTLE_TYPE_BOSS);
							return;
						}
					}

					if (t == 'Q' && !game.has_chosen_transmog) {
						set_tooltip(x, y, 1.5f,
						            "It's dangerous to go alone",
						            "in there! You might get hurt.",
						            "Go see The Doctor in The Lab.");
					}

					if (t == 'L' || t == 'l') {
						set_tooltip(x, y, 1.0f,
						            "It appears to be weird chemicals.", NULL, NULL);
					}

					if (t == 'm' || t == 'c') {
						set_tooltip(x, y, 1.0f,
						            "State of the art computers",
						            "The new Pear Bartlett!",
						            NULL);
					}
					if (t == 'P') {
						set_tooltip(x, y, 0.6f,
						            "Such a lovely picture!", NULL, NULL);
					}

					if (t == 'B' || t == 'b') {
						set_tooltip(x, y, 1.2f,
						            "It is not time to sleep.", NULL, NULL);
					}

					if (t == 'W') {
						set_tooltip(x, y, 0.6f,
						            "It's a beautiful view outside.",
						            "Why not go outside and explore?", NULL);
					}
				}
			}
		}

		move_game_camera(map);


		// Render 1x1 Sprites
		for (j = 0; j < map->height; j++) {
			y = j*TILE_SIZE;
			for (i = 0; i < map->width; i++) {
				char t = map->tiles[j][i];
				x = i*TILE_SIZE;
				switch (t) {
				case ' ':
				case '.':
				case 'g':
				case 'Q':
				case 'D':
				case 'Y': {
					i32 sx = 0;
					i32 sy = map->outside;
					if (map->outside) {
						sx = (i+j)%2;
					}
					draw_sprite(x, y, sx, sy, 0);

					if (t == 'g') draw_sprite(x, y, 2, 1, 0); // grass
					if (t == 'Q' && !game.has_chosen_transmog)
						draw_sprite(x, y, 0, 3, 0); // Person in the way
					if (t == 'D') draw_sprite(x, y, 1, 3, 0); // Dr.
					if (t == 'Y') draw_sprite(x, y, 2, 3, 0); // Yugi
				} break;
				case 'x': draw_sprite(x, y,  1, 0, 0); break; // Wall
				case 'P': draw_sprite(x, y,  2, 0, 0); break; // Hanging Picture
				case 'W': draw_sprite(x, y,  3, 0, 0); break; // Window
				case 'T': draw_sprite(x, y,  3, 1, 0); break; // Thick Grass
				case 't': draw_sprite(x, y,  4, 1, 0); break; // Tree trunk
				case 'B': draw_sprite(x, y,  5, 0, 0); break; // Bed Top
				case 'b': draw_sprite(x, y,  5, 1, 0); break; // Bed bottom
				case 'M': draw_sprite(x, y,  6, 0, 0); break; // Computer monitor
				case 'm': draw_sprite(x, y,  6, 1, 0); break; // Computer keyboard
				case 'C': draw_sprite(x, y,  7, 0, 0); break; // Computer case
				case 'c': draw_sprite(x, y,  7, 1, 0); break; // Computer mouse
				case 'L': draw_sprite(x, y,  8, 0, 0); break; // Lap Chemicals top
				case 'l': draw_sprite(x, y,  8, 1, 0); break; // Lap Chemicals bottom

				default: {
					if (gb_char_is_digit(t)) draw_sprite(x, y, 4, 0, 0);
				} break;
				}
			}
		}

		// Render NxM Sprites
		// TODO(bill): Be more efficient
		for (j = 0; j < map->height; j++) {
			y = j*TILE_SIZE;
			for (i = 0; i < map->width; i++) {
				char t = map->tiles[j][i];
				x = i*TILE_SIZE;
				switch (t) {
				case 'h': draw_sprite_size(x, y, 12, 2, 4, 4, 0); break;
				case 'd': draw_sprite_size(x, y,  8, 2, 4, 4, 0); break;
				}
			}
		}

		{ // Render player and particles
			i32 sx = 0;
			u32 flags = 0;
			// 0 - down
			// 1 - up
			// 2 - left
			// 3 - right (-ve left)
			if (game.player.orientation == 0) sx = 0;
			if (game.player.orientation == 1) sx = 1;
			if (game.player.orientation == 2) sx = 2;
			if (game.player.orientation == 3) { sx = 2; flags |= DrawFlags_FlipH; }
			if (game.player.is_moving) {
				u32 flip = 10.0f*CORE->perf_frame.stamp;
				b32 use_flip = true;
				if (game.player.orientation == 0) {
					if (use_flip) {
						sx = 3;
						flags |= DrawFlags_FlipH * (flip%2);
					}
				} else if (game.player.orientation == 1) {
					if (use_flip) {
						sx = 4;
						flags |= DrawFlags_FlipH * (flip%2);
					}
				} else {
					sx += 3 * (flip%2);
				}
			}
			draw_sprite(game.player.pos.x, game.player.pos.y, sx, 2, flags);
		}

		{ // Render Text
			CORE->translate_x = 0;
			CORE->translate_y = 0;

			if (game.show_map_name_ticks-- > 0) {
				if (game.show_map_name_ticks < 0)
					game.show_map_name_ticks = 0;

				{
					char *name = game.maps[game.curr_map_index].name;
					i32 name_len = gb_strlen(name);
					i32 w = name_len*font.char_width+6;
					i32 h = font.char_height+6;

					rect_draw(rect_make_size(1, 1, w, h), PC_WHITE);
					rect_draw(rect_make_size(1,   0, w, 1), PC_DARK_GREY);
					rect_draw(rect_make_size(1, h+1, w, 1), PC_DARK_GREY);
					rect_draw(rect_make_size(0,   1, 1, h), PC_DARK_GREY);
					rect_draw(rect_make_size(w+1, 1, 1, h), PC_DARK_GREY);


					text_draw(4, 4, name, PC_BLACK);
				}
			}

			if (render_doctor_text) {
				if (game.doctor_line_index < gb_count_of(doctor_lines)) {
					draw_message_box(doctor_lines[game.doctor_line_index], "", "[Z] to continue");

					if (key_pressed(KEY_Z)) game.doctor_line_index++;
				} else if (!game.has_chosen_transmog) {
					draw_message_box("Line          [X]",
					                 "Triangle      [C]",
					                 "Square        [V]");
					if (key_pressed(KEY_X)) {
						game.player.my_transmog = make_transmog(TRANSMOG_TYPE_LINE);
						game.has_chosen_transmog = true;
					} else if (key_pressed(KEY_C)) {
						game.player.my_transmog = make_transmog(TRANSMOG_TYPE_TRIANGLE);
						game.has_chosen_transmog = true;
					} else if (key_pressed(KEY_V)) {
						game.player.my_transmog = make_transmog(TRANSMOG_TYPE_SQUARE);
						game.has_chosen_transmog = true;
					}

				} else {
					draw_message_box("Go now and find Transmogs!", "", "");
				}
			} else if (draw_tooltip) {
				draw_message_box(tooltip_messages[0], tooltip_messages[1], tooltip_messages[2]);
			}
		}
	} break;

	case GAME_MODE_BATTLE: {
		i32 i, w = CANVAS_WIDTH, h = CANVAS_HEIGHT;
		Transmog *enemy_mog = &game.battle_mode.enemy_mog;
		Transmog *player_mog = game.battle_mode.player_mog;
		char name_buf[32] = "";
		char *attack_names[3] = {
			"TRANSLATE",
			"ROTATE",
			"DIVIDE",
		};
		i32 level_diff = enemy_mog->shift_level - player_mog->shift_level;


		CORE->translate_x = 0;
		CORE->translate_y = 0;

		canvas_clear(PC_WHITE);

		// Enemy Transmog
		gb_snprintf(name_buf, gb_size_of(name_buf),
		            "%s LVL%d", transmog_name(enemy_mog->type), enemy_mog->shift_level);
		text_draw(8, 5, name_buf, PC_BLACK);
		draw_sprite_size(8, 12,
		                 2, 4,
		                 3, 1, 0);
		draw_sprite_size(24, 15,
		                 3, 5,
		                 2, 1, 0);
		{
			f32 hp_percent = cast(f32)enemy_mog->health/cast(f32)enemy_mog->max_health;
			rect_draw(rect_make_size(25, 16, hp_percent*30, 1), PC_LIGHT_GREY);
			draw_big_transmog(84, 4, enemy_mog->type);
		}


		// Player Transmog
		gb_snprintf(name_buf, gb_size_of(name_buf),
		            "%s LVL%d", transmog_name(player_mog->type), player_mog->shift_level);
		text_draw(100, 80, name_buf, PC_BLACK);
		draw_sprite_size(104, 92,
		                 5, 4,
		                 3, 1, 0);
		draw_sprite_size(117, 95,
		                 3, 5,
		                 2, 1, 0);
		{
			f32 hp_percent = cast(f32)player_mog->health/cast(f32)player_mog->max_health;
			char buf[16] = {0};
			gb_snprintf(buf, gb_size_of(buf),
			            "%03d/%03d", player_mog->health, player_mog->max_health);
			rect_draw(rect_make_size(118, 96, hp_percent*30, 1), PC_LIGHT_GREY);
			text_draw(118, 99, buf, PC_BLACK);

			draw_big_transmog(4, 54, player_mog->type);
		}

		if (!game.battle_mode.is_enemies_turn) {
			switch (game.battle_mode.state) {
			case BATTLE_TURN_STATE_INTRO: {
				char buf[32] = {0};
				gb_snprintf(buf, gb_size_of(buf),
				            "A wild %s appears!", transmog_name(enemy_mog->type));
				draw_message_box(buf, "", "[Z] to continue");

				if (key_pressed(KEY_Z)) {
					game.battle_mode.state = BATTLE_TURN_STATE_WHAT_TO_DO;
					return;
				}
			} break;
			case BATTLE_TURN_STATE_WHAT_TO_DO: {
				u32 hot_item = 0;
				if (game.battle_mode.type == BATTLE_TYPE_GRASS) {
					game.battle_mode.state_index %= 3;
					hot_item = game.battle_mode.state_index;
	 				draw_message_box("What to do?           Fight     ",
					                 "                      Substitute",
					                 "                      Escape    ");
					draw_sprite(70, 111, 0, 4, 0);
					draw_sprite(70, 127, 0, 5, 0);
					draw_sprite(90, 117 + hot_item*font.char_height, 5, 5, 0);

					if (key_pressed(KEY_DOWN)) {
						game.battle_mode.state_index++;
					}
					if (key_pressed(KEY_UP)) {
						if (game.battle_mode.state_index == 0)
							game.battle_mode.state_index = 2;
						else
							game.battle_mode.state_index--;
					}

					if (key_pressed(KEY_Z)) {
						switch (hot_item) {
						case 0:
							game.battle_mode.state = BATTLE_TURN_STATE_FIGHT;
							game.battle_mode.state_index = 0;
							game.battle_mode.fighting_state = FIGHTING_STATE_NONE;
							return;
						case 1:
							game.battle_mode.state = BATTLE_TURN_STATE_SUBSTITUTE;
							game.battle_mode.state_index = 0;
						case 2:
							game.battle_mode.state = BATTLE_TURN_STATE_ESPACE;
							game.battle_mode.state_index = 0;
							return;
						}
					}
				} else {
					game.battle_mode.state_index %= 2;
					hot_item = game.battle_mode.state_index;
	 				draw_message_box("What to do?           Fight     ",
					                 "                      Escape    ",
					                 "                                ");
					draw_sprite(70, 111, 0, 4, 0);
					draw_sprite(70, 127, 0, 5, 0);
					draw_sprite(90, 117 + hot_item*font.char_height, 5, 5, 0);

					if (key_pressed(KEY_DOWN)) {
						game.battle_mode.state_index++;
					}
					if (key_pressed(KEY_UP)) {
						if (game.battle_mode.state_index == 0)
							game.battle_mode.state_index = 1;
						else
							game.battle_mode.state_index--;
					}

					if (key_pressed(KEY_Z)) {
						switch (hot_item) {
						case 0:
							game.battle_mode.state = BATTLE_TURN_STATE_FIGHT;
							game.battle_mode.state_index = 0;
							game.battle_mode.fighting_state = FIGHTING_STATE_NONE;
							return;
						case 1:
							game.battle_mode.state = BATTLE_TURN_STATE_ESPACE;
							game.battle_mode.state_index = 0;
							return;
						}
					}
				}


			} break;
			case BATTLE_TURN_STATE_FIGHT: {
				char buf[32] = "";
				switch (game.battle_mode.fighting_state) {
				case FIGHTING_STATE_NONE: {
					u32 hot_item = game.battle_mode.state_index;
					draw_message_box("Which attack?         Translate ",
					                 "                      Rotate    ",
					                 "                      Divide    ");
					draw_sprite(70, 111, 0, 4, 0);
					draw_sprite(70, 127, 0, 5, 0);
					draw_sprite(90, 117 + hot_item*font.char_height, 5, 5, 0);

					if (key_pressed(KEY_DOWN)) {
						game.battle_mode.state_index++;
						game.battle_mode.state_index %= 3;
					}
					if (key_pressed(KEY_UP)) {
						if (game.battle_mode.state_index == 0)
							game.battle_mode.state_index = 2;
						else
							game.battle_mode.state_index--;
					}

					if (key_pressed(KEY_X)) {
						game.battle_mode.state_index = 0;
						game.battle_mode.state = BATTLE_TURN_STATE_WHAT_TO_DO;
						return;
					}

					if (key_pressed(KEY_Z)) {
						game.battle_mode.attack_index = hot_item;
						game.battle_mode.state_index = 0;
						game.battle_mode.fighting_state = FIGHTING_STATE_USE;
						return;
					}
				} break;
				case FIGHTING_STATE_USE: {
					gb_snprintf(buf, gb_size_of(buf),
					            "Your %s used %s",
					            transmog_name(enemy_mog->type),
					            attack_names[game.battle_mode.attack_index]);
					draw_message_box(buf, NULL, NULL);

					if (key_pressed(KEY_Z)) {
					if (-level_diff < 0) { // Higher level enemy
						game.battle_mode.fighting_state = FIGHTING_STATE_SUPER_EFFECTIVE;
					} else {
						if (gb_random_range_int(0, -level_diff+1) == 0) {
							game.battle_mode.fighting_state = FIGHTING_STATE_SUPER_EFFECTIVE;
						} else {
							if (gb_random_range_int(0, -level_diff/2 + 1) == 0)
								game.battle_mode.fighting_state = FIGHTING_STATE_EFFECTIVE;
							else
								game.battle_mode.fighting_state = FIGHTING_STATE_NO_EFFECT;
						}
					}
					return;
				}
				} break;
				case FIGHTING_STATE_EFFECTIVE: {
					gb_snprintf(buf, gb_size_of(buf),
					            "%s was effective",
					            attack_names[game.battle_mode.attack_index]);
					draw_message_box(buf, NULL, NULL);

					if (key_pressed(KEY_Z)) {
						i32 damage = gb_clamp(0, player_mog->attack_power/3 + level_diff/2, 1000);
						enemy_mog->health -= damage;

						game.battle_mode.fighting_state = FIGHTING_STATE_NEXT_TURN;
					}
				} break;
				case FIGHTING_STATE_SUPER_EFFECTIVE: {
					gb_snprintf(buf, gb_size_of(buf),
					            "%s was super effective",
					            attack_names[game.battle_mode.attack_index]);
					draw_message_box(buf, NULL, NULL);

					if (key_pressed(KEY_Z)) {
						i32 damage = gb_clamp(0, player_mog->attack_power/1 + level_diff/2, 1000);
						enemy_mog->health -= damage;
						game.battle_mode.fighting_state = FIGHTING_STATE_NEXT_TURN;
						game.battle_mode.state_index = 0;
					}
				} break;
				case FIGHTING_STATE_NO_EFFECT: {
					gb_snprintf(buf, gb_size_of(buf),
					            "%s had no effect",
					            attack_names[game.battle_mode.attack_index]);
					draw_message_box(buf, NULL, NULL);

					if (key_pressed(KEY_Z))
						game.battle_mode.fighting_state = FIGHTING_STATE_NEXT_TURN;
				} break;
				case FIGHTING_STATE_NEXT_TURN: {
					char *end_message = "";
					if (enemy_mog->health <= 0 &&
					    !(game.battle_mode.state_index & 1)) {
						enemy_mog->health = 0;
						player_mog->xp += clamp(1, 4 + level_diff, 1000);

						while (player_mog->xp >= 10) {
							player_mog->xp -= 10;
							player_mog->shift_level++;
							update_transmog_stats(player_mog);
							player_mog->health = player_mog->max_health;
							game.battle_mode.state_index |= 2;
						}

						game.battle_mode.state_index |= 1;
					}
					if (game.battle_mode.state_index & 1) {
						if (game.battle_mode.type == BATTLE_TYPE_GRASS) {
							if (game.battle_mode.state_index & 2)
								end_message = "Your Transmog has levelled up!";
							draw_message_box("You win this battle!", end_message, "Exit the battle.");
							if (key_pressed(KEY_Z)) {
								game.mode = GAME_MODE_MAP;
								game.battle_mode.state_index = 0;
								return;
							}
						} else {
							canvas_clear(PC_WHITE);
							draw_sprite(72, 40,
							            2, 3, 0);

							draw_message_box("You defeated me?! HOW?!",
							                 "Well it's my first battle...",
							                 "Well done and thank you!");

							if (key_pressed(KEY_Z)) {
								game.mode = GAME_MODE_END_SUCCESS;
								return;
							}
						}
					} else {
						draw_message_box("End turn.", NULL, NULL);
						if (key_pressed(KEY_Z)) {
							end_battle_mode_turn();
							return;
						}
					}
				} break;
				}
			} break;
			case BATTLE_TURN_STATE_SUBSTITUTE: {
				i32 level_diff = enemy_mog->shift_level - player_mog->shift_level;

				if (level_diff <= 0) {
					draw_message_box("Failed to substitute",
					                 "",
					                 "End turn.");

					if (key_pressed(KEY_Z)) {
						end_battle_mode_turn();
						return;
					}

				} else {
					if (game.battle_mode.state_index == 0) {
						if (gb_random_range_int(0, level_diff) != 0)
							game.battle_mode.state_index = 1; // Success
						else
							game.battle_mode.state_index = 2; // Failure
					}

					if (game.battle_mode.state_index == 1) {
						draw_message_box("Well done!",
						                 "You successfully substituted.",
						                 "Exit to world");

						if (key_pressed(KEY_Z)) {
							// Change it!
							game.player.my_transmog = *enemy_mog;
							game.mode = GAME_MODE_MAP;
							return;
						}
					} else {
						draw_message_box("Substitution failed!",
						                 "",
						                 "End turn.");

						if (key_pressed(KEY_Z)) {
							end_battle_mode_turn();
							return;
						}
					}
				}
			} break;
			case BATTLE_TURN_STATE_ESPACE: {
				if (game.battle_mode.state_index == 0) {
					if (gb_random_range_int(0, 100) < 90) {
						game.battle_mode.state_index = 1;
					} else {
						game.battle_mode.state_index = 2;
					}
				}

				if (game.battle_mode.state_index == 1) {
					draw_message_box("You escaped from this battle!",
					                 "",
					                 "[Z] to return to the world.");

					if (key_pressed(KEY_Z)) {
						game.mode = GAME_MODE_MAP;
						return;
					}
				} else {
					draw_message_box("You could not escape!",
					                 "You'll have to try again!",
					                 "[Z] to end turn.");
					end_battle_mode_turn();
					return;
				}
			} break;
			}
		} else {
		// NOTE(bill): Enemies Turn
			char buf[32] = {0};

			switch (game.battle_mode.fighting_state) {
			case FIGHTING_STATE_NONE: {
				game.battle_mode.attack_index = gb_random_range_int(0, 2);
				game.battle_mode.fighting_state = FIGHTING_STATE_USE;
				return;
			} break;
			case FIGHTING_STATE_USE: {
				gb_snprintf(buf, gb_size_of(buf),
				            "Enemy %s used %s",
				            transmog_name(enemy_mog->type),
				            attack_names[game.battle_mode.attack_index]);
				draw_message_box(buf, NULL, NULL);

				if (key_pressed(KEY_Z)) {
					if (level_diff < 0) { // Higher level enemy
						game.battle_mode.fighting_state = FIGHTING_STATE_SUPER_EFFECTIVE;
					} else {
						if (gb_random_range_int(0, -level_diff+3) == 0) {
							game.battle_mode.fighting_state = FIGHTING_STATE_SUPER_EFFECTIVE;
						} else {
							if (gb_random_range_int(0, -level_diff/2 + 3) == 0)
								game.battle_mode.fighting_state = FIGHTING_STATE_EFFECTIVE;
							else
								game.battle_mode.fighting_state = FIGHTING_STATE_NO_EFFECT;
						}
					}
					return;
				}
			} break;
			case FIGHTING_STATE_EFFECTIVE: {
				gb_snprintf(buf, gb_size_of(buf),
				            "%s was effective",
				            attack_names[game.battle_mode.attack_index]);
				draw_message_box(buf, NULL, NULL);

				if (key_pressed(KEY_Z)) {
					i32 damage = gb_clamp(0, enemy_mog->attack_power/6.0f - level_diff/3.0f, 1000);

					player_mog->health -= damage;

					game.battle_mode.fighting_state = FIGHTING_STATE_NEXT_TURN;
				}

			} break;
			case FIGHTING_STATE_SUPER_EFFECTIVE: {
				gb_snprintf(buf, gb_size_of(buf),
				            "%s was super effective",
				            attack_names[game.battle_mode.attack_index]);
				draw_message_box(buf, NULL, NULL);

				if (key_pressed(KEY_Z)) {
					i32 damage = gb_clamp(0, enemy_mog->attack_power/3.0f - level_diff/2.0f, 1000);

					player_mog->health -= damage;

					game.battle_mode.fighting_state = FIGHTING_STATE_NEXT_TURN;
				}
			} break;
			case FIGHTING_STATE_NO_EFFECT: {
				gb_snprintf(buf, gb_size_of(buf),
				            "%s had no effect",
				            attack_names[game.battle_mode.attack_index]);
				draw_message_box(buf, NULL, NULL);

				if (key_pressed(KEY_Z))
					game.battle_mode.fighting_state = FIGHTING_STATE_NEXT_TURN;
			} break;
			case FIGHTING_STATE_NEXT_TURN: {
				char *end_message = "";
				if (player_mog->health <= 0 &&
				    !(game.battle_mode.state_index & 1)) {
					player_mog->health = 0;

					game.battle_mode.state_index |= 1;
				}
				if (game.battle_mode.state_index & 1) {
					draw_message_box("You lost this battle!", "And the game :(", "Exit the battle.");
					if (key_pressed(KEY_Z)) {
						game.mode = GAME_MODE_END_FAIL;
						return;
					}
				} else {
					draw_message_box("The enemy's turn has ended.", NULL, NULL);
					if (key_pressed(KEY_Z)) {
						end_battle_mode_turn();
						return;
					}
				}
			} break;
			}

		}
	} break;

	case GAME_MODE_END_FAIL: {
		canvas_clear(PC_BLACK);
		draw_message_box("You have failed :(",
		                 "Would you like to try again?",
		                 "Try again [z] Exit [esc]");
		if (key_pressed(KEY_Z)) {
			init_game();
			return;
		}
	} break;

	case GAME_MODE_END_SUCCESS: {
		canvas_clear(PC_BLACK);

		text_draw(4, 4,
		          "Thank you for playing Transmog!\n"
		          "Ginger Bill (c) 2016\n"
		          "\n"
		          "Ludum Dare 35\n"
		          "Theme: Shapeshift\n"
		          "\n"
		          "Please remember for vote!\n",
		          PC_WHITE);

		draw_message_box("Exit [esc]", NULL, NULL);
	} break;
	}
}
Exemplo n.º 7
0
int32_t main(int32_t argc, char *argv[]) {
    printf("<<watchlist//>>\n");

    if( init_sdl2() ) {
        return 1;
    }

    int32_t width = 1280;
    int32_t height = 720;

    SDL_Window* window;
    sdl2_window("cute3d: " __FILE__, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, &window);

    SDL_GLContext* context;
    sdl2_glcontext(3, 2, window, &context);

    if( init_shader() ) {
        return 1;
    }

    if( init_vbo() ) {
        return 1;
    }

    if( init_canvas(1280,720) ) {
        return 1;
    }
    canvas_create("global_dynamic_canvas", &global_dynamic_canvas);
    canvas_create("global_static_canvas", &global_static_canvas);

    struct Vbo vbo = {0};
    vbo_create(&vbo);
    vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX, 3, GL_FLOAT, GL_STATIC_DRAW);
    vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX_NORMAL, 3, GL_FLOAT, GL_STATIC_DRAW);
    vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX_COLOR, 4, GL_UNSIGNED_BYTE, GL_STATIC_DRAW);

    struct Ibo ibo = {0};
    ibo_create(GL_TRIANGLES, GL_UNSIGNED_INT, GL_STATIC_DRAW, &ibo);

    struct CollisionEntity entity_a = {0};
    entity_create("red", (Color){ 255, 0, 0, 255 }, &vbo, &ibo, &entity_a);
    /* quat_mul_axis_angle(entity_a.pivot.orientation, (Vec4f)UP_AXIS, PI/4, entity_a.pivot.orientation); */
    /* quat_mul_axis_angle(entity_a.pivot.orientation, (Vec4f)RIGHT_AXIS, PI/2 + 0.2, entity_a.pivot.orientation); */
    vec_add(entity_a.pivot.position, (Vec4f){0.2, 0.15, 0.8, 1.0}, entity_a.pivot.position);

    struct CollisionEntity entity_b = {0};
    entity_create("green", (Color){ 0, 255, 0, 255 }, &vbo, &ibo, &entity_b);
    quat_mul_axis_angle(entity_b.pivot.orientation, (Vec4f)RIGHT_AXIS, PI/4 - 0.2, entity_b.pivot.orientation);
    quat_mul_axis_angle(entity_b.pivot.orientation, (Vec4f)UP_AXIS, PI/2 + 0.0, entity_b.pivot.orientation);

    struct Shader flat_shader = {0};
    shader_create(&flat_shader);
    shader_attach(&flat_shader, GL_VERTEX_SHADER, "prefix.vert", 1, "flat_shading.vert");
    shader_attach(&flat_shader, GL_FRAGMENT_SHADER, "prefix.frag", 1, "flat_shading.frag");
    shader_make_program(&flat_shader, SHADER_DEFAULT_NAMES, "flat_shader");

    Vec4f light_direction = { 0.2, -0.5, -1.0 };
    shader_set_uniform_3f(&flat_shader, flat_shader.program, SHADER_UNIFORM_LIGHT_DIRECTION, 3, GL_FLOAT, light_direction);

    Color ambiance = { 65, 25, 50, 255 };
    shader_set_uniform_4f(&flat_shader, flat_shader.program, SHADER_UNIFORM_AMBIENT_LIGHT, 4, GL_UNSIGNED_BYTE, ambiance);

    struct Arcball arcball = {0};
    arcball_create(width, height, (Vec4f){5.0, 3.0, 5.0, 1.0}, (Vec4f){0.0, 0.0, 0.0, 1.0}, 1.0, 1000.0, &arcball);

    size_t num_entities = 2;
    struct PickingSphere* picking_spheres[2];
    picking_spheres[0] = &entity_a.picking_sphere;
    picking_spheres[1] = &entity_b.picking_sphere;

    struct CollisionEntity* picking_entities[2];
    picking_entities[0] = &entity_a;
    picking_entities[1] = &entity_b;

    struct GameTime time = {0};
    gametime_create(1.0f / 60.0f, &time);

    draw_grid(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){127, 127, 127, 127}, 0.01f, 12.0f, 12.0f, 12);

    while (true) {

        SDL_Event event;
        while( sdl2_poll_event(&event) ) {
            if( sdl2_handle_quit(event) ) {
                goto done;
            }
            sdl2_handle_resize(event);

            if( picking_sphere_drag_event(&arcball.camera, num_entities, picking_spheres, event) ) {
                struct CollisionEntity* selected_entity = NULL;
                float nearest = -FLT_MIN;
                for( size_t i = 0; i < num_entities; i++ ) {
                    if( picking_spheres[i]->picked && ( picking_spheres[i]->front < nearest || nearest < 0.0f ) ) {
                        nearest = picking_spheres[i]->front;
                        selected_entity = picking_entities[i];
                    }
                }

                static int32_t last_x = -1;
                static int32_t last_y = -1;
                if( selected_entity != NULL ) {
                    if( last_x > -1 && last_y > -1 ) {
                        float distance = selected_entity->picking_sphere.front;

                        Vec4f a = {0};
                        camera_ray(&arcball.camera, CAMERA_PERSPECTIVE, last_x, last_y, a);
                        vec_mul1f(a, distance, a);

                        Vec4f b = {0};
                        camera_ray(&arcball.camera, CAMERA_PERSPECTIVE, event.motion.x, event.motion.y, b);
                        vec_mul1f(b, distance, b);

                        Vec4f move = {0};
                        vec_sub(b, a, move);
                        float length = vec_length(move);

                        move[1] = 0.0f;
                        vec_normalize(move, move);
                        vec_mul1f(move, length, move);

                        vec_add(selected_entity->pivot.position, move, selected_entity->pivot.position);
                    }

                    last_x = event.motion.x;
                    last_y = event.motion.y;
                }

                if( event.type == SDL_MOUSEBUTTONUP ) {
                    last_x = -1;
                    last_y = -1;
                }
            } else {
                arcball_handle_resize(&arcball, event);
                arcball_handle_mouse(&arcball, event);
            }
        }

        sdl2_gl_set_swap_interval(0);

        gametime_advance(&time, sdl2_time_delta());

        ogl_debug( glClearDepth(1.0f);
                   glClearColor(.0f, .0f, .0f, 1.0f);
                   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); );

        Mat projection_mat = {0};
        Mat view_mat = {0};
        camera_matrices(&arcball.camera, CAMERA_PERSPECTIVE, projection_mat, view_mat);

        Mat identity = {0};
        mat_identity(identity);

        Mat transform_a = {0};
        pivot_world_transform(&entity_a.pivot, transform_a);
        //vbo_mesh_render(&entity_a.vbo_mesh, &flat_shader, &arcball.camera, transform_a);
        draw_halfedgemesh_wire(&global_dynamic_canvas, 0, transform_a, (Color){255, 0, 0, 255}, 0.02f, &entity_a.hemesh);

        Mat transform_b = {0};
        pivot_world_transform(&entity_b.pivot, transform_b);
        //vbo_mesh_render(&entity_b.vbo_mesh, &flat_shader, &arcball.camera, transform_b);
        draw_halfedgemesh_wire(&global_dynamic_canvas, 0, transform_b, (Color){0, 255, 0, 255}, 0.02f, &entity_b.hemesh);

        Mat between_transform = {0};
        pivot_between_transform(&entity_a.pivot, &entity_b.pivot, between_transform);

        Vec3f foo = {0};
        mat_mul_vec(between_transform, entity_a.hemesh.vertices.array[0].position, foo);

        struct CollisionConvexConvex collision = {0};
        struct CollisionParameter collision_parameter = {
            .face_tolerance = 0.9,
            .edge_tolerance = 0.95,
            .absolute_tolerance = 0.025
        };
        collision_create_convex_convex(&entity_a.hemesh, &entity_a.pivot,
                                       &entity_b.hemesh, &entity_b.pivot,
                                       collision_parameter,
                                       &collision);

        if( collision_test_convex_convex(&collision) ) {
            collision_contact_convex_convex(&collision);
            //printf("//collision: %d\n", collision_counter);

            const struct Contacts* contacts = &collision.contacts;
            VecP* m = contacts->points[contacts->num_contacts-1];
            for( int32_t i = 0; i < contacts->num_contacts; i++ ) {
                VecP* n = contacts->points[i];
                draw_line(&global_dynamic_canvas, 0, transform_b, (Color){255, 255, 255, 255}, 0.08f, m, n);
                m = n;
            }
        }

        gametime_integrate(&time);
        Vec4f screen_cursor = {0,0,0,1};
        text_show_fps(&global_dynamic_canvas, 0, screen_cursor, 0, 0, (Color){255, 255, 255, 255}, 20.0, "default_font", time.frame);

        canvas_render_layers(&global_static_canvas, 0, 0, &arcball.camera, (Mat)IDENTITY_MAT);

        canvas_render_layers(&global_dynamic_canvas, 0, 0, &arcball.camera, (Mat)IDENTITY_MAT);
        canvas_clear(&global_dynamic_canvas);

        sdl2_gl_swap_window(window);
    }


done:
    SDL_Quit();
    printf("done\n");
    return 0;
}