diff --git a/apps/demos/bunnymark/CMakeLists.txt b/apps/demos/bunnymark/CMakeLists.txt new file mode 100644 index 0000000..49866e8 --- /dev/null +++ b/apps/demos/bunnymark/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.21) + +project(bunnymark LANGUAGES C) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug) +endif() + +add_subdirectory($ENV{TWNROOT} $ENV{TWNBUILDDIR}) + +set(SOURCE_FILES + game.c + state.h +) + +use_townengine(${PROJECT_NAME} "${SOURCE_FILES}" ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/apps/demos/bunnymark/game.c b/apps/demos/bunnymark/game.c new file mode 100644 index 0000000..3b99855 --- /dev/null +++ b/apps/demos/bunnymark/game.c @@ -0,0 +1,115 @@ +#include "twn_game_api.h" +#include "state.h" + +#include +#include +#include +#include + +#define GRAY ((Color){ 130,130,130,255 }) +#define BLACK ((Color){ 0,0,0,255 }) + +#define LEFT_CLICK_ADD 20 +#define RIGHT_CLICK_ADD 500 + + +void handle_input(void){ + + State *state = ctx.udata; + if(ctx.input.mouse_state == 1 && ctx.input.mouse_window_position.y > 60){ // Left click + for (int i = 0; i < LEFT_CLICK_ADD; i++) + { + if (state->bunniesCount < MAX_BUNNIES) + { + state->bunnies[state->bunniesCount].position = (Vec2){ + (float)ctx.input.mouse_window_position.x, + (float)ctx.input.mouse_window_position.y + }; + state->bunnies[state->bunniesCount].speed.x = (float)(rand() % 500 - 250) / 60.0; + state->bunnies[state->bunniesCount].speed.y = (float)(rand() % 500 - 250) / 60.0; + state->bunnies[state->bunniesCount].color = (Color){ + rand() % 190 + 50, + rand() % 160 + 80, + rand() % 140 + 100, + 255 + }; + state->bunniesCount++; + } + } + } + if(ctx.input.mouse_state == 4){ // Right click + for (int i = 0; i < RIGHT_CLICK_ADD; i++) + { + if (state->bunniesCount < MAX_BUNNIES) + { + state->bunnies[state->bunniesCount].position = (Vec2){ + (float)ctx.input.mouse_window_position.x, + (float)ctx.input.mouse_window_position.y + }; + state->bunnies[state->bunniesCount].speed.x = (float)(rand() % 500 - 250) / 60.0; + state->bunnies[state->bunniesCount].speed.y = (float)(rand() % 500 - 250) / 60.0; + state->bunnies[state->bunniesCount].color = (Color){ + rand() % 190 + 50, + rand() % 160 + 80, + rand() % 140 + 100, + 255 + }; + state->bunniesCount++; + } + } + } +} + +void game_tick(void) { + static char bunny_count_text[64]; + static char bunny_path[64] = "wabbit_alpha.png"; + + // State *state = ctx.udata; + if (ctx.initialization_needed) { // First tick, initalizing data + // Allocating State struct to store data there + if (!ctx.udata) ctx.udata = ccalloc(1, sizeof(State)); + ((State *)ctx.udata)->bunniesCount = 0; + } + + State *state = ctx.udata; + + const double delta = (double)(ctx.delta_time) / 1000.0; // Receiving floating point delta value (diving by 1000 based on vibe) + + for (int i = 0; i < state->bunniesCount; i++){ + state->bunnies[i].position.x += state->bunnies[i].speed.x; + state->bunnies[i].position.y += state->bunnies[i].speed.y; + + if (((state->bunnies[i].position.x + BUNNY_W/2) > ctx.window_w) || + ((state->bunnies[i].position.x + BUNNY_W/2) < 0)) state->bunnies[i].speed.x *= -1; + if (((state->bunnies[i].position.y + BUNNY_H/2) > ctx.window_h) || + ((state->bunnies[i].position.y + BUNNY_H/2 - 60) < 0)) state->bunnies[i].speed.y *= -1; + } + + handle_input(); + + // Clear window with Gray color (set the background color this way) + draw_rectangle((Rect){0,0, ctx.window_w, ctx.window_h}, GRAY); + + for (int i = 0; i < state->bunniesCount; i++){ // Draw each bunny based on their position and color, also scale accordingly + m_sprite( + m_set(path, bunny_path), + m_set(rect, ((Rect){ .x = (int)state->bunnies[i].position.x, .y = (int)state->bunnies[i].position.y, + .w = BUNNY_W * SPRITE_SCALE, .h = BUNNY_H * SPRITE_SCALE + })), + m_opt(color, (state->bunnies[i].color)), + m_opt(stretch, true), + ); + } + // Formatting text to display, might want to add FPS here too + snprintf(bunny_count_text, 64, "Bunnies: %d", state->bunniesCount); + + draw_text(bunny_count_text, (Vec2){ 0, 0 }, 40, BLACK, "/fonts/kenney-pixel.ttf"); +} + + +void game_end(void) { + State *state = ctx.udata; + + // Free state when game ends + free(state); +} diff --git a/apps/demos/bunnymark/state.h b/apps/demos/bunnymark/state.h new file mode 100644 index 0000000..9c8db7d --- /dev/null +++ b/apps/demos/bunnymark/state.h @@ -0,0 +1,25 @@ +#ifndef STATE_H +#define STATE_H + +#include "twn_game_api.h" + +#define MAX_BUNNIES 50000 // 50K bunnies limit +#define BUNNY_W 26 +#define BUNNY_H 37 +#define SPRITE_SCALE 1 + +typedef struct Bunny { + Vec2 position; + Vec2 speed; + Color color; +} Bunny; + +typedef struct State { + Bunny bunnies[MAX_BUNNIES]; + int bunniesCount; + InputState mouse_state; +} State; + + + +#endif